From c4022539c1c75aba1fa1b943f1bece8240662496 Mon Sep 17 00:00:00 2001 From: Tomicyo Date: Thu, 12 Jan 2017 12:34:39 +0800 Subject: [PATCH] [rhi/mtl] command context update add ios build iOS: add Info.plist generator [core/module] fix static linked module impl [core] impl query cpu usage [rhi/mtl] add display link to metal view [core/string] add hash function for String [ios] add notification to loop the renderer [rhi/mtl] correct ios pixel format on metal layer remove interfaces update ios plist_gen [rhi/mtl] update metal rhi [render] add font renderer #38 [vk] upload texture directly with linear tiling option [android] fix build error caused by freetype [and] fix android compilation [vk] load device procs at runtime [vk] fix memory leaks [render] add font shaders [vk] refactor [vk] fix bugs [vk] refactor finished fix include path in core headers [rhi/mtl] make format of render target consistent with fragment shader output [rhi/mtl] disable arc [rhi] replace `VertexInputLayout` with `VertexInputState` unify shader binding across vk and mtl [tools] add visualstudio visualizer [unittest]add hlsl shader for triangle unit test [rhi] add hlsl shader test case [vk/hlsl] fix hlsl textured cube sample [vk/hlsl] merge image & sampler combination [rhi/unittest] add compute particles unit test [core/unittest] update core unit test [vk] update vk function entry initializer [ktl/sp] fix dual-free error of ref count instance #42 [vk] refactored vulkan resource [interface] update RHI [win] add vs2017 support [ktl] add sharedptr ref count tracker #43 fix clang build error caused by 'typedef uint64 VkObject..' --- .travis.yml | 3 +- Data/Test/TextRender.frag | 8 + Data/Test/TextRender.vert | 13 + Data/Test/calibri.ttf | Bin 0 -> 1331500 bytes Data/Test/cube.frag | 22 +- Data/Test/cube.vert | 41 +- Data/Test/particles.comp | 95 +++ Data/Test/particles.frag | 25 + Data/Test/particles.vert | 41 ++ Data/Test/triangle.frag | 18 + Data/Test/triangle.vert | 46 +- Include/Config/ReadMe.md | 2 + Include/Config/note.txt | 1 - Include/Core | 15 - .../Interface}/ICrossShaderCompiler.h | 10 +- Include/Interface/IIODevice.h | 6 +- Include/Interface/IJob.h | 84 --- .../Log/Public => Include/Interface}/ILog.h | 1 + Include/Interface/IMesh.h | 11 +- Include/Interface/IModule.h | 70 ++ Include/Interface/IParameter.h | 7 - {Source/RHI => Include/Interface}/IRHI.h | 49 +- {Source/RHI => Include/Interface}/IRHIDefs.h | 78 +- Include/Interface/IRefObj.h | 9 - Include/Interface/IReflectable.h | 5 - Include/Interface/IRenderMesh.h | 3 +- Include/Interface/IRenderer.h | 18 - Include/Interface/IRunnable.h | 26 - Include/Interface/IShader.h | 30 - Include/KTL/DynArray.hpp | 40 +- Include/KTL/IntrusiveList.hpp | 3 +- Include/KTL/LockFreeQueue.hpp | 8 +- Include/KTL/NonCopyable.hpp | 5 +- Include/KTL/RefCount.hpp | 13 +- Include/KTL/SharedPtr.hpp | 151 +++- Include/KTL/Singleton.hpp | 3 + Include/KTL/String.hpp | 379 ++++++++++ Include/Math/IK.hpp | 36 + Include/Math/kMath.hpp | 2 +- Include/Math/kMath_SSE.hpp | 2 +- Project/Common.cmake | 250 +++++-- Project/{pch.cmake => Compiler.cmake} | 0 Project/FindThirdParty.cmake | 112 ++- Project/NDKStlConfig.cmake | 6 +- Project/Platform.cmake | 15 +- Project/Util.cmake | 45 ++ Project/build.gradle | 2 +- Project/iOS.cmake | 65 +- Project/plist_gen | Bin 0 -> 134624 bytes README.md | 42 +- Source/CMakeLists.txt | 56 +- Source/Core/App.cpp | 5 + Source/Core/App.h | 20 + Source/Core/Archive.cpp | 38 - Source/Core/Archive.h | 70 -- Source/Core/AssetManager.cpp | 1 - Source/Core/AssetManager.h | 5 +- Source/Core/Bundle.cpp | 1 - Source/Core/Bundle.h | 2 + Source/Core/CMakeLists.txt | 65 +- Source/Core/CameraData.cpp | 1 - Source/Core/CameraData.h | 1 + Source/Core/Dispatch/WorkQueue.h | 1 - Source/Core/InputDevice.cpp | 12 +- Source/Core/InputDevice.h | 3 + Source/Core/LogUtil.cpp | 5 +- Source/Core/LogUtil.h | 4 +- Source/Core/LogUtil.inl | 1 - Source/Core/Looper.h | 1 + Source/Core/MeshData.cpp | 1 - Source/Core/MeshData.h | 7 +- Source/Core/Message.h | 4 +- Source/Core/Module.cpp | 101 ++- Source/Core/Module.h | 61 +- Source/Core/ObjectMesh.h | 4 +- Source/Core/Os.cpp | 3 +- Source/Core/Os.h | 3 + Source/Core/ReflectFactory.h | 4 +- Source/Core/String.cpp | 12 - Source/Core/String.h | 264 ------- Source/Core/StringImpl.cpp | 133 ++++ Source/Core/Timer.h | 3 +- Source/Core/UnitTest/CMakeLists.txt | 49 ++ Source/Core/UnitTest/Common.h | 19 + .../Base => Core/UnitTest}/UTCore.Bundle.cpp | 15 +- Source/Core/UnitTest/UTCore.Os.cpp | 36 + Source/Core/UnitTest/UTCore.String.cpp | 55 ++ .../UnitTest}/UTCore.WebSocket.cpp | 24 +- Source/Core/UnitTest/UTFontLoader.cpp | 24 + Source/Core/UnitTest/UTKTL.DynArray.cpp | 75 ++ Source/Core/UnitTest/UTKTL.SharedPtr.cpp | 130 ++++ .../Core/UnitTest/UTTools.ShaderCompiler.cpp | 94 +++ Source/Core/Utils/MD5.cpp | 30 +- Source/Core/Utils/MD5.h | 32 +- Source/Core/Variant.h | 71 -- Source/Core/WebSocket.h | 3 +- Source/Core/premake5.lua | 38 - Source/Engine/CMakeLists.txt | 31 +- Source/Engine/Engine.cpp | 17 - Source/Engine/Engine.h | 6 +- Source/Engine/RendererFactory.h | 2 - Source/Engine/ShaderParameter.h | 1 - Source/Log/CMakeLists.txt | 4 +- Source/Log/Private/LogImpl.cpp | 1 - Source/Log/Public/ILogModule.h | 5 +- Source/Platform/Apple/CpuUsage.mm | 88 +++ Source/Platform/Apple/iOS/AAPLAppDelegate.h | 15 - Source/Platform/Apple/iOS/AAPLAppDelegate.mm | 13 - Source/Platform/Apple/iOS/App.mm | 51 ++ Source/Platform/Apple/iOS/Info.plist | 37 - Source/Platform/Apple/iOS/LaunchScreen.xib | 44 -- Source/Platform/Apple/iOS/Main.storyboard | 25 - Source/Platform/Apple/iOS/ThreadImpl.h | 18 - Source/Platform/Apple/iOS/ThreadImpl.mm | 58 -- Source/Platform/Apple/iOS/Window.mm | 165 +++++ Source/Platform/Apple/iOS/WindowImpl.h | 45 -- Source/Platform/Apple/iOS/WindowImpl.mm | 1 - Source/Platform/Apple/iOS/main.m | 18 - Source/Platform/Windows/CpuUsage.cpp | 139 ++++ Source/RHI/CMakeLists.txt | 7 +- Source/RHI/Metal/CMakeLists.txt | 12 +- Source/RHI/Metal/Common.h | 6 + Source/RHI/Metal/Private/MetalBuffer.mm | 52 ++ .../RHI/Metal/Private/MetalCommandContext.mm | 101 ++- Source/RHI/Metal/Private/MetalDevice.mm | 204 +++++- Source/RHI/Metal/Private/MetalEnums.h | 235 +++--- .../RHI/Metal/Private/MetalPipelineState.mm | 146 +++- Source/RHI/Metal/Private/MetalRHI.h | 145 +++- Source/RHI/Metal/Private/MetalRHI.mm | 21 +- Source/RHI/Metal/Private/MetalResource.mm | 13 + Source/RHI/Metal/Private/MetalTexture.mm | 124 ++++ Source/RHI/Metal/Public/IMetalRHI.h | 6 +- Source/RHI/Metal/Public/MetalRHIResource.h | 76 +- Source/RHI/OpenGL/CMakeLists.txt | 5 +- Source/RHI/OpenGL/OpenGLCommon.h | 2 +- Source/RHI/UnitTest/1.Device.cpp | 70 ++ .../UnitTest/2.SwapChainPresent.cpp} | 13 +- .../UnitTest/3.Triangle.cpp} | 188 ++--- .../UnitTest/4.TexturedCube.cpp} | 168 ++--- Source/RHI/UnitTest/5.ComputeParticles.cpp | 84 +++ .../Android/TexturedCube/build.gradle | 8 +- .../TexturedCube/src/main/AndroidManifest.xml | 0 .../java/com/tsinstudio/app/MainActivity.java | 2 +- .../src/main/res/layout/activity_k.xml | 0 .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../src/main/res/values-w820dp/dimens.xml | 0 .../src/main/res/values/colors.xml | 0 .../src/main/res/values/dimens.xml | 0 .../src/main/res/values/strings.xml | 0 .../src/main/res/values/styles.xml | 0 .../UnitTest/Android/Triangle/build.gradle | 8 +- .../Triangle/src/main/AndroidManifest.xml | 0 .../java/com/tsinstudio/app/MainActivity.java | 2 +- .../src/main/res/layout/activity_k.xml | 0 .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../src/main/res/values-w820dp/dimens.xml | 0 .../Triangle/src/main/res/values/colors.xml | 0 .../Triangle/src/main/res/values/dimens.xml | 0 .../Triangle/src/main/res/values/strings.xml | 0 .../Triangle/src/main/res/values/styles.xml | 0 .../UnitTest/Base}/TextureObject.cpp | 55 +- .../UnitTest/Base}/TextureObject.h | 5 +- Source/RHI/UnitTest/Base/UTRHIAppBase.h | 131 ++++ Source/RHI/UnitTest/CMakeLists.txt | 36 + Source/RHI/Vulkan/CMakeLists.txt | 14 +- Source/RHI/Vulkan/Private/DynVulkanLoader.cpp | 31 +- Source/RHI/Vulkan/Private/DynVulkanLoader.h | 33 +- .../RHI/Vulkan/Private/VkCommandContext.cpp | 56 +- Source/RHI/Vulkan/Private/VkConfig.h | 1 - Source/RHI/Vulkan/Private/VkDebug.cpp | 48 +- Source/RHI/Vulkan/Private/VkDescriptor.cpp | 56 +- Source/RHI/Vulkan/Private/VkDevice.cpp | 294 ++++---- Source/RHI/Vulkan/Private/VkEnums.h | 5 + Source/RHI/Vulkan/Private/VkFrameBuffer.cpp | 69 -- Source/RHI/Vulkan/Private/VkImpl.cpp | 2 +- Source/RHI/Vulkan/Private/VkObjects.cpp | 629 +++++++++++++++- Source/RHI/Vulkan/Private/VkObjects.h | 380 ++++++++++ .../RHI/Vulkan/Private/VkPipelineLayout.cpp | 50 -- Source/RHI/Vulkan/Private/VkPipelineState.cpp | 185 ++++- Source/RHI/Vulkan/Private/VkRHI.cpp | 265 ++----- Source/RHI/Vulkan/Private/VkRHI.h | 397 ++++++---- Source/RHI/Vulkan/Private/VkRenderPass.cpp | 65 ++ .../RHI/Vulkan/Private/VkRenderViewport.cpp | 9 +- Source/RHI/Vulkan/Private/VkResource.cpp | 205 +++--- Source/RHI/Vulkan/Private/VkSampler.cpp | 44 -- Source/RHI/Vulkan/Private/VkSwapChain.cpp | 37 +- Source/RHI/Vulkan/Private/VkUtils.cpp | 18 +- Source/RHI/Vulkan/Private/VkUtils.h | 13 +- Source/RHI/Vulkan/Public/IVkRHI.h | 6 +- Source/RHI/Vulkan/VkCommon.h | 2 +- Source/Renderer/CMakeLists.txt | 25 +- Source/Renderer/FontRenderer.cpp | 201 ++++- Source/Renderer/FontRenderer.h | 84 +++ Source/Renderer/Render.h | 2 +- Source/Renderer/RenderContext.cpp | 9 +- Source/Tools/MayaDCC/DCTranslator.h | 2 +- Source/Tools/ShaderGen/CMakeLists.txt | 18 +- .../Tools/ShaderGen/Private/GLSLCompiler.cc | 22 - .../Tools/ShaderGen/Private/GLSLangUtils.cc | 44 +- Source/Tools/ShaderGen/Private/GLSLangUtils.h | 7 +- .../Tools/ShaderGen/Private/MetalCompiler.cc | 54 +- .../Tools/ShaderGen/Private/MetalCompiler.h | 4 +- .../ShaderGen/Private/SPIRVCrossUtils.cc | 11 + .../Tools/ShaderGen/Private/SPIRVCrossUtils.h | 4 +- .../Tools/ShaderGen/Private/ShaderCompiler.cc | 7 +- .../Tools/ShaderGen/Public/ShaderCompiler.h | 4 +- .../UnitTest/1.Device/UnitTestRHIDevice.cpp | 37 - Source/UnitTest/1.Device/UnitTestRHIDevice.h | 23 - Source/UnitTest/Base/Common.h | 41 -- Source/UnitTest/Base/Main.cpp | 11 - Source/UnitTest/Base/UTCore.Os.cpp | 12 - Source/UnitTest/Base/UTCore.String.cpp | 32 - Source/UnitTest/Base/UTKTL.DynArray.cpp | 68 -- Source/UnitTest/Base/UTKTL.SharedPtr.cpp | 47 -- .../UnitTest/Base/UTTools.ShaderCompiler.cpp | 88 --- Source/UnitTest/CMakeLists.txt | 39 - .../AppIcon.appiconset/Contents.json | 58 -- .../RHI_Metal/Base.lproj/MainMenu.xib | 686 ------------------ Source/UnitTest/RHI_Metal/Info.plist | 34 - Source/UnitTest/RHI_Metal/Shaders.metal | 52 -- Source/UnitTest/RHI_Metal/SharedStructures.h | 21 - .../RHI_Metal/UnitTestRHICommandContext.mm | 6 - Source/UnitTest/RHI_Metal/premake5.lua | 31 - Tools/VisualStudioVisualizer/kaleido3d.natvis | 17 + Tools/WebConsole/index.html | 22 + circle.yml | 1 - make.cmd | 34 +- make_android.cmd | 15 + make_android.sh | 17 + make_ios.sh | 3 + make_macos.sh | 8 +- settings.gradle | 4 +- 232 files changed, 6926 insertions(+), 4105 deletions(-) create mode 100644 Data/Test/TextRender.frag create mode 100644 Data/Test/TextRender.vert create mode 100644 Data/Test/calibri.ttf create mode 100644 Data/Test/particles.comp create mode 100644 Data/Test/particles.frag create mode 100644 Data/Test/particles.vert create mode 100644 Include/Config/ReadMe.md delete mode 100755 Include/Config/note.txt delete mode 100755 Include/Core rename {Source/RHI => Include/Interface}/ICrossShaderCompiler.h (97%) delete mode 100755 Include/Interface/IJob.h rename {Source/Log/Public => Include/Interface}/ILog.h (96%) mode change 100755 => 100644 create mode 100644 Include/Interface/IModule.h delete mode 100755 Include/Interface/IParameter.h rename {Source/RHI => Include/Interface}/IRHI.h (89%) rename {Source/RHI => Include/Interface}/IRHIDefs.h (87%) delete mode 100755 Include/Interface/IRefObj.h delete mode 100755 Include/Interface/IReflectable.h delete mode 100755 Include/Interface/IRenderer.h delete mode 100755 Include/Interface/IRunnable.h delete mode 100755 Include/Interface/IShader.h create mode 100644 Include/KTL/String.hpp create mode 100644 Include/Math/IK.hpp rename Project/{pch.cmake => Compiler.cmake} (100%) mode change 100755 => 100644 create mode 100644 Project/Util.cmake create mode 100755 Project/plist_gen delete mode 100755 Source/Core/Archive.cpp delete mode 100755 Source/Core/Archive.h delete mode 100755 Source/Core/LogUtil.inl delete mode 100755 Source/Core/String.cpp delete mode 100755 Source/Core/String.h create mode 100644 Source/Core/StringImpl.cpp create mode 100644 Source/Core/UnitTest/CMakeLists.txt create mode 100644 Source/Core/UnitTest/Common.h rename Source/{UnitTest/Base => Core/UnitTest}/UTCore.Bundle.cpp (86%) mode change 100755 => 100644 create mode 100644 Source/Core/UnitTest/UTCore.Os.cpp create mode 100644 Source/Core/UnitTest/UTCore.String.cpp rename Source/{UnitTest/Base => Core/UnitTest}/UTCore.WebSocket.cpp (75%) mode change 100755 => 100644 create mode 100644 Source/Core/UnitTest/UTFontLoader.cpp create mode 100644 Source/Core/UnitTest/UTKTL.DynArray.cpp create mode 100644 Source/Core/UnitTest/UTKTL.SharedPtr.cpp create mode 100644 Source/Core/UnitTest/UTTools.ShaderCompiler.cpp delete mode 100755 Source/Core/Variant.h delete mode 100755 Source/Core/premake5.lua create mode 100644 Source/Platform/Apple/CpuUsage.mm delete mode 100755 Source/Platform/Apple/iOS/AAPLAppDelegate.h delete mode 100755 Source/Platform/Apple/iOS/AAPLAppDelegate.mm create mode 100755 Source/Platform/Apple/iOS/App.mm delete mode 100755 Source/Platform/Apple/iOS/Info.plist delete mode 100755 Source/Platform/Apple/iOS/LaunchScreen.xib delete mode 100755 Source/Platform/Apple/iOS/Main.storyboard delete mode 100755 Source/Platform/Apple/iOS/ThreadImpl.h delete mode 100755 Source/Platform/Apple/iOS/ThreadImpl.mm create mode 100755 Source/Platform/Apple/iOS/Window.mm delete mode 100755 Source/Platform/Apple/iOS/WindowImpl.h delete mode 100755 Source/Platform/Apple/iOS/WindowImpl.mm delete mode 100755 Source/Platform/Apple/iOS/main.m create mode 100644 Source/Platform/Windows/CpuUsage.cpp create mode 100644 Source/RHI/UnitTest/1.Device.cpp rename Source/{UnitTest/2.SwapChain/SwapChainPresent.cpp => RHI/UnitTest/2.SwapChainPresent.cpp} (77%) mode change 100755 => 100644 rename Source/{UnitTest/3.Triangle/Triangle.cpp => RHI/UnitTest/3.Triangle.cpp} (50%) mode change 100755 => 100644 rename Source/{UnitTest/4.TexturedCube/TexturedCube.cpp => RHI/UnitTest/4.TexturedCube.cpp} (61%) mode change 100755 => 100644 create mode 100644 Source/RHI/UnitTest/5.ComputeParticles.cpp rename Source/{ => RHI}/UnitTest/Android/TexturedCube/build.gradle (83%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/AndroidManifest.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java (90%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/layout/activity_k.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/values-w820dp/dimens.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/values/colors.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/values/dimens.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/values/strings.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/TexturedCube/src/main/res/values/styles.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/build.gradle (84%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/AndroidManifest.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java (91%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/layout/activity_k.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/values-w820dp/dimens.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/values/colors.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/values/dimens.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/values/strings.xml (100%) mode change 100755 => 100644 rename Source/{ => RHI}/UnitTest/Android/Triangle/src/main/res/values/styles.xml (100%) mode change 100755 => 100644 rename Source/{UnitTest/4.TexturedCube => RHI/UnitTest/Base}/TextureObject.cpp (80%) mode change 100755 => 100644 rename Source/{UnitTest/4.TexturedCube => RHI/UnitTest/Base}/TextureObject.h (93%) mode change 100755 => 100644 create mode 100644 Source/RHI/UnitTest/Base/UTRHIAppBase.h create mode 100644 Source/RHI/UnitTest/CMakeLists.txt delete mode 100755 Source/RHI/Vulkan/Private/VkFrameBuffer.cpp delete mode 100755 Source/RHI/Vulkan/Private/VkPipelineLayout.cpp delete mode 100755 Source/RHI/Vulkan/Private/VkSampler.cpp delete mode 100755 Source/UnitTest/1.Device/UnitTestRHIDevice.cpp delete mode 100755 Source/UnitTest/1.Device/UnitTestRHIDevice.h delete mode 100755 Source/UnitTest/Base/Common.h delete mode 100755 Source/UnitTest/Base/Main.cpp delete mode 100755 Source/UnitTest/Base/UTCore.Os.cpp delete mode 100755 Source/UnitTest/Base/UTCore.String.cpp delete mode 100755 Source/UnitTest/Base/UTKTL.DynArray.cpp delete mode 100755 Source/UnitTest/Base/UTKTL.SharedPtr.cpp delete mode 100755 Source/UnitTest/Base/UTTools.ShaderCompiler.cpp delete mode 100755 Source/UnitTest/CMakeLists.txt delete mode 100755 Source/UnitTest/RHI_Metal/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100755 Source/UnitTest/RHI_Metal/Base.lproj/MainMenu.xib delete mode 100755 Source/UnitTest/RHI_Metal/Info.plist delete mode 100755 Source/UnitTest/RHI_Metal/Shaders.metal delete mode 100755 Source/UnitTest/RHI_Metal/SharedStructures.h delete mode 100755 Source/UnitTest/RHI_Metal/UnitTestRHICommandContext.mm delete mode 100755 Source/UnitTest/RHI_Metal/premake5.lua create mode 100644 Tools/VisualStudioVisualizer/kaleido3d.natvis create mode 100644 Tools/WebConsole/index.html create mode 100644 make_android.cmd create mode 100755 make_android.sh create mode 100755 make_ios.sh diff --git a/.travis.yml b/.travis.yml index 652a864..5309da7 100755 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ osx_image: xcode8.1 install: - brew install cmake - - git clone https://github.com/Tomicyo/kaleido3d_dep_prebuilt.git -b macos_debug Source/ThirdParty_Prebuilt/MacOS_Debug script: - - chmod 777 make_macos.sh && ./make_macos.sh \ No newline at end of file + - chmod 777 make_macos.sh && ./make_macos.sh diff --git a/Data/Test/TextRender.frag b/Data/Test/TextRender.frag new file mode 100644 index 0000000..c462a5f --- /dev/null +++ b/Data/Test/TextRender.frag @@ -0,0 +1,8 @@ +#version 430 +layout (location = 0) in vec2 inCoord; +layout (location = 0) out vec4 outFragColor; +uniform sampler2D fontTex; +void main() +{ + outFragColor = texture(fontTex, inCoord); +} diff --git a/Data/Test/TextRender.vert b/Data/Test/TextRender.vert new file mode 100644 index 0000000..e87620f --- /dev/null +++ b/Data/Test/TextRender.vert @@ -0,0 +1,13 @@ +#version 430 +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec2 inCoord; +layout (location = 0) out vec2 outCoord; +out gl_PerVertex +{ + vec4 gl_Position; +}; +void main() +{ + outCoord = inCoord; + gl_Position = vec4(inPos, 1.0); +} \ No newline at end of file diff --git a/Data/Test/calibri.ttf b/Data/Test/calibri.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2cb551561d1ed9a549e2c390e9e9179d2fe98c9a GIT binary patch literal 1331500 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 z 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�MyJlTJGaLv9kQoF$eX5*$ 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 z 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

2iFtY%}}fmgVH#3S3KGS8ha2_XmVDyIR2` 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�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

jZs^Ncg&dWKnxezxMRPdm@gAa5-{ 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

vOg~XX|seK4vOg~XX|seK4vOg~ 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

GO?%#-3XW?gsPqGAYm80uiA~@1zJxm0D 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

nJ_Y%I&eP?``Uhbv>7v7a~gK2|SyE)%|kQ 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 R;gi-AhHq%scms5w{|70O^kx76 literal 0 HcmV?d00001 diff --git a/Data/Test/cube.frag b/Data/Test/cube.frag index 7d63c45..ae85dee 100755 --- a/Data/Test/cube.frag +++ b/Data/Test/cube.frag @@ -1,3 +1,5 @@ +#define USE_GLSL 0 +#if USE_GLSL #version 400 #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable @@ -10,4 +12,22 @@ layout (location = 1) in vec2 uv; layout (location = 0) out vec4 uFragColor; void main() { uFragColor = texture(tex, uv) * color; -} \ No newline at end of file +} +#else + +SamplerState samp : register(s1); +Texture2D tex : register(t1); + +struct PS_IN +{ +// float4 outPos: SV_POSITION; + float4 outColor: COLOR; + float2 outCoord: TEXCOORD0; +}; + +float4 main(PS_IN ps_in) : SV_TARGET +{ + return tex.Sample(samp, ps_in.outCoord); +} + +#endif \ No newline at end of file diff --git a/Data/Test/cube.vert b/Data/Test/cube.vert index 3aeb566..5ba68e5 100755 --- a/Data/Test/cube.vert +++ b/Data/Test/cube.vert @@ -1,3 +1,7 @@ +#define USE_GLSL 0 + +#if USE_GLSL + #version 400 #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable @@ -20,4 +24,39 @@ void main() { color = vertColor; uv = vertUV; gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(pos, 1.0f); -} \ No newline at end of file +} + +#else + +cbuffer UBO : register(b0) +{ + row_major matrix projectMatrix; + row_major matrix modelMatrix; + row_major matrix viewMatrix; +}; + +struct VS_IN +{ + float3 pos : POSITION; + float4 vertColor: COLOR; + float2 vertUV: TEXCOORD0; +}; + +struct VS_OUT +{ + float4 outPos: SV_POSITION; + float4 outColor: COLOR; + float2 outCoord: TEXCOORD0; +}; + +VS_OUT main(VS_IN vs_in) +{ + VS_OUT vs_out; + vs_out.outPos = projectMatrix * viewMatrix * modelMatrix * float4(vs_in.pos, 1.0); + vs_out.outColor = vs_in.vertColor; + vs_out.outCoord = vs_in.vertUV; + return vs_out; +} + + +#endif \ No newline at end of file diff --git a/Data/Test/particles.comp b/Data/Test/particles.comp new file mode 100644 index 0000000..4fe2c68 --- /dev/null +++ b/Data/Test/particles.comp @@ -0,0 +1,95 @@ +#define USE_GLSL 0 + +#if USE_GLSL + +#version 430 + +layout (std140, binding = 0) uniform attractor_block +{ + vec4 attractor[64]; // xyz = position, w = mass +}; + +layout (local_size_x = 1024) in; + +layout (rgba32f, binding = 0) uniform imageBuffer velocity_buffer; +layout (rgba32f, binding = 1) uniform imageBuffer position_buffer; + +uniform float dt = 1.0; + +void main(void) +{ + vec4 vel = imageLoad(velocity_buffer, int(gl_GlobalInvocationID.x)); + vec4 pos = imageLoad(position_buffer, int(gl_GlobalInvocationID.x)); + + int i; + + pos.xyz += vel.xyz * dt; + pos.w -= 0.0001 * dt; + + for (i = 0; i < 4; i++) + { + vec3 dist = (attractor[i].xyz - pos.xyz); + vel.xyz += dt * dt * attractor[i].w * normalize(dist) / (dot(dist, dist) + 10.0); + } + + if (pos.w <= 0.0) + { + pos.xyz = -pos.xyz * 0.01; + vel.xyz *= 0.01; + pos.w += 1.0f; + } + + imageStore(position_buffer, int(gl_GlobalInvocationID.x), pos); + imageStore(velocity_buffer, int(gl_GlobalInvocationID.x), vel); +} + +#else + +#define blocksize 64 + +groupshared float4 attractor[blocksize]; + +cbuffer cbCS : register(b0) +{ + float dt; +}; + +//RWStructuredBuffer velocity_buffer : register(u0); // UAV +//RWStructuredBuffer position_buffer : register(u1); // UAV + +RWTexture1D velocity_buffer : register(t0); +RWTexture1D position_buffer : register(t1); + +[numthreads(1024, 1, 1)] +void main( + uint3 Gid : SV_GroupID, + uint3 DTid : SV_DispatchThreadID, + uint3 GTid : SV_GroupThreadID, + uint GI : SV_GroupIndex) +{ + float4 vel = velocity_buffer.Load(DTid.x); + float4 pos = position_buffer.Load(DTid.x); + + int i; + + pos.xyz += vel.xyz * dt; + pos.w -= 0.0001 * dt; + + for (i = 0; i < 4; i++) + { + float3 dist = (attractor[i].xyz - pos.xyz); + vel.xyz += dt * dt * attractor[i].w * normalize(dist) / (dot(dist, dist) + 10.0); + } + + if (pos.w <= 0.0) + { + pos.xyz = -pos.xyz * 0.01; + vel.xyz *= 0.01; + pos.w += 1.0f; + } + + position_buffer[DTid.x] = pos; + velocity_buffer[DTid.x] = vel; +} + +#endif \ No newline at end of file diff --git a/Data/Test/particles.frag b/Data/Test/particles.frag new file mode 100644 index 0000000..6c0018e --- /dev/null +++ b/Data/Test/particles.frag @@ -0,0 +1,25 @@ +#define USE_GLSL 0 + +#if USE_GLSL + +#version 430 +layout (location = 0) out vec4 color; +in float intensity; +void main(void) +{ + color = mix(vec4(0.0f, 0.2f, 1.0f, 1.0f), vec4(0.2f, 0.05f, 0.0f, 1.0f), intensity); +} + +#else + +struct PS_IN +{ + float intensity : INTENSITY; +}; + +float4 main(PS_IN ps_in) : SV_Target +{ + return lerp(float4(0.0f, 0.2f, 1.0f, 1.0f), float4(0.2f, 0.05f, 0.0f, 1.0f), ps_in.intensity); +} + +#endif \ No newline at end of file diff --git a/Data/Test/particles.vert b/Data/Test/particles.vert new file mode 100644 index 0000000..bde9e36 --- /dev/null +++ b/Data/Test/particles.vert @@ -0,0 +1,41 @@ +#define USE_GLSL 0 + +#if USE_GLSL + +#version 430 +in vec4 vert; +uniform mat4 mvp; +out float intensity; +void main(void) +{ + intensity = vert.w; + gl_Position = mvp * vec4(vert.xyz, 1.0); +} + +#else + +struct VS_IN +{ + float4 vert : POSITION; +}; + +cbuffer mat : register(b0) +{ + row_major matrix mvp; +}; + +struct VS_OUT +{ + float4 outPos : SV_POSITION; + float intensity : INTENSITY; +}; + +VS_OUT main(VS_IN vs_in) +{ + VS_OUT vs_out; + vs_out.outPos = mvp * float4(vs_in.vert.xyz, 1.0); + vs_out.intensity = vs_in.vert.w; + return vs_out; +} + +#endif \ No newline at end of file diff --git a/Data/Test/triangle.frag b/Data/Test/triangle.frag index 2c0ed49..8bf5680 100755 --- a/Data/Test/triangle.frag +++ b/Data/Test/triangle.frag @@ -1,3 +1,7 @@ +#define USE_GLSL 0 + +#if USE_GLSL + #version 430 #extension GL_ARB_separate_shader_objects : enable @@ -11,3 +15,17 @@ void main() { outFragColor = vec4(inColor, 1.0); } + +#else + +struct VS_OUT +{ +// float4 outPos : SV_POSITION; + float3 outColor: COLOR; +}; + +float4 main(VS_OUT psIn) : SV_TARGET { + return float4(psIn.outColor, 1.0); +} + +#endif \ No newline at end of file diff --git a/Data/Test/triangle.vert b/Data/Test/triangle.vert index a88e5b0..1879fbb 100755 --- a/Data/Test/triangle.vert +++ b/Data/Test/triangle.vert @@ -1,3 +1,7 @@ +#define USE_GLSL 0 + +#if USE_GLSL + #version 430 #extension GL_ARB_separate_shader_objects : enable @@ -6,7 +10,7 @@ layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inColor; -layout (binding = 0) uniform UBO +layout (binding = 0) uniform UBO { mat4 projectionMatrix; mat4 modelMatrix; @@ -15,14 +19,46 @@ layout (binding = 0) uniform UBO layout (location = 0) out vec3 outColor; -out gl_PerVertex +out gl_PerVertex { - vec4 gl_Position; + vec4 gl_Position; }; -void main() +void main() { outColor = inColor; gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0); -} \ No newline at end of file +} + +#else + +#pragma pack_matrix( row_major ) + +struct VS_IN +{ + float3 inPos : POSITION; + float3 inColor : COLOR; +}; + +struct VS_OUT +{ + float4 outPos : SV_POSITION; + float3 outColor : COLOR; +}; + +cbuffer UBO : register(b0) +{ + row_major matrix projectMatrix; + row_major matrix modelMatrix; + row_major matrix viewMatrix; +}; + +VS_OUT main(VS_IN vsin) +{ + VS_OUT vsout; + vsout.outPos = projectMatrix * viewMatrix * modelMatrix * float4(vsin.inPos.xyz, 1.0); + vsout.outColor = vsin.inColor; + return vsout; +} +#endif \ No newline at end of file diff --git a/Include/Config/ReadMe.md b/Include/Config/ReadMe.md new file mode 100644 index 0000000..bf3c66a --- /dev/null +++ b/Include/Config/ReadMe.md @@ -0,0 +1,2 @@ + +The "stdint.h" header is copied from llvm-3.5 diff --git a/Include/Config/note.txt b/Include/Config/note.txt deleted file mode 100755 index e2099e4..0000000 --- a/Include/Config/note.txt +++ /dev/null @@ -1 +0,0 @@ -this "stdint.h" is copied from llvm-3.5 diff --git a/Include/Core b/Include/Core deleted file mode 100755 index cba6077..0000000 --- a/Include/Core +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "../Source/Core/Archive.h" -#include "../Source/Core/AssetManager.h" -#include "../Source/Core/AsynMeshTask.h" -#include "../Source/Core/Os.h" -#include "../Source/Core/Image.h" -#include "../Source/Core/LogUtil.h" -#include "../Source/Core/Window.h" -#include "../Source/Core/Mesh.h" -#include "../Source/Core/Message.h" -#include "../Source/Core/Looper.h" -#include "../Source/Core/Dispatch/WorkQueue.h" -#include "../Source/Core/Dispatch/WorkItem.h" -#include "../Source/Core/Dispatch/WorkGroup.h" \ No newline at end of file diff --git a/Source/RHI/ICrossShaderCompiler.h b/Include/Interface/ICrossShaderCompiler.h similarity index 97% rename from Source/RHI/ICrossShaderCompiler.h rename to Include/Interface/ICrossShaderCompiler.h index 7feb4d8..b3aa286 100755 --- a/Source/RHI/ICrossShaderCompiler.h +++ b/Include/Interface/ICrossShaderCompiler.h @@ -1,7 +1,7 @@ #pragma once #include "IRHIDefs.h" -#include +#include "IModule.h" namespace rhi { @@ -76,8 +76,10 @@ namespace rhi EUndefined = 0, EBlock = 0x1, ESampler = 0x1 << 1, - EStorageImage = 0x1 << 2, + ESampledImage = 0x1 << 2, + ESamplerImageCombine = (ESampler | ESampledImage), EStorageBuffer = 0x1 << 3, + EStorageImage = 0x1 << 4, EConstants = 0x000000010 }; @@ -305,3 +307,7 @@ result.Member.Append(ele);\ //virtual ::k3d::DynArray ListAvailableShaderLanguage() const = 0; }; } + +#if BUILD_STATIC_PLUGIN +K3D_STATIC_MODULE_DECLARE(ShaderCompiler); +#endif \ No newline at end of file diff --git a/Include/Interface/IIODevice.h b/Include/Interface/IIODevice.h index e704e9f..c66fee3 100755 --- a/Include/Interface/IIODevice.h +++ b/Include/Interface/IIODevice.h @@ -2,9 +2,9 @@ #define __IIODevice_H__ #pragma once -#include -#include -#include +#include "../Math/kTypeTrait.hpp" +#include "../Config/Config.h" +#include "../Config/PlatformTypes.h" #include enum IOFlag diff --git a/Include/Interface/IJob.h b/Include/Interface/IJob.h deleted file mode 100755 index 257535d..0000000 --- a/Include/Interface/IJob.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include -/** -struct ICondition { - virtual void Notify() = 0; - virtual void Wait() = 0; -}; - - -struct IJob { - - virtual ~IJob() {} - - virtual void OnRun() = 0; - - virtual void AddDependency(IJob *) = 0; - - virtual void OnComplete() { - if (m_JoinedJob != nullptr) { - JobList list = m_JoinedJob->GetDependencies(); - list.remove(this); - m_JoinedJob->GetPreqCondition()->Notify(); - } - } - - virtual void Execute() = 0; - - void SetJoinedJob(JoinedJob * joinedJob) { - m_JoinedJob = joinedJob; - } - - using JobList = std::list; - -protected: - JoinedJob * m_JoinedJob; -}; - - -struct JoinedJob : IJob { - virtual ~JoinedJob() {} - virtual void OnRun() = 0; - - void AddDependency(IJob * job) override { - job->SetJoinedJob(this); - m_DependJobs.push_back(job); - } - - void Execute() override { - while (m_PreqCondition!=nullptr && !m_DependJobs.empty()) { - m_PreqCondition->Wait(); - } - OnRun(); - } - - ICondition * GetPreqCondition() { - return m_PreqCondition; - } - - JobList & GetDependencies(); - -private: - JobList m_DependJobs; - ICondition * m_PreqCondition; -}; - -struct SerialJob : IJob { - - void AddDependency(IJob * job) override { - m_DependJobs.push_back(job); - } - - void Execute() override { - while (!m_DependJobs.empty()) { - IJob* job = m_DependJobs.back(); - job->OnRun(); - m_DependJobs.remove(job); - } - OnRun(); - } - -private: - JobList m_DependJobs; -}; -**/ \ No newline at end of file diff --git a/Source/Log/Public/ILog.h b/Include/Interface/ILog.h old mode 100755 new mode 100644 similarity index 96% rename from Source/Log/Public/ILog.h rename to Include/Interface/ILog.h index daef12e..747c394 --- a/Source/Log/Public/ILog.h +++ b/Include/Interface/ILog.h @@ -1,3 +1,4 @@ +#pragma once #ifndef __ILog_h__ #define __ILog_h__ diff --git a/Include/Interface/IMesh.h b/Include/Interface/IMesh.h index 1fcee9d..933cf8f 100755 --- a/Include/Interface/IMesh.h +++ b/Include/Interface/IMesh.h @@ -1,7 +1,8 @@ #pragma once -#include +#include "../Math/kGeometry.hpp" -enum class VtxFormat : uint32 { +enum class VtxFormat : uint32 +{ POS3_F32 = 0, POS4_F32, POS3_F32_UV2_F32, @@ -12,13 +13,15 @@ enum class VtxFormat : uint32 { PER_INSTANCE // all components are seperated }; -enum class PrimType : uint32 { +enum class PrimType : uint32 +{ POINTS = 0, TRIANGLES, TRIANGLE_STRIPS }; -struct K3D_API IMesh { +struct K3D_API IMesh +{ virtual ~IMesh() {} virtual kMath::AABB GetBoundingBox() const = 0; virtual uint32 GetMaterialID() const = 0; diff --git a/Include/Interface/IModule.h b/Include/Interface/IModule.h new file mode 100644 index 0000000..df06de2 --- /dev/null +++ b/Include/Interface/IModule.h @@ -0,0 +1,70 @@ +#pragma once +#include "Config/Config.h" +#include + +#if K3DPLATFORM_OS_WIN +#define PLUGIN_API_DECLARE __declspec(dllexport) +#else +#define PLUGIN_API_DECLARE __attribute__((visibility("default"))) +#endif + +#ifdef BUILD_SHARED_LIB +#ifdef BUILD_WITH_PLUGIN +#if K3DPLATFORM_OS_WIN +#define CORE_API __declspec(dllimport) +#else +#define CORE_API __attribute__((visibility("default"))) +#endif +#else +#if K3DPLATFORM_OS_WIN +#define CORE_API __declspec(dllexport) +#else +#define CORE_API __attribute__((visibility("default"))) +#endif +#endif +#else +#define CORE_API +#endif + +#define K3D_DYNAMIC_MODULE_IMPLEMENT(ModuleName, ModuleClass) \ +extern "C" PLUGIN_API_DECLARE ::k3d::IModule *Get##ModuleName##Module() { return new ModuleClass; } + +#define K3D_STATIC_MODULE_IMPLEMENT(ModuleName, MoudleClass) \ +extern "C" ::k3d::IModule *Get##ModuleName##Module() { \ +return new MoudleClass; \ +} +#define K3D_STATIC_MODULE_DECLARE(ModuleName) \ +extern "C" ::k3d::IModule *Get##ModuleName##Module() + +/** +* build dlls +*/ +#ifdef BUILD_SHARED_CORE +#define MODULE_IMPLEMENT(ModuleName, MoudleClass) K3D_DYNAMIC_MODULE_IMPLEMENT(ModuleName, MoudleClass) +#else +#define MODULE_IMPLEMENT(ModuleName, MoudleClass) K3D_STATIC_MODULE_IMPLEMENT(ModuleName, MoudleClass) +#endif + +#if BUILD_STATIC_PLUGIN +#define ACQUIRE_PLUGIN(PLUGIN) Get##PLUGIN##Module(); +#else +#define ACQUIRE_PLUGIN(PLUGIN) k3d::GlobalModuleManager.FindModule(#PLUGIN) +#endif + +K3D_COMMON_NS +{ + /** + * Module interface definition [RHI, ShaderCompiler, etc] + * @see ModuleManager [Core/ModuleManager] + */ + class IModule + { + public: + virtual void Start() = 0; + virtual void Shutdown() = 0; + virtual const char * Name() = 0; + virtual ~IModule() {} + }; + + typedef SharedPtr ModuleRef; +} \ No newline at end of file diff --git a/Include/Interface/IParameter.h b/Include/Interface/IParameter.h deleted file mode 100755 index ffe0899..0000000 --- a/Include/Interface/IParameter.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "IShader.h" - -struct IParameterManager -{ - virtual void SetVector4(const char * paramName, void *vector4) = 0; -}; \ No newline at end of file diff --git a/Source/RHI/IRHI.h b/Include/Interface/IRHI.h similarity index 89% rename from Source/RHI/IRHI.h rename to Include/Interface/IRHI.h index 9f05ca6..a4ffed5 100755 --- a/Source/RHI/IRHI.h +++ b/Include/Interface/IRHI.h @@ -1,19 +1,25 @@ #pragma once -#include #include "ICrossShaderCompiler.h" -#include "Tools/ShaderGen/Public/ShaderCompiler.h" namespace rhi { struct ICommandContext; typedef ::k3d::SharedPtr CommandContextRef; + struct IDeviceAdapter; + typedef ::k3d::SharedPtr DeviceAdapterRef; struct IDevice; typedef ::k3d::SharedPtr DeviceRef; struct IGpuResource; typedef ::k3d::SharedPtr GpuResourceRef; struct ITexture; typedef ::k3d::SharedPtr TextureRef; + struct IBuffer; + typedef ::k3d::SharedPtr BufferRef; + struct ITextureView; + typedef ::k3d::SharedPtr TextureViewRef; + struct IBufferView; + typedef ::k3d::SharedPtr BufferViewRef; struct IShaderResourceView; typedef ::k3d::SharedPtr ShaderResourceViewRef; struct IPipelineStateObject; @@ -55,20 +61,19 @@ namespace rhi struct K3D_API IGpuResource { - virtual ~IGpuResource() {} + virtual ~IGpuResource() {} virtual void * Map(uint64 start, uint64 size) = 0; virtual void UnMap() = 0; - virtual uint64 GetResourceLocation() const { return 0; } - virtual ResourceDesc GetResourceDesc() const = 0; + virtual uint64 GetLocation() const { return 0; } + virtual ResourceDesc GetDesc() const = 0; /** * Vulkan: texture uses image layout as resource state * D3D12: used for transition, maybe used as ShaderVisiblity determination in STATIC_SAMPLER and descriptor table */ - virtual EResourceState GetUsageState() const { return ERS_Unknown; } - virtual EGpuResourceType GetResourceType() const { return ResourceTypeNum; } - virtual uint64 GetResourceSize() const = 0; + virtual EResourceState GetState() const { return ERS_Unknown; } + virtual uint64 GetSize() const = 0; }; struct ISampler @@ -76,19 +81,18 @@ namespace rhi virtual SamplerState GetSamplerDesc() const = 0; virtual ~ISampler() {} }; - - struct ITexture; - + struct IShaderResourceView { + virtual ~IShaderResourceView() {} virtual GpuResourceRef GetResource() const = 0; virtual ResourceViewDesc GetDesc() const = 0; }; - struct ITexture : virtual public IGpuResource + struct ITexture : public IGpuResource { - virtual ~ITexture() {} - virtual SamplerCRef GetSampler() const = 0; + virtual ~ITexture() {} + virtual SamplerCRef GetSampler() const = 0; virtual void BindSampler(SamplerRef) = 0; virtual void SetResourceView(ShaderResourceViewRef) = 0; virtual ShaderResourceViewRef GetResourceView() const = 0; @@ -97,12 +101,15 @@ namespace rhi struct IDescriptor { virtual void Update(uint32 bindSet, GpuResourceRef) = 0; + virtual void Update(uint32 bindSet, SamplerRef) {}; + virtual uint32 GetSlotNum() const { return 0; } virtual ~IDescriptor() {} }; struct IDeviceAdapter { virtual DeviceRef GetDevice() = 0; + virtual ~IDeviceAdapter() {} }; /** @@ -156,9 +163,9 @@ namespace rhi DepthStencilState DepthStencil; // Shaders - ShaderBundle Shaders[ShaderTypeNum]; - // VertexAttributes - VertexInputLayout VertexLayout; + ShaderBundle Shaders[ShaderTypeNum]; + // Vertex Input State + VertexInputState InputState; // InputAssemblyState EPrimitiveType PrimitiveTopology = rhi::EPT_Triangles; }; @@ -177,6 +184,8 @@ namespace rhi virtual void SetVertexInputLayout(rhi::VertexDeclaration const*, uint32 Count) = 0; virtual void SetRenderTargetFormat(const RenderTargetFormat &) = 0; virtual void SetSampler(SamplerRef) = 0; + virtual void SavePSO(const char* /*path*/) {} + virtual void LoadPSO(const char*) {} }; struct IDescriptorPool @@ -212,12 +221,14 @@ namespace rhi struct K3D_API IDevice { - enum Result { + enum Result + { DeviceNotFound, DeviceFound }; virtual ~IDevice() {} + // @deprecated virtual Result Create(IDeviceAdapter *, bool withDebug) = 0; virtual CommandContextRef NewCommandContext(ECommandType) = 0; @@ -235,7 +246,7 @@ namespace rhi /* equal with d3d12's getcopyfootprint or vulkan's getImagesubreslayout. */ - virtual void QueryTextureSubResourceLayout(GpuResourceRef, TextureResourceSpec const& spec, SubResourceLayout *) {} + virtual void QueryTextureSubResourceLayout(TextureRef, TextureResourceSpec const& spec, SubResourceLayout *) {} }; struct K3D_API IRenderViewport diff --git a/Source/RHI/IRHIDefs.h b/Include/Interface/IRHIDefs.h similarity index 87% rename from Source/RHI/IRHIDefs.h rename to Include/Interface/IRHIDefs.h index ca32667..f2135e7 100755 --- a/Source/RHI/IRHIDefs.h +++ b/Include/Interface/IRHIDefs.h @@ -2,11 +2,11 @@ #ifndef __IRHIDefs_h__ #define __IRHIDefs_h__ -#include "Config/PlatformTypes.h" -#include -#include -#include -#include +#include "../Config/PlatformTypes.h" +#include "../KTL/DynArray.hpp" +#include "../KTL/SharedPtr.hpp" +#include "../KTL/String.hpp" +#include "../Math/kGeometry.hpp" namespace rhi { @@ -48,8 +48,11 @@ namespace rhi EPF_R11G11B10Float, EPF_D32Float, EPF_RGB32Float, - EPF_RGB8Unorm, - PixelFormatNum + EPF_RGB8Unorm, + EPF_BGRA8Unorm, // Apple Metal Layer uses it as default pixel format + EPF_BGRA8Unorm_sRGB, + EPF_RGBA16Float, + PixelFormatNum, }; enum EVertexFormat @@ -61,6 +64,12 @@ namespace rhi VertexFormatNum }; + enum EVertexInputRate + { + EVIR_PerVertex, + EVIR_PerInstance + }; + enum EMultiSampleFlag { EMS_1x, @@ -180,6 +189,12 @@ namespace rhi } }; + struct ColorAttachmentState + { + BlendState Blend; + uint32 ColorWriteMask; // z-pass + }; + struct RasterizerState { enum EFillMode @@ -440,6 +455,7 @@ namespace rhi float MinDepth; float MaxDepth; }; + /** * EVertexFormat, * Stride, @@ -455,6 +471,39 @@ namespace rhi uint32 OffSet; uint32 BindID; }; + + struct VertexInputState + { + enum { + kInvalidValue = -1, + kMaxVertexLayouts = 4, + kMaxVertexBindings = 8, + }; + + struct Attribute + { + Attribute(EVertexFormat const& format = EVF_Float3x32, uint32 offset = kInvalidValue, uint32 slot = kInvalidValue) + : Format(format), OffSet(offset), Slot(slot) + {} + + EVertexFormat Format = EVF_Float3x32; + uint32 OffSet = kInvalidValue; + uint32 Slot = kInvalidValue; + }; + + struct Layout + { + Layout(EVertexInputRate const& inputRate = EVIR_PerVertex, uint32 stride = kInvalidValue) + : Rate(inputRate), Stride(stride) + {} + + EVertexInputRate Rate = EVIR_PerVertex; + uint32 Stride = kInvalidValue; + }; + + Attribute Attribs[kMaxVertexBindings]; + Layout Layouts[kMaxVertexLayouts]; + }; struct VertexBufferView { @@ -513,6 +562,11 @@ namespace rhi EGRAF_HostCached = 0x1 << 5, }; + inline EGpuResourceAccessFlag operator | (EGpuResourceAccessFlag const& lhs, EGpuResourceAccessFlag const& rhs) + { + return EGpuResourceAccessFlag(uint32(lhs) | uint32(rhs)); + } + enum EGpuResourceCreationFlag { EGRCF_Dynamic = 0, @@ -521,6 +575,11 @@ namespace rhi EGRCF_TransferDst = 4 }; + inline EGpuResourceCreationFlag operator | (EGpuResourceCreationFlag const& lhs, EGpuResourceCreationFlag const& rhs) + { + return EGpuResourceCreationFlag(uint32(lhs) | uint32(rhs)); + } + /** * Format, Width, Height, Depth, MipLevel, Layers */ @@ -575,6 +634,11 @@ namespace rhi ETAF_METADATA = 1<<3, }; + inline ETextureAspectFlag operator|(ETextureAspectFlag const& lhs, ETextureAspectFlag const& rhs) + { + return ETextureAspectFlag(uint32(lhs) | uint32(rhs)); + } + /*same as VkImageSubresource */ struct TextureResourceSpec { diff --git a/Include/Interface/IRefObj.h b/Include/Interface/IRefObj.h deleted file mode 100755 index 8084c0e..0000000 --- a/Include/Interface/IRefObj.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -class IRefObj -{ -public: - virtual uint32 AddRef() const = 0; - virtual uint32 Release() const = 0; - virtual uint32 GetRefCount() const = 0; -}; \ No newline at end of file diff --git a/Include/Interface/IReflectable.h b/Include/Interface/IReflectable.h deleted file mode 100755 index 2c27463..0000000 --- a/Include/Interface/IReflectable.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -struct IReflectable { - virtual IReflectable * Reflect() = 0; -}; \ No newline at end of file diff --git a/Include/Interface/IRenderMesh.h b/Include/Interface/IRenderMesh.h index aee19de..1b1f181 100755 --- a/Include/Interface/IRenderMesh.h +++ b/Include/Interface/IRenderMesh.h @@ -2,7 +2,8 @@ struct IMesh; -struct IRenderMesh { +struct IRenderMesh +{ virtual ~IRenderMesh() {} virtual void Render(IMesh *) = 0; diff --git a/Include/Interface/IRenderer.h b/Include/Interface/IRenderer.h deleted file mode 100755 index a14968e..0000000 --- a/Include/Interface/IRenderer.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -struct IRenderMesh; - -struct IRenderer { - - virtual ~IRenderer() {} - - virtual void PrepareFrame() = 0; - - virtual void DrawOneFrame() = 0; - - virtual void EndOneFrame() = 0; - - virtual void DrawMesh(IRenderMesh *) = 0; - - virtual void OnResize(int width, int height) = 0; -}; \ No newline at end of file diff --git a/Include/Interface/IRunnable.h b/Include/Interface/IRunnable.h deleted file mode 100755 index c09317b..0000000 --- a/Include/Interface/IRunnable.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ITask_H__ -#define __ITask_H__ - - -struct ITaskManager; -/*! - \class ITask -*/ -struct IRunnable -{ - virtual ~IRunnable () {} - virtual void OnRun() = 0; - - virtual void OnFinish() {} - virtual void OnStop() {} - virtual void OnResume() {} - virtual void OnCanceled() {} -}; - -enum class TaskPriority : uint32 { - RealTime, - BackGround, - Normal -}; - -#endif diff --git a/Include/Interface/IShader.h b/Include/Interface/IShader.h deleted file mode 100755 index 7561589..0000000 --- a/Include/Interface/IShader.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -enum class ShaderType { - Vertex, - Pixel, - Domain, - Hull, - Geometry, - Compute -}; - - -struct IShader { -public: - virtual ~IShader() {} - - virtual void SaveCache() {} - virtual void LoadCache() {} -}; - - -template -class TShader -{ -public: - static const ShaderType type = ShaderInstType; - ShaderInstClass Get() { return ShaderInst; } -protected: - ShaderInstClass ShaderInst; -}; \ No newline at end of file diff --git a/Include/KTL/DynArray.hpp b/Include/KTL/DynArray.hpp index c0ff20a..10ed38f 100755 --- a/Include/KTL/DynArray.hpp +++ b/Include/KTL/DynArray.hpp @@ -6,11 +6,15 @@ #include "Allocator.hpp" #include "Archive.hpp" -#ifndef K3DPLATFORM_OS_MAC +#if (K3DPLATFORM_OS_WIN) || (K3DPLATFORM_OS_ANDROID) #include #else #include #endif + + + + #include #ifdef DYNARRAY_TEST_CASE @@ -19,7 +23,7 @@ typedef unsigned int uint32; typedef size_t uint64; #endif -namespace k3d +K3D_COMMON_NS { template < class T, @@ -83,12 +87,22 @@ namespace k3d m_pElement = (ElementType*)m_Allocator.allocate(m_Capacity*sizeof(ElementType), 0); __Initializer::DoInit(m_pElement, m_pElement+m_Capacity); } - + + DynArray(int size) K3D_NOEXCEPT + : m_ElementIndex(0), m_ElementCount(0), m_Capacity(size), m_pElement(nullptr) + { + m_pElement = (ElementType*)m_Allocator.allocate(m_Capacity*sizeof(ElementType), 0); + __Initializer::DoInit(m_pElement, m_pElement+m_Capacity); + } + DynArray(DynArray && rhs) : m_ElementCount(0), m_ElementIndex(0), m_pElement(nullptr) { m_ElementCount = rhs.m_ElementCount; m_Capacity = rhs.m_Capacity; m_pElement = rhs.m_pElement; + rhs.m_pElement = nullptr; + rhs.m_Capacity = 0; + rhs.m_ElementCount = 0; } DynArray(DynArray && rhs, TAllocator & alloc) : m_ElementCount(0), m_ElementIndex(0), m_pElement(nullptr), m_Allocator(alloc) @@ -103,7 +117,8 @@ namespace k3d m_ElementCount = rhs.m_ElementCount; m_Capacity = rhs.m_Capacity; m_pElement = (ElementType*)m_Allocator.allocate(m_Capacity*sizeof(ElementType), 0); - memcpy(m_pElement, rhs.m_pElement, rhs.m_ElementCount * sizeof(ElementType)); + __Initializer::DoInit(m_pElement, m_pElement + m_Capacity); + __Copier::DoCopy(m_pElement, rhs.m_pElement, rhs.m_ElementCount); } template @@ -206,6 +221,23 @@ namespace k3d } } + void Resize(int NewElementCount) + { + if(NewElementCount > m_Capacity) + { + ElementType* pElement = (ElementType*)m_Allocator.allocate(NewElementCount*sizeof(ElementType), 0); + __Initializer::DoInit(pElement, pElement + NewElementCount); + if(m_ElementCount > 0) + { + __Copier::DoCopy(pElement, m_pElement, m_ElementCount); + m_Allocator.deallocate(m_pElement, 0); + } + m_Capacity = NewElementCount; + m_pElement = pElement; + } + m_ElementCount = NewElementCount; + } + ElementType const& operator[](uint32 index) const { return m_pElement[index]; diff --git a/Include/KTL/IntrusiveList.hpp b/Include/KTL/IntrusiveList.hpp index c6a3508..f7f365e 100755 --- a/Include/KTL/IntrusiveList.hpp +++ b/Include/KTL/IntrusiveList.hpp @@ -8,7 +8,8 @@ #include #include -namespace kTL { +K3D_COMMON_NS +{ class _My_Intrusive_List_Base; class _My_Intrusive_List_Node_Base; diff --git a/Include/KTL/LockFreeQueue.hpp b/Include/KTL/LockFreeQueue.hpp index 2ae883d..4164541 100755 --- a/Include/KTL/LockFreeQueue.hpp +++ b/Include/KTL/LockFreeQueue.hpp @@ -1,4 +1,8 @@ #pragma once + +K3D_COMMON_NS +{ + template class LockFreeQueue { public: @@ -105,4 +109,6 @@ class LockFreeQueue { volatile int m_Size; Node *m_Head, *m_Tail; -}; \ No newline at end of file +}; + +} \ No newline at end of file diff --git a/Include/KTL/NonCopyable.hpp b/Include/KTL/NonCopyable.hpp index 3dd851a..d36bdb1 100755 --- a/Include/KTL/NonCopyable.hpp +++ b/Include/KTL/NonCopyable.hpp @@ -1,5 +1,7 @@ #pragma once +K3D_COMMON_NS +{ class NonCopyable { protected: @@ -8,4 +10,5 @@ class NonCopyable NonCopyable(const NonCopyable &); NonCopyable(const NonCopyable &&); NonCopyable& operator=(const NonCopyable &); -}; \ No newline at end of file +}; +} \ No newline at end of file diff --git a/Include/KTL/RefCount.hpp b/Include/KTL/RefCount.hpp index 646dbb6..8c8bb57 100755 --- a/Include/KTL/RefCount.hpp +++ b/Include/KTL/RefCount.hpp @@ -96,19 +96,28 @@ K3D_COMMON_NS } }; + template + struct AlignedStorage + { + typedef struct { + alignas(Align) unsigned char CharData[N]; + } Type; + }; + + template class TRefCountInstance : public RefCountBase { public: - T m_Memory; + typename AlignedStorage::Type m_Memory; // use storage substitude T* GetValue() { return static_cast(static_cast(&m_Memory)); } template TRefCountInstance(Args&&... args) : RefCountBase() - , m_Memory(std::forward(args)...) { + new (&m_Memory) T(std::forward(args)...); } void FreeValue() K3D_NOEXCEPT override diff --git a/Include/KTL/SharedPtr.hpp b/Include/KTL/SharedPtr.hpp index 7e6f53c..471bb5c 100755 --- a/Include/KTL/SharedPtr.hpp +++ b/Include/KTL/SharedPtr.hpp @@ -2,8 +2,17 @@ #include "RefCount.hpp" +#if K3DPLATFORM_OS_WIN && ENABLE_SHAREDPTR_TRACKER +#include +#include "String.hpp" +#endif + K3D_COMMON_NS { + template class WeakPtr; + template class SharedPtr; + template class EnableSharedFromThis; + template struct TSharedPtrBase { @@ -16,6 +25,17 @@ K3D_COMMON_NS }; + template + void __EnableSharedFromThis(const RefCountBase* pRefCount, const EnableSharedFromThis* pEnableSharedFromThis, const U* pValue) + { + if (pEnableSharedFromThis) + pEnableSharedFromThis->m_WeakPtr.Assign(const_cast(pValue), const_cast(pRefCount)); + } + + inline void __EnableSharedFromThis(const RefCountBase*, ...) + { + } + template class SharedPtr : TSharedPtrBase { @@ -29,7 +49,16 @@ K3D_COMMON_NS , m_pRefCount(sharedPtr.m_pRefCount) { if (m_pRefCount) + { m_pRefCount->AddRef(); + +#if K3DPLATFORM_OS_WIN && ENABLE_SHAREDPTR_TRACKER + String debugStr; + debugStr.AppendSprintf("SharedPtr Track (Assign Construct) [%s] --- Strong=%d Weak=%d .\n", + typeid(T).name(), m_pRefCount->m_RefCount, m_pRefCount->m_WeakRefCount); + OutputDebugStringA(debugStr.CStr()); +#endif + } } SharedPtr(decltype(nullptr)) @@ -44,7 +73,16 @@ K3D_COMMON_NS , m_pRefCount(sharedPtr.m_pRefCount) { if (m_pRefCount) + { m_pRefCount->AddRef(); + +#if K3DPLATFORM_OS_WIN && ENABLE_SHAREDPTR_TRACKER + String debugStr; + debugStr.AppendSprintf("SharedPtr Track (Assign Construct) [%s] --- Strong=%d Weak=%d .\n", + typeid(U).name(), m_pRefCount->m_RefCount, m_pRefCount->m_WeakRefCount); + OutputDebugStringA(debugStr.CStr()); +#endif + } } template @@ -64,10 +102,30 @@ K3D_COMMON_NS AllocInternal(pValue, DefaultDeletor()); } + template + explicit SharedPtr(const WeakPtr& weakPtr) + : m_pValue(weakPtr.m_pValue), + m_pRefCount(weakPtr.m_pRefCount ? weakPtr.m_pRefCount->Lock() : weakPtr.m_pRefCount) + { + if(!m_pRefCount) + { + m_pValue = nullptr; + } + } + ~SharedPtr() { - if (m_pRefCount) + if (m_pRefCount) + { m_pRefCount->Release(); + +#if K3DPLATFORM_OS_WIN && ENABLE_SHAREDPTR_TRACKER + String debugStr; + debugStr.AppendSprintf("SharedPtr Track (Release) [%s] --- Strong=%d Weak=%d .\n", + typeid(T).name(), m_pRefCount->m_RefCount, m_pRefCount->m_WeakRefCount); + OutputDebugStringA(debugStr.CStr()); +#endif + } m_pValue = nullptr; m_pRefCount = nullptr; } @@ -101,6 +159,13 @@ K3D_COMMON_NS { ThisType(sharedPtr).Swap(*this); } + +#if K3DPLATFORM_OS_WIN && ENABLE_SHAREDPTR_TRACKER + String debugStr; + debugStr.AppendSprintf("SharedPtr Track (Assign) [%s] --- Strong=%d Weak=%d .\n", + typeid(T).name(), m_pRefCount->m_RefCount, m_pRefCount->m_WeakRefCount); + OutputDebugStringA(debugStr.CStr()); +#endif return *this; } @@ -129,6 +194,7 @@ K3D_COMMON_NS { m_pRefCount = ::new(pMemory) RefCountT(pValue, Move(deleter)); m_pValue = pValue; + __EnableSharedFromThis(m_pRefCount, pValue, pValue); } else { @@ -148,6 +214,7 @@ K3D_COMMON_NS RCT* pRefCount = ::new(pMemory) RCT(Forward(args)...); sharedPtr.m_pRefCount = (RefCountBase*)pRefCount; sharedPtr.m_pValue = pRefCount->GetValue(); + __EnableSharedFromThis(pRefCount, pRefCount->GetValue(), pRefCount->GetValue()); } return sharedPtr; } @@ -168,6 +235,14 @@ K3D_COMMON_NS class WeakPtr { public: + typedef WeakPtr ThisType; + + WeakPtr(decltype(nullptr)) + : m_pValue(nullptr) + , m_pRefCount(nullptr) + { + } + WeakPtr() : m_pValue(nullptr), m_pRefCount(nullptr) {} template @@ -185,11 +260,85 @@ K3D_COMMON_NS m_pRefCount->ReleaseWeakRef(); } + T& operator*() const { return *m_pValue; } + + T* operator->() const { return m_pValue; } + + void Swap(WeakPtr& weakPtr) + { + T * const pValue = weakPtr.m_pValue; + weakPtr.m_pValue = m_pValue; + m_pValue = pValue; + RefCountBase* const pRefCount = weakPtr.m_pRefCount; + weakPtr.m_pRefCount = m_pRefCount; + m_pRefCount = pRefCount; + } + + WeakPtr& operator=(const WeakPtr& weakPtr) + { + if (&weakPtr != this) + { + WeakPtr(weakPtr).Swap(*this); + } + return *this; + } + + explicit operator bool() const + { + return m_pValue != nullptr; + } + + T* Get() const { return m_pValue; } + + void Assign(T* pValue, RefCountBase* pRefCount) + { + m_pValue = pValue; + + if (pRefCount != m_pRefCount) + { + if (m_pRefCount) + m_pRefCount->ReleaseWeakRef(); + + m_pRefCount = pRefCount; + + if (m_pRefCount) + m_pRefCount->AddWeakRef(); + } + } + protected: T* m_pValue; RefCountBase* m_pRefCount; template friend class SharedPtr; template friend class WeakPtr; + template friend class EnableSharedFromThis; + private: + }; + + template class EnableSharedFromThis + { + protected: + template friend class SharedPtr; + EnableSharedFromThis() {} + EnableSharedFromThis(EnableSharedFromThis const &) {} + EnableSharedFromThis & operator=(EnableSharedFromThis const &) + { + return *this; + } + ~EnableSharedFromThis() + { + } + public: + SharedPtr SharedFromThis() + { + return SharedPtr(m_WeakPtr); + } + SharedPtr SharedFromThis() const + { + return SharedPtr(m_WeakPtr); + } + public: + mutable WeakPtr m_WeakPtr; }; } \ No newline at end of file diff --git a/Include/KTL/Singleton.hpp b/Include/KTL/Singleton.hpp index bd2e3f0..c214da4 100755 --- a/Include/KTL/Singleton.hpp +++ b/Include/KTL/Singleton.hpp @@ -1,6 +1,8 @@ #pragma once #include +K3D_COMMON_NS +{ template class K3D_API Singleton { @@ -14,3 +16,4 @@ class K3D_API Singleton protected: Singleton(){} }; +} \ No newline at end of file diff --git a/Include/KTL/String.hpp b/Include/KTL/String.hpp new file mode 100644 index 0000000..b19ea9b --- /dev/null +++ b/Include/KTL/String.hpp @@ -0,0 +1,379 @@ +#pragma once + +#include "Allocator.hpp" +#include "Archive.hpp" + +K3D_COMMON_NS +{ +template +inline uint64 CharLength(const BaseChar* cStr) +{ + const BaseChar *eos = cStr; + while (*eos++); + return(eos - cStr - 1); +} + +extern K3D_API int Vsnprintf(char*, int n, const char* fmt, va_list); + +template +class StringBase +{ +public: + typedef BaseChar* CharPointer; + typedef const BaseChar* ConstCharPointer; + typedef StringBase ThisString; + typedef uint64 CharPosition; + + StringBase() K3D_NOEXCEPT + : m_pStringData(nullptr) + , m_StringLength(0) + , m_Capacity(0) + { + } + + StringBase(const void * pData, size_t szData) K3D_NOEXCEPT + : m_pStringData(nullptr) + , m_StringLength(0) + , m_Capacity(0) + { + uint64 calLength = szData / sizeof(BaseChar); + uint64 remain = szData % sizeof(BaseChar); + if (remain == 0) + { + m_StringLength = calLength; + m_Capacity = m_StringLength + 1; + m_pStringData = Allocate(m_Capacity); + memcpy(m_pStringData, pData, szData); + m_pStringData[m_StringLength] = 0; + } + } + + StringBase(ConstCharPointer pStr) K3D_NOEXCEPT + : m_pStringData(nullptr) + , m_StringLength(0) + , m_Capacity(0) + { + m_StringLength = CharLength(pStr); + if (m_StringLength) + { + m_Capacity = (uint64)(1.5f * m_StringLength + 0.5f); + m_pStringData = Allocate(m_Capacity); + memcpy(m_pStringData, pStr, m_StringLength * sizeof(BaseChar)); + m_pStringData[m_StringLength] = 0; + } + } + + StringBase(const ThisString & rhs) K3D_NOEXCEPT + : m_pStringData(nullptr) + , m_StringLength(0) + , m_Capacity(rhs.m_Capacity) + , m_StringAllocator(rhs.m_StringAllocator) + { + Assign(rhs); + } + + StringBase(ThisString && rhs) K3D_NOEXCEPT + : m_pStringData(nullptr) + , m_StringLength(0) + { + MoveAssign(Move(rhs)); + } + + ~StringBase() + { + if (m_pStringData) + { + Deallocate(); + } + m_pStringData = nullptr; + m_StringLength = 0; + } + + uint64 Length() const { return m_StringLength; } + ConstCharPointer Data() const { return m_pStringData; } + ConstCharPointer CStr() const { return m_pStringData; } + + ThisString& operator=(const ThisString& rhs) { Assign(rhs); return *this; } + ThisString& operator=(ThisString&& rhs) { MoveAssign(Move(rhs)); return *this; } + ThisString& operator+=(const ThisString& rhs); + ThisString& operator+=(const BaseChar& rhs); + BaseChar operator[](uint64 id) const; + ThisString& AppendSprintf(const BaseChar* fmt, ...); + void Swap(ThisString& rhs); + + void Resize(int newSize); + //CharPosition FindFirstOf(BaseChar _char); + + template + friend Archive& operator<<(Archive & ar, StringBase const& str); + + template + friend Archive& operator >> (Archive & ar, StringBase & str); + +protected: + CharPointer Allocate(uint64 stringLength); + void Deallocate(); + + void MoveAssign(ThisString && rhs); + void Assign(ThisString const& rhs); + +private: + CharPointer m_pStringData; + uint64 m_StringLength; + uint64 m_Capacity; + Allocator m_StringAllocator; +}; + +template +KFORCE_INLINE BaseChar* StringBase::Allocate(uint64 length) +{ + return reinterpret_cast(m_StringAllocator.allocate(sizeof(BaseChar)*length, 0)); +} + +template +KFORCE_INLINE void StringBase::Deallocate() +{ + m_StringAllocator.deallocate(m_pStringData, sizeof(BaseChar)*m_StringLength); +} + +template +KFORCE_INLINE void StringBase::MoveAssign(StringBase && rhs) +{ + m_pStringData = rhs.m_pStringData; + m_StringLength = rhs.m_StringLength; + m_Capacity = rhs.m_Capacity; + m_StringAllocator = Move(rhs.m_StringAllocator); + rhs.m_pStringData = nullptr; + rhs.m_StringLength = 0; + rhs.m_Capacity = 0; +} + +template +KFORCE_INLINE void StringBase::Assign(StringBase const & rhs) +{ + if (m_pStringData != rhs.m_pStringData) + { + if (m_pStringData) + { + Deallocate(); + } + m_Capacity = rhs.m_StringLength + 1; + m_pStringData = Allocate(m_Capacity); + m_StringLength = rhs.m_StringLength; + memcpy(m_pStringData, rhs.m_pStringData, rhs.m_StringLength * sizeof(BaseChar)); + m_pStringData[m_StringLength] = 0; + } +} + +template +KFORCE_INLINE StringBase& +StringBase::AppendSprintf(const BaseChar *fmt, ...) +{ + va_list va; + va_start(va, fmt); + int length = Vsnprintf(m_pStringData + m_StringLength, m_Capacity - m_StringLength, fmt, va); + va_end(va); + + auto newLen = length + m_StringLength; + if (newLen >= m_Capacity) + { + m_Capacity = (uint64)(1.33f * newLen + 1.0f); + BaseChar* newString = Allocate(m_Capacity); + memcpy(newString, m_pStringData, m_StringLength * sizeof(BaseChar)); + + va_list va; + va_start(va, fmt); + Vsnprintf(newString + m_StringLength, m_Capacity - m_StringLength, fmt, va); + va_end(va); + + Deallocate(); + m_pStringData = newString; + } + + m_StringLength = newLen; + + return *this; +} + +template +KFORCE_INLINE void StringBase::Swap(StringBase & rhs) +{ + BaseChar* p = rhs.m_pStringData; + rhs.m_pStringData = m_pStringData; + m_pStringData = p; + + uint64 l = rhs.m_StringLength; + rhs.m_StringLength = m_StringLength; + m_StringLength = l; +} + +template +KFORCE_INLINE void StringBase::Resize(int newSize) +{ + auto newCapacity = (uint64)(1.1f * newSize + 1.0f); + if (newCapacity > m_Capacity) + { + m_Capacity = newCapacity; + auto pStringData = Allocate(m_Capacity); + if (m_StringLength) + { + memcpy(pStringData, m_pStringData, sizeof(BaseChar) * m_StringLength); + pStringData[m_StringLength] = 0; + Deallocate(); + } + else + { + memset(pStringData, 0, sizeof(BaseChar) * m_Capacity); + } + m_pStringData = pStringData; + } +} + +template +KFORCE_INLINE BaseChar StringBase::operator[](uint64 id) const +{ + return m_pStringData[id]; +} + +template +KFORCE_INLINE StringBase& +StringBase::operator+=(StringBase const& rhs) +{ + auto rLen = rhs.m_StringLength; + auto newLen = m_StringLength + rLen; + if (newLen >= m_Capacity) + { + m_Capacity = uint64(1.5*newLen + 1); + auto pNewData = Allocate(m_Capacity); + if (m_pStringData) + { + memcpy(pNewData, m_pStringData, m_StringLength * sizeof(BaseChar)); + Deallocate(); + } + m_pStringData = pNewData; + } + memcpy(m_pStringData + m_StringLength, rhs.m_pStringData, rLen * sizeof(BaseChar)); + m_pStringData[newLen] = 0; + m_StringLength = newLen; + return *this; +} + +template +KFORCE_INLINE StringBase& +StringBase::operator+=(BaseChar const& rhs) +{ + auto newLen = m_StringLength + 1; + if (newLen >= m_Capacity) + { + m_Capacity = uint64(1.5*newLen + 1); + auto pNewData = Allocate(m_Capacity); + if (m_pStringData) + { + memcpy(pNewData, m_pStringData, m_StringLength * sizeof(BaseChar)); + Deallocate(); + } + m_pStringData = pNewData; + } + m_pStringData[m_StringLength] = rhs; + m_pStringData[newLen] = 0; + m_StringLength = newLen; + return *this; +} + +template +KFORCE_INLINE StringBase +operator+(StringBase const& lhs, StringBase const& rhs) +{ + StringBase ret(lhs); + ret += rhs; + return ret; +} + +template +KFORCE_INLINE bool operator==(StringBase const& lhs, StringBase const& rhs) K3D_NOEXCEPT +{ + if (&lhs == &rhs) + return true; + return ((lhs.Length() == rhs.Length()) + && (memcmp(lhs.Data(), rhs.Data(), lhs.Length() * sizeof(BaseChar)) == 0)); +} + +template +Archive& operator<<(Archive & ar, StringBase const& str) +{ + ar << str.m_Capacity << str.m_StringLength; + ar.ArrayIn(str.CStr(), str.Length()); + return ar; +} + +template +Archive& operator >> (Archive & ar, StringBase & str) +{ + ar >> str.m_Capacity >> str.m_StringLength; + str.m_pStringData = str.Allocate(str.m_Capacity); + ar.ArrayOut(str.m_pStringData, str.Length()); + str.m_pStringData[str.m_StringLength] = 0; + return ar; +} + +typedef StringBase String; + +extern K3D_API String Base64Encode(String const & in); +extern K3D_API String Base64Decode(String const& in); +extern K3D_API String MD5Encode(String const& in); +} + +#include + +namespace std +{ + template + struct _FNVHash + { + size_t operator()(const unsigned char *pData, size_t count); + }; + + template <> + struct _FNVHash<8> + { + inline size_t operator()(const unsigned char *pData, size_t count) + { + const size_t fnvOffsetBase = 14695981039346656037ULL; + const size_t fnvPrime = 1099511628211ULL; + size_t val = fnvOffsetBase; + for (size_t i = 0; i < count; ++i) + { // fold in another byte + val ^= (size_t)pData[i]; + val *= fnvPrime; + } + return (val); + } + }; + + template <> + struct _FNVHash<4> + { + inline size_t operator()(const unsigned char *pData, size_t count) + { + const size_t fnvOffsetBase = 2166136261U; + const size_t fnvPrime = 16777619U; + size_t val = fnvOffsetBase; + for (size_t i = 0; i < count; ++i) + { + val ^= (size_t)pData[i]; + val *= fnvPrime; + } + return (val); + } + }; + + template<> + struct hash + { + size_t operator()(const k3d::String& val) const + { + _FNVHash _Hasher; + return _Hasher((const unsigned char *)val.CStr(), val.Length()); + } + }; +} \ No newline at end of file diff --git a/Include/Math/IK.hpp b/Include/Math/IK.hpp new file mode 100644 index 0000000..43164cf --- /dev/null +++ b/Include/Math/IK.hpp @@ -0,0 +1,36 @@ +/*********************************************** + * Kaleido3D Math Library (Inverse Kinematics Solver) + * Implements Jacobian, CCD and FABRIK + * Author : Qin Zhou + * Date : 2017/2/18 + * Email : dsotsen@gmail.com + ***********************************************/ +#include "kMath.hpp" + +NS_MATHLIB_BEGIN + +class Joint +{ +private: + tMatrixNxN m_LocalMatrix; + tMatrixNxN m_WorldMatrix; + tVectorN m_Direction; + tVectorN m_Dof; +}; + +class IKSolver +{ + +}; + +class CCDIKSolver : public IKSolver +{ + +}; + +class FABRIKSolver : public IKSolver +{ + +}; + +NS_MATHLIB_END diff --git a/Include/Math/kMath.hpp b/Include/Math/kMath.hpp index 9314a39..d3a0eaa 100755 --- a/Include/Math/kMath.hpp +++ b/Include/Math/kMath.hpp @@ -13,7 +13,7 @@ #include "kTypeTrait.hpp" #include "../Kaleido3D.h" -#include +#include "../Config/OSHeaders.h" #if K3DCOMPILER_CLANG || K3DCOMPILER_GCC #include diff --git a/Include/Math/kMath_SSE.hpp b/Include/Math/kMath_SSE.hpp index b39cf8e..0c7f11b 100755 --- a/Include/Math/kMath_SSE.hpp +++ b/Include/Math/kMath_SSE.hpp @@ -2,7 +2,7 @@ #ifndef __kMath_SSE_hpp__ #define __kMath_SSE_hpp__ -#include +#include "../Config/Config.h" #include #define _MM_PERM2_X 0 diff --git a/Project/Common.cmake b/Project/Common.cmake index 7fa6f67..d41da4c 100755 --- a/Project/Common.cmake +++ b/Project/Common.cmake @@ -1,73 +1,229 @@ set(GLSLANG_LIBS glslang OGLCompiler OSDependent SPIRV) -set(UNITTEST_DEPENDS Core Render ShaderCompiler) + +set(UT_LINK_LIBS Core Engine Render) +set(UT_DEP_PLUGIN "") + +set(DEVELOPMENT_TEAM "8HY898Y2MS") +set(CODE_SIGN_IDENTITY "iPhone Developer") + +function(link_plugin PLUGIN_NAME) # current plugins: RHI_*, KawaLog, ShaderCompiler +if(BUILD_SHARED) +else() + target_link_libraries(${PLUGIN_NAME} ${ARGN}) +endif() +endfunction() + if(ANDROID) - set(UNITTEST_DEPENDS ${UNITTEST_DEPENDS} RHI_Vulkan) + list(APPEND UT_LINK_LIBS RHI_Vulkan ShaderCompiler) elseif(WIN32) - set(UNITTEST_DEPENDS ${UNITTEST_DEPENDS} Engine RHI_Vulkan - winmm comctl32 ${GLSLANG_LIBS}) + list(APPEND UT_LINK_LIBS RHI_Vulkan winmm comctl32 ${GLSLANG_LIBS}) if(BUILD_WITH_D3D12) - set(UNITTEST_DEPENDS ${UNITTEST_DEPENDS} RHI_D3D12 ${DXSDK_LIBRARIES}) + list(UT_LINK_LIBS RHI_D3D12 ${DXSDK_LIBRARIES}) endif() elseif(MACOS) - set(UNITTEST_DEPENDS ${UNITTEST_DEPENDS} "-framework AppKit") + list(APPEND UT_LINK_LIBS "-framework AppKit" RHI_Metal) +elseif(IOS) + list(APPEND UT_LINK_LIBS "-framework UIKit" RHI_Metal) + set(PLIST_GEN ${Kaleido3D_ROOT_DIR}/Project/plist_gen) endif() -function(add_plugin PLUGIN_NAME PLUGIN_FOLDER) +if(BUILD_SHARED) +else() # Static Build + list(APPEND UT_LINK_LIBS ShaderCompiler) +endif(BUILD_SHARED) + +function(add_ios_framework TARGET) + cmake_parse_arguments(${TARGET} + "" + "FOLDER;ID;PDN" + "SRCS;LIBS;PUBLIC" + ${ARGN} + ) + add_library(${TARGET} SHARED ${${TARGET}_SRCS}) + target_link_libraries(${TARGET} ${${TARGET}_LIBS}) + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -id "@executable_path/${TARGET}.framework/${TARGET}" $) + if(NOT ${TARGET}_ID) + set(${TARGET}_ID "com.tsinstudio.kaleido3d") + endif() + if(NOT ${TARGET}_PDN) + set(${TARGET}_PDN "${TARGET}") + endif() + execute_process(COMMAND ${PLIST_GEN} -t "framework" --be "${TARGET}" + --bid "${${TARGET}_ID}" --cr "\"Copyright 2016 Tsin Studio\"" + --bn "${${TARGET}_ID}" --bdn "${${TARGET}_PDN}" + --outdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir") ## generate Info.plist + set_target_properties(${TARGET} PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir/Info.plist + # "current version" in semantic format in Mach-O binary file + VERSION 1.0.0 + # "compatibility version" in semantic format in Mach-O binary file + SOVERSION 1.0.0 + PUBLIC_HEADER "${${TARGET}_PUBLIC}" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM} + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY} + XCODE_ATTRIBUTE_PROVISIONING_STYLE Automatic + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + ) +endfunction() + +function(k3d_add_lib TARGET) + cmake_parse_arguments(${TARGET} + "" + "FOLDER" + "SRCS;LIBS" + ${ARGN} + ) if(BUILD_SHARED) - add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) + add_definitions(-DBUILD_SHARED_LIB) + if(IOS) + add_ios_framework(${TARGET} SRCS ${${TARGET}_SRCS} LIBS ${${TARGET}_LIBS}) + else() + add_library(${TARGET} SHARED ${${TARGET}_SRCS}) + target_link_libraries(${TARGET} ${${TARGET}_LIBS}) + endif(IOS) + else() + add_library(${TARGET} STATIC ${${TARGET}_SRCS}) endif() - set(LINK_BEGINS FALSE) - foreach(ITEM IN LISTS ARGN) - if("${ITEM}" STREQUAL "LINKLIBS") - set(LINK_BEGINS TRUE) - continue() - endif() - if(NOT LINK_BEGINS) - list(APPEND SRCS ${ITEM}) - else() - list(APPEND LIBS ${ITEM}) - endif() - endforeach() - - add_library(${PLUGIN_NAME} ${LIB_TYPE} ${SRCS}) - set_target_properties(${PLUGIN_NAME} PROPERTIES FOLDER "${PLUGIN_FOLDER}") - target_link_libraries(${PLUGIN_NAME} Core ${LIBS}) + set_target_properties(${TARGET} PROPERTIES FOLDER "${${TARGET}_FOLDER}") +endfunction() + +function(add_plugin PLUGIN_NAME) + cmake_parse_arguments(${PLUGIN_NAME} + "" + "FOLDER" + "SRCS;LIBS" + ${ARGN} + ) + if(BUILD_SHARED) + add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) + if(IOS) # use framework + add_ios_framework(${PLUGIN_NAME} SRCS ${${PLUGIN_NAME}_SRCS} LIBS Core ${${PLUGIN_NAME}_LIBS}) + else() + add_library(${PLUGIN_NAME} ${LIB_TYPE} ${${PLUGIN_NAME}_SRCS}) + target_link_libraries(${PLUGIN_NAME} Core ${${PLUGIN_NAME}_LIBS}) + endif(IOS) + else() + add_library(${PLUGIN_NAME} ${LIB_TYPE} ${${PLUGIN_NAME}_SRCS}) + target_link_libraries(${PLUGIN_NAME} Core ${${PLUGIN_NAME}_LIBS}) + endif(BUILD_SHARED) + set_target_properties(${PLUGIN_NAME} PROPERTIES FOLDER "${${PLUGIN_NAME}_FOLDER}") endfunction() if(MACOS) - function(target_pack_depend_libraries EXE_NAME) - set(${EXE_NAME}_DIR $) - foreach(DEPEND_LIB IN LISTS ARGN) - message("${EXE_NAME}: Coping lib${DEPEND_LIB}") - set(${DEPEND_LIB}_PACK_PATH "${${EXE_NAME}_DIR}/../../Contents/Frameworks/lib${DEPEND_LIB}.dylib") - # Copy Dependency Libraries To XX.app/Contents/Frameworks - add_custom_command(TARGET ${EXE_NAME} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy "$" "${${DEPEND_LIB}_PACK_PATH}") - endforeach() + function(add_mac_app TARGET) + cmake_parse_arguments(${TARGET} + "" + "PDN;OS;LDPATH;ID" # product name, target OS, LD_RUNPATH_SEARCH_PATHS, bundle identifier + "SRCS;LIBS;PLUGINS" # sources, link libs + ${ARGN}) + add_executable(${TARGET} MACOSX_BUNDLE ${${TARGET}_SRCS}) + if(BUILD_SHARED) + if(${TARGET}_LIBS) + target_link_libraries(${TARGET} ${${TARGET}_LIBS}) + set(${TARGET}_FRAMEWORK_DIR "$/../../Contents/Frameworks") + foreach(DEPEND_LIB IN LISTS ${TARGET}_LIBS) + # Copy Dependency Libraries To XX.app/Contents/Frameworks + add_custom_command(TARGET ${TARGET} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy "$" "${${TARGET}_FRAMEWORK_DIR}/lib${DEPEND_LIB}.dylib") + endforeach() + endif() + if(${TARGET}_PLUGINS) + set(${TARGET}_PLUGIN_DIR "$/../PlugIns") + foreach(PLUGIN IN LISTS ${TARGET}_PLUGINS) + set(${PLUGIN}_INSTALL_DIR "${${TARGET}_PLUGIN_DIR}/lib${PLUGIN}.dylib") + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E + copy "$" "${${PLUGIN}_INSTALL_DIR}") + endforeach() + endif() + else(BUILD_SHARED) # Static Build + list(APPEND ${TARGET}_LINK_LIBS ${${TARGET}_LIBS}) + list(APPEND ${TARGET}_LINK_LIBS ${${TARGET}_PLUGINS}) + target_link_libraries(${TARGET} ${${TARGET}_LINK_LIBS}) + endif(BUILD_SHARED) endfunction() +endif() - function(target_pack_plugins EXE_NAME) - set(${EXE_NAME}_PLUGIN_DIR $/../PlugIns) - foreach(PLUGIN IN LISTS ARGN) - set(${PLUGIN}_INSTALL_DIR "${${EXE_NAME}_PLUGIN_DIR}/lib${PLUGIN}.dylib") - add_custom_command(TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E - copy "$" "${${PLUGIN}_INSTALL_DIR}") - endforeach() +if(IOS) + function(add_ios_app TARGET) + cmake_parse_arguments(${TARGET} + "" + "PDN;OS;LDPATH;ID" # product name, target OS, LD_RUNPATH_SEARCH_PATHS, bundle identifier + "SRCS;LIBS;PLUGINS" # sources, link libs + ${ARGN}) + add_executable(${TARGET} MACOSX_BUNDLE ${${TARGET}_SRCS}) + if(NOT ${TARGET}_ID) + set(${TARGET}_ID "com.tsinstudio.kaleido3d") + endif() + if(NOT ${TARGET}_PDN) + set(${TARGET}_PDN "${TARGET}") + endif() + execute_process( + COMMAND ${PLIST_GEN} -t app --be "${TARGET}" --bid "${${TARGET}_ID}" + --cr "\"Copyright 2016 Tsin Studio\"" --bn "${${TARGET}_ID}" --bdn "${${TARGET}_PDN}" + --outdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir") ## generate Info.plist + if(${TARGET}_LIBS) + target_link_libraries(${TARGET} ${${TARGET}_LIBS}) + if(BUILD_SHARED) + foreach(DEPEND_LIB IN LISTS ${TARGET}_LIBS) + if(NOT (${DEPEND_LIB} MATCHES "-framework")) + # Copy Dependency Libraries To XX.app/Frameworks + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory "$" "$/${DEPEND_LIB}.framework") + endif() + endforeach() + endif(BUILD_SHARED) + endif() + set_target_properties(${TARGET} PROPERTIES + XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" + XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${${TARGET}_OS} + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES + XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES "NO" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM} + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY} + XCODE_ATTRIBUTE_PROVISIONING_STYLE Automatic + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir/Info.plist" + XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "${${TARGET}_LDPATH}") endfunction() -endif() +endif(IOS) + +if(ANDROID) + function(add_android_app TARGET) + cmake_parse_arguments(${TARGET} + "" + "" + "SRCS;LIBS" # sources, link libs + ${ARGN}) + add_library(${TARGET} SHARED ${${TARGET}_SRCS}) + target_link_libraries(${TARGET} ${${TARGET}_LIBS}) + endfunction() +endif(ANDROID) macro(add_unittest EXAMPLE_NAME) if(ANDROID) - add_library(${EXAMPLE_NAME} SHARED ${ARGN} ../Platform/Android/jni/RendererView.cpp ../Platform/Android/jni/RendererView_JNI.cpp) + add_android_app(${EXAMPLE_NAME} + SRCS ${ARGN} ${Kaleido3D_SOURCE_DIR}/Platform/Android/jni/RendererView.cpp ${Kaleido3D_SOURCE_DIR}/Platform/Android/jni/RendererView_JNI.cpp + LIBS ${UT_LINK_LIBS}) elseif(WIN32) - add_executable(${EXAMPLE_NAME} ${ARGN} ../Platform/Windows/win32icon.rc) + add_executable(${EXAMPLE_NAME} ${ARGN} ${Kaleido3D_SOURCE_DIR}/Platform/Windows/win32icon.rc) + target_link_libraries(${EXAMPLE_NAME} ${UT_LINK_LIBS}) elseif(MACOS) - add_executable(${EXAMPLE_NAME} MACOSX_BUNDLE ${ARGN} ../Platform/Windows/win32icon.rc) - target_pack_depend_libraries(${EXAMPLE_NAME} Core Render ShaderCompiler) - target_pack_plugins(${EXAMPLE_NAME} RHI_Metal KawaLog) + add_mac_app(${EXAMPLE_NAME} + SRCS ${ARGN} + LIBS Core Engine Render + PLUGINS RHI_Metal KawaLog ShaderCompiler) + elseif(IOS) + add_ios_app(${EXAMPLE_NAME} + SRCS ${ARGN} "${Kaleido3D_SOURCE_DIR}/Platform/Apple/iOS/App.mm" + LIBS ${UT_LINK_LIBS} + PDN ${EXAMPLE_NAME} + OS 8.0 + LDPATH "@executable_path") else() add_executable(${EXAMPLE_NAME} ${ARGN}) endif() - target_link_libraries(${EXAMPLE_NAME} ${UNITTEST_DEPENDS}) set_target_properties(${EXAMPLE_NAME} PROPERTIES FOLDER "Unit Test") endmacro() diff --git a/Project/pch.cmake b/Project/Compiler.cmake old mode 100755 new mode 100644 similarity index 100% rename from Project/pch.cmake rename to Project/Compiler.cmake diff --git a/Project/FindThirdParty.cmake b/Project/FindThirdParty.cmake index ff2c63e..440c5c2 100755 --- a/Project/FindThirdParty.cmake +++ b/Project/FindThirdParty.cmake @@ -1,13 +1,31 @@ message("ThirdParty includes vulkan, rapidjson, glslang, spirv2cross, freetype2. ") -message("build config = ${CMAKE_SYSTEM_NAME}_${CMAKE_BUILD_TYPE}") - +set(GIT_THIRDPARTY_REPO "https://github.com/Tomicyo/kaleido3d_dep_prebuilt") if(WIN32) - set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/Win64_${CMAKE_BUILD_TYPE}) + set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/Win64/${CMAKE_BUILD_TYPE}) + if(NOT (EXISTS ${ThirdParty_PREBUILT_DIR})) + message(AUTHOR_WARNING "cloning ${ThirdParty_PREBUILT_DIR} from ${GIT_THIRDPARTY_REPO}") + execute_process(COMMAND git clone ${GIT_THIRDPARTY_REPO} -b win64_${CMAKE_BUILD_TYPE} ${ThirdParty_PREBUILT_DIR}) + endif() elseif(ANDROID) - set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/Android_ARM_${CMAKE_BUILD_TYPE}) + set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/Android/${ANDROID_ABI}/${ANDROID_STL}/${CMAKE_BUILD_TYPE}) + if(NOT (EXISTS ${ThirdParty_PREBUILT_DIR})) + message(AUTHOR_WARNING "cloning ${ThirdParty_PREBUILT_DIR} from ${GIT_THIRDPARTY_REPO}") + execute_process(COMMAND git clone ${GIT_THIRDPARTY_REPO} -b android_${ANDROID_ABI}_${ANDROID_STL}_${CMAKE_BUILD_TYPE} ${ThirdParty_PREBUILT_DIR}) + endif() elseif(MACOS) - set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/MacOS_${CMAKE_BUILD_TYPE}) + set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/MacOS/${CMAKE_BUILD_TYPE}) + if(NOT (EXISTS ${ThirdParty_PREBUILT_DIR})) + message(AUTHOR_WARNING "cloning ${ThirdParty_PREBUILT_DIR} from ${GIT_THIRDPARTY_REPO}") + execute_process(COMMAND git clone ${GIT_THIRDPARTY_REPO} -b macos_${CMAKE_BUILD_TYPE} ${ThirdParty_PREBUILT_DIR}) + endif() +elseif(IOS) + set(ThirdParty_PREBUILT_DIR ${K3D_THIRD_PARTY}/iOS/${CMAKE_BUILD_TYPE}) + if(NOT (EXISTS ${ThirdParty_PREBUILT_DIR})) + message(AUTHOR_WARNING "cloning ${ThirdParty_PREBUILT_DIR} from ${GIT_THIRDPARTY_REPO}") + execute_process(COMMAND git clone ${GIT_THIRDPARTY_REPO} -b ios_${CMAKE_BUILD_TYPE} ${ThirdParty_PREBUILT_DIR}) + endif() endif() +message(STATUS "** 3rd party ** ${ThirdParty_PREBUILT_DIR}") unset(THIRDPARTY_FOUND CACHE) @@ -17,19 +35,33 @@ unset(GLSLANG_INCLUDE_DIR CACHE) unset(SPIRV2CROSS_INCLUDE_DIR CACHE) unset(FREETYPE2_INCLUDE_DIR CACHE) -set(FREETYPE2_LIBRARY freetyped) +set(FREETYPE2_LIBRARY freetype) set(GLSLANG_LIBRARIES glslang HLSL OGLCompiler OSDependent SPIRV SPVRemapper) -set(SPIRV2CROSS_LIBRARY Spirv2Cross) +set(SPIRV2CROSS_LIBRARY spirv-cross-core spirv-cross-msl spirv-cross-glsl) if(WIN32) unset(DXSDK_INCLUDE_DIR CACHE) endif() +if(WIN32 OR ANDROID) find_path(VULKANSDK_INCLUDE_DIR vulkan/vulkan.h PATH_SUFFIXES include PATHS ${ThirdParty_PREBUILT_DIR} ) +endif() + +if(WIN32) +find_library(VULKAN_LIB vulkan-1 + PATH_SUFFIXES lib/x64 + PATHS ${ThirdParty_PREBUILT_DIR}) +message(STATUS "** Vulkan \(Windows\) ** ${VULKAN_LIB}") +elseif(ANDROID) +find_library(VULKAN_LIB vulkan + PATH_SUFFIXES platforms/android-24/arch-${ANDROID_SYSROOT_ABI}/usr/lib + PATHS $ENV{ANDROID_NDK}) +message(STATUS "** Vulkan Lib \(Android\) ** ${VULKAN_LIB}") +endif() find_path(RAPIDJSON_INCLUDE_DIR rapidjson/rapidjson.h @@ -50,11 +82,55 @@ find_path(SPIRV2CROSS_INCLUDE_DIR ) find_path(FREETYPE2_INCLUDE_DIR - freetype2/ft2build.h - PATH_SUFFIXES include + ft2build.h + PATH_SUFFIXES include/freetype2 PATHS ${ThirdParty_PREBUILT_DIR} ) +find_library(FREETYPE2_LIBRARY + NAMES freetype + HINTS + $ENV{FREETYPE2_DIR} + PATH_SUFFIXES lib + PATHS + ${ThirdParty_PREBUILT_DIR} +) + +if(FREETYPE2_LIBRARY) +# Find dependencies + foreach (d ZLIB BZip2 PNG HarfBuzz) + string(TOUPPER "${d}" D) + + if (DEFINED WITH_${d} OR DEFINED WITH_${D}) + if (WITH_${d} OR WITH_${D}) + find_package(${d} QUIET REQUIRED) + endif () + else () + find_package(${d} QUIET) + endif () + + if (${d}_FOUND OR ${D}_FOUND) + message(STATUS "link FreeType with ${d}") + endif () + endforeach () + + include_directories(${FREETYPE2_INCLUDE_DIR}) + set(HAS_FREETYPE true) + + if (ZLIB_FOUND) + list(APPEND FREETYPE2_LIBRARY ${ZLIB_LIBRARIES}) + endif () + if (BZIP2_FOUND) + list(APPEND FREETYPE2_LIBRARY ${BZIP2_LIBRARIES}) + endif () + if (PNG_FOUND) + list(APPEND FREETYPE2_LIBRARY ${PNG_LIBRARIES}) + endif () + if (HARFBUZZ_FOUND) + list(APPEND FREETYPE2_LIBRARY ${HARFBUZZ_LIBRARIES}) + endif () +endif() + message("GLSLang = ${GLSLANG_INCLUDE_DIR}") if(WIN32) @@ -84,6 +160,7 @@ link_directories(${ThirdParty_PREBUILT_DIR}/lib) include(FindPackageHandleStandardArgs) +if(WIN32 OR ANDROID) find_package_handle_standard_args(ThirdParty DEFAULT_MSG VULKANSDK_INCLUDE_DIR RAPIDJSON_INCLUDE_DIR @@ -91,11 +168,24 @@ find_package_handle_standard_args(ThirdParty DEFAULT_MSG SPIRV2CROSS_INCLUDE_DIR FREETYPE2_INCLUDE_DIR ) - mark_as_advanced( VULKANSDK_INCLUDE_DIR RAPIDJSON_INCLUDE_DIR GLSLANG_INCLUDE_DIR SPIRV2CROSS_INCLUDE_DIR FREETYPE2_INCLUDE_DIR -) \ No newline at end of file +) +elseif(IOS OR MACOS) +find_package_handle_standard_args(ThirdParty DEFAULT_MSG + RAPIDJSON_INCLUDE_DIR + GLSLANG_INCLUDE_DIR + SPIRV2CROSS_INCLUDE_DIR + FREETYPE2_INCLUDE_DIR +) +mark_as_advanced( + RAPIDJSON_INCLUDE_DIR + GLSLANG_INCLUDE_DIR + SPIRV2CROSS_INCLUDE_DIR + FREETYPE2_INCLUDE_DIR +) +endif() \ No newline at end of file diff --git a/Project/NDKStlConfig.cmake b/Project/NDKStlConfig.cmake index 46b84d0..4dc9fda 100755 --- a/Project/NDKStlConfig.cmake +++ b/Project/NDKStlConfig.cmake @@ -7,13 +7,13 @@ # or # # find_package(ndk-stl REQUIRED PATHS ".") +if(ANDROID) if(NOT ${ANDROID_STL} MATCHES "_shared") return() endif() function(configure_shared_stl lib_path so_base) - message("Configuring STL ${so_base} for ${ANDROID_ABI}") configure_file( "${ANDROID_NDK}/sources/cxx-stl/${lib_path}/libs/${ANDROID_ABI}/lib${so_base}.so" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so" @@ -36,4 +36,6 @@ elseif("${ANDROID_STL}" STREQUAL "c++_shared") configure_shared_stl("llvm-libc++" "c++_shared") else() message(FATAL_ERROR "STL configuration ANDROID_STL=${ANDROID_STL} is not supported") -endif() \ No newline at end of file +endif() + +endif(ANDROID) \ No newline at end of file diff --git a/Project/Platform.cmake b/Project/Platform.cmake index 2f83a5f..58f2328 100755 --- a/Project/Platform.cmake +++ b/Project/Platform.cmake @@ -1,13 +1,24 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(CMAKE_CXX_FLAGS "-x objective-c++ ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-fno-objc-arc -x objective-c++ ${CMAKE_CXX_FLAGS}") if(IOS) add_definitions(-DK3DPLATFORM_OS_IOS=1) + set(K3D_TARGET_SYSTEM "iOS") else() set(MACOS TRUE) add_definitions(-DK3DPLATFORM_OS_MAC=1) - + set(K3D_TARGET_SYSTEM "MacOS") set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.tsinstudio.kaleido3d") set(MACOSX_BUNDLE_COPYRIGHT "Copyright Tsin Studio 2016. All Rights Reserved.") endif() endif() + +if(WIN32) + set(K3D_TARGET_SYSTEM "Windows") +endif(WIN32) + +if(ANDROID) # Android will above vars + set(K3D_TARGET_SYSTEM "Android") +endif(ANDROID) + +message(STATUS "Host System = ${CMAKE_SYSTEM_NAME}, Target System = ${K3D_TARGET_SYSTEM}") \ No newline at end of file diff --git a/Project/Util.cmake b/Project/Util.cmake new file mode 100644 index 0000000..ecadef8 --- /dev/null +++ b/Project/Util.cmake @@ -0,0 +1,45 @@ +if(NOT WIN32) + string(ASCII 27 Esc) + set(ColourReset "${Esc}[m") + set(ColourBold "${Esc}[1m") + set(Red "${Esc}[31m") + set(Green "${Esc}[32m") + set(Yellow "${Esc}[33m") + set(Blue "${Esc}[34m") + set(Magenta "${Esc}[35m") + set(Cyan "${Esc}[36m") + set(White "${Esc}[37m") + set(BoldRed "${Esc}[1;31m") + set(BoldGreen "${Esc}[1;32m") + set(BoldYellow "${Esc}[1;33m") + set(BoldBlue "${Esc}[1;34m") + set(BoldMagenta "${Esc}[1;35m") + set(BoldCyan "${Esc}[1;36m") + set(BoldWhite "${Esc}[1;37m") +endif() + +function(message) + list(GET ARGV 0 MessageType) + if(MessageType STREQUAL FATAL_ERROR OR MessageType STREQUAL SEND_ERROR) + list(REMOVE_AT ARGV 0) + _message(${MessageType} "${BoldRed}${ARGV}${ColourReset}") + elseif(MessageType STREQUAL WARNING) + list(REMOVE_AT ARGV 0) + _message(${MessageType} "${BoldYellow}${ARGV}${ColourReset}") + elseif(MessageType STREQUAL AUTHOR_WARNING) + list(REMOVE_AT ARGV 0) + _message(${MessageType} "${BoldCyan}${ARGV}${ColourReset}") + elseif(MessageType STREQUAL STATUS) + list(REMOVE_AT ARGV 0) + _message(${MessageType} "${Green}${ARGV}${ColourReset}") + else() + _message("${ARGV}") + endif() +endfunction() + +#message("No colour at all.") +#message(STATUS "\"Colour\" is spelled correctly.") +#message(AUTHOR_WARNING "\"Color\" is misspelled.") +#message(WARNING "Final warning: spell \"color\" correctly.") +#message(SEND_ERROR "Game over. It's \"colour\", not \"color\".") +#message(FATAL_ERROR "And there's no \"z\" in \"colourise\" either.") \ No newline at end of file diff --git a/Project/build.gradle b/Project/build.gradle index c90d529..b7366a6 100755 --- a/Project/build.gradle +++ b/Project/build.gradle @@ -23,7 +23,7 @@ android { } ndk { - abiFilters 'armeabi-v7a' + abiFilters 'arm64-v8a' } } diff --git a/Project/iOS.cmake b/Project/iOS.cmake index 6b6106d..788d1ad 100755 --- a/Project/iOS.cmake +++ b/Project/iOS.cmake @@ -1,35 +1,3 @@ - -# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake -# files which are included with CMake 2.8.4 -# It has been altered for iOS development - -# Options: -# -# IOS_PLATFORM = OS (default) or SIMULATOR -# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders -# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. -# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. -# -# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder -# By default this location is automatcially chosen based on the IOS_PLATFORM value above. -# If set manually, it will override the default location and force the user of a particular Developer Platform -# -# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder -# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. -# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. -# If set manually, this will force the use of a specific SDK version - -# Macros: -# -# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE) -# A convenience macro for setting xcode specific properties on targets -# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1") -# -# find_host_package (PROGRAM ARGS) -# A macro used to find executable programs on the host system, not within the iOS environment. -# Thanks to the android-cmake project for providing the command - -# Standard settings set (CMAKE_SYSTEM_NAME Darwin) set (CMAKE_SYSTEM_VERSION 1) set (UNIX True) @@ -46,10 +14,10 @@ if (CMAKE_UNAME) string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") endif (CMAKE_UNAME) -# Force the compilers to gcc for iOS +# Force the compilers to Clang for iOS include (CMakeForceCompiler) -CMAKE_FORCE_C_COMPILER (/usr/bin/clang Apple) -CMAKE_FORCE_CXX_COMPILER (/usr/bin/clang++ Apple) +set(CMAKE_C_COMPILER /usr/bin/clang Clang) +set(CMAKE_CXX_COMPILER /usr/bin/clang++ Clang) set(CMAKE_AR ar CACHE FILEPATH "" FORCE) # Skip the platform compiler checks for cross compiling @@ -63,6 +31,7 @@ set (CMAKE_SHARED_MODULE_PREFIX "lib") set (CMAKE_SHARED_MODULE_SUFFIX ".so") set (CMAKE_MODULE_EXISTS 1) set (CMAKE_DL_LIBS "") +set (CMAKE_SYSTEM_PROCESSOR "A10") set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") @@ -71,7 +40,7 @@ set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") # Hidden visibilty is required for cxx on iOS set (CMAKE_C_FLAGS_INIT "") -set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden -isysroot ${CMAKE_OSX_SYSROOT}") +set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden") set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") @@ -97,6 +66,12 @@ if (NOT DEFINED IOS_PLATFORM) endif (NOT DEFINED IOS_PLATFORM) set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") +# Setup building for arm64 or not +if (NOT DEFINED BUILD_ARM64) + set (BUILD_ARM64 true) +endif (NOT DEFINED BUILD_ARM64) +set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not") + # Check the platform selection and setup for developer root if (${IOS_PLATFORM} STREQUAL "OS") set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") @@ -104,6 +79,13 @@ if (${IOS_PLATFORM} STREQUAL "OS") # This causes the installers to properly locate the output libraries set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (SIMULATOR true) + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (SIMULATOR true) set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") # This causes the installers to properly locate the output libraries @@ -143,11 +125,12 @@ set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the select set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") # set the architecture for iOS -# NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually if (${IOS_PLATFORM} STREQUAL "OS") - set (IOS_ARCH armv6 armv7) -else (${IOS_PLATFORM} STREQUAL "OS") - set (IOS_ARCH i386) + set (IOS_ARCH armv7 armv7s arm64) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IOS_ARCH i386) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IOS_ARCH x86_64) endif (${IOS_PLATFORM} STREQUAL "OS") set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS") @@ -190,4 +173,4 @@ macro (find_host_package) set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endmacro (find_host_package) \ No newline at end of file +endmacro (find_host_package) diff --git a/Project/plist_gen b/Project/plist_gen new file mode 100755 index 0000000000000000000000000000000000000000..cc46b879001abf8501d5f4695b9761786c78437f GIT binary patch literal 134624 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 A?f?J) literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 32a4feb..aff0f50 100755 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ Introduction ========= +**kaleido3d** is a cross-platform graphics library. > **Main Feature** > >* `Next Generation Graphics Library` ->* Modern C++ Code (**`C++ 11`**) ->* Modern Graphics Renderer (`Metal`, `Vulkan`, `Direct3D 12`) +>* Modern C++ Code +>* Modern Graphics Renderer (`Metal`, `Vulkan`, `Direct3D 12`, `OpenGL|ES`) >* **`Maya`** Digital Content Creation Tools >* **Task-Oriented**, support `multi-thread` rendering >* Support Windows, Android, iOS, MacOS & Linux. @@ -22,7 +23,7 @@ Prerequisites |CI Status|[![Build status](https://ci.appveyor.com/api/projects/status/bkqv6wbtyr4538hf?svg=true)](https://ci.appveyor.com/project/TsinStudio/kaleido3d)|[![Circle CI](https://circleci.com/gh/TsinStudio/kaleido3d.svg?style=svg)](https://circleci.com/gh/TsinStudio/kaleido3d) |[![Build Status](https://travis-ci.org/TsinStudio/kaleido3d.svg?branch=master)](https://travis-ci.org/TsinStudio/kaleido3d)| |IDE| VS2015+ | Android Studio 2.2+| Xcode 8.1+ | |OS Requirements| Win10 | Android 7.+| MacOS Sierra | -|Dependency| [ThirdParty][8]/CMake 3.4+ | [ThirdParty][8]/NDK r12+/Gradle | [ThirdParty][8]/CMake 3.4+ | +|Dependency| [ThirdParty](https://github.com/Tomicyo/kaleido3d_dep)/CMake 3.4+ | [ThirdParty](https://github.com/Tomicyo/kaleido3d_dep)/NDK r12+/Gradle | [ThirdParty](https://github.com/Tomicyo/kaleido3d_dep)/CMake 3.4+ | ---------- @@ -41,14 +42,14 @@ Current Status - RHI(Render Hardware Interface) * [x] Vulkan backend **ready**. - * [ ] DirectX 12 backend **WIP** - * [ ] Metal backend **WIP** + * [x] DirectX 12 backend **WIP** + * [x] Metal backend **WIP** - Core.Platform * [x] Windows implementation ready. * [x] Android RendererView. - * [ ] iOS/MacOS not initialized. + * [x] iOS/MacOS **WIP**. - Tools @@ -57,15 +58,18 @@ Current Status - Planned Samples - * [x] Triangle(vk) - * [x] Textured Cube - * [ ] Compute Shader - * [ ] Shadow Mapping - * [ ] Physically Based Shading - * [ ] Deferred Shading - * [ ] Multi-thread Rendering + * [x] Triangle + * [x] Textured Cube + * [x] Compute Shader (WIP) + * [ ] Physically Based Shading (Material Model) + * [ ] Skinned Skeleton Animation + * [ ] Shadow Mapping (Render To Texture, Z-Pass) + * [ ] Deferred Shading (Multi-RenderTarget) + * [ ] Tile-Based Cluster Lighting (Compute Shading) + * [ ] Multi-Thread Rendering * [ ] Multi-GPU/CrossAdapter Rendering - * [ ] Cross Shader Language Compiler + * [x] Cross Shader Language Compiler + * [ ] Hand-writing Recognition CNN Sample (GPGPU) --- @@ -90,6 +94,7 @@ Documents * [rapidJson][3] * [glslang][7] * [spir2cross][10] + * [freetype][11] * DXSDK @@ -144,14 +149,16 @@ Samples Contact ========= -> If you have any suggestion, please contact me via [**email**](mailto:dsotsen@gmail.com). + +If you have any suggestion, please contact me via [**email**][12] . + Discuss [![Join the chat at https://gitter.im/TsinStudio/kaleido3d](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/TsinStudio/kaleido3d?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ========= -Please join the [gitter chat](https://gitter.im/TsinStudio/kaleido3d) to discuss on this project. +Please join the [gitter chat](https://gitter.im/TsinStudio/kaleido3d) or [QQ Group][13] to discuss on this project. Framework development discussions and thorough bug reports are collected on [Issues](https://github.com/TsinStudio/kaleido3d/issues). @@ -166,3 +173,6 @@ Framework development discussions and thorough bug reports are collected on [Iss [8]: https://github.com/Tomicyo/kaleido3d_dep [9]: https://vulkan.lunarg.com/ [10]: https://github.com/KhronosGroup/SPIRV-Cross +[11]: https://www.freetype.org +[12]: mailto:dsotsen@gmail.com +[13]: https://jq.qq.com/?_wv=1027&k=45tL869 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3636d67..85ec33d 100755 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -6,23 +6,25 @@ if(POLICY CMP0054) endif() set(Kaleido3D_ROOT_DIR "${Kaleido3D_SOURCE_DIR}/..") +set(K3D_THIRD_PARTY "${Kaleido3D_SOURCE_DIR}/ThirdParty_Prebuilt") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Kaleido3D_SOURCE_DIR}/../Project") +set(CMAKE_FIND_ROOT_PATH "${K3D_THIRD_PARTY};${CMAKE_FIND_ROOT_PATH}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${Kaleido3D_ROOT_DIR}/Binary/") -#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${Kaleido3D_ROOT_DIR}/Binary/") -set(K3D_THIRD_PARTY "${Kaleido3D_ROOT_DIR}/Source/ThirdParty_Prebuilt") -include(${Kaleido3D_ROOT_DIR}/Project/Platform.cmake) -include(${Kaleido3D_ROOT_DIR}/Project/FindThirdParty.cmake) +include(Util) +include(Platform) +include(Compiler) +include(Common) +include(NDKStlConfig) find_package(ThirdParty) option(BUILD_SHARED "Build runtime library as shared libs" ON) -option(BUILD_WITH_TBB "Build With Intel ThreadingBlocks" OFF) option(BUILD_WITH_EDITOR "Build With Editor" OFF) option(BUILD_WITH_D3D12 "Build With D3D12 RHI" OFF) option(BUILD_WITH_V8 "Build With V8 Script Module" OFF) - -include(${Kaleido3D_ROOT_DIR}/Project/Common.cmake) +option(BUILD_WITH_UNIT_TEST "Build With Unit Test" ON) +option(ENABLE_SHAREDPTR_TRACK "Enable SharedPtr Track" ON) if(IOS OR MACOS) set(LIB_DIR @loader_path/../Frameworks) @@ -35,13 +37,16 @@ set(LIB_TYPE STATIC) if(BUILD_SHARED) add_definitions(-DLIB_BUILD) add_definitions(-DBUILD_SHARED_CORE) + add_definitions(-DBUILD_STATIC_PLUGIN=0) set(LIB_TYPE SHARED) - message("----- All runtime lib will be built as shared library. \n\tLIB_BUILD defines,\n\tBUILD_SHARED_CORE defines") + message("----- All runtime lib will be built as shared library. \n\t${Yellow}LIB_BUILD${ColourReset} defines,\n\t${Red}BUILD_SHARED_CORE${ColourReset} defines") +else() + add_definitions(-DBUILD_STATIC_PLUGIN=1) + message("----- All runtime lib will be built as static library. \n\t${Yellow}BUILD_STATIC_PLUGIN=1${ColourReset}") endif() -if(BUILD_WITH_TBB) - add_definitions(-DUSE_TBB_MALLOC) - include_directories(${TBB_INCLUDE_DIR}) +if(ENABLE_SHAREDPTR_TRACK) + add_definitions(-DENABLE_SHAREDPTR_TRACKER=1) endif() message(STATUS "compiler is ${CMAKE_CXX_COMPILER_ID}" ) @@ -90,12 +95,7 @@ include_directories( ../Include ) -include(${Kaleido3D_ROOT_DIR}/Project/pch.cmake) - if(ANDROID) - include(${Kaleido3D_ROOT_DIR}/Project/NDKStlConfig.cmake) - include(${Kaleido3D_ROOT_DIR}/Project/FindVulkanSDK.cmake) - find_package(VulkanSDK) if(VULKANSDK_FOUND) add_definitions(-DUSEVULKANSDK) include_directories(${VULKANSDK_INCLUDE_DIR}) @@ -103,29 +103,14 @@ if(ANDROID) endif() if(WIN32) - set(TBB_INSTALL_DIR ${K3D_THIRD_PARTY}/tbb43_20150424) - #include(${Kaleido3D_ROOT_DIR}/Project/FindVulkanSDK.cmake) - include(${Kaleido3D_ROOT_DIR}/Project/FindMaya.cmake) - #include(${Kaleido3D_ROOT_DIR}/Project/FindTBB.cmake) - #include(${Kaleido3D_ROOT_DIR}/Project/FindDXSDK.cmake) - #include(${Kaleido3D_ROOT_DIR}/Project/FindV8.cmake) - #include(${Kaleido3D_ROOT_DIR}/Project/FindLua.cmake) - #include(${Kaleido3D_ROOT_DIR}/Project/FindFreeType.cmake) find_package(OpenGL) find_package(Maya) - #find_package(TBB) - #find_package(V8) - #find_package(Lua) - #find_package(DXSDK) - #find_package(FreeType) - #find_package(VulkanSDK) if(VULKANSDK_FOUND) include_directories(${VULKANSDK_INCLUDE_DIR}) endif() endif() if(MACOS) - include(${Kaleido3D_ROOT_DIR}/Project/FindMaya.cmake) find_package(Maya) endif() @@ -146,13 +131,6 @@ if(MAYA_FOUND) endif() add_subdirectory(Tools/ShaderGen) -#add_subdirectory(ThirdParty/glslang) -#add_subdirectory(ThirdParty/spir2cross) - -#add_subdirectory(ThirdParty/EASTL) - -add_subdirectory(UnitTest) -#add_subdirectory(Example) if(BUILD_WITH_EDITOR) set(CMAKE_AUTOMOC ON) @@ -162,5 +140,3 @@ if(BUILD_WITH_EDITOR) find_package(Qt5 COMPONENTS Core Widgets REQUIRED) add_subdirectory(Tools/Editor) endif() - -#file(copy ${K3D_THIRD_PARTY}/v8-5.5.1/vs2015/debug_x64/* DESTINATION Binary/Debug) diff --git a/Source/Core/App.cpp b/Source/Core/App.cpp index 1a1cfcb..9e89e08 100755 --- a/Source/Core/App.cpp +++ b/Source/Core/App.cpp @@ -1,6 +1,7 @@ #include "Kaleido3D.h" #include "App.h" #include "Message.h" +#include "LogUtil.h" namespace k3d { @@ -41,6 +42,7 @@ namespace k3d void App::OnDestroy() { + KLOG(Info, App, "Super::OnDestroy.."); } AppStatus App::Run() { @@ -222,6 +224,9 @@ namespace k3d lEnvVars[Environment::ENV_KEY_APP_NAME] = exeFilePath.substr(0, nPos - 4); } lEnvVars[Environment::ENV_KEY_LOG_DIR] = lEnvVars[Environment::ENV_KEY_MODULE_DIR]; +#elif K3DPLATFORM_OS_IOS + lEnvVars[Environment::ENV_KEY_MODULE_DIR] = KT("./"); + //lEnvVars[Environment::ENV_KEY_LOG_DIR] = KT("./"); #endif } diff --git a/Source/Core/App.h b/Source/Core/App.h index 2cd900e..076819e 100755 --- a/Source/Core/App.h +++ b/Source/Core/App.h @@ -114,6 +114,26 @@ namespace k3d className app(#className); \ return ::k3d::RunApplication(app, #className); \ } +#elif K3DPLATFORM_OS_IOS +#import +@interface AppDelegate : UIResponder +{ + k3d::App * m_App; +} +@end + +k3d::App * __entry_ios_main__(); + +#define K3D_APP_MAIN(className) \ +int main(int argc, char *argv[]) \ +{\ +@autoreleasepool {\ + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\ +}}\ +k3d::App * __entry_ios_main__()\ +{\ +return new className(#className);\ +} #elif K3DPLATFORM_OS_WIN #define K3D_APP_MAIN(className) \ diff --git a/Source/Core/Archive.cpp b/Source/Core/Archive.cpp deleted file mode 100755 index 69a924b..0000000 --- a/Source/Core/Archive.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "Kaleido3D.h" -#include "Archive.h" - - -#if 0 -kMemoryArchiveReader::kMemoryArchiveReader(const kByte *data) -{ - -} - -kMemoryArchiveReader::~kMemoryArchiveReader() -{ - -} - - -kMemoryArchiveWriter::kMemoryArchiveWriter(kByte *data, int dataLen) - : m_DataArchive(nullptr) - , m_DataLength(0) -{ - m_DataArchive = data; - m_DataLength = dataLen; -} - -kMemoryArchiveWriter::~kMemoryArchiveWriter() -{ - if(m_DataArchive) { - ::free(data); - m_DataArchive = nullptr; - m_DataLength = 0; - } -} - -void kMemoryArchiveWriter::WriteToFile(const char *fileName) -{ - assert( fileName && m_DataArchive && m_DataLength > 0); -} -#endif diff --git a/Source/Core/Archive.h b/Source/Core/Archive.h deleted file mode 100755 index e6194c4..0000000 --- a/Source/Core/Archive.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#define ARCHIVEEXTENSION ".k3darch"; - -namespace k3d -{ - enum ArchiveVersion - { - VER_2014_4 = 0x201404 - }; - - struct ArchHeader - { - uint32 Version; - }; - - enum ArchiveChunkType - { - CHUNK_MESH, - CHUNK_PHYSICPROXY, - CHUNK_MATERIAL, - CHUNK_SHADER, - CHUNK_GLFX, - CHUNK_TEXTURE, - CHUNK_TERRIAN, - CHUNK_JSON, - CHUNK_UNKNOWN - }; - - struct ArchClassChunk { - char ClassName[64]; - uint32 ClassInternalSize; - }; - - struct ArchChunkTag - { - uint32 ChunkType; - uint32 ChunkSize; - }; -} - - -#if 0 -class kMemoryArchiveReader : public Archive { -public: - explicit kMemoryArchiveReader(const kByte *data); - virtual ~kMemoryArchiveReader(); - -private: - kByte *m_DataArchive; -}; - - -class kMemoryArchiveWriter : public Archive { -public: - explicit kMemoryArchiveWriter(kByte *data, int dataLen); - virtual ~kMemoryArchiveWriter(); - - void WriteToFile(const char * fileName); - -private: - uint32 m_DataLength; - kByte* m_DataArchive; -}; -#endif diff --git a/Source/Core/AssetManager.cpp b/Source/Core/AssetManager.cpp index 41e506f..b9816ce 100755 --- a/Source/Core/AssetManager.cpp +++ b/Source/Core/AssetManager.cpp @@ -4,7 +4,6 @@ #include "Core/LogUtil.h" #include "ImageData.h" #include "App.h" -#include "Variant.h" #include "ObjectMesh.h" #ifdef USE_TBB_MALLOC diff --git a/Source/Core/AssetManager.h b/Source/Core/AssetManager.h index 4646b07..43cf9d1 100755 --- a/Source/Core/AssetManager.h +++ b/Source/Core/AssetManager.h @@ -4,11 +4,12 @@ #include #include -#include + +#include "MeshData.h" + #include #include - namespace k3d { class ImageData; diff --git a/Source/Core/Bundle.cpp b/Source/Core/Bundle.cpp index 10dd24b..7115ad9 100755 --- a/Source/Core/Bundle.cpp +++ b/Source/Core/Bundle.cpp @@ -3,7 +3,6 @@ #include "MeshData.h" #include "CameraData.h" #include "ImageData.h" -#include "Archive.h" #include "Os.h" #include "LogUtil.h" #include "Utils/StringUtils.h" diff --git a/Source/Core/Bundle.h b/Source/Core/Bundle.h index 1bcb35f..dfa2e2b 100755 --- a/Source/Core/Bundle.h +++ b/Source/Core/Bundle.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace k3d { enum class EAssetVersion : uint64 diff --git a/Source/Core/CMakeLists.txt b/Source/Core/CMakeLists.txt index 9f734ac..937a75e 100755 --- a/Source/Core/CMakeLists.txt +++ b/Source/Core/CMakeLists.txt @@ -1,8 +1,6 @@ include_directories(.. ../../Include) -add_definitions(-DBUILD_SHARED_LIB) - -set(SRC_ASSETMANAGER AssetManager.h AssetManager.cpp Bundle.h Bundle.cpp Archive.h Archive.cpp) +set(SRC_ASSETMANAGER AssetManager.h AssetManager.cpp Bundle.h Bundle.cpp) set(SRC_CAMERA CameraData.h CameraData.cpp) set(SRC_MESH MeshData.h MeshData.cpp ObjectMesh.h ObjectMesh.cpp RiggedMeshData.h RiggedMeshData.cpp) set(SRC_IMAGE ImageData.h ImageData.cpp) @@ -57,7 +55,6 @@ source_group("XPlatform\\Message" FILES ${MSG_SRCS}) set(COMMON_SRCS Timer.h Timer.cpp - Variant.h Os.h Os.cpp WebSocket.h @@ -68,8 +65,7 @@ set(COMMON_SRCS App.h App.cpp AllocatorImpl.cpp - String.h - String.cpp + StringImpl.cpp ) source_group(XPlatform FILES ${COMMON_SRCS}) @@ -85,27 +81,66 @@ elseif(ANDROID) file(GLOB ANDROID_SRCS "../Platform/Android/cpp/*.cpp" "../Platform/Android/cpp/*.h") source_group("XPlatform\\Android" FILES ${ANDROID_SRCS}) set(CORE_SRCS ${CORE_SRCS} ${ANDROID_SRCS}) + list(APPEND CORE_DEP_LIBS log android) elseif(IOS) - file(GLOB IOS_IMPL_SRCS "iOS/*.h" "iOS/*.mm") + #file(GLOB IOS_IMPL_SRCS "../Platform/Apple/iOS/*.mm" "../Platform/Apple/iOS/*.h") + set(IOS_IMPL_SRCS "../Platform/Apple/iOS/Window.mm" "../Platform/Apple/CpuUsage.mm") source_group("XPlatform\\iOS" FILES ${IOS_IMPL_SRCS}) set(CORE_SRCS ${CORE_SRCS} ${IOS_IMPL_SRCS}) + list(APPEND CORE_DEP_LIBS "-framework Foundation" "-framework UIKit" "-framework QuartzCore") elseif(MACOS) file(GLOB OSX_IMPL_SRCS "../Platform/Apple/MacOS/*.mm" "../Platform/Apple/MacOS/*.h") + list(APPEND OSX_IMPL_SRCS "../Platform/Apple/CpuUsage.mm") source_group("XPlatform\\OSX" FILES ${OSX_IMPL_SRCS}) set(CORE_SRCS ${CORE_SRCS} ${OSX_IMPL_SRCS}) + list(APPEND CORE_DEP_LIBS "-framework Cocoa" "-framework AppKit" "-framework QuartzCore" "-framework CoreData" "-framework Foundation") endif() -add_library(Core ${LIB_TYPE} ${CORE_SRCS}) +k3d_add_lib(Core SRCS ${CORE_SRCS} LIBS ${CORE_DEP_LIBS} FOLDER "Runtime") if(WIN32) - install(TARGETS Core ARCHIVE DESTINATION lib) add_precompiled_header(Core "Kaleido3D.h" "${Kaleido3D_ROOT_DIR}/Include" "${Kaleido3D_ROOT_DIR}/Source/Core/App.cpp") -elseif(ANDROID) - target_link_libraries(Core log android) elseif(MACOS) - target_link_libraries(Core "-framework Cocoa" "-framework AppKit" "-framework QuartzCore" "-framework CoreData" "-framework Foundation") - add_custom_command(TARGET Core POST_BUILD COMMAND - ${CMAKE_INSTALL_NAME_TOOL} -id "@loader_path/../Frameworks/libCore.dylib" $) + if(BUILD_SHARED) + add_custom_command(TARGET Core POST_BUILD COMMAND + ${CMAKE_INSTALL_NAME_TOOL} -id "@loader_path/../Frameworks/libCore.dylib" $) + endif() endif() -set_target_properties(Core PROPERTIES FOLDER "Runtime") +install(TARGETS Core + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DESTINATION include/kaleido3d + FILES_MATCHING PATTERN "*.h" +) + +install(FILES ${Kaleido3D_ROOT_DIR}/Include/Kaleido3D.h + DESTINATION include/kaleido3d +) + +install(DIRECTORY ${Kaleido3D_ROOT_DIR}/Include/KTL + DESTINATION include/kaleido3d + FILES_MATCHING PATTERN "*.hpp" +) + +install(DIRECTORY ${Kaleido3D_ROOT_DIR}/Include/Math + DESTINATION include/kaleido3d + FILES_MATCHING PATTERN "*.hpp" +) + +install(DIRECTORY ${Kaleido3D_ROOT_DIR}/Include/Interface + DESTINATION include/kaleido3d + FILES_MATCHING PATTERN "*.h" +) + +install(DIRECTORY ${Kaleido3D_ROOT_DIR}/Include/Config + DESTINATION include/kaleido3d + FILES_MATCHING PATTERN "*.h" +) + +if(BUILD_WITH_UNIT_TEST) + add_subdirectory(UnitTest) +endif() \ No newline at end of file diff --git a/Source/Core/CameraData.cpp b/Source/Core/CameraData.cpp index 28e35cf..7f0aeaa 100755 --- a/Source/Core/CameraData.cpp +++ b/Source/Core/CameraData.cpp @@ -1,6 +1,5 @@ #include "Kaleido3D.h" #include "CameraData.h" -#include "Archive.h" namespace k3d { diff --git a/Source/Core/CameraData.h b/Source/Core/CameraData.h index 7dbadc5..bb121c6 100755 --- a/Source/Core/CameraData.h +++ b/Source/Core/CameraData.h @@ -3,6 +3,7 @@ #include "Bundle.h" #include #include +#include namespace k3d { diff --git a/Source/Core/Dispatch/WorkQueue.h b/Source/Core/Dispatch/WorkQueue.h index 96f3157..2d5ff2b 100755 --- a/Source/Core/Dispatch/WorkQueue.h +++ b/Source/Core/Dispatch/WorkQueue.h @@ -3,7 +3,6 @@ #include #include #include "../Os.h" -#include namespace Dispatch { diff --git a/Source/Core/InputDevice.cpp b/Source/Core/InputDevice.cpp index dd68ef8..af3a292 100755 --- a/Source/Core/InputDevice.cpp +++ b/Source/Core/InputDevice.cpp @@ -11,7 +11,7 @@ namespace k3d { bool Mouse::IsButtonPressed(Button button) { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::isMouseButtonPressed(button); #else return true; @@ -20,7 +20,7 @@ namespace k3d Mouse::Vector2i Mouse::GetPosition() { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::getMousePosition(); #else return Mouse::Vector2i(); @@ -29,7 +29,7 @@ namespace k3d Mouse::Vector2i Mouse::GetPosition(const IWindow& relativeTo) { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::getMousePosition(relativeTo); #else return Mouse::Vector2i(); @@ -38,21 +38,21 @@ namespace k3d void Mouse::SetPosition(const Mouse::Vector2i& position) { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::setMousePosition(position); #endif } void Mouse::SetPosition(const Mouse::Vector2i& position, const IWindow& relativeTo) { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::setMousePosition(position, relativeTo); #endif } bool Keyboard::IsKeyPressed(Key key) { -#ifndef K3DPLATFORM_OS_MAC +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID return InputDeviceImpl::isKeyPressed(key); #else return true; diff --git a/Source/Core/InputDevice.h b/Source/Core/InputDevice.h index bcf4fcb..72b1d39 100755 --- a/Source/Core/InputDevice.h +++ b/Source/Core/InputDevice.h @@ -1,8 +1,11 @@ #ifndef __InputDevice_h__ #define __InputDevice_h__ #pragma once + #include "Window.h" + #include + namespace k3d { class Mouse diff --git a/Source/Core/LogUtil.cpp b/Source/Core/LogUtil.cpp index 9c3ff29..1e05740 100755 --- a/Source/Core/LogUtil.cpp +++ b/Source/Core/LogUtil.cpp @@ -4,13 +4,14 @@ #include #include #include +#include "Log/Public/ILogModule.h" #include "../../Data/style.css.h" namespace k3d { void Log(ELogLevel const & Lv, const char * tag, const char * fmt, ...) { - static thread_local char dbgStr[2048] = { 0 }; + static /*thread_local*/ char dbgStr[2048] = { 0 }; va_list va; va_start(va, fmt); #if K3DPLATFORM_OS_ANDROID @@ -20,7 +21,7 @@ namespace k3d #endif va_end(va); - k3d::ILogModule* logModule = (k3d::ILogModule*)GlobalModuleManager.FindModule("KawaLog"); + auto logModule = StaticPointerCast(GlobalModuleManager.FindModule("KawaLog")); if (logModule) { int logType = (int)ELoggerType::EConsole; diff --git a/Source/Core/LogUtil.h b/Source/Core/LogUtil.h index 99ea4ac..e7a31cd 100755 --- a/Source/Core/LogUtil.h +++ b/Source/Core/LogUtil.h @@ -2,8 +2,10 @@ #ifndef __LogUtil_h__ #define __LogUtil_h__ #include "Utils/StringUtils.h" + #include -#include +#include + #include "Os.h" namespace k3d diff --git a/Source/Core/LogUtil.inl b/Source/Core/LogUtil.inl deleted file mode 100755 index 6f70f09..0000000 --- a/Source/Core/LogUtil.inl +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/Source/Core/Looper.h b/Source/Core/Looper.h index cf1073f..78af73c 100755 --- a/Source/Core/Looper.h +++ b/Source/Core/Looper.h @@ -4,6 +4,7 @@ #include #include #include + #include "Os.h" namespace k3d { diff --git a/Source/Core/MeshData.cpp b/Source/Core/MeshData.cpp index 6d26014..9e4b546 100755 --- a/Source/Core/MeshData.cpp +++ b/Source/Core/MeshData.cpp @@ -1,6 +1,5 @@ #include "Kaleido3D.h" #include "MeshData.h" -#include "Archive.h" #include #include diff --git a/Source/Core/MeshData.h b/Source/Core/MeshData.h index 338384c..0467f48 100755 --- a/Source/Core/MeshData.h +++ b/Source/Core/MeshData.h @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -72,9 +71,7 @@ namespace k3d }; - class K3D_API MeshData : - public IMesh, - public IReflectable { + class K3D_API MeshData : public IMesh { public: MeshData(); @@ -110,8 +107,6 @@ namespace k3d void SetVertexBuffer(void* dataPtr); void SetVertexNum(int num) { m_NumVertices = num; } - MeshData * Reflect() override { return new MeshData; } - std::string DumpMeshInfo() { std::ostringstream meshInfo; diff --git a/Source/Core/Message.h b/Source/Core/Message.h index e4c6969..d0617bc 100755 --- a/Source/Core/Message.h +++ b/Source/Core/Message.h @@ -3,8 +3,8 @@ #define __Message_h__ #include "InputDevice.h" -namespace k3d { - +namespace k3d +{ class Message final { public: diff --git a/Source/Core/Module.cpp b/Source/Core/Module.cpp index 8caf2df..c339c56 100755 --- a/Source/Core/Module.cpp +++ b/Source/Core/Module.cpp @@ -2,6 +2,8 @@ #include "Module.h" #include "App.h" #include "Os.h" +#include "LogUtil.h" +#include #include #include #include @@ -11,86 +13,125 @@ namespace k3d { typedef IModule * (*PFN_GetModule)(); + class ModuleManagerPrivate + { + public: #if K3DPLATFORM_OS_WIN - std::list > g_ModuleList; + std::list > g_ModuleList; + std::unordered_map g_Win32ModuleMap; #endif + std::unordered_map g_ModuleMap; + mutable bool g_IsInited = false; + }; ModuleManager GlobalModuleManager; - static std::unordered_map g_ModuleMap; - -#if K3DPLATFORM_OS_WIN - static std::unordered_map g_Win32ModuleMap; -#endif ModuleManager::~ModuleManager() { - //g_ModuleMap.clear(); TODO crash + KLOG(Info, ModuleManager, "Destroyed"); + p->g_IsInited = false; + if (!p->g_ModuleMap.empty()) + { + p->g_ModuleMap.clear(); + } + //KLOG(Info, ModuleManager, "Destroyed"); + +#if K3DPLATFORM_OS_WIN + if (!p->g_Win32ModuleMap.empty()) + { + for (auto & entry : p->g_Win32ModuleMap) + { + ::FreeLibrary(entry.second); + } + p->g_Win32ModuleMap.clear(); + } +#endif } - void ModuleManager::AddModule(const char * name, IModule * module) + void ModuleManager::AddModule(const char * name, ModuleRef module) { - g_ModuleMap[name] = module; + if (!p->g_IsInited) + return; + p->g_ModuleMap[name] = module; } void ModuleManager::RemoveModule(const char * name) { - g_ModuleMap.erase(name); + if (!p->g_IsInited) + return; + p->g_ModuleMap.erase(name); } bool ModuleManager::LoadModule(const char * moduleName) { + if (!p->g_IsInited) + return nullptr; + String entryFunction; + entryFunction.AppendSprintf("Get%sModule", moduleName); #if K3DPLATFORM_OS_WIN std::string moduleDir = "./"; HMODULE hModule = LoadLibraryA((moduleDir + moduleName + ".dll").c_str()); if (hModule) { - std::string entryName("Get"); - entryName += moduleName; - entryName += "Module"; - PFN_GetModule pFn = (PFN_GetModule)::GetProcAddress((HMODULE)hModule, entryName.c_str()); - g_Win32ModuleMap[moduleName] = hModule; - g_ModuleMap[moduleName] = pFn(); + PFN_GetModule pFn = (PFN_GetModule)::GetProcAddress((HMODULE)hModule, entryFunction.CStr()); + p->g_Win32ModuleMap[moduleName] = hModule; + p->g_ModuleMap[moduleName] = ModuleRef(pFn()); return true; } #else - std::string entryName("Get"); - entryName += moduleName; - entryName += "Module"; + +#if !K3DPLATFORM_OS_IOS kString libDir = GetEnv()->GetEnvValue(Environment::ENV_KEY_MODULE_DIR) + "/lib" + moduleName + #if K3DPLATFORM_OS_MAC ".dylib"; #else ".so"; #endif - void* handle = ::dlopen(libDir.c_str(), RTLD_LAZY); - if(handle) { - PFN_GetModule fn = (PFN_GetModule)dlsym(handle, entryName.c_str()); - if(!fn) { + if(libDir.empty()) + { + return false; + } + void* handle = ::dlopen(libDir.c_str(), RTLD_LAZY); +#else + //kString libDir = kString(moduleName) + ".framework/" + moduleName; + String libDir; + libDir.AppendSprintf("%s.framework/%s", moduleName, moduleName); + void* handle = ::dlopen(libDir.CStr(), RTLD_LAZY); +#endif + if(handle) + { + PFN_GetModule fn = (PFN_GetModule)dlsym(handle, entryFunction.CStr()); + if(!fn) + { return false; } - g_ModuleMap[moduleName] = fn(); + auto mod = fn(); + //g_ModuleMap[moduleName] = mod; + p->g_ModuleMap.insert({moduleName, ModuleRef(mod)}); return true; } #endif return false; } - IModule * ModuleManager::FindModule(const char * moduleName) + ModuleRef ModuleManager::FindModule(const char * moduleName) { - std::string mName(moduleName); - if (g_ModuleMap.find(moduleName) != g_ModuleMap.end()) + if (!p->g_IsInited) + return nullptr; + if (p->g_ModuleMap.find(moduleName) != p->g_ModuleMap.end()) { - return g_ModuleMap[mName]; + return p->g_ModuleMap[moduleName]; } else { if(LoadModule(moduleName)) - return g_ModuleMap[mName]; + return p->g_ModuleMap[moduleName]; } return nullptr; } - ModuleManager::ModuleManager() + ModuleManager::ModuleManager() : p(new ModuleManagerPrivate) { + p->g_IsInited = true; } } diff --git a/Source/Core/Module.h b/Source/Core/Module.h index 695f815..c099566 100755 --- a/Source/Core/Module.h +++ b/Source/Core/Module.h @@ -1,74 +1,29 @@ #ifndef __Module_h__ #define __Module_h__ -#if K3DPLATFORM_OS_WIN -#define PLUGIN_API_DECLARE __declspec(dllexport) -#else -#define PLUGIN_API_DECLARE -#endif - -#ifdef BUILD_SHARED_LIB -#ifdef BUILD_WITH_PLUGIN -#if K3DPLATFORM_OS_WIN -#define CORE_API __declspec(dllimport) -#else -#define CORE_API __attribute__((visibility("default"))) -#endif -#else -#if K3DPLATFORM_OS_WIN -#define CORE_API __declspec(dllexport) -#else -#define CORE_API __attribute__((visibility("default"))) -#endif -#endif -#else -#define CORE_API -#endif - -#define K3D_DYNAMIC_MODULE_IMPLEMENT(ModuleName, ModuleClass) \ -extern "C" PLUGIN_API_DECLARE ::k3d::IModule *Get##ModuleName##Module() { return new ModuleClass; } - -#define K3D_STATIC_MODULE_IMPLEMENT(ModuleName, MoudleClass) \ -class MoudleName##StaticInitializer {\ -public:\ - MoudleName##StaticInitializer() { k3d::ModuleManager::Get().AddModule(#ModuleName, new MoudleClass); }\ - ~MoudleName##StaticInitializer() { k3d::ModuleManager::Get().RemoveModule(#ModuleName); }\ -}; \ -static MoudleName##StaticInitializer mInitializer; - -/** - * build dlls - */ -#ifdef BUILD_SHARED_CORE -#define MODULE_IMPLEMENT K3D_DYNAMIC_MODULE_IMPLEMENT -#else -#define MODULE_IMPLEMENT K3D_STATIC_MODULE_IMPLEMENT -#endif +#include namespace k3d { - class IModule - { - public: - virtual void Start() = 0; - virtual void Shutdown() = 0; - virtual const char * Name() = 0; - virtual ~IModule() {} - }; + class ModuleManagerPrivate; class CORE_API ModuleManager { public: ~ModuleManager(); - void AddModule(const char* name, IModule* module); + void AddModule(const char* name, ModuleRef module); void RemoveModule(const char * name); bool LoadModule(const char * moduleName); - IModule* FindModule(const char * moduleName); + ModuleRef FindModule(const char * moduleName); ModuleManager(); + + private: + ModuleManagerPrivate * p; }; + extern CORE_API ModuleManager GlobalModuleManager; } diff --git a/Source/Core/ObjectMesh.h b/Source/Core/ObjectMesh.h index 6881d48..27fafcf 100755 --- a/Source/Core/ObjectMesh.h +++ b/Source/Core/ObjectMesh.h @@ -1,7 +1,7 @@ #pragma once -namespace k3d { - +namespace k3d +{ struct ObjectLoadListener { virtual void OnLoad() = 0; }; diff --git a/Source/Core/Os.cpp b/Source/Core/Os.cpp index 9fb24a8..7323db2 100755 --- a/Source/Core/Os.cpp +++ b/Source/Core/Os.cpp @@ -212,7 +212,7 @@ namespace Os if (m_hFile) { ::CloseHandle(m_hFile); - m_hFile = INVALID_HANDLE_VALUE; + m_hFile = NULL; } #else if (m_fd) ::close(m_fd); @@ -615,6 +615,7 @@ namespace Os Mutex::~Mutex() { delete m_Impl; + m_Impl = nullptr; } void Mutex::Lock() diff --git a/Source/Core/Os.h b/Source/Core/Os.h index eaba44a..50f9c02 100755 --- a/Source/Core/Os.h +++ b/Source/Core/Os.h @@ -3,6 +3,7 @@ #include #include + #include #include @@ -120,6 +121,7 @@ namespace Os typedef void(*PFN_FileProcessRoutine)(const ::k3d::kchar * path, bool isDir); extern K3D_API bool ListFiles(const ::k3d::kchar * srcPath, PFN_FileProcessRoutine); extern K3D_API uint32 GetCpuCoreNum(); + extern K3D_API float* GetCpuUsage(); enum class ThreadPriority { @@ -167,6 +169,7 @@ namespace Os if (m_OnwerShipGot) { delete m_Mutex; + m_Mutex = nullptr; } } private: diff --git a/Source/Core/ReflectFactory.h b/Source/Core/ReflectFactory.h index 25997d7..b106322 100755 --- a/Source/Core/ReflectFactory.h +++ b/Source/Core/ReflectFactory.h @@ -5,8 +5,8 @@ #include #include -namespace k3d { - +namespace k3d +{ class ReflectFactory : public Singleton { public: //template diff --git a/Source/Core/String.cpp b/Source/Core/String.cpp deleted file mode 100755 index d187349..0000000 --- a/Source/Core/String.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Kaleido3D.h" -#include "String.h" -#include -#include - -K3D_COMMON_NS -{ - int Vsnprintf(char*dest, int n, const char* fmt, va_list list) - { - return ::vsnprintf(dest, n, fmt, list); - } -} diff --git a/Source/Core/String.h b/Source/Core/String.h deleted file mode 100755 index 2c38a2a..0000000 --- a/Source/Core/String.h +++ /dev/null @@ -1,264 +0,0 @@ -#pragma once -#include -#include "Archive.h" - -K3D_COMMON_NS -{ -template -inline uint64 CharLength(const BaseChar* cStr) -{ - const BaseChar *eos = cStr; - while (*eos++); - return(eos - cStr - 1); -} - -extern K3D_API int Vsnprintf(char*, int n, const char* fmt, va_list); - -template -class StringBase -{ -public: - typedef BaseChar* CharPointer; - typedef const BaseChar* ConstCharPointer; - typedef StringBase ThisString; - typedef uint64 CharPosition; - - StringBase() K3D_NOEXCEPT - : m_pStringData(nullptr) - , m_StringLength(0) - , m_Capacity(0) - { - } - - StringBase(const void * pData, size_t szData) - : m_pStringData(nullptr) - , m_StringLength(0) - , m_Capacity(0) - { - uint64 calLength = szData/sizeof(BaseChar); - uint64 remain = szData%sizeof(BaseChar); - if(remain == 0) - { - m_StringLength = calLength; - m_Capacity = m_StringLength + 1; - m_pStringData = Allocate(m_Capacity); - memcpy(m_pStringData, pData, szData); - m_pStringData[m_StringLength] = 0; - } - } - - StringBase(ConstCharPointer pStr) - : m_pStringData(nullptr) - , m_StringLength(0) - , m_Capacity(0) - { - m_StringLength = CharLength(pStr); - if(m_StringLength) - { - m_Capacity = (uint64)(1.5f * m_StringLength + 0.5f); - m_pStringData = Allocate(m_Capacity); - memcpy(m_pStringData, pStr, m_StringLength * sizeof(BaseChar)); - m_pStringData[m_StringLength] = 0; - } - } - - StringBase(const ThisString & rhs) - : m_pStringData(nullptr) - , m_StringLength(0) - , m_Capacity(rhs.m_Capacity) - , m_StringAllocator(rhs.m_StringAllocator) - { - Assign(rhs); - } - - StringBase(ThisString && rhs) - : m_pStringData(nullptr) - , m_StringLength(0) - { - MoveAssign(Move(rhs)); - } - - virtual ~StringBase() - { - if (m_pStringData) - { - Deallocate(); - m_pStringData = nullptr; - m_StringLength = 0; - } - } - - uint64 Length() const { return m_StringLength; } - ConstCharPointer Data() const { return m_pStringData; } - ConstCharPointer CStr() const { return m_pStringData; } - - ThisString& operator=(const ThisString& rhs) { Assign(rhs); return *this; } - ThisString& operator=(ThisString&& rhs) { MoveAssign(Move(rhs)); return *this; } - ThisString& operator+=(const ThisString& rhs); - ThisString& AppendSprintf(const BaseChar* fmt, ...); - void Swap(ThisString& rhs); - - //CharPosition FindFirstOf(BaseChar _char); - - template - friend Archive& operator<<(Archive & ar, StringBase const& str); - - template - friend Archive& operator>>(Archive & ar, StringBase & str); - -protected: - CharPointer Allocate(uint64 stringLength); - void Deallocate(); - - void MoveAssign(ThisString && rhs); - void Assign(ThisString const& rhs); - -private: - CharPointer m_pStringData; - uint64 m_StringLength; - uint64 m_Capacity; - Allocator m_StringAllocator; -}; - -template -KFORCE_INLINE BaseChar* StringBase::Allocate(uint64 length) -{ - return reinterpret_cast(m_StringAllocator.allocate(sizeof(BaseChar)*length, 0)); -} - -template -KFORCE_INLINE void StringBase::Deallocate() -{ - m_StringAllocator.deallocate(m_pStringData, sizeof(BaseChar)*m_StringLength); -} - -template -KFORCE_INLINE void StringBase::MoveAssign(StringBase && rhs) -{ - m_pStringData = rhs.m_pStringData; - m_StringLength = rhs.m_StringLength; - m_Capacity = rhs.m_Capacity; - m_StringAllocator = Move(rhs.m_StringAllocator); - rhs.m_pStringData = nullptr; - rhs.m_StringLength = 0; - rhs.m_Capacity = 0; -} - -template -KFORCE_INLINE void StringBase::Assign(StringBase const & rhs) -{ - if (m_pStringData != rhs.m_pStringData) - { - if (m_pStringData) - { - Deallocate(); - } - m_Capacity = rhs.m_StringLength + 1; - m_pStringData = Allocate(m_Capacity); - m_StringLength = rhs.m_StringLength; - memcpy(m_pStringData, rhs.m_pStringData, rhs.m_StringLength * sizeof(BaseChar)); - m_pStringData[m_StringLength] = 0; - } -} - -template -KFORCE_INLINE StringBase& -StringBase::AppendSprintf(const BaseChar *fmt, ...) -{ - va_list va; - va_start(va, fmt); - int length = Vsnprintf(m_pStringData + m_StringLength, m_Capacity-m_StringLength, fmt, va); - va_end(va); - - auto newLen = length + m_StringLength; - if(newLen >= m_Capacity) - { - m_Capacity = (uint64)( 1.33f * newLen + 1.0f ); - BaseChar* newString = Allocate(m_Capacity); - memcpy(newString, m_pStringData, m_StringLength*sizeof(BaseChar)); - - va_list va; - va_start(va, fmt); - Vsnprintf(newString + m_StringLength, m_Capacity-m_StringLength, fmt, va); - va_end(va); - - Deallocate(); - m_pStringData = newString; - } - - m_StringLength = newLen; - - return *this; -} - -template -KFORCE_INLINE void StringBase::Swap(StringBase & rhs) -{ - BaseChar* p = rhs.m_pStringData; - rhs.m_pStringData = m_pStringData; - m_pStringData = p; - - uint64 l = rhs.m_StringLength; - rhs.m_StringLength = m_StringLength; - m_StringLength = l; -} - -template -KFORCE_INLINE StringBase& -StringBase::operator+=(StringBase const& rhs) -{ - auto rLen = rhs.m_StringLength; - auto newLen = m_StringLength + rLen; - if(newLen>=m_Capacity) - { - m_Capacity = uint64(1.5*newLen + 1); - auto pNewData = Allocate(m_Capacity); - if(m_pStringData) - { - memcpy(pNewData, m_pStringData, m_StringLength*sizeof(BaseChar)); - Deallocate(); - } - m_pStringData = pNewData; - } - memcpy(m_pStringData + m_StringLength, rhs.m_pStringData, rLen*sizeof(BaseChar)); - m_pStringData[newLen] = 0; - m_StringLength = newLen; - return *this; -} - -template -KFORCE_INLINE StringBase -operator+(StringBase const& lhs, StringBase const& rhs) -{ - StringBase ret(lhs); - ret += rhs; - return ret; -} - -template -KFORCE_INLINE bool operator==(StringBase const& lhs, StringBase const& rhs) -{ - return ((lhs.Length() == rhs.Length()) && (memcmp(lhs.Data(), rhs.Data(), lhs.Length() * sizeof(BaseChar)) == 0)); -} - -template -Archive& operator<<(Archive & ar, StringBase const& str) -{ - ar << str.m_Capacity << str.m_StringLength; - ar.ArrayIn(str.CStr(), str.Length()); - return ar; -} - -template -Archive& operator>>(Archive & ar, StringBase & str) -{ - ar >> str.m_Capacity >> str.m_StringLength; - str.m_pStringData = str.Allocate(str.m_Capacity); - ar.ArrayOut(str.m_pStringData, str.Length()); - str.m_pStringData[str.m_StringLength] = 0; - return ar; -} - -typedef StringBase String; - -} diff --git a/Source/Core/StringImpl.cpp b/Source/Core/StringImpl.cpp new file mode 100644 index 0000000..a546698 --- /dev/null +++ b/Source/Core/StringImpl.cpp @@ -0,0 +1,133 @@ +#include "Kaleido3D.h" +#include +#include +#include +#include "Utils/MD5.h" + +K3D_COMMON_NS +{ +K3D_API int Vsnprintf(char*dest, int n, const char* fmt, va_list list) +{ + return ::vsnprintf(dest, n, fmt, list); +} + +// ------------------------------------------------------------------------------------------------------------- +// Base64 +//-------------------------------------------------------------------------------------------------------------- +static const char* base64_chars = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + +K3D_API K3D_API String Base64Encode(String const & in) +{ + auto in_len = in.Length(); + auto bytes_to_encode = in.CStr(); + int reckon_len = ((4 * in_len / 3) + 3) & ~3; + String ret; + ret.Resize(reckon_len); + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (i = 0; (i <4); i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for (j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while ((i++ < 3)) + ret += '='; + + } + return ret; +} + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +static inline int find_base64char(unsigned char c) +{ + for (int i = 0; i < 64; i++) + { + if (c == base64_chars[i]) + return i; + } + return -1; +} + +K3D_API String Base64Decode(String const& encoded_string) +{ + size_t in_len = encoded_string.Length(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + String ret; + ret.Resize(encoded_string.Length()); + + while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i == 4) { + for (i = 0; i <4; i++) + char_array_4[i] = static_cast(find_base64char(char_array_4[i])); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = static_cast(find_base64char(char_array_4[j])); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + return ret; +} +// ------------------------------------------------------------------------------------------------------------- +// Base64 End +//-------------------------------------------------------------------------------------------------------------- + +K3D_API String MD5Encode(String const& in) +{ + MD5 md5; + md5.Update(in); + return md5.Str(); +} +} diff --git a/Source/Core/Timer.h b/Source/Core/Timer.h index 3f50df3..46b42b0 100755 --- a/Source/Core/Timer.h +++ b/Source/Core/Timer.h @@ -2,7 +2,8 @@ #define __k3dTimer_h__ #pragma once -namespace k3d { +namespace k3d +{ class K3D_API Timer { public: diff --git a/Source/Core/UnitTest/CMakeLists.txt b/Source/Core/UnitTest/CMakeLists.txt new file mode 100644 index 0000000..9add754 --- /dev/null +++ b/Source/Core/UnitTest/CMakeLists.txt @@ -0,0 +1,49 @@ +if(BUILD_SHARED) + add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) +endif() +################################## Unit Test For RHI ##################################### + +include_directories( + ${FREETYPE2_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_unittest( + Core-UnitTest-1.Os + UTCore.Os.cpp +) + +add_unittest( + Core-UnitTest-2.Bundle + UTCore.Bundle.cpp +) + +add_unittest( + Core-UnitTest-3.WebSocket + UTCore.WebSocket.cpp +) + +add_unittest( + Core-UnitTest-4.SharedPtr + UTKTL.SharedPtr.cpp +) + +add_unittest( + Core-UnitTest-5.DynArray + UTKTL.DynArray.cpp +) + +add_unittest( + Core-UnitTest-6.String + UTCore.String.cpp +) + +add_unittest( + Core-UnitTest-7.ShaderCompiler + UTTools.ShaderCompiler.cpp +) + +add_unittest( + Core-UnitTest-8.UTFontLoader + UTFontLoader.cpp +) \ No newline at end of file diff --git a/Source/Core/UnitTest/Common.h b/Source/Core/UnitTest/Common.h new file mode 100644 index 0000000..5317e15 --- /dev/null +++ b/Source/Core/UnitTest/Common.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include diff --git a/Source/UnitTest/Base/UTCore.Bundle.cpp b/Source/Core/UnitTest/UTCore.Bundle.cpp old mode 100755 new mode 100644 similarity index 86% rename from Source/UnitTest/Base/UTCore.Bundle.cpp rename to Source/Core/UnitTest/UTCore.Bundle.cpp index b0eb63e..3494276 --- a/Source/UnitTest/Base/UTCore.Bundle.cpp +++ b/Source/Core/UnitTest/UTCore.Bundle.cpp @@ -2,12 +2,15 @@ #include #include +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + using namespace k3d; using namespace std; -threadptr TestBundle() +void TestBundle() { - auto ret = std::make_shared([]() { Os::File file("../../Data/Test/test.bundle"); file.Open(IORead); Archive arch; @@ -50,6 +53,10 @@ threadptr TestBundle() } file.Close(); - }); - return ret; +} + +int main(int argc, char**argv) +{ + TestBundle(); + return 0; } \ No newline at end of file diff --git a/Source/Core/UnitTest/UTCore.Os.cpp b/Source/Core/UnitTest/UTCore.Os.cpp new file mode 100644 index 0000000..c324aa3 --- /dev/null +++ b/Source/Core/UnitTest/UTCore.Os.cpp @@ -0,0 +1,36 @@ +#include "Common.h" +#include +#include + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace std; +using namespace k3d; + +void TestOs() +{ + K3D_ASSERT(Os::MakeDir(KT("./TestOs"))); + K3D_ASSERT(Os::Remove(KT("./TestOs"))); + while (1) + { + Os::Sleep(1000); + int count = Os::GetCpuCoreNum(); + float * usage = Os::GetCpuUsage(); + stringstream str; + str << "usage: "; + for (int i = 0; i < count; i++) + { + str << usage[i] << ","; + } + cout << str.str() << endl; + } +} + + +int main(int argc, char**argv) +{ + TestOs(); + return 0; +} \ No newline at end of file diff --git a/Source/Core/UnitTest/UTCore.String.cpp b/Source/Core/UnitTest/UTCore.String.cpp new file mode 100644 index 0000000..7098e6b --- /dev/null +++ b/Source/Core/UnitTest/UTCore.String.cpp @@ -0,0 +1,55 @@ +#include "Common.h" +#include + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace k3d; +using namespace std; + +String toBeRemoved("Love you later."); + +void TestString() +{ + String testString("HeyYou!"); + cout << testString.CStr() << endl; + String testStringBaby("BabyGirl!!"); + testStringBaby.Swap(testString); + cout << testString.CStr() << endl; + + testString += toBeRemoved; + testString += ".."; + cout << testString.CStr() << endl; + + testString.AppendSprintf("%d %s", 5, "fhdsfjdhjkfdhksfhdkjshfjkdshfk"); + testString += 'B'; + cout << testString.CStr() << endl; + + MD5 md5; + md5.Update(testString); + auto testMd5 = md5.Str(); + cout << "md5:" << testMd5.CStr() << endl; + + cout << "md5:" << MD5Encode(testString).CStr() << endl; + + //Archive ar; + //ar << testString; + + String testMoveString(Move(toBeRemoved)); + cout << "testMove:" << testMoveString.CStr() + << " original:" << (toBeRemoved.CStr()?toBeRemoved.CStr():"null") << endl; + + auto b64 = Base64Encode(testMoveString); + cout << "b64:" << b64.CStr() << endl; + + auto d64 = Base64Decode(b64); + cout << "d64:" << d64.CStr() << endl; + +} + +int main(int argc, char**argv) +{ + TestString(); + return 0; +} \ No newline at end of file diff --git a/Source/UnitTest/Base/UTCore.WebSocket.cpp b/Source/Core/UnitTest/UTCore.WebSocket.cpp old mode 100755 new mode 100644 similarity index 75% rename from Source/UnitTest/Base/UTCore.WebSocket.cpp rename to Source/Core/UnitTest/UTCore.WebSocket.cpp index 4a2612d..d646f6a --- a/Source/UnitTest/Base/UTCore.WebSocket.cpp +++ b/Source/Core/UnitTest/UTCore.WebSocket.cpp @@ -1,6 +1,10 @@ #include "Common.h" #include -#include +#include + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif using namespace net; @@ -14,7 +18,7 @@ class TestServer : public WebSocket void BindAndListen() { Create(); - Os::IPv4Address addr(":7000"); + Os::IPv4Address addr("192.168.0.112:7000"); this->SetBlocking(true); Bind(addr); Listen(10); @@ -54,12 +58,16 @@ class TestServer : public WebSocket std::stringstream m_LogStream; }; -threadptr TestWebSocket() +void TestWebSocket() { - auto ret = std::make_shared([]() { - TestServer server; - server.BindAndListen(); + TestServer server; + server.BindAndListen(); server.Start(); - }); - return ret; } + +int main(int argc, char**argv) +{ + TestWebSocket(); + return 0; +} + diff --git a/Source/Core/UnitTest/UTFontLoader.cpp b/Source/Core/UnitTest/UTFontLoader.cpp new file mode 100644 index 0000000..ae64129 --- /dev/null +++ b/Source/Core/UnitTest/UTFontLoader.cpp @@ -0,0 +1,24 @@ +#include "Common.h" + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace k3d; +using namespace std; +using namespace render; + +void TestFontManager() +{ + FontManager fm; + fm.LoadLib("../../Data/Test/calibri.ttf"); + fm.ChangeFontSize(64); + auto quads = fm.AcquireText("FuckYou"); + quads.Count(); +} + +int main(int argc, char**argv) +{ + TestFontManager(); + return 0; +} \ No newline at end of file diff --git a/Source/Core/UnitTest/UTKTL.DynArray.cpp b/Source/Core/UnitTest/UTKTL.DynArray.cpp new file mode 100644 index 0000000..85ce16c --- /dev/null +++ b/Source/Core/UnitTest/UTKTL.DynArray.cpp @@ -0,0 +1,75 @@ +#include "Common.h" + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace std; +using namespace k3d; + +struct B +{ + B() : msg_(nullptr) + { + std::cout << "construct" << std::endl; + } + B(const char* msg) : msg_(msg) + { + std::cout << msg << std::endl; + } + + B& operator=(const B& rhs) + { + std::cout << "rhs " << rhs.msg_ + << " assigned to " << std::endl; + this->msg_ = rhs.msg_; + return *this; + } + + ~B() + { + std::cout << "deconstructB " << msg_ << std::endl; + } + const char *msg_; +}; + +void TestDynArrray() +{ + B b1{ "b1" }, b3{ "b3" }; + DynArray ints; + ints.Append(5).Append(6).Append(7).Append(0).Append(8); + std::cout << ints[3] << std::endl; + ints[3] = 0; + + std::cout << "for begin - end test start-----" << std::endl; + for (auto& iter : ints) + { + std::cout << iter << std::endl; + } + std::cout << "for begin - end test end-----" << std::endl; + + std::cout << ints[3] << std::endl; + std::cout << ints.Count() << std::endl; + { + B b2{ "b2" }; + DynArray bs; + bs.Append(b1) + .Append(std::move(b2)) + .Append(b3); + bs[2] = B("B modified"); + } + { + DynArray bs; + bs.Append(B("A1")) + .Append(B("A2")) + .Append(B("A3")) + .Append(B("A4")) + .Append(B("A5")); + } +} + +int main(int argc, char**argv) +{ + TestDynArrray(); + return 0; +} \ No newline at end of file diff --git a/Source/Core/UnitTest/UTKTL.SharedPtr.cpp b/Source/Core/UnitTest/UTKTL.SharedPtr.cpp new file mode 100644 index 0000000..d37729c --- /dev/null +++ b/Source/Core/UnitTest/UTKTL.SharedPtr.cpp @@ -0,0 +1,130 @@ +#include "Common.h" +#include +#include +#include + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace std; +using namespace k3d; + +class SharedTest +{ +public: + SharedTest() + { + + } + ~SharedTest() + { + cout << "SharedTest Destroy. " << endl; + } +}; + +class ESFT; + +class ESFTChild1 +{ +public: + ESFTChild1(SharedPtr pERoot) + : Root(pERoot) + { + cout << "ESFTChild1 init .." << endl; +#if K3DPLATFORM_OS_WIN + OutputDebugStringA("ESFTChild1 init ..\n"); +#endif + } + ~ESFTChild1() + { + cout << "ESFTChild1 release .." << endl; +#if K3DPLATFORM_OS_WIN + OutputDebugStringA("ESFTChild1 release ..\n"); +#endif + } + SharedPtr Root; +}; + +class Root +{ +public: + static DynArray< SharedPtr< ESFT > > root; + static DynArray< SharedPtr > childrenTracker; +}; + +DynArray< SharedPtr< ESFT > > Root::root; +DynArray< SharedPtr > Root::childrenTracker; + +class ESFT : public EnableSharedFromThis +{ +public: + ESFT() + { +#if K3DPLATFORM_OS_WIN + OutputDebugStringA ("ESFT init ..\n"); +#endif + } + ~ESFT() + { +#if K3DPLATFORM_OS_WIN + OutputDebugStringA("ESFT release ..\n"); +#endif + cout << "ESFT release .." << endl; + } + SharedPtr NewChild1() + { + auto child = MakeShared(SharedFromThis()); + Root::childrenTracker.Append(child); + return child; + } +}; + +void TestSharedPtr() +{ + SharedPtr spFile(new Os::File); + cout << "file:" << spFile.UseCount() << endl; + + SharedPtr spCam(new CameraData); + spCam.UseCount(); + spCam->SetName("TestSharedPtr"); + + SharedPtr spTest(new SharedTest); + cout << "SharedTest:" << spTest.UseCount() << endl; + + SharedPtr ioFile = spFile; + K3D_ASSERT(ioFile.UseCount()==2); + + { + WeakPtr weakRef(ioFile); + cout << "weakREf:" << ioFile.UseCount() << endl; + } + + auto makeShared = MakeShared(); + makeShared->Open(KT("TestSharedPtr"), IOWrite); + + auto esft = MakeShared(); + Root::root. Append (esft); + { + auto child = esft->NewChild1(); + } + auto child2 = esft->NewChild1(); + auto refMakeShared = makeShared; + cout << "refMakeShared:" << refMakeShared.UseCount() << endl; + + refMakeShared->Close(); +} + +int atexit(void) +{ +#if K3DPLATFORM_OS_WIN + OutputDebugStringA("At Exit ..\n"); +#endif + return 0; +} + +int main(int argc, char**argv) +{ + TestSharedPtr(); + return 0; +} diff --git a/Source/Core/UnitTest/UTTools.ShaderCompiler.cpp b/Source/Core/UnitTest/UTTools.ShaderCompiler.cpp new file mode 100644 index 0000000..1463766 --- /dev/null +++ b/Source/Core/UnitTest/UTTools.ShaderCompiler.cpp @@ -0,0 +1,94 @@ +#include "Common.h" +#include +#include + +#if K3DPLATFORM_OS_WIN +#pragma comment(linker,"/subsystem:console") +#endif + +using namespace std; +using namespace k3d; + +void TestShaderCompiler() +{ + Os::MemMapFile vShFile; + vShFile.Open("../../Data/Test/testCompiler.glsl", IOFlag::IORead); + String vertexSource((const char*)vShFile.FileData()); + vShFile.Close(); + + auto shMod = StaticPointerCast(GlobalModuleManager.FindModule("ShaderCompiler")); + if (shMod) + { + // test compile + SharedPtr vkCompiler = shMod->CreateShaderCompiler(rhi::ERHI_Vulkan); + if (vkCompiler) + { + rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; + rhi::ShaderBundle bundle; + auto ret = vkCompiler->Compile(vertexSource, desc, bundle); + K3D_ASSERT(ret == rhi::shc::E_Ok); + + // test shader serialize + Os::File shBundle; + shBundle.Open(KT("shaderbundle.sh"), IOWrite); + Archive ar; + ar.SetIODevice(&shBundle); + ar << bundle; + shBundle.Close(); + + // write spirv to file + Os::File spirvFile; + spirvFile.Open(KT("triangle.spv"), IOWrite); + spirvFile.Write(bundle.RawData.Data(), bundle.RawData.Length()); + spirvFile.Close(); + + // test shader deserialize; + Os::File shBundleRead; + rhi::ShaderBundle bundleRead; + shBundleRead.Open(KT("shaderbundle.sh"), IORead); + Archive readar; + readar.SetIODevice(&shBundleRead); + readar >> bundleRead; + shBundleRead.Close(); + + // test hlsl compile + rhi::ShaderBundle hlslBundle; + Os::MemMapFile hlslVertFile; + hlslVertFile.Open("../../Data/Test/TestMaterial.hlsl", IOFlag::IORead); + rhi::ShaderDesc hlsldesc = { rhi::EShFmt_Text, rhi::EShLang_HLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; + auto hlslret = vkCompiler->Compile(String((const char*)hlslVertFile.FileData()), hlsldesc, hlslBundle); + K3D_ASSERT(hlslret == rhi::shc::E_Ok); + + // test spirv reflect + Os::MemMapFile spirvFileRead; + rhi::ShaderBundle spirvBundle; + spirvFileRead.Open(KT("triangle.spv"), IORead); + rhi::ShaderDesc spirvDesc = { rhi::EShFmt_ByteCode, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; + auto spirvRet = vkCompiler->Compile(String(spirvFileRead.FileData(), spirvFileRead.GetSize()), spirvDesc, spirvBundle); + K3D_ASSERT(spirvRet == rhi::shc::E_Ok); + } + + SharedPtr mtlCompiler = shMod->CreateShaderCompiler(rhi::ERHI_Metal); + if(mtlCompiler) + { + rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; + rhi::ShaderBundle bundle; + auto ret = mtlCompiler->Compile(vertexSource, desc, bundle); + K3D_ASSERT(ret == rhi::shc::E_Ok); + + // test shader serialize + Os::File shBundle; + shBundle.Open(KT("metalshaderbundle.sh"), IOWrite); + Archive ar; + ar.SetIODevice(&shBundle); + ar << bundle; + shBundle.Close(); + } + } +} + +int main(int argc, char**argv) +{ + TestShaderCompiler(); + return 0; +} \ No newline at end of file diff --git a/Source/Core/Utils/MD5.cpp b/Source/Core/Utils/MD5.cpp index 267e42a..99b767d 100755 --- a/Source/Core/Utils/MD5.cpp +++ b/Source/Core/Utils/MD5.cpp @@ -1,8 +1,10 @@ #include "Kaleido3D.h" #include "MD5.h" - +#ifndef DISABLE_STL using namespace std; +#endif // !DISABLE_STL + /* Constants for MD5Transform routine. */ #define S11 7 @@ -79,6 +81,7 @@ MD5::MD5(const void* input, size_t length) { update(input, length); } +#ifndef DISABLE_STL /* Construct a MD5 object with a string. */ MD5::MD5(const string& str) { reset(); @@ -90,6 +93,7 @@ MD5::MD5(ifstream& in) { reset(); update(in); } +#endif /* Return the message-digest */ const byte* MD5::digest() { @@ -119,6 +123,7 @@ void MD5::update(const void* input, size_t length) { update((const byte*)input, length); } +#ifndef DISABLE_STL /* Updating the context with a string. */ void MD5::update(const string& str) { update((const byte*)str.c_str(), str.length()); @@ -142,6 +147,7 @@ void MD5::update(ifstream& in) { } in.close(); } +#endif /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the @@ -326,9 +332,9 @@ void MD5::decode(const byte* input, uint32* output, size_t length) { } } +#ifndef DISABLE_STL /* Convert byte array to hex string. */ string MD5::bytesToHexString(const byte* input, size_t length) { - string str; str.reserve(length << 1); for (size_t i = 0; i < length; ++i) { @@ -344,4 +350,24 @@ string MD5::bytesToHexString(const byte* input, size_t length) { /* Convert digest to string value */ string MD5::toString() { return bytesToHexString(digest(), 16); +} +#endif + +k3d::String MD5::Str() +{ + k3d::String str; + str.Resize(32); + for (size_t i = 0; i < 16; ++i) { + int t = digest()[i]; + int a = t / 16; + int b = t % 16; + str += HEX[a]; + str += HEX[b]; + } + return str; +} + +void MD5::Update(const k3d::String & str) +{ + update((const byte*)str.CStr(), str.Length()); } \ No newline at end of file diff --git a/Source/Core/Utils/MD5.h b/Source/Core/Utils/MD5.h index 10b06a8..bf3ed0b 100755 --- a/Source/Core/Utils/MD5.h +++ b/Source/Core/Utils/MD5.h @@ -1,27 +1,36 @@ #pragma once +#ifndef DISABLE_STL #include #include +#endif + +#include /* Type define */ typedef unsigned char byte; typedef unsigned int uint32; -using std::string; -using std::ifstream; - /* MD5 declaration. */ -class K3D_API MD5 { +class K3D_API MD5 +{ public: MD5(); MD5(const void* input, size_t length); - MD5(const string& str); - MD5(ifstream& in); void update(const void* input, size_t length); - void update(const string& str); - void update(ifstream& in); + +#ifndef DISABLE_STL + MD5(const std::string& str); + MD5(std::ifstream& in); + void update(const std::string& str); + void update(std::ifstream& in); + std::string toString(); +#endif + void Update(const k3d::String& str); + + k3d::String Str(); + const byte* digest(); - string toString(); void reset(); private: @@ -30,7 +39,10 @@ class K3D_API MD5 { void transform(const byte block[64]); void encode(const uint32* input, byte* output, size_t length); void decode(const byte* input, uint32* output, size_t length); - string bytesToHexString(const byte* input, size_t length); + +#ifndef DISABLE_STL + std::string bytesToHexString(const byte* input, size_t length); +#endif /* class uncopyable */ MD5(const MD5&); diff --git a/Source/Core/Variant.h b/Source/Core/Variant.h deleted file mode 100755 index 51db399..0000000 --- a/Source/Core/Variant.h +++ /dev/null @@ -1,71 +0,0 @@ -/********************************************** -Variant is for Streamable Class -***********************************************/ -#pragma once -#ifndef __k3dVariant_h__ -#define __k3dVariant_h__ -#include -#include "Archive.h" - -namespace k3d { - /// Variant - /// \brief The Variant class - /// A class data Wrapper For all types - class Variant - { - public: - inline Variant() : m_DataSize(0), m_DataPtr(nullptr), m_isDeepCopied(false) - {} - - ~Variant() { - } - - inline void Release() { - if (m_DataSize != 0) - { - ::free(m_DataPtr); - m_DataSize = 0; - } - } - - inline void DeepCopy(void *data, int64 size, bool move = false) - { - if (m_DataPtr == nullptr) - { - m_DataPtr = malloc(size); - m_DataSize = size; - } - ::memcpy(m_DataPtr, data, size); - if (move) { - ::free(data); - } - m_isDeepCopied = true; - } - - inline Variant(void *data, int size) - { - m_DataPtr = data; m_DataSize = size; - m_isDeepCopied = false; - } - - const size_t Size() const { return m_DataSize; } - const void* ConstData() const { return static_cast(m_DataPtr); } - void* Data() { return m_DataPtr; } - - bool IsDeepCopied() const { return m_isDeepCopied; } - - typedef const char Type; - - private: - size_t m_DataSize; - void* m_DataPtr; - bool m_isDeepCopied; - }; - - inline Archive & operator << (Archive & arch, Variant const & data) { - arch.ArrayIn(static_cast(data.ConstData()), (uint32)data.Size()); - return arch; - } -} - -#endif diff --git a/Source/Core/WebSocket.h b/Source/Core/WebSocket.h index 02c737a..d801a3b 100755 --- a/Source/Core/WebSocket.h +++ b/Source/Core/WebSocket.h @@ -1,7 +1,8 @@ #ifndef __WebSocket_H__ #define __WebSocket_H__ -#include +#include "Os.h" + #include namespace net diff --git a/Source/Core/premake5.lua b/Source/Core/premake5.lua deleted file mode 100755 index 8182b72..0000000 --- a/Source/Core/premake5.lua +++ /dev/null @@ -1,38 +0,0 @@ -project "Core" - kind "StaticLib" - language "C++" - - includedirs { - "..", - "../../Include", - } - - pchheader "../../Include/Kaleido3D.h" - - defines { - "MAC_OSX=1" - } - - buildoptions "-std=c++14 -stdlib=libc++" - - files { - "App.h", - "MacOS/App.mm", - "MacOS/ModuleCore.mm", - "LogUtil.h", - "MacOS/LogUtil.mm", - "Utils/MD5.h", - "Utils/MD5.cpp", - "File.h", - "File.cpp", - "Mesh.h", - "Mesh.cpp", - "AssetManager.h", - "AssetManager.cpp", - "Image.h", - "Image.cpp", - "Window.h", - "MacOS/Window.mm", - "ModuleCore.h", - "ModuleCore.cpp" - } diff --git a/Source/Engine/CMakeLists.txt b/Source/Engine/CMakeLists.txt index 4d69e07..87f84eb 100755 --- a/Source/Engine/CMakeLists.txt +++ b/Source/Engine/CMakeLists.txt @@ -1,7 +1,4 @@ - -#if(BUILD_SHARED) - add_definitions(-DBUILD_SHARED_LIB) -#endif() +#include_directories(${RAPIDJSON_INCLUDE_DIR}) set(ENGINE_SRCS Engine.h @@ -84,20 +81,22 @@ source_group( ${PARAM_SRCS} ) -add_library( - Engine ${LIB_TYPE} +k3d_add_lib(Engine +SRCS ${CAMERA_SRCS} ${SCENE_SRCS} ${RENDERER_SRCS} ${ENGINE_SRCS} ${MAT_SRCS} - ${PARAM_SRCS} -) - -target_link_libraries( - Engine - Core -) - -set_target_properties(Engine PROPERTIES FOLDER "Runtime") -add_precompiled_header(Engine "Kaleido3D.h" "${Kaleido3D_ROOT_DIR}/Include" "${Kaleido3D_ROOT_DIR}/Source/Engine/Engine.cpp") \ No newline at end of file + ${PARAM_SRCS} +LIBS + Core +FOLDER + "Runtime") + +add_precompiled_header(Engine "Kaleido3D.h" "${Kaleido3D_ROOT_DIR}/Include" "${Kaleido3D_ROOT_DIR}/Source/Engine/Engine.cpp") + +install(TARGETS Engine + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) \ No newline at end of file diff --git a/Source/Engine/Engine.cpp b/Source/Engine/Engine.cpp index 91a9709..5272733 100755 --- a/Source/Engine/Engine.cpp +++ b/Source/Engine/Engine.cpp @@ -4,20 +4,10 @@ namespace k3d { Engine::Engine() { - pRenderer = nullptr; } Engine::~Engine() { - if (pRenderer != nullptr) { - delete pRenderer; - pRenderer = nullptr; - } - } - - void Engine::SetRenderer(IRenderer * renderer) - { - pRenderer = renderer; } void Engine::DoOnInitEngine() @@ -26,13 +16,6 @@ namespace k3d { void Engine::DoOnDrawFrame() { - assert(pRenderer != nullptr && "You should call \"SetRenderer\" method!!"); - pRenderer->PrepareFrame(); - //.... - pRenderer->DrawOneFrame(); - - //.... - pRenderer->EndOneFrame(); } diff --git a/Source/Engine/Engine.h b/Source/Engine/Engine.h index 27ee7f3..4a6aee1 100755 --- a/Source/Engine/Engine.h +++ b/Source/Engine/Engine.h @@ -1,6 +1,5 @@ #pragma once #include -#include namespace k3d { class Engine { @@ -8,8 +7,6 @@ namespace k3d { ~Engine(); - void SetRenderer(IRenderer * renderer); - void DoOnInitEngine(); void DoOnDrawFrame(); @@ -19,7 +16,6 @@ namespace k3d { Engine(); private: - IRenderer *pRenderer; - + }; } diff --git a/Source/Engine/RendererFactory.h b/Source/Engine/RendererFactory.h index 1b751d8..ff48a03 100755 --- a/Source/Engine/RendererFactory.h +++ b/Source/Engine/RendererFactory.h @@ -1,7 +1,5 @@ #pragma once -#include - namespace k3d { class IWindow; diff --git a/Source/Engine/ShaderParameter.h b/Source/Engine/ShaderParameter.h index 1d389ed..fc0483e 100755 --- a/Source/Engine/ShaderParameter.h +++ b/Source/Engine/ShaderParameter.h @@ -1,5 +1,4 @@ #pragma once -#include namespace k3d { diff --git a/Source/Log/CMakeLists.txt b/Source/Log/CMakeLists.txt index 0369c81..d265c28 100755 --- a/Source/Log/CMakeLists.txt +++ b/Source/Log/CMakeLists.txt @@ -1,6 +1,6 @@ set(MODULE_NAME KawaLog) include_directories(.. ../../Include .) -set(LOG_SRCS Public/ILog.h Public/ILogModule.h Private/LogImpl.cpp) +set(LOG_SRCS Public/ILogModule.h Private/LogImpl.cpp) source_group(Log FILES ${LOG_SRCS}) -add_plugin(KawaLog "Runtime/Plugins" ${LOG_SRCS}) +add_plugin(KawaLog FOLDER "Runtime/Plugins" SRCS ${LOG_SRCS}) add_precompiled_header(${MODULE_NAME} "Kaleido3D.h" "${Kaleido3D_ROOT_DIR}/Include" "${Kaleido3D_ROOT_DIR}/Source/Log/Private/LogImpl.cpp") \ No newline at end of file diff --git a/Source/Log/Private/LogImpl.cpp b/Source/Log/Private/LogImpl.cpp index 292eda5..777c2e9 100755 --- a/Source/Log/Private/LogImpl.cpp +++ b/Source/Log/Private/LogImpl.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include diff --git a/Source/Log/Public/ILogModule.h b/Source/Log/Public/ILogModule.h index 8c36330..c09ea9a 100755 --- a/Source/Log/Public/ILogModule.h +++ b/Source/Log/Public/ILogModule.h @@ -2,7 +2,7 @@ #define __ILogModule_h__ #include -#include "ILog.h" +#include namespace k3d { @@ -22,4 +22,7 @@ namespace k3d } +#if BUILD_STATIC_PLUGIN +K3D_STATIC_MODULE_DECLARE(KawaLog); +#endif #endif // !__ILogModule_h__ diff --git a/Source/Platform/Apple/CpuUsage.mm b/Source/Platform/Apple/CpuUsage.mm new file mode 100644 index 0000000..3ecf27a --- /dev/null +++ b/Source/Platform/Apple/CpuUsage.mm @@ -0,0 +1,88 @@ +#include "Kaleido3D.h" +#include +#include +#include +#include + +struct __CPU_Ticks +{ + uint64 usertime; + uint64 nicetime; + uint64 systemtime; + uint64 idletime; + + uint64 used() { return usertime + nicetime + systemtime; } + uint64 total() { return usertime + nicetime + systemtime + idletime; } +}; + +static k3d::DynArray usages; +static k3d::DynArray<__CPU_Ticks> ticks; +static k3d::DynArray<__CPU_Ticks> curTicks; +static int cpuCount = 0; + +int __UpdateCpuUsage(k3d::DynArray<__CPU_Ticks> & ticks) +{ + unsigned int cpu_count; + processor_cpu_load_info_t cpu_load; + mach_msg_type_number_t cpu_msg_count; + int rc = host_processor_info( + mach_host_self( ), + PROCESSOR_CPU_LOAD_INFO, + &cpu_count, + (processor_info_array_t *) &cpu_load, + &cpu_msg_count + ); + + if (rc != 0) + return 1; + + for(int core=0; core - -@interface AAPLAppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end diff --git a/Source/Platform/Apple/iOS/AAPLAppDelegate.mm b/Source/Platform/Apple/iOS/AAPLAppDelegate.mm deleted file mode 100755 index cef18cb..0000000 --- a/Source/Platform/Apple/iOS/AAPLAppDelegate.mm +++ /dev/null @@ -1,13 +0,0 @@ -/* - Copyright (C) 2015 Apple Inc. All Rights Reserved. - See LICENSE.txt for this sample’s licensing information - - Abstract: - Application delegate for Metal Sample Code - */ - -#import "AAPLAppDelegate.h" - -@implementation AAPLAppDelegate - -@end diff --git a/Source/Platform/Apple/iOS/App.mm b/Source/Platform/Apple/iOS/App.mm new file mode 100755 index 0000000..4352ee4 --- /dev/null +++ b/Source/Platform/Apple/iOS/App.mm @@ -0,0 +1,51 @@ +#include "Kaleido3D.h" +#include +#include + +@implementation AppDelegate +- (BOOL)application:(NSNotification*)notification didFinishLaunchingWithOptions:(NSDictionary*)launchOptions +{ + K3D_UNUSED(notification); + m_App = __entry_ios_main__(); + [self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0]; + return YES; +} + +- (void)applicationWillResignActive:(NSNotification*)notification +{ + K3D_UNUSED(notification); +} + +- (void)applicationDidBecomeActive:(NSNotification*)notification +{ + K3D_UNUSED(notification); + if(m_App) + { + m_App->OnInit(); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFrame) name:@"RHIRender" object:nil]; + } +} + +- (void)applicationWillTerminate:(NSNotification*)notification +{ + K3D_UNUSED(notification); + if(m_App) + { + m_App->OnDestroy(); + [[NSNotificationCenter defaultCenter] removeObserver:self]; + } + } + +- (void) onFrame +{ + if(m_App) + { + k3d::Message msg; + m_App->OnProcess(msg); + } +} + +- (void)postFinishLaunch +{ +} +@end diff --git a/Source/Platform/Apple/iOS/Info.plist b/Source/Platform/Apple/iOS/Info.plist deleted file mode 100755 index 2938aef..0000000 --- a/Source/Platform/Apple/iOS/Info.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - com.example.apple-samplecode.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - metal - armv7 - - UIRequiresFullScreen - - - diff --git a/Source/Platform/Apple/iOS/LaunchScreen.xib b/Source/Platform/Apple/iOS/LaunchScreen.xib deleted file mode 100755 index 7960e4b..0000000 --- a/Source/Platform/Apple/iOS/LaunchScreen.xib +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Source/Platform/Apple/iOS/Main.storyboard b/Source/Platform/Apple/iOS/Main.storyboard deleted file mode 100755 index 549cbbe..0000000 --- a/Source/Platform/Apple/iOS/Main.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Source/Platform/Apple/iOS/ThreadImpl.h b/Source/Platform/Apple/iOS/ThreadImpl.h deleted file mode 100755 index 30f1f65..0000000 --- a/Source/Platform/Apple/iOS/ThreadImpl.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include "../TaskManager.h" - -namespace k3d { - - namespace ThreadImpl - { - void getSysInfo(); - void createThread(IBaseThread & task, TaskPriority priority, WThread::ThreadFunctionPtr func); - void createThread(IBaseThread & task, TaskPriority priority, bool deferred, WThread::ThreadFunctionPtr func); - void sleep(uint32 milliSeconds); - void terminateThread(IBaseThread &); - void suspendThread(IBaseThread &); - void resumeThread(IBaseThread &); - } - -} \ No newline at end of file diff --git a/Source/Platform/Apple/iOS/ThreadImpl.mm b/Source/Platform/Apple/iOS/ThreadImpl.mm deleted file mode 100755 index 7697c0e..0000000 --- a/Source/Platform/Apple/iOS/ThreadImpl.mm +++ /dev/null @@ -1,58 +0,0 @@ -#include "ThreadImpl.h" - -#import - - -namespace k3d { - - namespace ThreadImpl - { - void getSysInfo() - { - - } - - void createThread(IBaseThread & task, TaskPriority priority, WThread::ThreadFunctionPtr func) - { - task.m_Handle = [[NSThread alloc] init]; - NSThread * instance = (NSThread*)task.m_Handle; - [instance setThreadPriority:0.0]; - [instance performSelector:@selector(func)]; - [instance start]; - } - - void createThread(IBaseThread & task, TaskPriority priority, bool deferred, WThread::ThreadFunctionPtr func) - { - task.m_Handle = [[NSThread alloc] init]; - NSThread * instance = (NSThread*)task.m_Handle; - [instance setThreadPriority:0.0]; - [instance performSelector:@selector(func)]; - if(!deferred) - [instance start]; - } - - void sleep(uint32 milliSeconds) - { - [NSThread sleepForTimeInterval:milliSeconds]; - } - - void suspendThread(IBaseThread & task) - { - NSThread* instance = (NSThread*)task.m_Handle; - [instance cancel]; - } - - void terminateThread(IBaseThread & task) - { - NSThread* instance = (NSThread*)task.m_Handle; - [instance cancel]; - } - - void resumeThread(IBaseThread & task) - { - NSThread* instance = (NSThread*)task.m_Handle; - [instance start]; - } - } - -} \ No newline at end of file diff --git a/Source/Platform/Apple/iOS/Window.mm b/Source/Platform/Apple/iOS/Window.mm new file mode 100755 index 0000000..6d2128c --- /dev/null +++ b/Source/Platform/Apple/iOS/Window.mm @@ -0,0 +1,165 @@ +#include "Kaleido3D.h" +#include +#include +#import +#import +#import + +@interface MetalView : UIView +@property (nonatomic) CAMetalLayer *metalLayer; +- (void) onRender; +@end + +namespace k3d +{ + namespace WindowImpl + { + class iOSWindow : public IWindow + { + public: + iOSWindow(const kchar *windowName, int width, int height); + ~iOSWindow(); + + int Init(); + void SetWindowCaption(const kchar * name) override; + void Show(WindowMode mode) override; + void Resize(int width, int height) override; + void Move(int x, int y) override; + + + bool IsOpen() override { return true;} + void* GetHandle() const override { return m_Window; }; + + bool PollMessage(Message & messge) override { return PopMessage(messge, true); }; + + uint32 Width() const override {return 0;} + uint32 Height() const override {return 0;} + + virtual void PushMessage(const Message & message); + virtual bool PopMessage(Message & message, bool block); + virtual void ProcessMessage(); + void * handle; + + private: + UIWindow* m_Window; + }; + + iOSWindow::iOSWindow(const kchar *windowName, int width, int height) + : m_Window(nil) + { + Init(); + SetWindowCaption(windowName); + Resize(width, height); + } + + iOSWindow::~iOSWindow() + { + if(nil!=m_Window) + { + [m_Window release]; + m_Window = nil; + } + } + + int iOSWindow::Init() + { + CGRect bounds = [[UIScreen mainScreen] bounds]; + UIViewController* view_controller = [[UIViewController alloc] initWithNibName:nil bundle:nil]; + // create window + UIWindow* window = [[UIWindow alloc] initWithFrame:bounds]; + MetalView * mtlView = [[MetalView alloc] initWithFrame:bounds]; [window setRootViewController:view_controller]; + [window setBackgroundColor:[UIColor blackColor]]; + [window addSubview:mtlView]; + [window makeKeyAndVisible]; + m_Window = window; + return 0; + } + + void iOSWindow::Move(int x, int y) + { + + } + + void iOSWindow::Resize(int width, int height) + { + + } + + void iOSWindow::Show(k3d::WindowMode mode) + { + + } + + void iOSWindow::SetWindowCaption(const kchar *name) + { + + } + + void iOSWindow::PushMessage(const k3d::Message &message) + { + + } + + void iOSWindow::ProcessMessage() + { + + } + + bool iOSWindow::PopMessage(k3d::Message &message, bool block) + { + return true; + } + + } + + IWindow::Ptr MakePlatformWindow(const kchar *windowName, int width, int height) + { + return std::make_shared(windowName, width, height); + } +} + +@implementation MetalView +{ + CADisplayLink *dispLink; +} +@synthesize metalLayer; + +- (BOOL) isOpaque { + return YES; +} + +- (void) onRender +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"RHIRender" object:nil]; +} + +-(instancetype) initWithFrame:(CGRect)frameRect { + self = [super initWithFrame: frameRect]; + dispLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onRender)]; + [dispLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + if (self) + { + metalLayer = (CAMetalLayer*)self.layer; + metalLayer.opaque = YES; + } + return self; +} + ++ (Class)layerClass +{ + return [CAMetalLayer class]; +} + +- (BOOL) wantsLayer { + return YES; +} + +- (BOOL) wantsUpdateLayer { + return YES; +} + +- (void)dealloc { + [dispLink invalidate]; +} + +@end diff --git a/Source/Platform/Apple/iOS/WindowImpl.h b/Source/Platform/Apple/iOS/WindowImpl.h deleted file mode 100755 index 984886f..0000000 --- a/Source/Platform/Apple/iOS/WindowImpl.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include -#include "../Message.h" - -namespace k3d -{ - enum class WindowMode; - - namespace WindowImpl - { - class WindowPrivate { - public: - WindowPrivate() = default; - - union { - HWND handle; - }; - LONG_PTR callback; - - int Init(); - void SetCaption(const char * name); - void Show(WindowMode mode); - void Resize(int width, int height); - void Move(int x, int y); - - void PushMessage(const Message & message); - bool PopMessage(Message & message, bool block); - void ProcessMessage(); - - static LRESULT CALLBACK WindowProc(HWND hwnd, UINT32 msg, WPARAM wParam, LPARAM lParam); - - protected: - void RegisterWindowClass(); - void ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); - - std::queue m_MessageQueue; - }; - - extern int InitApp(); - - extern Keyboard::Key virtualKeyCodeToSF(WPARAM key, LPARAM flags); - } - -} \ No newline at end of file diff --git a/Source/Platform/Apple/iOS/WindowImpl.mm b/Source/Platform/Apple/iOS/WindowImpl.mm deleted file mode 100755 index 4521885..0000000 --- a/Source/Platform/Apple/iOS/WindowImpl.mm +++ /dev/null @@ -1 +0,0 @@ -#include "Kaleido3D.h" \ No newline at end of file diff --git a/Source/Platform/Apple/iOS/main.m b/Source/Platform/Apple/iOS/main.m deleted file mode 100755 index a5b047c..0000000 --- a/Source/Platform/Apple/iOS/main.m +++ /dev/null @@ -1,18 +0,0 @@ -// -// main.m -// MetalTemplate -// -// Created by Filip Iliescu on 5/13/14. -// Copyright (c) 2014 Apple Inc. All rights reserved. -// - -#import - -#import "AAPLAppDelegate.h" - -int main(int argc, char * argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AAPLAppDelegate class])); - } -} diff --git a/Source/Platform/Windows/CpuUsage.cpp b/Source/Platform/Windows/CpuUsage.cpp new file mode 100644 index 0000000..bad5c91 --- /dev/null +++ b/Source/Platform/Windows/CpuUsage.cpp @@ -0,0 +1,139 @@ +#include "Kaleido3D.h" +#include + + +#include +#include +#define WIN32_NO_STATUS +#include +#include +#include + +#pragma comment(lib, "wbemuuid.lib") +#pragma comment(lib, "comsuppw.lib") + +static IWbemServices *s_service; +static IWbemLocator *s_locator; +static UINT64 *s_old_time_stamp; +static UINT64 *s_old_pproc_usage; +static UINT s_cores_count; +static float *s_cores_load_data; + +static float *__GetCpuUsage(void) +{ + HRESULT hr = NULL; + ULONG retVal; + UINT i; + + IWbemClassObject *pclassObj; + IEnumWbemClassObject *pEnumerator; + + hr = s_service->ExecQuery(bstr_t("WQL"), bstr_t("SELECT TimeStamp_Sys100NS, PercentProcessorTime, Frequency_PerfTime FROM Win32_PerfRawData_PerfOS_Processor"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); + for (i = 0; i < s_cores_count; i++) { + hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclassObj, &retVal); + if (!retVal) { + break; + } + + VARIANT vtPropTime; + VARIANT vtPropClock; + VariantInit(&vtPropTime); + VariantInit(&vtPropClock); + + hr = pclassObj->Get(L"TimeStamp_Sys100NS", 0, &vtPropTime, 0, 0); + UINT64 newTimeStamp = _wtoi64(vtPropTime.bstrVal); + + hr = pclassObj->Get(L"PercentProcessorTime", 0, &vtPropClock, 0, 0); + UINT64 newPProcUsage = _wtoi64(vtPropClock.bstrVal); + + s_cores_load_data[i] = (float)(1.0 - (((double)newPProcUsage - (double)s_old_pproc_usage[i]) / ((double)newTimeStamp - (double)s_old_time_stamp[i]))) * 100.0f; + + if (s_cores_load_data[i] < 0) s_cores_load_data[i] = 0.0; + else if (s_cores_load_data[i] > 100.0) s_cores_load_data[i] = 100.0; + + s_old_pproc_usage[i] = newPProcUsage; + s_old_time_stamp[i] = newTimeStamp; + + VariantClear(&vtPropTime); + VariantClear(&vtPropClock); + + pclassObj->Release(); + } + + pEnumerator->Release(); + return &s_cores_load_data[0]; +} + +int __Init(void) +{ + IWbemClassObject *pclassObj; + IEnumWbemClassObject *pEnumerator; + HRESULT hr; + ULONG retVal; + + s_service = NULL; + s_cores_count = 0; + + s_old_time_stamp = NULL; + s_old_pproc_usage = NULL; + s_locator = NULL; + + s_cores_load_data = NULL; + + CoInitializeEx(0, COINIT_MULTITHREADED); + CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); + + hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&s_locator); + if (FAILED(hr)) { + return 0; + } + hr = s_locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &s_service); + if (FAILED(hr)) { + return 0; + } + + CoSetProxyBlanket(s_service, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); + + hr = s_service->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Processor"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); + hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclassObj, &retVal); + if (retVal) { + VARIANT vtProp; + VariantInit(&vtProp); + hr = pclassObj->Get(L"NumberOfLogicalProcessors", 0, &vtProp, 0, 0); + s_cores_count = vtProp.uintVal; + + if (s_cores_count) { + s_old_time_stamp = new UINT64[s_cores_count]; + s_old_pproc_usage = new UINT64[s_cores_count]; + s_cores_load_data = new float[s_cores_count]; + float zeroFloat = 0.0; + memset(s_cores_load_data, *(int*)&zeroFloat, sizeof(float)*s_cores_count); + } + + VariantClear(&vtProp); + } + + pclassObj->Release(); + pEnumerator->Release(); + + // warm-up query engine + for (int i = 0; i < 16; ++i) { + __GetCpuUsage(); + } + return 1; +} + +namespace Os +{ +float* GetCpuUsage() +{ + if (!s_service) + { + __Init(); + } + return __GetCpuUsage(); +} +} diff --git a/Source/RHI/CMakeLists.txt b/Source/RHI/CMakeLists.txt index 3b9578e..2259c50 100755 --- a/Source/RHI/CMakeLists.txt +++ b/Source/RHI/CMakeLists.txt @@ -8,4 +8,9 @@ elseif(ANDROID) add_subdirectory(Vulkan) elseif(IOS OR MACOS) add_subdirectory(Metal) -endif() \ No newline at end of file + add_subdirectory(OpenGL) +endif() + +if(BUILD_WITH_UNIT_TEST) + add_subdirectory(UnitTest) +endif(BUILD_WITH_UNIT_TEST) \ No newline at end of file diff --git a/Source/RHI/Metal/CMakeLists.txt b/Source/RHI/Metal/CMakeLists.txt index 5071736..67057be 100755 --- a/Source/RHI/Metal/CMakeLists.txt +++ b/Source/RHI/Metal/CMakeLists.txt @@ -16,14 +16,18 @@ Private/MetalRHI.h set(INCS Public/IMetalRHI.h Public/MetalRHIResource.h -../IRHI.h -../IRHIDefs.h -../ICrossShaderCompiler.h ) source_group(Private FILES ${SRCS}) source_group(Public FILES ${INCS}) set(CMAKE_CXX_FLAGS "-fobjc-abi-version=2 -fobjc-arc ${CMAKE_CXX_FLAGS}") -add_plugin(${TARGET} "Runtime/RHI" ${SRCS} ${INCS}) +add_plugin(${TARGET} + FOLDER "Runtime/RHI" + SRCS ${SRCS} ${INCS}) + +if(MACOS) target_link_libraries(${TARGET} "-framework Metal" "-framework MetalKit" "-framework AppKit" "-framework Foundation") +elseif(IOS) +target_link_libraries(${TARGET} "-framework Metal" "-framework MetalKit" "-framework UIKit" "-framework Foundation") +endif() diff --git a/Source/RHI/Metal/Common.h b/Source/RHI/Metal/Common.h index 15a22f3..447384d 100755 --- a/Source/RHI/Metal/Common.h +++ b/Source/RHI/Metal/Common.h @@ -8,4 +8,10 @@ #import #include +#define MTLLOG(Level, ...) \ +::k3d::Log(::k3d::ELogLevel::Level, "kaleido3d::MetalRHI", __VA_ARGS__); + +#define MTLLOGI(...) MTLLOG(Info, __VA_ARGS__); +#define MTLLOGE(...) MTLLOG(Error, __VA_ARGS__); + #endif diff --git a/Source/RHI/Metal/Private/MetalBuffer.mm b/Source/RHI/Metal/Private/MetalBuffer.mm index 51a3858..dc2eb86 100755 --- a/Source/RHI/Metal/Private/MetalBuffer.mm +++ b/Source/RHI/Metal/Private/MetalBuffer.mm @@ -1,6 +1,58 @@ #include "Public/MetalRHIResource.h" +#include "Private/MetalRHI.h" NS_K3D_METAL_BEGIN +Buffer::Buffer(Device* device, rhi::ResourceDesc const & desc) +: m_Desc(desc) +, m_Device(device) +{ + m_Buf = [m_Device->GetDevice() + newBufferWithLength:desc.Size + options: MTLResourceStorageModeManaged]; +} + +Buffer::~Buffer() +{ + if(m_Buf) + { + [m_Buf release]; + m_Buf = nil; + } +} + +void * Buffer::Map(uint64 start, uint64 size) +{ + m_MapRange.location = start; + m_MapRange.length = size; + return [m_Buf contents]; +} + +void Buffer::UnMap() +{ +#if K3DPLATFORM_OS_MAC + [m_Buf didModifyRange:m_MapRange]; +#endif +} + +uint64 Buffer::GetLocation() const +{ + return (uint64)m_Buf; +} + +rhi::ResourceDesc Buffer::GetDesc() const +{ + return m_Desc; +} + +rhi::EResourceState Buffer::GetState() const +{ + return rhi::ERS_Unknown; +} + +uint64 Buffer::GetSize() const +{ + return m_Buf.length; +} NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalCommandContext.mm b/Source/RHI/Metal/Private/MetalCommandContext.mm index c50aa4e..33d5c0c 100755 --- a/Source/RHI/Metal/Private/MetalCommandContext.mm +++ b/Source/RHI/Metal/Private/MetalCommandContext.mm @@ -1,11 +1,14 @@ #include "Kaleido3D.h" +#include "Math/IK.hpp" #include "MetalRHI.h" +#include "MetalEnums.h" NS_K3D_METAL_BEGIN -CommandContext::CommandContext() +CommandContext::CommandContext(rhi::ECommandType const & cmdType, id cmdBuf) +: m_CommandType(cmdType) +, m_CmdBuffer(cmdBuf) { - } CommandContext::~CommandContext() @@ -18,6 +21,18 @@ } +void CommandContext::Begin() +{ + if(m_CommandType == rhi::ECMD_Compute) + { + m_ComputeEncoder = [m_CmdBuffer computeCommandEncoder]; + } + else if(m_CommandType == rhi::ECMD_Bundle) + { + m_ParallelRenderEncoder = [m_CmdBuffer parallelRenderCommandEncoderWithDescriptor:m_RenderpassDesc]; + } +} + void CommandContext::CopyTexture(const rhi::TextureCopyLocation& Dest, const rhi::TextureCopyLocation& Src) { @@ -30,53 +45,107 @@ void CommandContext::Execute(bool Wait) { - + [m_CmdBuffer commit]; } void CommandContext::Reset() { - +} + +void CommandContext::BeginRendering() +{ +} + +void CommandContext::SetRenderTarget(rhi::RenderTargetRef pRenderTarget) +{ + auto pRt = k3d::StaticPointerCast(pRenderTarget); + m_RenderpassDesc = pRt->m_RenderPassDescriptor; + m_RenderEncoder = [m_CmdBuffer renderCommandEncoderWithDescriptor:m_RenderpassDesc]; } void CommandContext::SetIndexBuffer(const rhi::IndexBufferView& IBView) { - + m_TmpIndexBuffer = (id)IBView.BufferLocation; } void CommandContext::SetVertexBuffer(uint32 Slot, const rhi::VertexBufferView& VBView) { - + [m_RenderEncoder setVertexBuffer:(id)VBView.BufferLocation offset:0 atIndex:Slot]; } -void CommandContext::SetPipelineState(uint32 HashCode, rhi::PipelineStateObjectRef) +void CommandContext::SetPipelineState(uint32 HashCode, rhi::PipelineStateObjectRef pPipelineState) { - + if(!pPipelineState) + { + MTLLOGE("CommandContext::setPipelineState pPipelineState==null!"); + return; + } + auto mtlPs = StaticPointerCast(pPipelineState); + if(pPipelineState->GetType() == rhi::EPSO_Graphics) + { + [m_RenderEncoder setRenderPipelineState: mtlPs->m_RenderPipelineState]; + [m_RenderEncoder setDepthStencilState: mtlPs->m_DepthStencilState]; + [m_RenderEncoder setCullMode: mtlPs->m_CullMode]; + m_CurPrimType = mtlPs->m_PrimitiveType; + } + else + { + [m_ComputeEncoder setComputePipelineState: mtlPs->m_ComputePipelineState]; + } } -void CommandContext::SetViewport(const rhi::ViewportDesc &) +void CommandContext::SetViewport(const rhi::ViewportDesc & vpDesc) { - + MTLViewport viewport = { vpDesc.Left, vpDesc.Top, vpDesc.Width, vpDesc.Height, vpDesc.MinDepth, vpDesc.MaxDepth }; + [m_RenderEncoder setViewport:viewport]; } -void CommandContext::SetPrimitiveType(rhi::EPrimitiveType) +void CommandContext::SetPrimitiveType(rhi::EPrimitiveType Type) { - + m_CurPrimType = g_PrimitiveType[Type]; } -void CommandContext::DrawInstanced(rhi::DrawInstancedParam) +void CommandContext::DrawInstanced(rhi::DrawInstancedParam param) { - + [m_RenderEncoder drawPrimitives:m_CurPrimType + vertexStart:param.StartVertexLocation + vertexCount:param.VertexCountPerInstance + instanceCount:param.InstanceCount + baseInstance:param.StartInstanceLocation]; } -void CommandContext::DrawIndexedInstanced(rhi::DrawIndexedInstancedParam) +void CommandContext::DrawIndexedInstanced(rhi::DrawIndexedInstancedParam param) { - + [m_RenderEncoder drawIndexedPrimitives:m_CurPrimType + indexCount:param.IndexCountPerInstance + indexType:MTLIndexTypeUInt32 + indexBuffer:m_TmpIndexBuffer + indexBufferOffset:param.StartIndexLocation]; +} + +void CommandContext::EndRendering() +{ + [m_RenderEncoder endEncoding]; } void CommandContext::Dispatch(uint32 x, uint32 y, uint32 z) +{ + [m_ComputeEncoder dispatchThreadgroups:MTLSizeMake(x, y, z) threadsPerThreadgroup:MTLSizeMake(x, y, z)]; +} + +void CommandContext::End() { } +void CommandContext::PresentInViewport(rhi::RenderViewportRef rvp) +{ + [m_CmdBuffer addCompletedHandler:^(id buffer) { + + }]; + auto vp = k3d::StaticPointerCast(rvp); + [m_CmdBuffer presentDrawable:vp->m_CurrentDrawable]; + [m_CmdBuffer commit]; +} NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalDevice.mm b/Source/RHI/Metal/Private/MetalDevice.mm index 5f86ffc..9219e7d 100755 --- a/Source/RHI/Metal/Private/MetalDevice.mm +++ b/Source/RHI/Metal/Private/MetalDevice.mm @@ -9,7 +9,12 @@ #include #include "MetalRHI.h" #include "MetalEnums.h" -#import +#if K3DPLATFORM_OS_MAC +#include +#else +#include +#endif + #import #define __debugbreak __builtin_trap @@ -20,6 +25,10 @@ { } +Device::Device(id pDevice) : m_Device(pDevice) +{ +} + Device::~Device() { } @@ -37,23 +46,14 @@ K3D_ASSERT(adapter!=nullptr); m_Device = static_cast(adapter)->m_Device; m_CommandQueue = [m_Device newCommandQueue]; -// m_MetalLayer = [CAMetalLayer layer]; -// m_MetalLayer.device = m_Device; -// m_MetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; -// m_MetalLayer.framebufferOnly = YES; return Result::DeviceFound; } rhi::CommandContextRef Device::NewCommandContext(rhi::ECommandType Type) { - return nullptr; -} - -rhi::GpuResourceRef -Device::NewGpuResource(rhi::ResourceDesc const&) -{ - return nullptr; + id CmdBuf = [m_CommandQueue commandBuffer]; + return k3d::MakeShared(Type, CmdBuf); } rhi::ShaderResourceViewRef @@ -69,9 +69,9 @@ } rhi::PipelineStateObjectRef -Device::NewPipelineState(rhi::PipelineDesc const&,rhi::PipelineLayoutRef,rhi::EPipelineType) +Device::NewPipelineState(rhi::PipelineDesc const& desc,rhi::PipelineLayoutRef,rhi::EPipelineType type) { - return nullptr; + return k3d::MakeShared(m_Device, desc, type); } rhi::PipelineLayoutRef @@ -92,22 +92,50 @@ return nullptr; } +// The pixel format for a Metal layer must be bgra8Unorm, bgra8Unorm_srgb, or rgba16Float. +// The default value is bgra8Unorm. https://developer.apple.com/reference/quartzcore/cametallayer/1478155-pixelformat +MTLPixelFormat CorrectFormat(rhi::GfxSetting & setting) +{ + auto pf = g_PixelFormat[setting.ColorFormat]; + switch (pf) { + case MTLPixelFormatRGBA16Float: + case MTLPixelFormatBGRA8Unorm_sRGB: + case MTLPixelFormatBGRA8Unorm: + return pf; + default: + setting.ColorFormat = rhi::EPF_BGRA8Unorm; + break; + } + return g_PixelFormat[setting.ColorFormat]; +} + rhi::RenderViewportRef Device::NewRenderViewport(void * winHandle, rhi::GfxSetting & setting) { +#if K3DPLATFORM_OS_MAC NSWindow* nWindow = (__bridge NSWindow*)winHandle; NSView* view = nWindow.contentView; NSRect rect = [view frame]; +#else + UIWindow* nWindow = (__bridge UIWindow*)winHandle; + UIView* view = nWindow.subviews[0]; + CGRect rect = [view frame]; +#endif setting.Width = rect.size.width; setting.Height = rect.size.height; - CAMetalLayer* mtlayer = (CAMetalLayer*)nWindow.contentView.layer; - mtlayer.device = GetDevice(); + CAMetalLayer* mtlayer = (CAMetalLayer*)view.layer; + mtlayer.device = GetDevice(); + mtlayer.pixelFormat = CorrectFormat(setting); + mtlayer.framebufferOnly = YES; return k3d::MakeShared(mtlayer); } RenderViewport::RenderViewport(CAMetalLayer * mtlLayer) : m_Layer(mtlLayer) +, m_CurrentDrawable(nil) +, m_RenderPassDescriptor(nil) { + m_RenderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; } RenderViewport::~RenderViewport() @@ -118,14 +146,156 @@ { m_Width = setting.Width; m_Height = setting.Height; - [m_Layer nextDrawable]; + m_CurrentDrawable = [m_Layer nextDrawable]; + id texture = m_CurrentDrawable.texture; + MTLRenderPassColorAttachmentDescriptor *colorAttachment = m_RenderPassDescriptor.colorAttachments[0]; + colorAttachment.texture = texture; + + // make sure to clear every frame for best performance + colorAttachment.loadAction = MTLLoadActionClear; + colorAttachment.clearColor = MTLClearColorMake(0.65f, 0.65f, 0.65f, 1.0f); + + // if sample count is greater than 1, render into using MSAA, then resolve into our color texture +// if(_sampleCount > 1) +// { +// BOOL doUpdate = ( _msaaTex.width != texture.width ) +// || ( _msaaTex.height != texture.height ) +// || ( _msaaTex.sampleCount != _sampleCount ); +// +// if(!_msaaTex || (_msaaTex && doUpdate)) +// { +// MTLTextureDescriptor* desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm +// width: texture.width +// height: texture.height +// mipmapped: NO]; +// desc.textureType = MTLTextureType2DMultisample; +// +// // sample count was specified to the view by the renderer. +// // this must match the sample count given to any pipeline state using this render pass descriptor +// desc.sampleCount = _sampleCount; +// +// _msaaTex = [_device newTextureWithDescriptor: desc]; +// } +// +// // When multisampling, perform rendering to _msaaTex, then resolve +// // to 'texture' at the end of the scene +// colorAttachment.texture = _msaaTex; +// colorAttachment.resolveTexture = texture; +// +// // set store action to resolve in this case +// colorAttachment.storeAction = MTLStoreActionMultisampleResolve; +// } +// else + { + // store only attachments that will be presented to the screen, as in this case + colorAttachment.storeAction = MTLStoreActionStore; + } // color0 + + // Now create the depth and stencil attachments + + if(setting.HasDepth) + { +// BOOL doUpdate = ( _depthTex.width != texture.width ) +// || ( _depthTex.height != texture.height ) +// || ( _depthTex.sampleCount != _sampleCount ); +// +// if(!_depthTex || doUpdate) +// { + // If we need a depth texture and don't have one, or if the depth texture we have is the wrong size + // Then allocate one of the proper size + MTLTextureDescriptor* desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: g_PixelFormat[setting.DepthStencilFormat] + width: texture.width + height: texture.height + mipmapped: NO]; + + desc.textureType = /*(_sampleCount > 1) ? MTLTextureType2DMultisample :*/ MTLTextureType2D; +#if K3DPLATFORM_OS_MAC + desc.resourceOptions = MTLResourceStorageModePrivate; + desc.usage = MTLTextureUsageRenderTarget; +#endif + //desc.sampleCount = _sampleCount; + + m_DepthTex = [m_Layer.device newTextureWithDescriptor: desc]; + + MTLRenderPassDepthAttachmentDescriptor *depthAttachment = m_RenderPassDescriptor.depthAttachment; + depthAttachment.texture = m_DepthTex; + depthAttachment.loadAction = MTLLoadActionClear; + depthAttachment.storeAction = MTLStoreActionDontCare; + depthAttachment.clearDepth = 1.0; +// } + } // depth + +// if(_stencilPixelFormat != MTLPixelFormatInvalid) +// { +// BOOL doUpdate = ( _stencilTex.width != texture.width ) +// || ( _stencilTex.height != texture.height ) +// || ( _stencilTex.sampleCount != _sampleCount ); +// +// if(!_stencilTex || doUpdate) +// { +// // If we need a stencil texture and don't have one, or if the depth texture we have is the wrong size +// // Then allocate one of the proper size +// MTLTextureDescriptor* desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: _stencilPixelFormat +// width: texture.width +// height: texture.height +// mipmapped: NO]; +// +// desc.textureType = (_sampleCount > 1) ? MTLTextureType2DMultisample : MTLTextureType2D; +// desc.sampleCount = _sampleCount; +// +// _stencilTex = [_device newTextureWithDescriptor: desc]; +// +// MTLRenderPassStencilAttachmentDescriptor* stencilAttachment = m_RenderPassDescriptor.stencilAttachment; +// stencilAttachment.texture = _stencilTex; +// stencilAttachment.loadAction = MTLLoadActionClear; +// stencilAttachment.storeAction = MTLStoreActionDontCare; +// stencilAttachment.clearStencil = 0; +// } +// } //stencil + return true; } +void RenderViewport::PrepareNextFrame() +{ + m_CurrentDrawable = [m_Layer nextDrawable]; +} + +rhi::RenderTargetRef +RenderViewport::GetCurrentBackRenderTarget() +{ + return k3d::MakeShared(m_RenderPassDescriptor, m_CurrentDrawable.texture); +} + rhi::RenderTargetRef Device::NewRenderTarget(rhi::RenderTargetLayout const&) { return nullptr; } +RenderTarget::RenderTarget(MTLRenderPassDescriptor* rpd, id color) +: m_RenderPassDescriptor(rpd) +, m_ColorTexture(color) +{ +} + +RenderTarget::~RenderTarget() +{ +} + +void RenderTarget::SetClearColor(kMath::Vec4f clrColor) +{ + +} + +void RenderTarget::SetClearDepthStencil(float depth, uint32 stencil) +{ + +} + +rhi::GpuResourceRef RenderTarget::GetBackBuffer() +{ + return nullptr; +} + NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalEnums.h b/Source/RHI/Metal/Private/MetalEnums.h index 3d0678c..68cca44 100755 --- a/Source/RHI/Metal/Private/MetalEnums.h +++ b/Source/RHI/Metal/Private/MetalEnums.h @@ -3,103 +3,150 @@ #define __MetalEnums_h__ #include "../Common.h" -#include +#include NS_K3D_METAL_BEGIN -/* - Points, - Lines, - Triangles, - TriangleStrip, - */ -MTLPrimitiveType g_PrimitiveType[] = { - MTLPrimitiveTypePoint, - MTLPrimitiveTypeLine, - MTLPrimitiveTypeTriangle, - MTLPrimitiveTypeTriangleStrip, -}; -/* - None, - Front, - Back, - */ -MTLCullMode g_CullMode[] = { - MTLCullModeNone, - MTLCullModeFront, - MTLCullModeBack -}; -/* - WireFrame, - Solid, - */ -MTLTriangleFillMode g_FillMode[] = { - MTLTriangleFillModeLines, - MTLTriangleFillModeFill -}; -/* - Add, - Sub, - */ -MTLBlendOperation g_BlendOperation[] = { - MTLBlendOperationAdd, - MTLBlendOperationSubtract -}; -/* - Zero, - One, - SrcColor, - DestColor, - SrcAlpha, - DestAlpha, - BlendTypeNum - */ -MTLBlendFactor g_BlendFactor[] = { - MTLBlendFactorZero, - MTLBlendFactorOne, - MTLBlendFactorSourceColor, - MTLBlendFactorDestinationColor, - MTLBlendFactorSourceAlpha, - MTLBlendFactorDestinationAlpha -}; -/* - Keep, - Zero, - Replace, - Invert, - Increment, - Decrement, - */ -MTLStencilOperation g_StencilOp[] = { - MTLStencilOperationKeep, - MTLStencilOperationZero, - MTLStencilOperationReplace, - MTLStencilOperationInvert, - MTLStencilOperationIncrementClamp, // TODO - MTLStencilOperationDecrementClamp // TODO -}; -/*Never, - Less, - Equal, - LessEqual, - Greater, - NotEqual, - GreaterEqual, - Always, - */ -MTLCompareFunction g_ComparisonFunc[] = { - MTLCompareFunctionLess, - MTLCompareFunctionEqual, - MTLCompareFunctionLessEqual, - MTLCompareFunctionGreater, - MTLCompareFunctionNotEqual, - MTLCompareFunctionGreaterEqual, - MTLCompareFunctionAlways -}; -/* - WriteZero, - WriteAll, -*/ + +namespace +{ + /** + EPF_RGBA16Uint, + EPF_RGBA32Float, + EPF_RGBA8Unorm, + EPF_RGBA8Unorm_sRGB, + EPF_R11G11B10Float, + EPF_D32Float, + EPF_RGB32Float, + EPF_RGB8Unorm, + */ + MTLPixelFormat g_PixelFormat[] = { + MTLPixelFormatRGBA16Uint, + MTLPixelFormatRGBA32Float, + MTLPixelFormatRGBA8Unorm, + MTLPixelFormatRGBA8Unorm_sRGB, + MTLPixelFormatRG11B10Float, + MTLPixelFormatDepth32Float, + MTLPixelFormatInvalid, + MTLPixelFormatInvalid, + MTLPixelFormatBGRA8Unorm, + MTLPixelFormatBGRA8Unorm_sRGB, + MTLPixelFormatRGBA16Float, + }; + + /* + Points, + Lines, + Triangles, + TriangleStrip, + */ + MTLPrimitiveType g_PrimitiveType[] = { + MTLPrimitiveTypePoint, + MTLPrimitiveTypeLine, + MTLPrimitiveTypeTriangle, + MTLPrimitiveTypeTriangleStrip, + }; + /* + None, + Front, + Back, + */ + MTLCullMode g_CullMode[] = { + MTLCullModeNone, + MTLCullModeFront, + MTLCullModeBack + }; + /* + WireFrame, + Solid, + */ + MTLTriangleFillMode g_FillMode[] = { + MTLTriangleFillModeLines, + MTLTriangleFillModeFill + }; + /* + Add, + Sub, + */ + MTLBlendOperation g_BlendOperation[] = { + MTLBlendOperationAdd, + MTLBlendOperationSubtract + }; + /* + Zero, + One, + SrcColor, + DestColor, + SrcAlpha, + DestAlpha, + BlendTypeNum + */ + MTLBlendFactor g_BlendFactor[] = { + MTLBlendFactorZero, + MTLBlendFactorOne, + MTLBlendFactorSourceColor, + MTLBlendFactorDestinationColor, + MTLBlendFactorSourceAlpha, + MTLBlendFactorDestinationAlpha + }; + /* + Keep, + Zero, + Replace, + Invert, + Increment, + Decrement, + */ + MTLStencilOperation g_StencilOp[] = { + MTLStencilOperationKeep, + MTLStencilOperationZero, + MTLStencilOperationReplace, + MTLStencilOperationInvert, + MTLStencilOperationIncrementClamp, // TODO + MTLStencilOperationDecrementClamp // TODO + }; + /*Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always, + */ + MTLCompareFunction g_ComparisonFunc[] = { + MTLCompareFunctionLess, + MTLCompareFunctionEqual, + MTLCompareFunctionLessEqual, + MTLCompareFunctionGreater, + MTLCompareFunctionNotEqual, + MTLCompareFunctionGreaterEqual, + MTLCompareFunctionAlways + }; + /* + WriteZero, + WriteAll, + */ + + /*enum EVertexFormat + { + EVF_Float1x32, + EVF_Float2x32, + EVF_Float3x32, + EVF_Float4x32, + */ + MTLVertexFormat g_VertexFormats[] = { + MTLVertexFormatFloat, + MTLVertexFormatFloat2, + MTLVertexFormatFloat3, + MTLVertexFormatFloat4, + }; + + MTLVertexStepFunction g_VertexInputRates[] = { + MTLVertexStepFunctionPerVertex, + MTLVertexStepFunctionPerInstance, + }; +} NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalPipelineState.mm b/Source/RHI/Metal/Private/MetalPipelineState.mm index 6558c9c..0b40cf6 100755 --- a/Source/RHI/Metal/Private/MetalPipelineState.mm +++ b/Source/RHI/Metal/Private/MetalPipelineState.mm @@ -1,12 +1,33 @@ #include "Kaleido3D.h" #include "MetalRHI.h" +#include "MetalEnums.h" #include NS_K3D_METAL_BEGIN -PipelineState::PipelineState() +MTLPrimitiveTopologyClass ConvertPrimTopology(rhi::EPrimitiveType const& type) { + switch(type) + { + case rhi::EPT_Triangles: + case rhi::EPT_TriangleStrip: + return MTLPrimitiveTopologyClassTriangle; + case rhi::EPT_Points: + return MTLPrimitiveTopologyClassPoint; + case rhi::EPT_Lines: + return MTLPrimitiveTopologyClassLine; + } + return MTLPrimitiveTopologyClassUnspecified; +} +PipelineState::PipelineState(id pDevice, rhi::PipelineDesc const & desc, rhi::EPipelineType const& type) +: m_DepthStencilDesc(nil) +, m_RenderPipelineDesc(nil) +, m_Type(type) +, m_Device(pDevice) +{ + InitPSO(desc); + Finalize(); } PipelineState::~PipelineState() @@ -14,6 +35,114 @@ } +void PipelineState::InitPSO(const rhi::PipelineDesc &desc) +{ + if(m_Type==rhi::EPSO_Graphics) + { + m_RenderPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; + // depth stencil setup + m_DepthStencilDesc = [[MTLDepthStencilDescriptor alloc] init]; + m_DepthStencilDesc.depthCompareFunction = g_ComparisonFunc[desc.DepthStencil.DepthFunc]; + m_DepthStencilDesc.depthWriteEnabled = desc.DepthStencil.DepthEnable; + + MTLStencilDescriptor * stencilFront = m_DepthStencilDesc.frontFaceStencil; + stencilFront.depthStencilPassOperation = g_StencilOp[desc.DepthStencil.FrontFace.StencilPassOp]; + stencilFront.depthFailureOperation = g_StencilOp[desc.DepthStencil.FrontFace.DepthStencilFailOp]; + stencilFront.stencilFailureOperation = g_StencilOp[desc.DepthStencil.FrontFace.StencilFailOp]; + stencilFront.stencilCompareFunction = g_ComparisonFunc[desc.DepthStencil.FrontFace.StencilFunc]; + + MTLStencilDescriptor * stencilBack = m_DepthStencilDesc.backFaceStencil; + stencilBack.depthStencilPassOperation = g_StencilOp[desc.DepthStencil.BackFace.StencilPassOp]; + stencilBack.depthFailureOperation = g_StencilOp[desc.DepthStencil.BackFace.DepthStencilFailOp]; + stencilBack.stencilFailureOperation = g_StencilOp[desc.DepthStencil.BackFace.StencilFailOp]; + stencilBack.stencilCompareFunction = g_ComparisonFunc[desc.DepthStencil.BackFace.StencilFunc]; + + m_DepthBias = desc.Rasterizer.DepthBias; + m_DepthBiasClamp = desc.Rasterizer.DepthBiasClamp; + m_CullMode = g_CullMode[desc.Rasterizer.CullMode]; + m_RenderPipelineDesc.inputPrimitiveTopology = ConvertPrimTopology(desc.PrimitiveTopology); + m_PrimitiveType = g_PrimitiveType[desc.PrimitiveTopology]; + // blending setup + MTLRenderPipelineColorAttachmentDescriptor *renderbufferAttachment = m_RenderPipelineDesc.colorAttachments[0]; + + renderbufferAttachment.pixelFormat = MTLPixelFormatBGRA8Unorm; + + renderbufferAttachment.blendingEnabled = desc.Blend.Enable?YES:NO; + renderbufferAttachment.rgbBlendOperation = g_BlendOperation[desc.Blend.Op]; + renderbufferAttachment.alphaBlendOperation = g_BlendOperation[desc.Blend.BlendAlphaOp]; + renderbufferAttachment.sourceRGBBlendFactor = g_BlendFactor[desc.Blend.Src]; + renderbufferAttachment.sourceAlphaBlendFactor = g_BlendFactor[desc.Blend.SrcBlendAlpha]; + renderbufferAttachment.destinationRGBBlendFactor = g_BlendFactor[desc.Blend.Dest]; + renderbufferAttachment.destinationAlphaBlendFactor = g_BlendFactor[desc.Blend.DestBlendAlpha]; + + m_RenderPipelineDesc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; + + + // vertex descriptor setup + for(uint32 i = 0; i lib = [m_Device newLibraryWithData:data error:&error]; + if(error) + { + MTLLOGE("Failed to AssignShader, error: %s, occured %s@%d.", [[error localizedFailureReason] UTF8String], __FILE__, __LINE__); + } + NSString *entryName = [NSString stringWithFormat:@"%@0", + [NSString stringWithUTF8String:shaderBundle.Desc.EntryFunction.CStr()]]; + id function = [lib newFunctionWithName:entryName]; + switch(shaderBundle.Desc.Stage) + { + case rhi::ES_Vertex: + m_RenderPipelineDesc.vertexFunction = function; + break; + case rhi::ES_Fragment: + m_RenderPipelineDesc.fragmentFunction = function; + break; + } + } + } +} + void PipelineState::SetLayout(rhi::PipelineLayoutRef) { @@ -61,7 +190,20 @@ void PipelineState::Finalize() { - + NSError *error = NULL; + if(m_Type==rhi::EPSO_Graphics) + { + m_DepthStencilState = [m_Device newDepthStencilStateWithDescriptor:m_DepthStencilDesc]; + m_RenderPipelineState = [m_Device newRenderPipelineStateWithDescriptor:m_RenderPipelineDesc error:&error]; + if (error) + { + MTLLOGE("Failed to created render pipeline state, error: %s", [error.localizedDescription cStringUsingEncoding:NSASCIIStringEncoding]); + } + } + else + { +// m_ComputePipelineState = [m_Device newCom] + } } NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalRHI.h b/Source/RHI/Metal/Private/MetalRHI.h index d50e2f4..4a10fd8 100755 --- a/Source/RHI/Metal/Private/MetalRHI.h +++ b/Source/RHI/Metal/Private/MetalRHI.h @@ -10,7 +10,7 @@ #define __CommandContext_h__ #include "../Common.h" -#include +#include NS_K3D_METAL_BEGIN @@ -54,6 +54,8 @@ class Device : public rhi::IDevice void Destroy(); private: + Device(id device); + friend class DeviceAdapter; id m_Device; id m_CommandQueue; @@ -65,7 +67,9 @@ inline rhi::DeviceRef DeviceAdapter::GetDevice() { if(!m_pRHIDevice) { - m_pRHIDevice = k3d::MakeShared(); + auto pDevice = new Device(m_Device); + pDevice->Create(this, false); + m_pRHIDevice = rhi::DeviceRef(pDevice); } return m_pRHIDevice; } @@ -74,8 +78,9 @@ inline rhi::DeviceRef DeviceAdapter::GetDevice() class PipelineState : public rhi::IPipelineStateObject { friend class Device; + friend class CommandContext; public: - PipelineState(); + PipelineState(id pDevice, rhi::PipelineDesc const & desc, rhi::EPipelineType const& type); ~PipelineState(); rhi::EPipelineType GetType () override { return m_Type; } @@ -93,18 +98,59 @@ class PipelineState : public rhi::IPipelineStateObject void Finalize() override; private: + void InitPSO(rhi::PipelineDesc const & desc); + void AssignShader(rhi::ShaderBundle const& shaderBundle); + rhi::EPipelineType m_Type; id m_Device; + id m_ComputePipelineState; + MTLComputePipelineDescriptor* m_ComputePipelineDesc; + id m_RenderPipelineState; MTLRenderPipelineDescriptor* m_RenderPipelineDesc; + + MTLDepthStencilDescriptor* m_DepthStencilDesc; + MTLCullMode m_CullMode; + float m_DepthBias; + float m_DepthBiasClamp; + + MTLPrimitiveType m_PrimitiveType; + + MTLRenderPipelineReflection* m_RenderReflection; + MTLComputePipelineReflection* m_ComputeReflection; + id m_DepthStencilState; }; +class DescriptorSet : public rhi::IDescriptor +{ +public: + DescriptorSet() + {} + + void Update(uint32 bindSet, rhi::GpuResourceRef res) override; + +private: + +}; + +class PipelineLayout : public rhi::IPipelineLayout +{ +public: + PipelineLayout(rhi::PipelineLayoutDesc const&); + ~PipelineLayout(); + + rhi::DescriptorRef GetDescriptorSet() const override; + +private: + +}; + class CommandContext : public rhi::ICommandContext { public: - CommandContext(); + CommandContext(rhi::ECommandType const & cmdType, id cmdBuf); ~CommandContext() override; @@ -112,27 +158,48 @@ class CommandContext : public rhi::ICommandContext void CopyTexture(const rhi::TextureCopyLocation& Dest, const rhi::TextureCopyLocation& Src) override; void CopyBuffer(rhi::IGpuResource& Dest, rhi::IGpuResource& Src, rhi::CopyBufferRegion const & Region) override; + void TransitionResourceBarrier(rhi::GpuResourceRef resource, /*EPipelineStage stage,*/ rhi::EResourceState dstState) override {} void Execute(bool Wait) override; void Reset() override; - void SetIndexBuffer(const rhi::IndexBufferView& IBView) override; - void SetVertexBuffer(uint32 Slot, const rhi::VertexBufferView& VBView) override; + void Begin() override; + + void ClearColorBuffer(rhi::GpuResourceRef, kMath::Vec4f const&) override {} + void ClearDepthBuffer(rhi::IDepthBuffer*) override {} + + void BeginRendering() override; + void SetRenderTargets(uint32 NumColorBuffer, rhi::IColorBuffer*, rhi::IDepthBuffer*, bool ReadOnlyDepth = false) override {} + void SetRenderTarget(rhi::RenderTargetRef) override; void SetPipelineState(uint32 HashCode, rhi::PipelineStateObjectRef) override; + void SetPipelineLayout(rhi::PipelineLayoutRef) override {} + void SetScissorRects(uint32, const rhi::Rect*) override {} void SetViewport(const rhi::ViewportDesc &) override; void SetPrimitiveType(rhi::EPrimitiveType) override; + void SetIndexBuffer(const rhi::IndexBufferView& IBView) override; + void SetVertexBuffer(uint32 Slot, const rhi::VertexBufferView& VBView) override; void DrawInstanced(rhi::DrawInstancedParam) override; void DrawIndexedInstanced(rhi::DrawIndexedInstancedParam) override; + void EndRendering() override; + void PresentInViewport(rhi::RenderViewportRef rvp) override; + void Dispatch(uint32 X = 1, uint32 Y =1, uint32 Z = 1) override; + void ExecuteBundle(rhi::ICommandContext*) override {} + + void End() override; + protected: private: + MTLRenderPassDescriptor* m_RenderpassDesc; rhi::ECommandType m_CommandType; + MTLPrimitiveType m_CurPrimType; id m_ComputeEncoder; id m_RenderEncoder; - + id m_ParallelRenderEncoder; id m_CmdBuffer; - id m_CmdQueue; + + id m_TmpIndexBuffer; }; class RenderViewport : public rhi::IRenderViewport @@ -141,26 +208,58 @@ class RenderViewport : public rhi::IRenderViewport RenderViewport(CAMetalLayer * mtlLayer = nil); ~RenderViewport() override; - bool InitViewport(void *windowHandle, - rhi::IDevice * pDevice, - rhi::GfxSetting & - ) override; + bool InitViewport(void *windowHandle, rhi::IDevice * pDevice, rhi::GfxSetting &) override; + void PrepareNextFrame() override; + bool Present(bool vSync) override { return false; } + + rhi::RenderTargetRef GetRenderTarget(uint32 index) override { return nullptr; } + + rhi::RenderTargetRef GetCurrentBackRenderTarget() override; + uint32 GetSwapChainCount()override { return 0; } + uint32 GetSwapChainIndex()override { return 0; } + + uint32 GetWidth() const override { return m_Width; } + uint32 GetHeight() const override { return m_Height; } - void PrepareNextFrame() override {} - bool Present(bool vSync) override { return false; } + friend class Device; + friend class CommandContext; +private: + + CAMetalLayer * m_Layer; + id m_CurrentDrawable; + MTLRenderPassDescriptor*m_RenderPassDescriptor; + id m_DepthTex; + uint32 m_Width; + uint32 m_Height; +}; + +class RenderTarget : public rhi::IRenderTarget +{ +public: + RenderTarget() {} + RenderTarget(MTLRenderPassDescriptor* rpd, id color); + ~RenderTarget() override; - rhi::RenderTargetRef GetRenderTarget(uint32 index) override { return nullptr; } + void SetClearColor(kMath::Vec4f clrColor) override; + void SetClearDepthStencil(float depth, uint32 stencil) override; + rhi::GpuResourceRef GetBackBuffer() override; + + friend class CommandContext; +private: + MTLRenderPassDescriptor*m_RenderPassDescriptor = nil; + id m_ColorTexture; +}; + +class Sampler : public rhi::ISampler +{ +public: + explicit Sampler(rhi::SamplerState const & state); + ~Sampler() override; - rhi::RenderTargetRef GetCurrentBackRenderTarget() override { return nullptr; } - uint32 GetSwapChainCount()override { return 0; } - uint32 GetSwapChainIndex()override { return 0; } + rhi::SamplerState GetSamplerDesc() const override; - uint32 GetWidth() const override { return m_Width; } - uint32 GetHeight() const override { return m_Height; } private: - CAMetalLayer * m_Layer; - uint32 m_Width; - uint32 m_Height; + id m_SampleState; }; NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalRHI.mm b/Source/RHI/Metal/Private/MetalRHI.mm index 9479841..d0678c3 100755 --- a/Source/RHI/Metal/Private/MetalRHI.mm +++ b/Source/RHI/Metal/Private/MetalRHI.mm @@ -20,15 +20,14 @@ void Start()override { KLOG(Info, MetalRHI, "Starting..."); +#if K3DPLATFORM_OS_MAC NSArray> * deviceList = MTLCopyAllDevices(); m_Adapters.resize(deviceList.count); -#if K3DPLATFORM_OS_MAC MTLFeatureSet fSets[] = { MTLFeatureSet_OSX_ReadWriteTextureTier2, MTLFeatureSet_OSX_GPUFamily1_v2, MTLFeatureSet_OSX_GPUFamily1_v1 }; -#endif for (uint32 i = 0; i device = [deviceList objectAtIndex:i]; @@ -38,6 +37,24 @@ void Start()override [device supportsFeatureSet:fSets[0]], [device supportsFeatureSet:fSets[1]]); } +#else + MTLFeatureSet fSets[] = { + MTLFeatureSet_iOS_GPUFamily2_v1, + MTLFeatureSet_iOS_GPUFamily1_v2, + MTLFeatureSet_iOS_GPUFamily2_v2, + MTLFeatureSet_iOS_GPUFamily3_v1, + MTLFeatureSet_iOS_GPUFamily1_v3, + MTLFeatureSet_iOS_GPUFamily2_v3, + MTLFeatureSet_iOS_GPUFamily3_v2 + }; + id device = MTLCreateSystemDefaultDevice(); + m_Adapters.resize(1); + m_Adapters[0] = new metal::DeviceAdapter(device); + KLOG(Info, MetalRHI, "DeviceName: %s ReadWriteTextureTier2:%d GPUv2:%d", + [[device name] UTF8String], + [device supportsFeatureSet:fSets[0]], + [device supportsFeatureSet:fSets[1]]); +#endif } void Shutdown()override diff --git a/Source/RHI/Metal/Private/MetalResource.mm b/Source/RHI/Metal/Private/MetalResource.mm index 8c4f340..8130fcf 100755 --- a/Source/RHI/Metal/Private/MetalResource.mm +++ b/Source/RHI/Metal/Private/MetalResource.mm @@ -4,5 +4,18 @@ NS_K3D_METAL_BEGIN +rhi::GpuResourceRef +Device::NewGpuResource(rhi::ResourceDesc const& desc) +{ + switch (desc.Type) { + case rhi::EGT_Buffer: + return k3d::MakeShared(this, desc); + case rhi::EGT_Texture2D: + return k3d::MakeShared(this, desc); + default: + break; + } + return nullptr; +} NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Private/MetalTexture.mm b/Source/RHI/Metal/Private/MetalTexture.mm index 51a3858..3157ffe 100755 --- a/Source/RHI/Metal/Private/MetalTexture.mm +++ b/Source/RHI/Metal/Private/MetalTexture.mm @@ -1,6 +1,130 @@ #include "Public/MetalRHIResource.h" +#include "MetalRHI.h" +#include "MetalEnums.h" NS_K3D_METAL_BEGIN +MTLTextureType RHIMTLTextureType(rhi::EGpuResourceType const & type) +{ + switch(type) + { + case rhi::EGT_Texture1D: + return MTLTextureType1D; + case rhi::EGT_Texture1DArray: + return MTLTextureType1DArray; + case rhi::EGT_Texture2D: + return MTLTextureType2D; + case rhi::EGT_Texture3D: + return MTLTextureType3D; + case rhi::EGT_Texture2DArray: + return MTLTextureType2DArray; + } + return MTLTextureType2D; +} + +MTLTextureUsage RHIMTLTexUsage(rhi::EGpuMemViewType const & viewType, rhi::EGpuResourceAccessFlag const & accessType) +{ + MTLTextureUsage usage = MTLTextureUsageUnknown; + switch (viewType) { + case rhi::EGVT_SRV: + usage |= MTLTextureUsagePixelFormatView; + break; + case rhi::EGVT_RTV: + usage |= MTLTextureUsageRenderTarget; + break; + default: + break; + } + switch (accessType) { + case rhi::EGRAF_Read: + usage |= MTLTextureUsageShaderRead; + break; + case rhi::EGRAF_Write: + usage |= MTLTextureUsageShaderWrite; + break; + case rhi::EGRAF_ReadAndWrite: + usage |= (MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite); + break; + default: + break; + } + return usage; +} + +MTLTextureDescriptor * RHIMTLTexDesc(rhi::ResourceDesc const & desc) +{ + MTLTextureDescriptor* texDesc = [MTLTextureDescriptor new]; + texDesc.width = desc.TextureDesc.Width; + texDesc.height = desc.TextureDesc.Height; + texDesc.depth = desc.TextureDesc.Depth; + texDesc.pixelFormat = g_PixelFormat[desc.TextureDesc.Format]; + texDesc.mipmapLevelCount = desc.TextureDesc.MipLevels; + texDesc.arrayLength = desc.TextureDesc.Layers; + texDesc.textureType = RHIMTLTextureType(desc.Type); + texDesc.usage = RHIMTLTexUsage(desc.ViewType, desc.Flag); + texDesc.resourceOptions; + texDesc.cpuCacheMode; + texDesc.storageMode; + return texDesc; +} + +Texture::Texture(Device * device, rhi::ResourceDesc const & desc) +: m_Device(device) +, m_Desc(desc) +, m_TexDesc(nil) +{ + m_TexDesc = RHIMTLTexDesc(desc); + m_Tex = [m_Device->GetDevice() newTextureWithDescriptor:m_TexDesc]; +} + +Texture::~Texture() +{ +} + +void * Texture::Map(uint64 start, uint64 size) +{ + return nullptr; +} + +void Texture::UnMap() +{ + +} + +uint64 Texture::GetLocation() const +{ + return 0; +} + +rhi::ResourceDesc Texture::GetDesc() const +{ + return m_Desc; +} + +uint64 Texture::GetSize() const +{ + return 0; +} + +rhi::SamplerCRef Texture::GetSampler() const +{ + return nullptr; +} + +void Texture::BindSampler(rhi::SamplerRef) +{ + +} + +void Texture::SetResourceView(rhi::ShaderResourceViewRef) +{ + +} + +rhi::ShaderResourceViewRef +Texture::GetResourceView() const +{ + return nullptr; +} NS_K3D_METAL_END diff --git a/Source/RHI/Metal/Public/IMetalRHI.h b/Source/RHI/Metal/Public/IMetalRHI.h index 298e3c5..c76b3bd 100755 --- a/Source/RHI/Metal/Public/IMetalRHI.h +++ b/Source/RHI/Metal/Public/IMetalRHI.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace k3d { @@ -10,3 +10,7 @@ namespace k3d virtual rhi::DeviceRef GetPrimaryDevice() = 0; }; } + +#if BUILD_STATIC_PLUGIN +K3D_STATIC_MODULE_DECLARE(RHI_Metal); +#endif diff --git a/Source/RHI/Metal/Public/MetalRHIResource.h b/Source/RHI/Metal/Public/MetalRHIResource.h index 1e512e6..52de015 100755 --- a/Source/RHI/Metal/Public/MetalRHIResource.h +++ b/Source/RHI/Metal/Public/MetalRHIResource.h @@ -3,22 +3,96 @@ #define __MetalRHIResource_h__ #include "../Common.h" -#include +#include NS_K3D_METAL_BEGIN +class Device; + +class BufferRef +{ +public: + BufferRef(id iBuf) + : m_InterCnt(0) + , m_ExtCnt(0) + { + m_iBuffer = iBuf; + } + + ~BufferRef() + { + } + + void Retain() + { + + } + + void Release() + { + + } + +private: + id m_iBuffer; + int m_InterCnt; + int m_ExtCnt; +}; + class Buffer : public rhi::IGpuResource { public: + Buffer(Device* device, rhi::ResourceDesc const & desc); + ~Buffer(); + void * Map(uint64 start, uint64 size) override; + void UnMap() override; + + uint64 GetLocation() const override; + rhi::ResourceDesc GetDesc() const override; + rhi::EResourceState GetState() const override; +// rhi::EGpuResourceType GetType() const override; + uint64 GetSize() const override; + +private: + NSRange m_MapRange; + id m_Buf; + + rhi::ResourceDesc m_Desc; + Device* m_Device; }; class Texture : public rhi::ITexture { public: + Texture(Device* device, rhi::ResourceDesc const & desc); + ~Texture(); + + void * Map(uint64 start, uint64 size) override; + void UnMap() override; + uint64 GetLocation() const override; + rhi::ResourceDesc GetDesc() const override; + rhi::EResourceState GetState() const override { return rhi::ERS_Unknown; } +// rhi::EGpuResourceType GetResourceType() const override { return rhi::ResourceTypeNum; } + uint64 GetSize() const override; + + rhi::SamplerCRef GetSampler() const override; + void BindSampler(rhi::SamplerRef) override; + void SetResourceView(rhi::ShaderResourceViewRef) override; + rhi::ShaderResourceViewRef GetResourceView() const override; + +private: + id m_Tex; + MTLTextureDescriptor* m_TexDesc; + rhi::ResourceDesc m_Desc; + MTLStorageMode storageMode; + + MTLTextureUsage usage; + Device* m_Device; }; + NS_K3D_METAL_END #endif diff --git a/Source/RHI/OpenGL/CMakeLists.txt b/Source/RHI/OpenGL/CMakeLists.txt index 0588958..c580a80 100755 --- a/Source/RHI/OpenGL/CMakeLists.txt +++ b/Source/RHI/OpenGL/CMakeLists.txt @@ -11,7 +11,6 @@ elseif(ANDROID OR IOS) endif() set(RHI_HEADERS - ../IRHI.h OpenGLCommon.h Public/IOpenGLRHI.h ) @@ -30,10 +29,10 @@ source_group( ${RHI_IMPL_SRCS} ) -add_plugin(RHI_OpenGL "Runtime/RHI" ${OGLRHI_SRC_LIST} ${RHI_HEADERS} ${RHI_IMPL_SRCS}) +add_plugin(RHI_OpenGL FOLDER "Runtime/RHI" SRCS ${OGLRHI_SRC_LIST} ${RHI_HEADERS} ${RHI_IMPL_SRCS}) if(NOT ANDROID) - install(TARGETS RHI_OpenGL ARCHIVE DESTINATION lib) + #install(TARGETS RHI_OpenGL ARCHIVE DESTINATION lib) add_precompiled_header(RHI_OpenGL "OpenGLCommon.h" "${Kaleido3D_ROOT_DIR}/Source/RHI/OpenGL" "${Kaleido3D_ROOT_DIR}/Source/RHI/OpenGL/Private/OpenGLRHI.cpp") endif() diff --git a/Source/RHI/OpenGL/OpenGLCommon.h b/Source/RHI/OpenGL/OpenGLCommon.h index 47be7cb..726851d 100755 --- a/Source/RHI/OpenGL/OpenGLCommon.h +++ b/Source/RHI/OpenGL/OpenGLCommon.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #define NS_GLRHI_BEGIN K3D_COMMON_NS { namespace opengl { #define NS_GLRHI_END }} diff --git a/Source/RHI/UnitTest/1.Device.cpp b/Source/RHI/UnitTest/1.Device.cpp new file mode 100644 index 0000000..feabc94 --- /dev/null +++ b/Source/RHI/UnitTest/1.Device.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace k3d; + +class UnitTestRHIDevice : public App +{ +public: + explicit UnitTestRHIDevice(kString const & appName) + : App(appName, 1920, 1080) + {} + + UnitTestRHIDevice(kString const & appName, uint32 width, uint32 height) + : App(appName, width, height) + {} + + bool OnInit() override; + void OnDestroy() override; + void OnProcess(Message & msg) override; + +private: + +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID + SharedPtr m_pRHI; +#else + SharedPtr m_pRHI; +#endif + rhi::DeviceRef m_TestDevice; +}; + +K3D_APP_MAIN(UnitTestRHIDevice); + +using namespace rhi; +using namespace k3d; + +bool UnitTestRHIDevice::OnInit() +{ + App::OnInit(); +#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID + m_pRHI = StaticPointerCast(ACQUIRE_PLUGIN(RHI_Vulkan)); + if (m_pRHI) + { + m_pRHI->Initialize("UnitTestRHIDevice", false); + m_pRHI->Start(); + m_TestDevice = m_pRHI->GetPrimaryDevice(); + } +#else + auto pMtlRHI = StaticPointerCast(ACQUIRE_PLUGIN(RHI_Metal)); + if(pMtlRHI) + { + pMtlRHI->Start(); + m_TestDevice = pMtlRHI->GetPrimaryDevice(); + } +#endif + return true; +} + +void UnitTestRHIDevice::OnDestroy() +{ + App::OnDestroy(); +} + +void UnitTestRHIDevice::OnProcess(Message & msg) +{ +} diff --git a/Source/UnitTest/2.SwapChain/SwapChainPresent.cpp b/Source/RHI/UnitTest/2.SwapChainPresent.cpp old mode 100755 new mode 100644 similarity index 77% rename from Source/UnitTest/2.SwapChain/SwapChainPresent.cpp rename to Source/RHI/UnitTest/2.SwapChainPresent.cpp index a7bdcd0..f6610f5 --- a/Source/UnitTest/2.SwapChain/SwapChainPresent.cpp +++ b/Source/RHI/UnitTest/2.SwapChainPresent.cpp @@ -1,13 +1,13 @@ #include #include #include -#include +#include #include using namespace k3d; using namespace render; -rhi::GfxSetting setting{ 1920, 1080, rhi::EPF_RGBA8Unorm, rhi::EPF_RGBA8Unorm, true, 2 }; +rhi::GfxSetting setting{ 1920, 1080, rhi::EPF_RGBA8Unorm, rhi::EPF_D32Float, true, 2 }; class VkSwapChainPresent : public App { @@ -15,6 +15,9 @@ class VkSwapChainPresent : public App explicit VkSwapChainPresent(kString const & appName) : App(appName, 1920, 1080) {} + VkSwapChainPresent(kString const & appName, uint32 width, uint32 height) + : App(appName, width, height) + {} bool OnInit() override; void OnDestroy() override; @@ -32,7 +35,11 @@ K3D_APP_MAIN(VkSwapChainPresent); bool VkSwapChainPresent::OnInit() { App::OnInit(); - m_RenderContext.Init(RHIType::ERTVulkan); +#if K3DPLATFORM_OS_IOS || K3DPLATFORM_OS_MAC + m_RenderContext.Init(RHIType::ERTMetal); +#else + m_RenderContext.Init(RHIType::ERTVulkan); +#endif m_pDevice = m_RenderContext.GetDevice(); m_RenderVp = m_pDevice->NewRenderViewport(HostWindow()->GetHandle(), setting); m_RenderVp->InitViewport(nullptr, nullptr, setting); diff --git a/Source/UnitTest/3.Triangle/Triangle.cpp b/Source/RHI/UnitTest/3.Triangle.cpp old mode 100755 new mode 100644 similarity index 50% rename from Source/UnitTest/3.Triangle/Triangle.cpp rename to Source/RHI/UnitTest/3.Triangle.cpp index e7fdf0f..9c6023c --- a/Source/UnitTest/3.Triangle/Triangle.cpp +++ b/Source/RHI/UnitTest/3.Triangle.cpp @@ -1,9 +1,10 @@ #include +#include #include #include #include #include -#include +#include #include #include @@ -18,55 +19,15 @@ struct ConstantBuffer { Mat4f modelMatrix; Mat4f viewMatrix; }; -const char* vertSource = "#version 430\n" - "\n" - "#extension GL_ARB_separate_shader_objects : enable\n" - "#extension GL_ARB_shading_language_420pack : enable\n" - "\n" - "layout (location = 0) in vec3 inPos;\n" - "layout (location = 1) in vec3 inColor;\n" - "\n" - "layout (binding = 0) uniform UBO \n" - "{\n" - "\tmat4 projectionMatrix;\n" - "\tmat4 modelMatrix;\n" - "\tmat4 viewMatrix;\n" - "} ubo;\n" - "\n" - "layout (location = 0) out vec3 outColor;\n" - "\n" - "out gl_PerVertex \n" - "{\n" - " vec4 gl_Position; \n" - "};\n" - "\n" - "\n" - "void main() \n" - "{\n" - "\toutColor = inColor;\n" - "\tgl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0);\n" - "}"; -const char* fragSource = "#version 430\n" - "\n" - "#extension GL_ARB_separate_shader_objects : enable\n" - "#extension GL_ARB_shading_language_420pack : enable\n" - "\n" - "layout (location = 0) in vec3 inColor;\n" - "\n" - "layout (location = 0) out vec4 outFragColor;\n" - "\n" - "void main()\n" - "{\n" - " outFragColor = vec4(inColor, 1.0);\n" - "}"; -class VkTriangleUnitTest : public App + +class VkTriangleUnitTest : public RHIAppBase { public: VkTriangleUnitTest(kString const & appName, uint32 width, uint32 height) - : App(appName, width, height), m_Width(width), m_Height(height) + : RHIAppBase(appName, width, height) {} explicit VkTriangleUnitTest(kString const & appName) - : App(appName, 1920, 1080), m_Width(1920), m_Height(1080) + : RHIAppBase(appName, 1920, 1080) {} bool OnInit() override; @@ -76,8 +37,6 @@ class VkTriangleUnitTest : public App void OnUpdate() override; protected: - void LoadGlslangCompiler(); - void compile(const char *shaderSource, rhi::EShaderType const& type, rhi::ShaderBundle & shader); void PrepareResource(); void PreparePipeline(); @@ -90,15 +49,10 @@ class VkTriangleUnitTest : public App rhi::GpuResourceRef m_ConstBuffer; ConstantBuffer m_HostBuffer; - RenderContext m_RenderContext; - rhi::RenderViewportRef m_Viewport; rhi::PipelineStateObjectRef m_pPso; rhi::PipelineLayoutRef m_pl; std::vector m_Cmds; rhi::SyncFenceRef m_pFence; - - uint32 m_Width; - uint32 m_Height; }; K3D_APP_MAIN(VkTriangleUnitTest) @@ -117,16 +71,19 @@ class TriangleMesh { m_szVBuf = sizeof(TriangleMesh::Vertex)*m_VertexBuffer.size(); m_szIBuf = sizeof(uint32)*m_IndexBuffer.size(); - m_VertDecs[0] = { rhi::EVF_Float3x32, sizeof(Vertex), 0,0,0 }; /* Position */ - m_VertDecs[1] = { rhi::EVF_Float3x32, sizeof(Vertex), 1,sizeof(float)*3,0 }; /* Color */ + + m_IAState.Attribs[0] = {rhi::EVF_Float3x32, 0, 0}; + m_IAState.Attribs[1] = {rhi::EVF_Float3x32, sizeof(float)*3, 0}; + + m_IAState.Layouts[0] = {rhi::EVIR_PerVertex, sizeof(Vertex)}; } ~TriangleMesh() { } - - const rhi::VertexDeclaration * GetVertDec() const { return m_VertDecs; } - + + const rhi::VertexInputState & GetInputState() const { return m_IAState;} + void Upload(); void SetLoc(uint64 ibo, uint64 vbo) @@ -141,7 +98,7 @@ class TriangleMesh private: - rhi::VertexDeclaration m_VertDecs[2]; + rhi::VertexInputState m_IAState; uint64 m_szVBuf; uint64 m_szIBuf; @@ -166,7 +123,7 @@ void TriangleMesh::Upload() rhi::ResourceDesc stageDesc; stageDesc.ViewType = rhi::EGpuMemViewType::EGVT_Undefined; stageDesc.CreationFlag = rhi::EGpuResourceCreationFlag::EGRCF_TransferSrc; - stageDesc.Flag = (rhi::EGpuResourceAccessFlag) (rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible); + stageDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; stageDesc.Size = m_szVBuf; auto vStageBuf = m_pDevice->NewGpuResource(stageDesc); void * ptr = vStageBuf->Map(0, m_szVBuf); @@ -197,9 +154,9 @@ void TriangleMesh::Upload() cmd->CopyBuffer(*ibuf, *iStageBuf, region); cmd->End(); cmd->Execute(true); -// m_pDevice->WaitIdle(); - uint64 vboLoc = vbuf->GetResourceLocation(); - uint64 iboLoc = ibuf->GetResourceLocation(); +// m_m_pDevice->WaitIdle(); + uint64 vboLoc = vbuf->GetLocation(); + uint64 iboLoc = ibuf->GetLocation(); SetLoc(iboLoc, vboLoc); KLOG(Info, TriangleMesh, "finish buffer upload.."); } @@ -207,14 +164,12 @@ void TriangleMesh::Upload() bool VkTriangleUnitTest::OnInit() { - bool inited = App::OnInit(); + bool inited = RHIAppBase::OnInit(); if(!inited) return inited; - m_RenderContext.Init(RHIType::ERTVulkan, m_Width, m_Height); - m_RenderContext.Attach(HostWindow()); - m_Viewport = m_RenderContext.GetViewport(); - LoadGlslangCompiler(); + KLOG(Info, Test, __K3D_FUNC__); + PrepareResource(); PreparePipeline(); PrepareCommandBuffer(); @@ -222,117 +177,66 @@ bool VkTriangleUnitTest::OnInit() return true; } -void VkTriangleUnitTest::LoadGlslangCompiler() -{ - rhi::IShModule* shMod = (rhi::IShModule*)GlobalModuleManager.FindModule("ShaderCompiler"); - if (shMod) - { - m_Compiler = shMod->CreateShaderCompiler(rhi::ERHI_Vulkan); - } -} - -void VkTriangleUnitTest::compile(const char * shaderPath, rhi::EShaderType const & type, rhi::ShaderBundle & shader) -{ - auto pDevice = m_RenderContext.GetDevice(); - IAsset * shaderFile = AssetManager::Open(shaderPath); - if (!shaderFile) - { - KLOG(Fatal, "VkTriangle", "Error opening %s.", shaderPath); - return; - } - std::vector buffer; - uint64 len = shaderFile->GetLength(); - buffer.resize(len+1); - shaderFile->Read(buffer.data(), shaderFile->GetLength()); - buffer[len] = 0; - String src(buffer.data()); - rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, type, "main" }; - m_Compiler->Compile(src, desc, shader); -} - void VkTriangleUnitTest::PrepareResource() { KLOG(Info, Test, __K3D_FUNC__); - m_TriMesh = std::make_unique(m_RenderContext.GetDevice()); + m_TriMesh = std::make_unique(m_pDevice); m_TriMesh->Upload(); - auto pDevice = m_RenderContext.GetDevice(); rhi::ResourceDesc desc; desc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; desc.ViewType = rhi::EGpuMemViewType::EGVT_CBV; desc.Size = sizeof(ConstantBuffer); - m_ConstBuffer = pDevice->NewGpuResource(desc); + m_ConstBuffer = m_pDevice->NewGpuResource(desc); OnUpdate(); -// pDevice->WaitIdle(); TOFIX: this may cause crash on Android N +// m_pDevice->WaitIdle(); TOFIX: this may cause crash on Android N } void VkTriangleUnitTest::PreparePipeline() { - auto pDevice = m_RenderContext.GetDevice(); rhi::ShaderBundle vertSh, fragSh; - compile("asset://Test/triangle.vert", rhi::ES_Vertex, vertSh); - compile("asset://Test/triangle.frag", rhi::ES_Fragment, fragSh); + Compile("asset://Test/triangle.vert", rhi::ES_Vertex, vertSh); + Compile("asset://Test/triangle.frag", rhi::ES_Fragment, fragSh); rhi::PipelineLayoutDesc ppldesc = vertSh.BindingTable; - m_pl = pDevice->NewPipelineLayout(ppldesc); - auto descriptor = m_pl->GetDescriptorSet(); - descriptor->Update(0, m_ConstBuffer); + m_pl = m_pDevice->NewPipelineLayout(ppldesc); + if(m_pl) + { + auto descriptor = m_pl->GetDescriptorSet(); + descriptor->Update(0, m_ConstBuffer); + } auto attrib = vertSh.Attributes; rhi::PipelineDesc desc; desc.Shaders[rhi::ES_Vertex] = vertSh; desc.Shaders[rhi::ES_Fragment] = fragSh; - desc.VertexLayout.Append(m_TriMesh->GetVertDec()[0]).Append(m_TriMesh->GetVertDec()[1]); - m_pPso = pDevice->NewPipelineState(desc, m_pl, rhi::EPSO_Graphics); - + desc.InputState = m_TriMesh->GetInputState(); + m_pPso = m_pDevice->NewPipelineState(desc, m_pl, rhi::EPSO_Graphics); + //m_pPso->LoadPSO("triagle.psocache"); } void VkTriangleUnitTest::PrepareCommandBuffer() { - auto pDevice = m_RenderContext.GetDevice(); - m_pFence = pDevice->NewFence(); - /* - for (uint32 i = 0; i < m_Viewport->GetSwapChainCount(); i++) - { - auto pRT = m_Viewport->GetRenderTarget(i); - auto gfxCmd = pDevice->NewCommandContext(rhi::ECMD_Graphics); - gfxCmd->Begin(); - gfxCmd->TransitionResourceBarrier(pRT->GetBackBuffer(), rhi::EPS_All, rhi::ERS_RenderTarget); - gfxCmd->SetPipelineLayout(m_pl); - rhi::Rect rect{ 0,0, (long)m_Viewport->GetWidth(), (long)m_Viewport->GetHeight() }; - gfxCmd->SetRenderTarget(pRT); - gfxCmd->SetScissorRects(1, &rect); - gfxCmd->SetViewport(rhi::ViewportDesc(m_Viewport->GetWidth(), m_Viewport->GetHeight())); - gfxCmd->SetPipelineState(0, m_pPso); - gfxCmd->SetIndexBuffer(m_TriMesh->IBO()); - gfxCmd->SetVertexBuffer(0, m_TriMesh->VBO()); - gfxCmd->DrawIndexedInstanced(rhi::DrawIndexedInstancedParam(3, 1)); - gfxCmd->EndRendering(); - gfxCmd->TransitionResourceBarrier(pRT->GetBackBuffer(), rhi::EPS_All, rhi::ERS_Present); - gfxCmd->End(); - m_Cmds.push_back(gfxCmd); - } - */ + m_pFence = m_pDevice->NewFence(); } void VkTriangleUnitTest::OnDestroy() { + App::OnDestroy(); m_TriMesh->~TriangleMesh(); - m_RenderContext.Destroy(); } void VkTriangleUnitTest::OnProcess(Message& msg) { - KLOG(Info, VkTriangleUnitTest, __K3D_FUNC__); - m_Viewport->PrepareNextFrame(); - auto curRt = m_Viewport->GetCurrentBackRenderTarget(); - auto pDevice = m_RenderContext.GetDevice(); - auto renderCmd = pDevice->NewCommandContext(rhi::ECMD_Graphics); +// KLOG(Info, VkTriangleUnitTest, __K3D_FUNC__); + m_pViewport->PrepareNextFrame(); + auto curRt = m_pViewport->GetCurrentBackRenderTarget(); + auto renderCmd = m_pDevice->NewCommandContext(rhi::ECMD_Graphics); renderCmd->Begin(); renderCmd->TransitionResourceBarrier(curRt->GetBackBuffer(), rhi::ERS_RenderTarget); renderCmd->SetPipelineLayout(m_pl); - rhi::Rect rect{ 0,0, (long)m_Viewport->GetWidth(), (long)m_Viewport->GetHeight() }; + rhi::Rect rect{ 0,0, (long)m_pViewport->GetWidth(), (long)m_pViewport->GetHeight() }; renderCmd->SetRenderTarget(curRt); renderCmd->SetScissorRects(1, &rect); - renderCmd->SetViewport(rhi::ViewportDesc(m_Viewport->GetWidth(), m_Viewport->GetHeight())); + renderCmd->SetViewport(rhi::ViewportDesc(m_pViewport->GetWidth(), m_pViewport->GetHeight())); renderCmd->SetPipelineState(0, m_pPso); renderCmd->SetIndexBuffer(m_TriMesh->IBO()); renderCmd->SetVertexBuffer(0, m_TriMesh->VBO()); @@ -340,12 +244,12 @@ void VkTriangleUnitTest::OnProcess(Message& msg) renderCmd->EndRendering(); renderCmd->TransitionResourceBarrier(curRt->GetBackBuffer(), rhi::ERS_Present); renderCmd->End(); - renderCmd->PresentInViewport(m_Viewport); + renderCmd->PresentInViewport(m_pViewport); } void VkTriangleUnitTest::OnUpdate() { - m_HostBuffer.projectionMatrix = Perspective(60.0f, (float)m_Viewport->GetWidth() / (float)m_Viewport->GetHeight(), 0.1f, 256.0f); + m_HostBuffer.projectionMatrix = Perspective(60.0f, (float)m_pViewport->GetWidth() / (float)m_pViewport->GetHeight(), 0.1f, 256.0f); m_HostBuffer.viewMatrix = Translate(Vec3f(0.0f, 0.0f, -2.5f), MakeIdentityMatrix()); m_HostBuffer.modelMatrix = MakeIdentityMatrix(); m_HostBuffer.modelMatrix = Rotate(Vec3f(1.0f, 0.0f, 0.0f), 0.f, m_HostBuffer.modelMatrix); diff --git a/Source/UnitTest/4.TexturedCube/TexturedCube.cpp b/Source/RHI/UnitTest/4.TexturedCube.cpp old mode 100755 new mode 100644 similarity index 61% rename from Source/UnitTest/4.TexturedCube/TexturedCube.cpp rename to Source/RHI/UnitTest/4.TexturedCube.cpp index 1ae69b0..ea835c2 --- a/Source/UnitTest/4.TexturedCube/TexturedCube.cpp +++ b/Source/RHI/UnitTest/4.TexturedCube.cpp @@ -1,12 +1,12 @@ #include +#include #include #include #include #include -#include #include #include -#include "TextureObject.h" +#include using namespace k3d; using namespace render; @@ -20,17 +20,21 @@ struct ConstantBuffer { Mat4f viewMatrix; }; -class TCubeUnitTest : public App +class TCubeUnitTest : public RHIAppBase { public: TCubeUnitTest(kString const & appName, uint32 width, uint32 height) - : App(appName, width, height), m_Width(width), m_Height(height) + : RHIAppBase(appName, width, height) {} explicit TCubeUnitTest(kString const & appName) - : App(appName, 1920, 1080) + : RHIAppBase(appName, 1920, 1080) {} - + + ~TCubeUnitTest() + { + KLOG(Info, CubeTest, "Destroying.."); + } bool OnInit() override; void OnDestroy() override; void OnProcess(Message & msg) override; @@ -38,8 +42,7 @@ class TCubeUnitTest : public App void OnUpdate() override; protected: - void LoadGlslangCompiler(); - void compile(const char *shaderPath, rhi::EShaderType const& type, rhi::ShaderBundle & bundle); + rhi::GpuResourceRef CreateStageBuffer(uint64 size); void LoadTexture(); void PrepareResource(); @@ -48,21 +51,15 @@ class TCubeUnitTest : public App private: - rhi::IShCompiler::Ptr m_Compiler; - std::unique_ptr m_TriMesh; - + SharedPtr m_CubeMesh; rhi::GpuResourceRef m_ConstBuffer; - TextureObject* m_Texture; + SharedPtr m_Texture; ConstantBuffer m_HostBuffer; - RenderContext m_RenderContext; - rhi::RenderViewportRef m_Viewport; rhi::PipelineStateObjectRef m_pPso; rhi::PipelineLayoutRef m_pl; std::vector m_Cmds; rhi::SyncFenceRef m_pFence; - uint32 m_Width; - uint32 m_Height; }; K3D_APP_MAIN(TCubeUnitTest); @@ -81,16 +78,18 @@ class CubeMesh explicit CubeMesh(rhi::DeviceRef device) : m_pDevice (device), vbuf(nullptr) { m_szVBuf = sizeof(CubeMesh::Vertex)*m_VertexBuffer.size(); - m_VertDecs[0] = { rhi::EVF_Float3x32, sizeof(Vertex), 0,0,0 }; /* Position */ - m_VertDecs[1] = { rhi::EVF_Float4x32, sizeof(Vertex), 1,sizeof(float)*3,0 }; /* Color */ - m_VertDecs[2] = { rhi::EVF_Float2x32, sizeof(Vertex), 2,sizeof(float)*7,0 }; /* UV */ + m_IAState.Attribs[0] = {rhi::EVF_Float3x32, 0, 0}; + m_IAState.Attribs[1] = {rhi::EVF_Float4x32, sizeof(float)*3, 0}; + m_IAState.Attribs[2] = {rhi::EVF_Float2x32, sizeof(float)*7, 0}; + + m_IAState.Layouts[0] = {rhi::EVIR_PerVertex, sizeof(Vertex)}; } ~CubeMesh() { } - - const rhi::VertexDeclaration * GetVertDec() const { return m_VertDecs; } + + const rhi::VertexInputState & GetInputState() const { return m_IAState;} void Upload(); @@ -102,42 +101,41 @@ class CubeMesh const rhi::VertexBufferView VBO() const { return rhi::VertexBufferView{ vboLoc, 0, 0 }; } private: - - rhi::VertexDeclaration m_VertDecs[3]; + rhi::VertexInputState m_IAState; uint64 m_szVBuf; VertexList m_VertexBuffer = { //left - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, - { -1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, - { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }, - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, //back { 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f }, //top { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, -1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, - { -1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, //front { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, @@ -174,7 +172,7 @@ void CubeMesh::Upload() rhi::ResourceDesc stageDesc; stageDesc.ViewType = rhi::EGpuMemViewType::EGVT_Undefined; stageDesc.CreationFlag = rhi::EGpuResourceCreationFlag::EGRCF_TransferSrc; - stageDesc.Flag = (rhi::EGpuResourceAccessFlag) (rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible); + stageDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; stageDesc.Size = m_szVBuf; auto vStageBuf = m_pDevice->NewGpuResource(stageDesc); void * ptr = vStageBuf->Map(0, m_szVBuf); @@ -195,65 +193,31 @@ void CubeMesh::Upload() cmd->End(); cmd->Execute(true); // m_pDevice->WaitIdle(); - SetLoc(vbuf->GetResourceLocation()); + SetLoc(vbuf->GetLocation()); KLOG(Info, TCubeMesh, "finish buffer upload.."); } -bool TCubeUnitTest::OnInit() +bool TCubeUnitTest::OnInit() { - bool inited = App::OnInit(); + bool inited = RHIAppBase::OnInit(); if(!inited) return inited; - LoadGlslangCompiler(); - m_RenderContext.Init(RHIType::ERTVulkan, m_Width, m_Height); - m_RenderContext.Attach(HostWindow()); - m_Viewport = m_RenderContext.GetViewport(); - KLOG(Info, Test, __K3D_FUNC__); PrepareResource(); PreparePipeline(); PrepareCommandBuffer(); - return true; } -void TCubeUnitTest::LoadGlslangCompiler() -{ - rhi::IShModule* shMod = (rhi::IShModule*)GlobalModuleManager.FindModule("ShaderCompiler"); - if (shMod) - { - m_Compiler = shMod->CreateShaderCompiler(rhi::ERHI_Vulkan); - } -} - -void TCubeUnitTest::compile(const char * shaderPath, rhi::EShaderType const & type, rhi::ShaderBundle & bundle) -{ - IAsset * shaderFile = AssetManager::Open(shaderPath); - if (!shaderFile) - { - KLOG(Fatal, "TCube", "Error opening %s.", shaderPath); - return; - } - std::vector buffer; - uint64 len = shaderFile->GetLength(); - buffer.resize(len+1); - shaderFile->Read(buffer.data(), shaderFile->GetLength()); - buffer[len] = 0; - - String src(buffer.data()); - rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, type, "main" }; - m_Compiler->Compile(src, desc, bundle); -} - rhi::GpuResourceRef TCubeUnitTest::CreateStageBuffer(uint64 size) { rhi::ResourceDesc stageDesc; stageDesc.ViewType = rhi::EGpuMemViewType::EGVT_Undefined; stageDesc.CreationFlag = rhi::EGpuResourceCreationFlag::EGRCF_TransferSrc; - stageDesc.Flag = (rhi::EGpuResourceAccessFlag) (rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible); + stageDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; stageDesc.Size = size; - return m_RenderContext.GetDevice()->NewGpuResource(stageDesc); + return m_pDevice->NewGpuResource(stageDesc); } void TCubeUnitTest::LoadTexture() @@ -264,75 +228,69 @@ void TCubeUnitTest::LoadTexture() uint64 length = textureFile->GetLength(); uint8* data = new uint8[length]; textureFile->Read(data, length); - m_Texture = new TextureObject(m_RenderContext.GetDevice(), data); + m_Texture = MakeShared(m_pDevice, data, false); auto texStageBuf = CreateStageBuffer(m_Texture->GetSize()); m_Texture->MapIntoBuffer(texStageBuf); m_Texture->CopyAndInitTexture(texStageBuf); rhi::ResourceViewDesc viewDesc; - auto pDevice = m_RenderContext.GetDevice(); - auto srv = pDevice->NewShaderResourceView(m_Texture->GetResource(), viewDesc); - auto texure = DynamicPointerCast(m_Texture->GetResource()); - texure->SetResourceView(srv); + auto srv = m_pDevice->NewShaderResourceView(m_Texture->GetResource(), viewDesc); // TODO: Fix circle ref of `m_Texture->m_Resource` + auto texure = StaticPointerCast(m_Texture->GetResource()); // + texure->SetResourceView(Move(srv)); // here rhi::SamplerState samplerDesc; - auto sampler2D = pDevice->NewSampler(samplerDesc); - texure->BindSampler(sampler2D); + auto sampler2D = m_pDevice->NewSampler(samplerDesc); + texure->BindSampler(Move(sampler2D)); } } void TCubeUnitTest::PrepareResource() { KLOG(Info, Test, __K3D_FUNC__); - m_TriMesh = std::make_unique(m_RenderContext.GetDevice()); - m_TriMesh->Upload(); + m_CubeMesh = MakeShared(m_pDevice); + m_CubeMesh->Upload(); LoadTexture(); - auto pDevice = m_RenderContext.GetDevice(); rhi::ResourceDesc desc; desc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; desc.ViewType = rhi::EGpuMemViewType::EGVT_CBV; desc.Size = sizeof(ConstantBuffer); - m_ConstBuffer = pDevice->NewGpuResource(desc); + m_ConstBuffer = m_pDevice->NewGpuResource(desc); OnUpdate(); } void TCubeUnitTest::PreparePipeline() { - auto pDevice = m_RenderContext.GetDevice(); rhi::ShaderBundle vertSh, fragSh; - compile("asset://Test/cube.vert", rhi::ES_Vertex, vertSh); - compile("asset://Test/cube.frag", rhi::ES_Fragment, fragSh); + Compile("asset://Test/cube.vert", rhi::ES_Vertex, vertSh); + Compile("asset://Test/cube.frag", rhi::ES_Fragment, fragSh); auto vertBinding = vertSh.BindingTable; auto fragBinding = fragSh.BindingTable; auto mergedBindings = vertBinding | fragBinding; - m_pl = pDevice->NewPipelineLayout(mergedBindings); + m_pl = m_pDevice->NewPipelineLayout(mergedBindings); auto descriptor = m_pl->GetDescriptorSet(); descriptor->Update(0, m_ConstBuffer); descriptor->Update(1, m_Texture->GetResource()); - //auto attrib = vertSh->GetAttributes(); rhi::PipelineDesc desc; desc.Shaders[rhi::ES_Vertex] = vertSh; desc.Shaders[rhi::ES_Fragment] = fragSh; - desc.VertexLayout.Append(m_TriMesh->GetVertDec()[0]).Append(m_TriMesh->GetVertDec()[1]).Append(m_TriMesh->GetVertDec()[2]); - m_pPso = pDevice->NewPipelineState(desc, m_pl, rhi::EPSO_Graphics); - + desc.InputState = m_CubeMesh->GetInputState(); + m_pPso = m_pDevice->NewPipelineState(desc, m_pl, rhi::EPSO_Graphics); } void TCubeUnitTest::PrepareCommandBuffer() { - auto pDevice = m_RenderContext.GetDevice(); - m_pFence = pDevice->NewFence(); - for (uint32 i = 0; i < m_Viewport->GetSwapChainCount(); i++) + m_pFence = m_pDevice->NewFence(); + for (uint32 i = 0; i < m_pViewport->GetSwapChainCount(); i++) { - auto pRT = m_Viewport->GetRenderTarget(i); - auto gfxCmd = pDevice->NewCommandContext(rhi::ECMD_Graphics); + auto pRT = m_pViewport->GetRenderTarget(i); + auto gfxCmd = m_pDevice->NewCommandContext(rhi::ECMD_Graphics); gfxCmd->Begin(); gfxCmd->TransitionResourceBarrier(pRT->GetBackBuffer(), rhi::ERS_RenderTarget); gfxCmd->SetPipelineLayout(m_pl); - rhi::Rect rect{ 0,0, (long)m_Viewport->GetWidth(), (long)m_Viewport->GetHeight() }; + rhi::Rect rect{ 0,0, (long)m_pViewport->GetWidth(), (long)m_pViewport->GetHeight() }; gfxCmd->SetRenderTarget(pRT); gfxCmd->SetScissorRects(1, &rect); - gfxCmd->SetViewport(rhi::ViewportDesc(1.f*m_Viewport->GetWidth(), 1.f*m_Viewport->GetHeight())); + gfxCmd->SetViewport(rhi::ViewportDesc(1.f*m_pViewport->GetWidth(), 1.f*m_pViewport->GetHeight())); gfxCmd->SetPipelineState(0, m_pPso); - gfxCmd->SetVertexBuffer(0, m_TriMesh->VBO()); + gfxCmd->SetVertexBuffer(0, m_CubeMesh->VBO()); gfxCmd->DrawInstanced(rhi::DrawInstancedParam(36, 1)); gfxCmd->EndRendering(); gfxCmd->TransitionResourceBarrier(pRT->GetBackBuffer(), rhi::ERS_Present); @@ -344,20 +302,20 @@ void TCubeUnitTest::PrepareCommandBuffer() void TCubeUnitTest::OnDestroy() { - m_TriMesh->~CubeMesh(); - m_RenderContext.Destroy(); + m_pFence->WaitFor(1000); + RHIAppBase::OnDestroy(); } void TCubeUnitTest::OnProcess(Message& msg) { KLOG(Info, TCubeUnitTest, __K3D_FUNC__); - m_Viewport->PrepareNextFrame(); - m_Cmds[m_Viewport->GetSwapChainIndex()]->PresentInViewport(m_Viewport); + m_pViewport->PrepareNextFrame(); + m_Cmds[m_pViewport->GetSwapChainIndex()]->PresentInViewport(m_pViewport); } void TCubeUnitTest::OnUpdate() { - m_HostBuffer.projectionMatrix = Perspective(60.0f, (float)m_Viewport->GetWidth() / (float)m_Viewport->GetHeight(), 0.1f, 256.0f); + m_HostBuffer.projectionMatrix = Perspective(60.0f, (float)m_pViewport->GetWidth() / (float)m_pViewport->GetHeight(), 0.1f, 256.0f); m_HostBuffer.viewMatrix = Translate(Vec3f(0.0f, 0.0f, -4.5f), MakeIdentityMatrix()); m_HostBuffer.modelMatrix = MakeIdentityMatrix(); static auto angle = 60.f; diff --git a/Source/RHI/UnitTest/5.ComputeParticles.cpp b/Source/RHI/UnitTest/5.ComputeParticles.cpp new file mode 100644 index 0000000..acfb857 --- /dev/null +++ b/Source/RHI/UnitTest/5.ComputeParticles.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace k3d; +using namespace kMath; + +class UTComputeParticles : public RHIAppBase +{ +public: + UTComputeParticles(kString const & appName, uint32 width, uint32 height) + : RHIAppBase(appName, width, height) + {} + explicit UTComputeParticles(kString const & appName) + : RHIAppBase(appName, 1920, 1080) + {} + + bool OnInit() override; + void OnDestroy() override; + void OnProcess(Message & msg) override; + + void OnUpdate() override; + +protected: + void PreparePipeline(); + +private: + rhi::PipelineStateObjectRef m_pGfxPso; + rhi::PipelineLayoutRef m_pGfxPl; + rhi::PipelineStateObjectRef m_pCompPso; + rhi::PipelineLayoutRef m_pCompPl; +}; + +K3D_APP_MAIN(UTComputeParticles); + +bool UTComputeParticles::OnInit() +{ + bool inited = RHIAppBase::OnInit(); + if(!inited) + return inited; + PreparePipeline(); + return true; +} + +void UTComputeParticles::PreparePipeline() +{ + rhi::ShaderBundle vertSh, fragSh, compSh; + Compile("asset://Test/particles.vert", rhi::ES_Vertex, vertSh); + Compile("asset://Test/particles.frag", rhi::ES_Fragment, fragSh); + Compile("asset://Test/particles.comp", rhi::ES_Compute, compSh); + auto vertBinding = vertSh.BindingTable; + auto fragBinding = fragSh.BindingTable; + auto mergedBindings = vertBinding | fragBinding; + m_pGfxPl = m_pDevice->NewPipelineLayout(mergedBindings); + m_pCompPl = m_pDevice->NewPipelineLayout(compSh.BindingTable); + + rhi::PipelineDesc gfxDesc; + gfxDesc.Shaders[rhi::ES_Vertex] = vertSh; + gfxDesc.Shaders[rhi::ES_Fragment] = fragSh; + //gfxDesc.InputState = m_CubeMesh->GetInputState(); + rhi::PipelineDesc compDesc; + compDesc.Shaders[rhi::ES_Compute] = compSh; + m_pGfxPso = m_pDevice->NewPipelineState(gfxDesc, m_pGfxPl, rhi::EPSO_Graphics); + m_pCompPso = m_pDevice->NewPipelineState(compDesc, m_pCompPl, rhi::EPSO_Compute); +} + +void UTComputeParticles::OnUpdate() +{ + +} + +void UTComputeParticles::OnProcess(Message & msg) +{ + +} + +void UTComputeParticles::OnDestroy() +{ + +} \ No newline at end of file diff --git a/Source/UnitTest/Android/TexturedCube/build.gradle b/Source/RHI/UnitTest/Android/TexturedCube/build.gradle old mode 100755 new mode 100644 similarity index 83% rename from Source/UnitTest/Android/TexturedCube/build.gradle rename to Source/RHI/UnitTest/Android/TexturedCube/build.gradle index b4ce206..50d81f9 --- a/Source/UnitTest/Android/TexturedCube/build.gradle +++ b/Source/RHI/UnitTest/Android/TexturedCube/build.gradle @@ -16,17 +16,17 @@ android { '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_shared', '-DANDROID_CPP_FEATURES=rtti' - targets '4.TexturedCube','KawaLog','RHI_Vulkan' + targets 'RHI-UnitTest-4.TexturedCube','KawaLog','RHI_Vulkan' } } ndk { - abiFilters 'armeabi-v7a' + abiFilters 'arm64-v8a' } } sourceSets { main { - assets.srcDirs '../../../../Data' + assets.srcDirs '../../../../../Data' } } @@ -38,7 +38,7 @@ android { } externalNativeBuild { cmake { - path "../../../CMakeLists.txt" + path "../../../../CMakeLists.txt" } } } diff --git a/Source/UnitTest/Android/TexturedCube/src/main/AndroidManifest.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/AndroidManifest.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/AndroidManifest.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/AndroidManifest.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java b/Source/RHI/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java old mode 100755 new mode 100644 similarity index 90% rename from Source/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java index 285ae5d..0e757fe --- a/Source/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java +++ b/Source/RHI/UnitTest/Android/TexturedCube/src/main/java/com/tsinstudio/app/MainActivity.java @@ -27,6 +27,6 @@ public void onDestroy() { } static { - System.loadLibrary("4.TexturedCube"); + System.loadLibrary("RHI-UnitTest-4.TexturedCube"); } } diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/layout/activity_k.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/layout/activity_k.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/layout/activity_k.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/layout/activity_k.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/mipmap-xhdpi/ic_launcher.png b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/mipmap-xhdpi/ic_launcher.png old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/mipmap-xhdpi/ic_launcher.png rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/values-w820dp/dimens.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values-w820dp/dimens.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/values-w820dp/dimens.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values-w820dp/dimens.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/values/colors.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/colors.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/values/colors.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/colors.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/values/dimens.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/dimens.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/values/dimens.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/dimens.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/values/strings.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/strings.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/values/strings.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/strings.xml diff --git a/Source/UnitTest/Android/TexturedCube/src/main/res/values/styles.xml b/Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/styles.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/TexturedCube/src/main/res/values/styles.xml rename to Source/RHI/UnitTest/Android/TexturedCube/src/main/res/values/styles.xml diff --git a/Source/UnitTest/Android/Triangle/build.gradle b/Source/RHI/UnitTest/Android/Triangle/build.gradle old mode 100755 new mode 100644 similarity index 84% rename from Source/UnitTest/Android/Triangle/build.gradle rename to Source/RHI/UnitTest/Android/Triangle/build.gradle index 9fd0373..b505390 --- a/Source/UnitTest/Android/Triangle/build.gradle +++ b/Source/RHI/UnitTest/Android/Triangle/build.gradle @@ -16,17 +16,17 @@ android { '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_shared', '-DANDROID_CPP_FEATURES=rtti' - targets '3.Triangle','RHI_Vulkan' + targets 'RHI-UnitTest-3.Triangle','RHI_Vulkan' } } ndk { - abiFilters 'armeabi-v7a' + abiFilters 'arm64-v8a' } } sourceSets { main { - assets.srcDirs '../../../../Data' + assets.srcDirs '../../../../../Data' } } @@ -38,7 +38,7 @@ android { } externalNativeBuild { cmake { - path "../../../CMakeLists.txt" + path "../../../../CMakeLists.txt" } } } diff --git a/Source/UnitTest/Android/Triangle/src/main/AndroidManifest.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/AndroidManifest.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/AndroidManifest.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/AndroidManifest.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java b/Source/RHI/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java old mode 100755 new mode 100644 similarity index 91% rename from Source/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java rename to Source/RHI/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java index bb8c3aa..0aafc0b --- a/Source/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java +++ b/Source/RHI/UnitTest/Android/Triangle/src/main/java/com/tsinstudio/app/MainActivity.java @@ -27,6 +27,6 @@ public void onDestroy() { } static { - System.loadLibrary("3.Triangle"); + System.loadLibrary("RHI-UnitTest-3.Triangle"); } } diff --git a/Source/UnitTest/Android/Triangle/src/main/res/layout/activity_k.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/layout/activity_k.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/layout/activity_k.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/layout/activity_k.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/res/mipmap-xhdpi/ic_launcher.png b/Source/RHI/UnitTest/Android/Triangle/src/main/res/mipmap-xhdpi/ic_launcher.png old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/mipmap-xhdpi/ic_launcher.png rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/Source/UnitTest/Android/Triangle/src/main/res/values-w820dp/dimens.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/values-w820dp/dimens.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/values-w820dp/dimens.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/values-w820dp/dimens.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/res/values/colors.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/values/colors.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/values/colors.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/values/colors.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/res/values/dimens.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/values/dimens.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/values/dimens.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/values/dimens.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/res/values/strings.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/values/strings.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/values/strings.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/values/strings.xml diff --git a/Source/UnitTest/Android/Triangle/src/main/res/values/styles.xml b/Source/RHI/UnitTest/Android/Triangle/src/main/res/values/styles.xml old mode 100755 new mode 100644 similarity index 100% rename from Source/UnitTest/Android/Triangle/src/main/res/values/styles.xml rename to Source/RHI/UnitTest/Android/Triangle/src/main/res/values/styles.xml diff --git a/Source/UnitTest/4.TexturedCube/TextureObject.cpp b/Source/RHI/UnitTest/Base/TextureObject.cpp old mode 100755 new mode 100644 similarity index 80% rename from Source/UnitTest/4.TexturedCube/TextureObject.cpp rename to Source/RHI/UnitTest/Base/TextureObject.cpp index 634d72d..0591746 --- a/Source/UnitTest/4.TexturedCube/TextureObject.cpp +++ b/Source/RHI/UnitTest/Base/TextureObject.cpp @@ -1,22 +1,29 @@ +#include #include "TextureObject.h" -#include "RHI/IRHI.h" +#include /////////////////////////////////////////////////////////////////////////////// -TextureObject::TextureObject(rhi::DeviceRef pDevice, const uint8_t * dataInMemory) - : m_pDevice(pDevice), m_width(0), m_height(0), m_format(rhi::EPF_RGB8Unorm), m_pBits(nullptr), m_DataSize(0) +TextureObject::TextureObject(rhi::DeviceRef pDevice, const uint8_t * dataInMemory, bool useStaging) + : m_pDevice(pDevice), m_width(0), m_height(0), m_format(rhi::EPF_RGB8Unorm), m_pBits(nullptr), m_DataSize(0), m_UseStaging(useStaging) { InitData(dataInMemory); - InitTexture(); + if (!useStaging) + { + InitTexture(); + } } TextureObject::~TextureObject() { + KLOG(Info, TextureObject, "Destroying.."); Destroy(); } void TextureObject::MapIntoBuffer(rhi::GpuResourceRef stageBuff) { + if (!m_UseStaging) + return; void * pData = stageBuff->Map(0, GetSize()); memcpy(pData, m_pBits, GetSize()); stageBuff->UnMap(); @@ -24,6 +31,8 @@ void TextureObject::MapIntoBuffer(rhi::GpuResourceRef stageBuff) void TextureObject::CopyAndInitTexture(rhi::GpuResourceRef stageBuff) { + if (!m_UseStaging) + return; rhi::ResourceDesc texDesc; texDesc.Type = rhi::EGT_Texture2D; texDesc.ViewType = rhi::EGpuMemViewType::EGVT_SRV; @@ -93,11 +102,10 @@ void TextureObject::InitData(const uint8* dataInMemory) void TextureObject::InitTexture() { - /*rhi::ResourceDesc texDesc; + rhi::ResourceDesc texDesc; texDesc.Type = rhi::EGT_Texture2D; texDesc.ViewType = rhi::EGpuMemViewType::EGVT_SRV; - texDesc.CreationFlag = rhi::EGpuResourceCreationFlag::EGRCF_TransferDst; - texDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_DeviceVisible; + texDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; texDesc.TextureDesc.Format = rhi::EPF_RGBA8Unorm; texDesc.TextureDesc.Width = m_width; texDesc.TextureDesc.Height = m_height; @@ -106,26 +114,33 @@ void TextureObject::InitTexture() texDesc.TextureDesc.Depth = 1; m_Resource = m_pDevice->NewGpuResource(texDesc); - m_pContext = m_pDevice->NewCommandContext(rhi::ECMD_Graphics); - m_pContext->Begin(); - m_pContext->TransitionResourceBarrier(m_Resource, rhi::ERS_Unknown, rhi::ERS_ShaderResource); - m_pContext->End(); - m_pContext->Execute(false); - uint64 sz = m_Resource->GetResourceSize(); + uint64 sz = m_Resource->GetSize(); void * pData = m_Resource->Map(0, sz); rhi::SubResourceLayout layout = {}; rhi::TextureResourceSpec spec = { rhi::ETAF_COLOR,0,0 }; - m_pDevice->QueryTextureSubResourceLayout(m_Resource, spec, &layout); - - for (int y = 0; y < m_height; y++) + m_pDevice->QueryTextureSubResourceLayout(k3d::StaticPointerCast(m_Resource), spec, &layout); + if (m_width * 4 == layout.RowPitch) // directly upload + { + memcpy(pData, m_pBits, sz); + } + else { - uint32_t *row = (uint32_t *)((char *)pData + layout.RowPitch * y); - for (int x = 0; x < m_width; x++) + for (int y = 0; y < m_height; y++) { - row[x] = m_pBits[x + y * m_width]; + uint32_t *row = (uint32_t *)((char *)pData + layout.RowPitch * y); + for (int x = 0; x < m_width; x++) + { + row[x] = m_pBits[x + y * m_width]; + } } } - m_Resource->UnMap();*/ + m_Resource->UnMap(); + + m_pContext = m_pDevice->NewCommandContext(rhi::ECMD_Graphics); + m_pContext->Begin(); + m_pContext->TransitionResourceBarrier(m_Resource, rhi::ERS_ShaderResource); + m_pContext->End(); + m_pContext->Execute(false); } diff --git a/Source/UnitTest/4.TexturedCube/TextureObject.h b/Source/RHI/UnitTest/Base/TextureObject.h old mode 100755 new mode 100644 similarity index 93% rename from Source/UnitTest/4.TexturedCube/TextureObject.h rename to Source/RHI/UnitTest/Base/TextureObject.h index 00045c9..6ef5236 --- a/Source/UnitTest/4.TexturedCube/TextureObject.h +++ b/Source/RHI/UnitTest/Base/TextureObject.h @@ -1,7 +1,7 @@ #ifndef __TextureObject_h__ #define __TextureObject_h__ -#include +#include /* * Defines a simple object for creating and holding Vulkan texture objects. * Supports loading from TGA files in Android Studio asset folder. @@ -11,7 +11,7 @@ class TextureObject { public: - TextureObject(rhi::DeviceRef pDevice, const uint8_t* dataInMemory); + TextureObject(rhi::DeviceRef pDevice, const uint8_t* dataInMemory, bool useStaging = true); ~TextureObject(); uint64 GetSize() const { return m_DataSize; } @@ -39,6 +39,7 @@ class TextureObject rhi::GpuResourceRef m_Resource; rhi::SamplerRef m_sampler; rhi::EPixelFormat m_format; + bool m_UseStaging; uint64 m_DataSize; uint32_t m_width; uint32_t m_height; diff --git a/Source/RHI/UnitTest/Base/UTRHIAppBase.h b/Source/RHI/UnitTest/Base/UTRHIAppBase.h new file mode 100644 index 0000000..8878014 --- /dev/null +++ b/Source/RHI/UnitTest/Base/UTRHIAppBase.h @@ -0,0 +1,131 @@ +#ifndef __UTRHIBaseApp_h__ +#define __UTRHIBaseApp_h__ + +#include +#include +#include +#include +#include +#include + +#if K3DPLATFORM_OS_WIN +#include +#include +#elif K3DPLATFORM_OS_MAC||K3DPLATFORM_OS_IOS +#include +#include +#else +#include +#include +#endif + +using namespace k3d; +using namespace kMath; + +class RHIAppBase : public App +{ +public: + RHIAppBase(kString const & appName, uint32 width, uint32 height) + : App(appName, width, height), m_Width(width), m_Height(height) + { + + } + + virtual ~RHIAppBase() override + { + } + + virtual bool OnInit() override + { + bool inited = App::OnInit(); + if(!inited) + return inited; + LoadGlslangCompiler(); + LoadRHI(); + InitViewport(); + return true; + } + + void Compile(const char * shaderPath, rhi::EShaderType const & type, rhi::ShaderBundle & shader); + +protected: + SharedPtr m_ShaderModule; + rhi::IShCompiler::Ptr m_RHICompiler; + SharedPtr m_RHIModule; + + rhi::DeviceRef m_pDevice; + rhi::RenderViewportRef m_pViewport; + + uint32 m_Width; + uint32 m_Height; + +private: + void LoadGlslangCompiler(); + void LoadRHI(); + void InitViewport(); + +private: + rhi::GfxSetting m_Setting{m_Width, m_Height, rhi::EPF_RGBA8Unorm, rhi::EPF_D32Float, true, 2 }; +}; + +void RHIAppBase::LoadGlslangCompiler() +{ + m_ShaderModule = k3d::StaticPointerCast(ACQUIRE_PLUGIN(ShaderCompiler)); + if (m_ShaderModule) + { +#if K3DPLATFORM_OS_MAC + m_RHICompiler = m_ShaderModule->CreateShaderCompiler(rhi::ERHI_Metal); +#else + m_RHICompiler = m_ShaderModule->CreateShaderCompiler(rhi::ERHI_Vulkan); +#endif + } +} + +void RHIAppBase::LoadRHI() +{ +#if !(K3DPLATFORM_OS_MAC || K3DPLATFORM_OS_IOS) + m_RHIModule = SharedPtr( ACQUIRE_PLUGIN(RHI_Vulkan) ); + auto pRHI = StaticPointerCast(m_RHIModule); + pRHI->Initialize("RenderContext", true); + pRHI->Start(); + m_pDevice = pRHI->GetPrimaryDevice(); +#else + m_RHIModule = ACQUIRE_PLUGIN(RHI_Metal); + auto pRHI = StaticPointerCast(m_RHIModule); + if(pRHI) + { + pRHI->Start(); + m_pDevice = pRHI->GetPrimaryDevice(); + } +#endif +} + +void RHIAppBase::Compile(const char * shaderPath, rhi::EShaderType const & type, rhi::ShaderBundle & shader) +{ + IAsset * shaderFile = AssetManager::Open(shaderPath); + if (!shaderFile) + { + KLOG(Fatal, "RHIAppBase", "Error opening %s.", shaderPath); + return; + } + std::vector buffer; + uint64 len = shaderFile->GetLength(); + buffer.resize(len+1); + shaderFile->Read(buffer.data(), shaderFile->GetLength()); + buffer[len] = 0; + String src(buffer.data()); + rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_HLSL, rhi::EShProfile_Modern, type, "main" }; + m_RHICompiler->Compile(src, desc, shader); +} + +void RHIAppBase::InitViewport() +{ + if (!m_pViewport) + { + rhi::GfxSetting setting{m_Width, m_Height, rhi::EPF_RGBA8Unorm, rhi::EPF_D32Float, true, 2 }; + m_pViewport = m_pDevice->NewRenderViewport(HostWindow()->GetHandle(), setting); + m_pViewport->InitViewport(nullptr, nullptr, setting); + } +} + +#endif diff --git a/Source/RHI/UnitTest/CMakeLists.txt b/Source/RHI/UnitTest/CMakeLists.txt new file mode 100644 index 0000000..e82aae8 --- /dev/null +++ b/Source/RHI/UnitTest/CMakeLists.txt @@ -0,0 +1,36 @@ +if(BUILD_SHARED) + add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) +endif() +################################## Unit Test For RHI ##################################### + +include_directories( + ${FREETYPE2_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_unittest( + RHI-UnitTest-1.Device + 1.Device.cpp +) + +add_unittest( + RHI-UnitTest-2.SwapChainPresent + 2.SwapChainPresent.cpp +) + +add_unittest( + RHI-UnitTest-3.Triangle + 3.Triangle.cpp +) + +add_unittest( + RHI-UnitTest-4.TexturedCube + 4.TexturedCube.cpp + Base/TextureObject.h + Base/TextureObject.cpp +) + +add_unittest( + RHI-UnitTest-5.ComputeParticles + 5.ComputeParticles.cpp +) \ No newline at end of file diff --git a/Source/RHI/Vulkan/CMakeLists.txt b/Source/RHI/Vulkan/CMakeLists.txt index ab7abb5..500fb1d 100755 --- a/Source/RHI/Vulkan/CMakeLists.txt +++ b/Source/RHI/Vulkan/CMakeLists.txt @@ -11,7 +11,6 @@ elseif(ANDROID) endif() set(RHI_HEADERS - ../IRHI.h VkCommon.h Public/IVkRHI.h ) @@ -29,11 +28,8 @@ set(RHI_IMPL_SRCS Private/VkCommandContext.cpp Private/VkResource.cpp Private/VkPipelineState.cpp - Private/VkSampler.cpp - Private/VkPipelineLayout.cpp Private/VkDescriptor.cpp Private/VkSwapChain.cpp - Private/VkFrameBuffer.cpp Private/VkRenderPass.cpp Private/VkDebug.cpp Private/VkImpl.cpp @@ -51,10 +47,16 @@ source_group( ${RHI_IMPL_SRCS} ) -add_plugin(RHI_Vulkan "Runtime/RHI" ${VKRHI_SRC_LIST} ${RHI_HEADERS} ${RHI_IMPL_SRCS} LINKLIBS ShaderCompiler) +add_plugin(RHI_Vulkan + FOLDER "Runtime/RHI" + SRCS ${VKRHI_SRC_LIST} ${RHI_HEADERS} ${RHI_IMPL_SRCS} + LIBS ShaderCompiler ${VULKAN_LIB}) if(NOT ANDROID) - install(TARGETS RHI_Vulkan ARCHIVE DESTINATION lib) add_precompiled_header(RHI_Vulkan "VkCommon.h" "${Kaleido3D_ROOT_DIR}/Source/RHI/Vulkan" "${Kaleido3D_ROOT_DIR}/Source/RHI/Vulkan/Private/VkRHI.cpp") endif() +install(TARGETS RHI_Vulkan + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/DynVulkanLoader.cpp b/Source/RHI/Vulkan/Private/DynVulkanLoader.cpp index 52403e1..c7c7e5b 100755 --- a/Source/RHI/Vulkan/Private/DynVulkanLoader.cpp +++ b/Source/RHI/Vulkan/Private/DynVulkanLoader.cpp @@ -15,7 +15,9 @@ static const char* LIBVULKAN = "libvulkan.so"; namespace dynlib { Lib::Lib(const char* libName) - : m_LibHandle(NULL) + : m_pUserData(nullptr) + , m_LibHandle(nullptr) + , m_CallBack(nullptr) { #if K3DPLATFORM_OS_WIN m_LibHandle = LoadLibrary(libName); @@ -28,8 +30,14 @@ namespace dynlib { if (m_LibHandle) { + if (m_CallBack) + { + m_CallBack(m_pUserData); + m_CallBack = nullptr; + } + VKLOG(Warn, "Vulkan Library will be freed, any vk-call after here(%s@%d) would be dangerous!", __FILE__, __LINE__); #if K3DPLATFORM_OS_WIN - ::FreeLibrary((HMODULE)m_LibHandle); + //::FreeLibrary((HMODULE)m_LibHandle); #else dlclose(m_LibHandle); #endif @@ -46,12 +54,14 @@ namespace dynlib #endif } - Lib & GetVulkanLib() { - static Lib vkLib(LIBVULKAN); - return vkLib; + void Lib::SetDestroyCallBack(void * userData, CallBack callback) + { + m_pUserData = userData; + m_CallBack = callback; } } +#ifdef VK_NO_PROTOTYPES _DEF_VK_FUNC_(GetInstanceProcAddr); _DEF_VK_FUNC_(GetDeviceProcAddr); @@ -203,14 +213,11 @@ _DEF_VK_FUNC_(CmdNextSubpass); _DEF_VK_FUNC_(CmdEndRenderPass); _DEF_VK_FUNC_(CmdExecuteCommands); _DEF_VK_FUNC_(AcquireNextImageKHR); +#endif int LoadVulkan(VkInstance instance, VkDevice device) { - vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dynlib::GetVulkanLib().ResolveEntry("vkGetInstanceProcAddr"); - vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties)dynlib::GetVulkanLib().ResolveEntry("vkEnumerateInstanceLayerProperties"); - vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)dynlib::GetVulkanLib().ResolveEntry("vkEnumerateInstanceExtensionProperties"); - vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)dynlib::GetVulkanLib().ResolveEntry("vkGetPhysicalDeviceSurfaceSupportKHR"); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)dynlib::GetVulkanLib().ResolveEntry("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); +#ifdef VK_NO_PROTOTYPES #if K3DPLATFORM_OS_WIN _VK_GET_INSTANCE_POINTER_(instance, CreateWin32SurfaceKHR); @@ -353,7 +360,7 @@ int LoadVulkan(VkInstance instance, VkDevice device) _VK_GET_DEVICE_POINTER_(device, CmdEndRenderPass); _VK_GET_DEVICE_POINTER_(device, CmdExecuteCommands); _VK_GET_DEVICE_POINTER_(device, AcquireNextImageKHR); - +#endif return 0; } @@ -494,7 +501,7 @@ VkResult vkCmd::CreateGraphicsPipelines(VkDevice Device, VkPipelineCache Pipelin { std::stringstream param; param << "vkCmd::CreateGraphicsPipelines() device=" << std::hex << std::setfill('0') << Device << ", cache=" << std::hex << std::setfill('0') << PipelineCache << ", CreateInfoCount=" << CreateInfoCount; - if (CreateInfoCount) + if (CreateInfoCount && CreateInfos) { for (int i = 0; i < CreateInfoCount; i++) param << ", \n\tCreateInfos[" << i << "]=" << DumpGraphicsPipelineCreateInfo(CreateInfos[i]); diff --git a/Source/RHI/Vulkan/Private/DynVulkanLoader.h b/Source/RHI/Vulkan/Private/DynVulkanLoader.h index 6e3ff8c..518b301 100755 --- a/Source/RHI/Vulkan/Private/DynVulkanLoader.h +++ b/Source/RHI/Vulkan/Private/DynVulkanLoader.h @@ -3,16 +3,30 @@ #ifndef __DynVulkanLoader_h__ #define __DynVulkanLoader_h__ -#define VK_NO_PROTOTYPES +//#define VK_NO_PROTOTYPES #if K3DPLATFORM_OS_WIN #define VK_USE_PLATFORM_WIN32_KHR 1 #elif K3DPLATFORM_OS_ANDROID #define VK_USE_PLATFORM_ANDROID_KHR 1 #endif #include +#include +#include + +#ifdef VK_NO_PROTOTYPES -#define _VK_GET_FUNCTION_FROM_LIB_(funcName) vk##funcName = (PFN_vk##funcName)dynlib::GetVulkanLib().ResolveEntry("vk" K3D_STRINGIFY(funcName)); #define _VK_GET_INSTANCE_POINTER_(instance, funcName) vk##funcName = (PFN_vk##funcName)vkGetInstanceProcAddr(instance, "vk" K3D_STRINGIFY(funcName)); + +// Macro to get a procedure address based on a vulkan instance +#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \ +{ \ + fp##entrypoint = (PFN_vk##entrypoint) gpGetInstanceProcAddr(inst, "vk"#entrypoint); \ + if (fp##entrypoint == NULL) \ + { \ + exit(1); \ + } \ +} + #define _VK_GET_DEVICE_POINTER_(device, funcName) vk##funcName = (PFN_vk##funcName)vkGetDeviceProcAddr(device, "vk" K3D_STRINGIFY(funcName)); #define _DEF_VK_FUNC_(funcName) PFN_vk##funcName vk##funcName = NULL #define _PREDEF_VK_FUNC_(funcName) extern K3D_API PFN_vk##funcName vk##funcName @@ -174,21 +188,26 @@ _PREDEF_VK_FUNC_(CmdEndRenderPass); _PREDEF_VK_FUNC_(CmdExecuteCommands); _PREDEF_VK_FUNC_(AcquireNextImageKHR); +#endif + namespace dynlib { + typedef void(*CallBack)(void* pUserData); class Lib { public: - Lib(const char* libName); + Lib(const char* libName = nullptr); ~Lib(); - void* ResolveEntry(const char* functionName); + void* ResolveEntry(const char* functionName); + void SetDestroyCallBack(void *userData, CallBack callback); private: - void*m_LibHandle; + void* m_pUserData; + void* m_LibHandle; + CallBack m_CallBack; }; - - Lib & GetVulkanLib(); + using LibRef = ::k3d::SharedPtr; } extern int LoadVulkan(VkInstance instance, VkDevice device); diff --git a/Source/RHI/Vulkan/Private/VkCommandContext.cpp b/Source/RHI/Vulkan/Private/VkCommandContext.cpp index d797b51..cd61932 100755 --- a/Source/RHI/Vulkan/Private/VkCommandContext.cpp +++ b/Source/RHI/Vulkan/Private/VkCommandContext.cpp @@ -10,8 +10,8 @@ K3D_VK_BEGIN using namespace Os; -CommandQueue::CommandQueue(Device::Ptr pDevice, VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex) - : DeviceChild(pDevice) +CommandQueue::CommandQueue(VkDevice pDevice, VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex) + : m_Device(pDevice) { Initialize(queueTypes, queueFamilyIndex, queueIndex); } @@ -45,7 +45,7 @@ VkResult CommandQueue::Submit(const std::vector& submits, VkFence K3D_ASSERT(!submits.empty()); uint32_t submitCount = static_cast(submits.size()); const VkSubmitInfo* pSubmits = submits.data(); - VkResult err = vkCmd::QueueSubmit(m_Queue, submitCount, pSubmits, fence); + VkResult err = vkQueueSubmit(m_Queue, submitCount, pSubmits, fence); K3D_ASSERT((err == VK_SUCCESS) || (err == VK_ERROR_DEVICE_LOST)); return err; } @@ -59,7 +59,7 @@ void CommandQueue::Initialize(VkQueueFlags queueTypes, uint32 queueFamilyIndex, { m_QueueFamilyIndex = queueFamilyIndex; m_QueueIndex = queueIndex; - vkGetDeviceQueue(GetRawDevice(), m_QueueFamilyIndex, m_QueueIndex, &m_Queue); + vkGetDeviceQueue(m_Device, m_QueueFamilyIndex, m_QueueIndex, &m_Queue); } void CommandQueue::Destroy() @@ -76,10 +76,10 @@ CommandContextPool::CommandContextPool(Device::Ptr pDevice) CommandContextPool::~CommandContextPool() { - VKLOG(Info, "CommandContextPool-Destroying...."); + VKLOG(Info, "CommandContextPool Destroying...."); } -CommandContext* CommandContextPool::RequestContext(rhi::ECommandType type) +rhi::CommandContextRef CommandContextPool::RequestContext(rhi::ECommandType type) { ::Os::Mutex::AutoLock lock(&m_ContextMutex); PtrCmdAlloc pAllocator = RequestCommandAllocator(); @@ -94,7 +94,7 @@ CommandContext* CommandContextPool::RequestContext(rhi::ECommandType type) } VkCommandBuffer cmdBuffer; K3D_VK_VERIFY(vkAllocateCommandBuffers(GetRawDevice(), &info, &cmdBuffer)); - auto context = new CommandContext(GetDevice(), cmdBuffer, pAllocator->GetCommandPool(), type); + auto context = rhi::CommandContextRef(new CommandContext(GetDevice(), cmdBuffer, pAllocator->GetCommandPool(), type)); //uint32 tid = Thread::GetId(); //m_ContextList[tid].push_back(context); VKLOG(Info, "CommandContextPool::RequestContext() called in thread [%s], (cmdBuf=0x%x, type=%d).", Thread::GetCurrentThreadName().c_str(), cmdBuffer, type); @@ -121,14 +121,16 @@ CommandContext::CommandContext(Device::Ptr pDevice) } CommandContext::CommandContext(Device::Ptr pDevice, VkCommandBuffer cmdBuf, VkCommandPool pool, rhi::ECommandType type) - : DeviceChild(pDevice), m_CommandBuffer(cmdBuf), m_CommandPool(pool), m_CmdType(type) + : DeviceChild(pDevice), m_CommandBuffer(cmdBuf),/* m_CommandPool(pool),*/ m_CmdType(type) { } CommandContext::~CommandContext() { - VKRHI_METHOD_TRACE - vkFreeCommandBuffers(GetRawDevice(), m_CommandPool, 1, &m_CommandBuffer); + GetDevice()->WaitIdle(); + VKLOG(Info, "CommandContext destroy.. -- %0x. ", m_CommandBuffer); + //vkFreeCommandBuffers(GetRawDevice(), m_CommandPool, 1, &m_CommandBuffer); + //m_CommandBuffer = VK_NULL_HANDLE; } void CommandContext::Detach(rhi::IDevice * pDevice) @@ -138,13 +140,13 @@ void CommandContext::Detach(rhi::IDevice * pDevice) void CommandContext::CopyBuffer(rhi::IGpuResource& Dest, rhi::IGpuResource& Src, rhi::CopyBufferRegion const& Region) { - vkCmd::CopyBuffer(m_CommandBuffer, (VkBuffer)Src.GetResourceLocation(), (VkBuffer)Dest.GetResourceLocation(), 1, (const VkBufferCopy*)&Region); + vkCmdCopyBuffer(m_CommandBuffer, (VkBuffer)Src.GetLocation(), (VkBuffer)Dest.GetLocation(), 1, (const VkBufferCopy*)&Region); } void CommandContext::CopyTexture(const rhi::TextureCopyLocation & Dest, const rhi::TextureCopyLocation & Src) { K3D_ASSERT(Dest.pResource && Src.pResource); - if (Src.pResource->GetResourceType() == rhi::EGT_Buffer && Dest.pResource->GetResourceType() != rhi::EGT_Buffer) + if (Src.pResource->GetDesc().Type == rhi::EGT_Buffer && Dest.pResource->GetDesc().Type != rhi::EGT_Buffer) { DynArray Copies; for (auto footprint : Src.SubResourceFootPrints) @@ -156,7 +158,7 @@ void CommandContext::CopyTexture(const rhi::TextureCopyLocation & Dest, const rh bImgCpy.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; Copies.Append(bImgCpy); } - vkCmdCopyBufferToImage(m_CommandBuffer, (VkBuffer)Src.pResource->GetResourceLocation(), (VkImage)Dest.pResource->GetResourceLocation(), + vkCmdCopyBufferToImage(m_CommandBuffer, (VkBuffer)Src.pResource->GetLocation(), (VkImage)Dest.pResource->GetLocation(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Copies.Count(), Copies.Data()); } } @@ -238,7 +240,7 @@ void CommandContext::SubmitAndWait(PtrSemaphore wait, PtrSemaphore signal, PtrFe q = GetImmCmdQueue(); break; } - q->Submit({ submitInfo }, fence ? fence->m_Fence : VK_NULL_HANDLE); + q->Submit({ submitInfo }, fence ? fence->NativeHandle() : VK_NULL_HANDLE); } void CommandContext::InitCommandBufferPool() @@ -347,6 +349,11 @@ void CommandContext::PipelineBarrierImageMemory(const ImageMemoryBarrierParams & VkImageMemoryBarrier barrier = params.m_Barrier; switch (params.m_Barrier.oldLayout) { + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + { + barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + break; + } case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: { barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; @@ -390,7 +397,11 @@ void CommandContext::PipelineBarrierImageMemory(const ImageMemoryBarrierParams & barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; break; } - + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + { + barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + break; + } case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: { barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; @@ -406,7 +417,6 @@ void CommandContext::PipelineBarrierImageMemory(const ImageMemoryBarrierParams & barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; break; } - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: { barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -434,8 +444,8 @@ void CommandContext::SetScissorRects(uint32 count, VkRect2D * pRects) void CommandContext::ClearColorBuffer(rhi::GpuResourceRef gpuRes, kMath::Vec4f const& color) { VkImageSubresourceRange image_subresource_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkCmdClearColorImage(m_CommandBuffer, (VkImage)gpuRes->GetResourceLocation(), - g_ResourceState[ gpuRes->GetUsageState() ], (const VkClearColorValue*)&color, 1, &image_subresource_range); + vkCmdClearColorImage(m_CommandBuffer, (VkImage)gpuRes->GetLocation(), + g_ResourceState[ gpuRes->GetState() ], (const VkClearColorValue*)&color, 1, &image_subresource_range); } void CommandContext::ClearDepthBuffer(rhi::IDepthBuffer* iDepthBuffer) @@ -499,7 +509,7 @@ void CommandContext::SetPipelineLayout(rhi::PipelineLayoutRef pRHIPipelineLayout K3D_ASSERT(pRHIPipelineLayout); auto pipelineLayout = StaticPointerCast(pRHIPipelineLayout); VkDescriptorSet sets[] = { pipelineLayout->GetNativeDescriptorSet() }; - vkCmdBindDescriptorSets(m_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->GetNativeLayout(), 0, 1, sets, 0, NULL); + vkCmdBindDescriptorSets(m_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->NativeHandle(), 0, 1, sets, 0, NULL); } void CommandContext::SetPrimitiveType(rhi::EPrimitiveType) @@ -557,16 +567,16 @@ void CommandContext::Dispatch(uint32 x, uint32 y, uint32 z) void CommandContext::TransitionResourceBarrier(rhi::GpuResourceRef resource,/* rhi::EPipelineStage stage,*/ rhi::EResourceState dstState) { - VKRHI_METHOD_TRACE - auto pTex = k3d::DynamicPointerCast(resource); + //VKRHI_METHOD_TRACE + auto pTex = k3d::StaticPointerCast(resource); if (pTex) { - VkImageLayout srcLayout = g_ResourceState[resource->GetUsageState()]; + VkImageLayout srcLayout = g_ResourceState[resource->GetState()]; VkImageLayout dstLayout = g_ResourceState[dstState]; ImageMemoryBarrierParams param(pTex->Get(), srcLayout, dstLayout); VkImageSubresourceRange texSubRange = pTex->GetSubResourceRange(); param.SrcStageMask(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT).DstStageMask(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT).SubResourceRange(texSubRange); - if (dstState == rhi::ERS_TransferDst || resource->GetUsageState() == rhi::ERS_TransferDst) + if (dstState == rhi::ERS_TransferDst || resource->GetState() == rhi::ERS_TransferDst) { param.SrcStageMask(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT).DstStageMask(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); } diff --git a/Source/RHI/Vulkan/Private/VkConfig.h b/Source/RHI/Vulkan/Private/VkConfig.h index cac6481..a8a57ff 100755 --- a/Source/RHI/Vulkan/Private/VkConfig.h +++ b/Source/RHI/Vulkan/Private/VkConfig.h @@ -14,7 +14,6 @@ namespace { "VK_LAYER_LUNARG_standard_validation", }; - } #ifdef DEBUG_MARKER diff --git a/Source/RHI/Vulkan/Private/VkDebug.cpp b/Source/RHI/Vulkan/Private/VkDebug.cpp index 79da241..8a8717d 100755 --- a/Source/RHI/Vulkan/Private/VkDebug.cpp +++ b/Source/RHI/Vulkan/Private/VkDebug.cpp @@ -1,11 +1,9 @@ #include "VkCommon.h" #include "VkConfig.h" +#include "VkObjects.h" K3D_VK_BEGIN -_DEF_VK_FUNC_(CreateDebugReportCallbackEXT); -_DEF_VK_FUNC_(DestroyDebugReportCallbackEXT); - PFN_vkDebugReportMessageEXT dbgBreakCallback; static VkDebugReportCallbackEXT msgCallback = NULL; @@ -53,39 +51,39 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( return VK_TRUE; } -void SetupDebugging(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportCallbackEXT callBack) -{ - VKRHI_METHOD_TRACE - _VK_GET_FUNCTION_FROM_LIB_(CreateDebugReportCallbackEXT); - if (!vkCreateDebugReportCallbackEXT) - _VK_GET_INSTANCE_POINTER_(instance, CreateDebugReportCallbackEXT); - _VK_GET_FUNCTION_FROM_LIB_(DestroyDebugReportCallbackEXT); - if (!vkDestroyDebugReportCallbackEXT) - _VK_GET_INSTANCE_POINTER_(instance, DestroyDebugReportCallbackEXT); +#define __VK_GLOBAL_PROC_GET__(name, functor) fp##name = reinterpret_cast(functor("vk" K3D_STRINGIFY(name))) +void Instance::SetupDebugging(VkDebugReportFlagsEXT flags, PFN_vkDebugReportCallbackEXT callBack) +{ + if (!m_Instance) + { + VKLOG(Error, "SetupDebugging Failed. (m_Instance == null)"); + return; + } +// __VK_GLOBAL_PROC_GET__(CreateDebugReportCallbackEXT, m_VulkanLib->ResolveEntry); +// if (!vkCreateDebugReportCallbackEXT) +// GET_INSTANCE_PROC_ADDR(m_Instance, CreateDebugReportCallbackEXT); +// __VK_GLOBAL_PROC_GET__(DestroyDebugReportCallbackEXT, m_VulkanLib->ResolveEntry); +// if (!fpDestroyDebugReportCallbackEXT) +// GET_INSTANCE_PROC_ADDR(m_Instance, DestroyDebugReportCallbackEXT); VkDebugReportCallbackCreateInfoEXT dbgCreateInfo; dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; dbgCreateInfo.pNext = NULL; - dbgCreateInfo.pfnCallback = &DebugReportCallback; + dbgCreateInfo.pfnCallback = callBack; dbgCreateInfo.pUserData = NULL; - dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | - VK_DEBUG_REPORT_WARNING_BIT_EXT | - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; - K3D_VK_VERIFY(vkCreateDebugReportCallbackEXT( - instance, - &dbgCreateInfo, - NULL, - &msgCallback)); + dbgCreateInfo.flags = flags; + //K3D_VK_VERIFY(vkCreateDebugReportCallbackEXT(m_Instance, &dbgCreateInfo, NULL, &m_DebugMsgCallback)); } -void FreeDebugCallback(VkInstance instance) +void Instance::FreeDebugCallback() { - if (msgCallback != NULL) + if (m_Instance && m_DebugMsgCallback) { - vkDestroyDebugReportCallbackEXT(instance, msgCallback, nullptr); - KLOG(Info, kaleido3d::VulkanRHI, "free debug callback.."); + //vkDestroyDebugReportCallbackEXT(m_Instance, m_DebugMsgCallback, nullptr); + m_DebugMsgCallback = VK_NULL_HANDLE; } } + #ifdef DEBUG_MARKER namespace DebugMarker { diff --git a/Source/RHI/Vulkan/Private/VkDescriptor.cpp b/Source/RHI/Vulkan/Private/VkDescriptor.cpp index eaa2513..15393f0 100755 --- a/Source/RHI/Vulkan/Private/VkDescriptor.cpp +++ b/Source/RHI/Vulkan/Private/VkDescriptor.cpp @@ -21,6 +21,10 @@ VkDescriptorType RHIDataType2VkType(rhi::shc::EBindType const & type) case rhi::shc::EBindType::EBlock: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case rhi::shc::EBindType::ESampler: + return VK_DESCRIPTOR_TYPE_SAMPLER; + case rhi::shc::EBindType::ESampledImage: + return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + case rhi::shc::EBindType::ESamplerImageCombine: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; case rhi::shc::EBindType::EStorageImage: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; @@ -90,7 +94,7 @@ void DescriptorAllocator::Initialize(uint32 maxSets, BindingArray const& binding void DescriptorAllocator::Destroy() { - if (VK_NULL_HANDLE == m_Pool) + if (VK_NULL_HANDLE == m_Pool || !GetRawDevice() ) return; vkDestroyDescriptorPool(GetRawDevice(), m_Pool, nullptr); m_Pool = VK_NULL_HANDLE; @@ -106,7 +110,7 @@ DescriptorSetLayout::DescriptorSetLayout(Device::Ptr pDevice, BindingArray const DescriptorSetLayout::~DescriptorSetLayout() { - Destroy(); + //Destroy(); } void DescriptorSetLayout::Initialize(BindingArray const & bindings) @@ -114,19 +118,19 @@ void DescriptorSetLayout::Initialize(BindingArray const & bindings) VkDescriptorSetLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; createInfo.bindingCount = bindings.Count(); createInfo.pBindings = bindings.Count()==0 ? nullptr : bindings.Data(); - K3D_VK_VERIFY(vkCmd::CreateDescriptorSetLayout( GetRawDevice(), &createInfo, nullptr, &m_DescriptorSetLayout )); + K3D_VK_VERIFY(vkCreateDescriptorSetLayout( GetRawDevice(), &createInfo, nullptr, &m_DescriptorSetLayout )); } void DescriptorSetLayout::Destroy() { - if( VK_NULL_HANDLE == m_DescriptorSetLayout ) + if( VK_NULL_HANDLE == m_DescriptorSetLayout || !GetRawDevice() ) return; vkDestroyDescriptorSetLayout( GetRawDevice(), m_DescriptorSetLayout, nullptr ); + VKLOG(Info, "DescriptorSetLayout destroying... -- %0x.", m_DescriptorSetLayout); m_DescriptorSetLayout = VK_NULL_HANDLE; - VKLOG(Info, "DescriptorSetLayout-destroying vkDescriptorSetLayout..."); } -DescriptorSet::DescriptorSet( DescriptorAllocator *descriptorAllocator, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice ) +DescriptorSet::DescriptorSet( DescriptorAllocRef descriptorAllocator, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice ) : DeviceChild( pDevice ) , m_DescriptorAllocator( descriptorAllocator ) , m_Bindings(bindings) @@ -135,7 +139,7 @@ DescriptorSet::DescriptorSet( DescriptorAllocator *descriptorAllocator, VkDescri } -DescriptorSet * DescriptorSet::CreateDescSet(DescriptorAllocator * descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice) +DescriptorSet * DescriptorSet::CreateDescSet(DescriptorAllocRef descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice) { return new DescriptorSet(descriptorPool, layout, bindings, pDevice); } @@ -145,40 +149,53 @@ DescriptorSet::~DescriptorSet() Destroy(); } +void DescriptorSet::Update(uint32 bindSet, rhi::SamplerRef pRHISampler) +{ + auto pSampler = StaticPointerCast(pRHISampler); + VkDescriptorImageInfo imageInfo = { pSampler->NativeHandle(), VK_NULL_HANDLE, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; + m_BoundDescriptorSet[bindSet].pImageInfo = &imageInfo; + vkUpdateDescriptorSets(GetRawDevice(), 1, &m_BoundDescriptorSet[bindSet], 0, NULL); + VKLOG(Info, "%s , Set (0x%0x) updated with sampler(location:0x%x).", __K3D_FUNC__, m_DescriptorSet, pSampler->NativeHandle()); +} + void DescriptorSet::Update(uint32 bindSet, rhi::GpuResourceRef gpuResource) { - auto desc = gpuResource->GetResourceDesc(); + auto desc = gpuResource->GetDesc(); switch(desc.Type) { case rhi::EGT_Buffer: { - VkDescriptorBufferInfo bufferInfo = { (VkBuffer)gpuResource->GetResourceLocation(), 0, gpuResource->GetResourceSize() }; + VkDescriptorBufferInfo bufferInfo = { (VkBuffer)gpuResource->GetLocation(), 0, gpuResource->GetSize() }; m_BoundDescriptorSet[bindSet].pBufferInfo = &bufferInfo; vkUpdateDescriptorSets(GetRawDevice(), 1, &m_BoundDescriptorSet[bindSet], 0, NULL); VKLOG(Info, "%s , Set (0x%0x) updated with buffer(location:0x%x, size:%d).", __K3D_FUNC__, m_DescriptorSet, - gpuResource->GetResourceLocation(), gpuResource->GetResourceSize()); + gpuResource->GetLocation(), gpuResource->GetSize()); break; } case rhi::EGT_Texture1D: case rhi::EGT_Texture2D: case rhi::EGT_Texture3D: - case rhi::EGT_Texture2DArray: + case rhi::EGT_Texture2DArray: // combined/seperated image sampler should be considered { - auto pTex = k3d::DynamicPointerCast(gpuResource); + auto pTex = k3d::StaticPointerCast(gpuResource); auto rSampler = k3d::StaticPointerCast(pTex->GetSampler()); assert(rSampler); auto srv = k3d::StaticPointerCast(pTex->GetResourceView()); - VkDescriptorImageInfo imageInfo = { rSampler->NativePtr(), srv->NativeImageView(), pTex->GetImageLayout() }; //TODO : sampler shouldn't be null - VKLOG(Warn, "pTex->GetSampler return null!"); + VkDescriptorImageInfo imageInfo = { rSampler->NativeHandle(), srv->NativeImageView(), pTex->GetImageLayout() }; //TODO : sampler shouldn't be null m_BoundDescriptorSet[bindSet].pImageInfo = &imageInfo; vkUpdateDescriptorSets(GetRawDevice(), 1, &m_BoundDescriptorSet[bindSet], 0, NULL); VKLOG(Info, "%s , Set (0x%0x) updated with image(location:0x%x, size:%d).", __K3D_FUNC__, m_DescriptorSet, - gpuResource->GetResourceLocation(), gpuResource->GetResourceSize()); + gpuResource->GetLocation(), gpuResource->GetSize()); break; } } } +uint32 DescriptorSet::GetSlotNum() const +{ + return (uint32)m_BoundDescriptorSet.size(); +} + void DescriptorSet::Initialize( VkDescriptorSetLayout layout, BindingArray const & bindings) { std::vector layouts = { layout }; @@ -186,7 +203,7 @@ void DescriptorSet::Initialize( VkDescriptorSetLayout layout, BindingArray const allocInfo.descriptorPool = m_DescriptorAllocator->m_Pool; allocInfo.descriptorSetCount = static_cast( layouts.size() ); allocInfo.pSetLayouts = layouts.empty() ? nullptr : layouts.data(); - K3D_VK_VERIFY( vkAllocateDescriptorSets( GetRawDevice(), &allocInfo, &m_DescriptorSet ) ); + K3D_VK_VERIFY(vkAllocateDescriptorSets( GetRawDevice(), &allocInfo, &m_DescriptorSet ) ); VKLOG(Info, "%s , Set (0x%0x) created.", __K3D_FUNC__, m_DescriptorSet); for (auto& binding : m_Bindings) @@ -203,19 +220,18 @@ void DescriptorSet::Initialize( VkDescriptorSetLayout layout, BindingArray const void DescriptorSet::Destroy() { - if( VK_NULL_HANDLE == m_DescriptorSet ) + if( VK_NULL_HANDLE == m_DescriptorSet || !GetRawDevice() ) return; - if( nullptr != m_DescriptorAllocator ) + if (m_DescriptorAllocator) { //const auto& options = m_DescriptorAllocator->m_Options; //if( options.hasFreeDescriptorSetFlag() ) { VkDescriptorSet descSets[1] = { m_DescriptorSet }; vkFreeDescriptorSets( GetRawDevice(), m_DescriptorAllocator->m_Pool, 1, descSets ); + m_DescriptorSet = VK_NULL_HANDLE; //} } - m_DescriptorSet = VK_NULL_HANDLE; - m_DescriptorAllocator = nullptr; VKRHI_METHOD_TRACE } diff --git a/Source/RHI/Vulkan/Private/VkDevice.cpp b/Source/RHI/Vulkan/Private/VkDevice.cpp index b4e4414..ba7cd79 100755 --- a/Source/RHI/Vulkan/Private/VkDevice.cpp +++ b/Source/RHI/Vulkan/Private/VkDevice.cpp @@ -7,17 +7,42 @@ using namespace rhi; K3D_VK_BEGIN -DeviceRef DeviceAdapter::GetDevice() +::k3d::DynArray Instance::EnumGpus() { - if (!m_pDevice) + DynArray gpus; + DynArray gpuDevices; + uint32_t gpuCount = 0; + K3D_VK_VERIFY(vkEnumeratePhysicalDevices(m_Instance, &gpuCount, nullptr)); + //gpus.Resize(gpuCount); + gpuDevices.Resize(gpuCount); + K3D_VK_VERIFY(vkEnumeratePhysicalDevices(m_Instance, &gpuCount, gpuDevices.Data())); + for (auto gpu : gpuDevices) { - m_pDevice = MakeShared(); + auto gpuRef = GpuRef(new Gpu(gpu, SharedFromThis())); + gpus.Append(gpuRef); } - return m_pDevice; + return gpus; } +//DeviceAdapter::DeviceAdapter(GpuRef const & gpu) +// : m_Gpu(gpu) +//{ +// m_pDevice = MakeShared(); +// m_pDevice->Create(this, gpu->m_Inst->WithValidation()); +// //m_Gpu->m_Inst->AppendLogicalDevice(m_pDevice); +//} +// +//DeviceAdapter::~DeviceAdapter() +//{ +//} +// +//DeviceRef DeviceAdapter::GetDevice() +//{ +// return m_pDevice; +//} + Device::Device() - : m_pGpu(nullptr) + : m_Gpu(nullptr) , m_Device(VK_NULL_HANDLE) { } @@ -31,164 +56,105 @@ void Device::Destroy() { if (VK_NULL_HANDLE == m_Device) return; - for (auto pll : m_CachedPipelineLayout) - { - pll.second->~PipelineLayout(); - } - m_CachedPipelineLayout.clear(); - - for (auto dsl : m_CachedDescriptorSetLayout) - { - dsl.second->~DescriptorSetLayout(); - } - - for (auto alloc : m_CachedDescriptorPool) + vkDeviceWaitIdle(m_Device); + VKLOG(Info, "Device Destroying . -- %0x.", m_Device); + ///*if (!m_CachedDescriptorSetLayout.empty()) + //{ + // m_CachedDescriptorSetLayout.erase(m_CachedDescriptorSetLayout.begin(), + // m_CachedDescriptorSetLayout.end()); + //} + //if (!m_CachedDescriptorPool.empty()) + //{ + // m_CachedDescriptorPool.erase(m_CachedDescriptorPool.begin(), + // m_CachedDescriptorPool.end()); + //} + //if (!m_CachedPipelineLayout.empty()) + //{ + // m_CachedPipelineLayout.erase(m_CachedPipelineLayout.begin(), + // m_CachedPipelineLayout.end()); + //}*/ + //m_PendingPass.~vector(); + //m_ResourceManager->~ResourceManager(); + //m_ContextPool->~CommandContextPool(); + if (m_CmdBufManager) { - alloc.second->~DescriptorAllocator(); + m_CmdBufManager->~CommandBufferManager(); } - - m_CachedDescriptorSetLayout.clear(); - m_PendingPass.~vector(); - m_ResourceManager->~ResourceManager(); - m_ContextPool->~CommandContextPool(); - vkDestroyDevice(m_Device, nullptr); - VKLOG(Info, "Device-Destroyed"); + VKLOG(Info, "Device Destroyed . -- %0x.", m_Device); m_Device = VK_NULL_HANDLE; } IDevice::Result Device::Create(rhi::IDeviceAdapter* pAdapter, bool withDbg) { - m_pGpu = static_cast(pAdapter)->m_pGpu; - VkPhysicalDevice& Gpu = *static_cast(pAdapter)->m_pGpu; - vkGetPhysicalDeviceMemoryProperties(Gpu, &m_MemoryProperties); - VkResult err = CreateDevice(Gpu, withDbg, &m_Device); - if (err) - { - VKLOG(Fatal, "Device-Create: Could not create Vulkan Device : %s.", ErrorString(err).c_str()); - return rhi::IDevice::DeviceNotFound; - } - else + //m_Gpu = static_cast(pAdapter)->m_Gpu; + //m_Device = m_Gpu->CreateLogicDevice(withDbg); + //if(m_Device) + //{ + // //LoadVulkan(m_Gpu->m_Inst->m_Instance, m_Device); + // if (withDbg) + // { + // RHIRoot::SetupDebug(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT + // | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, DebugReportCallback); + // } + // //m_ResourceManager = std::make_unique(SharedFromThis(), 1024, 1024); + // //m_ContextPool = std::make_unique(SharedFromThis()); + // m_DefCmdQueue = InitCmdQueue(VK_QUEUE_GRAPHICS_BIT, m_Gpu->m_GraphicsQueueIndex, 0); + // m_ComputeCmdQueue = InitCmdQueue(VK_QUEUE_COMPUTE_BIT, m_Gpu->m_ComputeQueueIndex, 0); + // return rhi::IDevice::DeviceFound; + //} + return rhi::IDevice::DeviceNotFound; +} + +IDevice::Result +Device::Create(GpuRef const & gpu, bool withDebug) +{ + m_Gpu = gpu; + m_Device = m_Gpu->CreateLogicDevice(withDebug); + if (m_Device) { - LoadVulkan(RHIRoot::GetInstance(), m_Device); -#if K3DPLATFORM_OS_WIN && _DEBUG - if (withDbg) + //LoadVulkan(m_Gpu->m_Inst->m_Instance, m_Device); + if (withDebug) { - SetupDebugging(RHIRoot::GetInstance(), VK_DEBUG_REPORT_ERROR_BIT_EXT | - VK_DEBUG_REPORT_WARNING_BIT_EXT | - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, nullptr); + RHIRoot::SetupDebug(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT + | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, DebugReportCallback); } -#endif - m_ResourceManager = std::make_unique(this, 1024, 1024); - m_ContextPool = std::make_unique(this); - m_DefCmdQueue = InitCmdQueue(VK_QUEUE_GRAPHICS_BIT, m_GraphicsQueueIndex, 0); - m_ComputeCmdQueue = InitCmdQueue(VK_QUEUE_COMPUTE_BIT, m_ComputeQueueIndex, 0); + //m_ResourceManager = std::make_unique(SharedFromThis(), 1024, 1024); + //m_ContextPool = std::make_unique(SharedFromThis()); + m_DefCmdQueue = InitCmdQueue(VK_QUEUE_GRAPHICS_BIT, m_Gpu->m_GraphicsQueueIndex, 0); + m_ComputeCmdQueue = InitCmdQueue(VK_QUEUE_COMPUTE_BIT, m_Gpu->m_ComputeQueueIndex, 0); return rhi::IDevice::DeviceFound; } + return rhi::IDevice::DeviceNotFound; } RenderTargetRef Device::NewRenderTarget(rhi::RenderTargetLayout const & layout) { - return RenderTargetRef(new RenderTarget(this, layout)); + return RenderTargetRef(new RenderTarget(SharedFromThis(), layout)); } uint64 Device::GetMaxAllocationCount() { - return m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount; + return m_Gpu->m_Prop.limits.maxMemoryAllocationCount; } SpCmdQueue Device::InitCmdQueue(VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex) { - return std::make_shared(this, queueTypes, queueFamilyIndex, queueIndex); -} - -VkResult Device::CreateDevice(VkPhysicalDevice gpu, bool withDebug, VkDevice * pDevice) -{ - // get all device queues and find graphics queue - GetDeviceQueueProps(gpu); - - // get device limits - vkGetPhysicalDeviceProperties(gpu, &m_PhysicalDeviceProperties); - - std::array queuePriorities = { 0.0f }; - VkDeviceQueueCreateInfo queueCreateInfo = {}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = m_GraphicsQueueIndex; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = queuePriorities.data(); - - std::vector enabledExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - VkDeviceCreateInfo deviceCreateInfo = {}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.pNext = NULL; - deviceCreateInfo.queueCreateInfoCount = 1; - deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; - deviceCreateInfo.pEnabledFeatures = NULL; - - if (withDebug) - { - deviceCreateInfo.enabledLayerCount = (uint32)RHIRoot::s_LayerNames.size(); - deviceCreateInfo.ppEnabledLayerNames = RHIRoot::s_LayerNames.data(); - } - - if (enabledExtensions.size() > 0) - { - deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledExtensions.size(); - deviceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data(); - } - return vkCreateDevice(gpu, &deviceCreateInfo, nullptr, pDevice); -} - -bool Device::GetDeviceQueueProps(VkPhysicalDevice gpu) -{ - vkGetPhysicalDeviceQueueFamilyProperties(gpu, &m_QueueCount, NULL); - if(m_QueueCount < 1) - return false; - VKLOG(Info, "Device-PhysicDeviceQueue count = %d.", m_QueueCount); - queueProps.resize(m_QueueCount); - vkGetPhysicalDeviceQueueFamilyProperties(gpu, &m_QueueCount, queueProps.data()); - uint32 qId = 0; - for (qId = 0; qId < m_QueueCount; qId++) - { - if (queueProps[qId].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - m_GraphicsQueueIndex = qId; - VKLOG(Info, "Device-graphicsQueueIndex(%d) queueFlags(%d).", m_GraphicsQueueIndex, queueProps[qId].queueFlags); - break; - } - } - for (qId = 0; qId < m_QueueCount; qId++) - { - if (queueProps[qId].queueFlags & VK_QUEUE_COMPUTE_BIT) - { - m_ComputeQueueIndex = qId; - VKLOG(Info, "Device::ComputeQueueIndex(%d).", m_ComputeQueueIndex); - break; - } - } - for (qId = 0; qId < m_QueueCount; qId++) - { - if (queueProps[qId].queueFlags & VK_QUEUE_TRANSFER_BIT) - { - m_CopyQueueIndex = qId; - VKLOG(Info, "Device::CopyQueueIndex(%d).", m_CopyQueueIndex); - break; - } - } - return qId < m_QueueCount; + return std::make_shared(m_Device, queueTypes, queueFamilyIndex, queueIndex); } -bool Device::FindMemoryType(uint32_t typeBits, VkFlags requirementsMask, uint32_t *typeIndex) const +bool Device::FindMemoryType(uint32 typeBits, VkFlags requirementsMask, uint32 *typeIndex) const { #ifdef max #undef max *typeIndex = std::numeric_limits::type>::max(); #endif - for (uint32_t i = 0; i < m_MemoryProperties.memoryTypeCount; ++i) { + auto memProp = m_Gpu->m_MemProp; + for (uint32_t i = 0; i < memProp.memoryTypeCount; ++i) { if (typeBits & 0x00000001) { - if (requirementsMask == (m_MemoryProperties.memoryTypes[i].propertyFlags & requirementsMask)) { + if (requirementsMask == (memProp.memoryTypes[i].propertyFlags & requirementsMask)) { *typeIndex = i; return true; } @@ -202,49 +168,58 @@ bool Device::FindMemoryType(uint32_t typeBits, VkFlags requirementsMask, uint32_ CommandContextRef Device::NewCommandContext(rhi::ECommandType Type) { - return CommandContextRef(m_ContextPool->RequestContext(Type)); + if (!m_CmdBufManager) + { + m_CmdBufManager = CmdBufManagerRef(new CommandBufferManager(m_Device, VK_COMMAND_BUFFER_LEVEL_PRIMARY, m_Gpu->m_GraphicsQueueIndex)); + } + return rhi::CommandContextRef(new CommandContext(SharedFromThis(), m_CmdBufManager->RequestCommandBuffer(), VK_NULL_HANDLE, Type)); + //return m_ContextPool->RequestContext(Type); } SamplerRef Device::NewSampler(const rhi::SamplerState& samplerDesc) { - return MakeShared(this, samplerDesc); + return MakeShared(SharedFromThis(), samplerDesc); } -PipelineLayoutRef +rhi::PipelineLayoutRef Device::NewPipelineLayout(rhi::PipelineLayoutDesc const & table) { // Hash the table parameter here, // Lookup the layout by hash code - rhi::PipelineLayoutKey key = HashPipelineLayoutDesc(table); + /*rhi::PipelineLayoutKey key = HashPipelineLayoutDesc(table); if (m_CachedPipelineLayout.find(key) == m_CachedPipelineLayout.end()) { - m_CachedPipelineLayout[key] = new PipelineLayout(this, table);; - } - return PipelineLayoutRef(m_CachedPipelineLayout[key]); + auto plRef = rhi::PipelineLayoutRef(new PipelineLayout(this, table)); + m_CachedPipelineLayout.insert({ key, plRef }); + }*/ + return rhi::PipelineLayoutRef(new PipelineLayout(SharedFromThis(), table)); } -DescriptorAllocator * +DescriptorAllocRef Device::NewDescriptorAllocator(uint32 maxSets, BindingArray const & bindings) { uint32 key = util::Hash32((const char*)bindings.Data(), bindings.Count() * sizeof(VkDescriptorSetLayoutBinding)); - if (m_CachedDescriptorPool.find(key) == m_CachedDescriptorPool.end()) + /*if (m_CachedDescriptorPool.find(key) == m_CachedDescriptorPool.end()) { - DescriptorAllocator::Options options = {}; - m_CachedDescriptorPool[key] = new DescriptorAllocator(this, options, maxSets, bindings); - } - return m_CachedDescriptorPool[key]; + DescriptorAllocator::Options options = {}; + auto descAllocRef = DescriptorAllocRef(new DescriptorAllocator(this, options, maxSets, bindings)); + m_CachedDescriptorPool.insert({ key, descAllocRef }); + }*/ + DescriptorAllocator::Options options = {}; + return DescriptorAllocRef(new DescriptorAllocator(SharedFromThis(), options, maxSets, bindings)); } -DescriptorSetLayout * +DescriptorSetLayoutRef Device::NewDescriptorSetLayout(BindingArray const & bindings) { uint32 key = util::Hash32((const char*)bindings.Data(), bindings.Count() * sizeof(VkDescriptorSetLayoutBinding)); - if (m_CachedDescriptorSetLayout.find(key) == m_CachedDescriptorSetLayout.end()) + /*if (m_CachedDescriptorSetLayout.find(key) == m_CachedDescriptorSetLayout.end()) { - m_CachedDescriptorSetLayout[key] = new DescriptorSetLayout(this, bindings); - } - return m_CachedDescriptorSetLayout[key]; + auto descSetLayoutRef = DescriptorSetLayoutRef(new DescriptorSetLayout(this, bindings)); + m_CachedDescriptorSetLayout.insert({ key, descSetLayoutRef }); + }*/ + return DescriptorSetLayoutRef(new DescriptorSetLayout(SharedFromThis(), bindings)); } PipelineStateObjectRef @@ -256,13 +231,13 @@ Device::NewPipelineState(rhi::PipelineDesc const & desc, rhi::PipelineLayoutRef PipelineStateObjectRef Device::CreatePipelineStateObject(rhi::PipelineDesc const & desc, rhi::PipelineLayoutRef ppl) { - return MakeShared(this, desc, static_cast(ppl.Get())); + return MakeShared(SharedFromThis(), desc, static_cast(ppl.Get())); } SyncFenceRef Device::NewFence() { - return MakeShared(this); + return MakeShared(SharedFromThis()); } GpuResourceRef @@ -272,12 +247,12 @@ Device::NewGpuResource(rhi::ResourceDesc const& Desc) switch (Desc.Type) { case rhi::EGT_Buffer: - resource = new Buffer(this, Desc); + resource = new Buffer(SharedFromThis(), Desc); break; case rhi::EGT_Texture1D: break; case rhi::EGT_Texture2D: - resource = new Texture(this, Desc); + resource = new Texture(SharedFromThis(), Desc); break; default: break; @@ -288,7 +263,7 @@ Device::NewGpuResource(rhi::ResourceDesc const& Desc) ShaderResourceViewRef Device::NewShaderResourceView(rhi::GpuResourceRef pRes, rhi::ResourceViewDesc const & desc) { - return MakeShared(desc, pRes.Get()); + return MakeShared(SharedFromThis(), desc, pRes); } rhi::IDescriptorPool * @@ -300,29 +275,32 @@ Device::NewDescriptorPool() RenderViewportRef Device::NewRenderViewport(void * winHandle, rhi::GfxSetting& setting) { - return MakeShared(this, winHandle, setting); + auto pViewport = MakeShared(SharedFromThis(), winHandle, setting); + RHIRoot::AddViewport(pViewport); + return pViewport; } PtrCmdAlloc Device::NewCommandAllocator(bool transient) { - return CommandAllocator::CreateAllocator(m_GraphicsQueueIndex, false, this); + return CommandAllocator::CreateAllocator(m_Gpu->m_GraphicsQueueIndex, transient, SharedFromThis()); } PtrSemaphore Device::NewSemaphore() { - return std::make_shared(this); + return std::make_shared(SharedFromThis()); } -void Device::QueryTextureSubResourceLayout(rhi::GpuResourceRef resource, rhi::TextureResourceSpec const & spec, rhi::SubResourceLayout * layout) +void Device::QueryTextureSubResourceLayout(rhi::TextureRef resource, rhi::TextureResourceSpec const & spec, rhi::SubResourceLayout * layout) { - K3D_ASSERT(resource && resource->GetResourceType() != rhi::EGT_Buffer); - vkGetImageSubresourceLayout(m_Device, (VkImage)resource->GetResourceLocation(), (const VkImageSubresource*)&spec, (VkSubresourceLayout*)layout); + K3D_ASSERT(resource); + auto texture = StaticPointerCast(resource); + vkGetImageSubresourceLayout(m_Device, (VkImage)resource->GetLocation(), (const VkImageSubresource*)&spec, (VkSubresourceLayout*)layout); } SwapChainRef Device::NewSwapChain(rhi::GfxSetting const & setting) { - return k3d::MakeShared(this); + return k3d::MakeShared(SharedFromThis()); } K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkEnums.h b/Source/RHI/Vulkan/Private/VkEnums.h index 60acef1..cfd7af9 100755 --- a/Source/RHI/Vulkan/Private/VkEnums.h +++ b/Source/RHI/Vulkan/Private/VkEnums.h @@ -24,6 +24,11 @@ namespace VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, }; + VkVertexInputRate g_InputRates[] = { + VK_VERTEX_INPUT_RATE_VERTEX, + VK_VERTEX_INPUT_RATE_INSTANCE, + }; + VkCullModeFlagBits g_CullMode[rhi::RasterizerState::CullModeNum] = { VK_CULL_MODE_NONE, VK_CULL_MODE_FRONT_BIT, diff --git a/Source/RHI/Vulkan/Private/VkFrameBuffer.cpp b/Source/RHI/Vulkan/Private/VkFrameBuffer.cpp deleted file mode 100755 index 9a216d7..0000000 --- a/Source/RHI/Vulkan/Private/VkFrameBuffer.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "VkCommon.h" -#include "VkRHI.h" -#include "VkUtils.h" - -K3D_VK_BEGIN - -FrameBuffer::FrameBuffer(Device::Ptr pDevice, VkRenderPass renderPass, FrameBuffer::Option const& op) - : DeviceChild(pDevice) - , m_RenderPass(renderPass) - , m_Width(op.Width) - , m_Height(op.Height) -{ - VKRHI_METHOD_TRACE - for (auto& elem : op.Attachments) - { - if (elem.ImageAttachment) - { - continue; - } - } - - std::vector attachments; - for (const auto& elem : op.Attachments) { - attachments.push_back(elem.ImageAttachment); - } - - VkFramebufferCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.renderPass = m_RenderPass; - createInfo.attachmentCount = static_cast(op.Attachments.size()); - createInfo.pAttachments = attachments.data(); - createInfo.width = m_Width; - createInfo.height = m_Height; - createInfo.layers = 1; - createInfo.flags = 0; - K3D_VK_VERIFY(vkCreateFramebuffer(GetRawDevice(), &createInfo, nullptr, &m_FrameBuffer)); -} - -FrameBuffer::FrameBuffer(Device::Ptr pDevice, RenderPass * renderPass, RenderTargetLayout const &) - : DeviceChild(pDevice) -{ -} - -FrameBuffer::~FrameBuffer() -{ - if (VK_NULL_HANDLE == m_FrameBuffer) - { - return; - } - vkDestroyFramebuffer(GetRawDevice(), m_FrameBuffer, nullptr); - m_FrameBuffer = VK_NULL_HANDLE; - VKRHI_METHOD_TRACE -} - -FrameBuffer::Attachment::Attachment(VkFormat format, VkSampleCountFlagBits samples) -{ - VkImageAspectFlags aspectMask = DetermineAspectMask(Format); - if (VK_IMAGE_ASPECT_COLOR_BIT == aspectMask) - { - FormatFeatures = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - } - else - { - FormatFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; - } -} - -K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkImpl.cpp b/Source/RHI/Vulkan/Private/VkImpl.cpp index da664c3..4d499ec 100755 --- a/Source/RHI/Vulkan/Private/VkImpl.cpp +++ b/Source/RHI/Vulkan/Private/VkImpl.cpp @@ -31,7 +31,7 @@ void VkLog(k3d::ELogLevel const& Lv, const char * tag, const char * fmt, ...) vsprintf(logContent, fmt, va); va_end(va); - k3d::ILogModule* logModule = (k3d::ILogModule*)k3d::GlobalModuleManager.FindModule("KawaLog"); + auto logModule = k3d::StaticPointerCast(k3d::GlobalModuleManager.FindModule("KawaLog")); if (logModule) { k3d::ILogger* logger = logModule->GetLogger(k3d::ELoggerType::EWebsocket); diff --git a/Source/RHI/Vulkan/Private/VkObjects.cpp b/Source/RHI/Vulkan/Private/VkObjects.cpp index 89244b3..b10087c 100755 --- a/Source/RHI/Vulkan/Private/VkObjects.cpp +++ b/Source/RHI/Vulkan/Private/VkObjects.cpp @@ -1,6 +1,8 @@ #include "VkCommon.h" #include "VkObjects.h" #include "VkEnums.h" +#include "VkConfig.h" +#include K3D_VK_BEGIN @@ -207,6 +209,22 @@ std::pair ImageViewInfo::CreateColorImageVie return std::make_pair(std::move(imageView), std::move(info)); } +std::pair ImageViewInfo::CreateColorImageView(GpuRef device, VkFormat colorFmt, VkImage colorImage, VkImageAspectFlags aspectMask) +{ + VkImageView imageView = VK_NULL_HANDLE; + VkImageViewCreateInfo info = CreateColorImageInfo(colorFmt, colorImage); + K3D_ASSERT(0 != info.subresourceRange.aspectMask); + if (VK_IMAGE_ASPECT_COLOR_BIT == info.subresourceRange.aspectMask) + { + info.components.r = VK_COMPONENT_SWIZZLE_R; + info.components.g = VK_COMPONENT_SWIZZLE_G; + info.components.b = VK_COMPONENT_SWIZZLE_B; + info.components.a = VK_COMPONENT_SWIZZLE_A; + } + K3D_VK_VERIFY(vkCreateImageView(device->m_LogicalDevice, &info, nullptr, &imageView)); + return std::make_pair(std::move(imageView), std::move(info)); +} + std::pair ImageViewInfo::CreateDepthStencilImageView(VkDevice device, VkFormat colorFmt, VkImage colorImage, VkImageAspectFlags aspectMask) { VkImageView imageView = VK_NULL_HANDLE; @@ -230,4 +248,613 @@ ImageViewInfo ImageViewInfo::From(ImageInfo const & info, VkImage image) return imageViewInfo; } -K3D_VK_END +void * VkObjectAllocator::Allocation(void * pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) +{ + return static_cast(pUserData)->Allocation(size, alignment, allocationScope); +} + +void * VkObjectAllocator::Reallocation(void * pUserData, void * pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) +{ + return static_cast(pUserData)->Reallocation(pOriginal, size, alignment, allocationScope); +} + +void VkObjectAllocator::Free(void * pUserData, void * pMemory) +{ + return static_cast(pUserData)->Free(pMemory); +} + +void * VkObjectAllocator::Allocation(size_t size, size_t alignment, VkSystemAllocationScope allocationScope) +{ + return __k3d_malloc__(size); +} + +void * VkObjectAllocator::Reallocation(void * pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) +{ + return __k3d_malloc__(size); +} + +void VkObjectAllocator::Free(void * pMemory) +{ + __k3d_free__(pMemory, 0); +} + + +CommandBufferManager::CommandBufferManager(VkDevice gpu, VkCommandBufferLevel bufferLevel, + unsigned graphicsQueueIndex) + : m_Device(gpu) + , m_CommandBufferLevel(bufferLevel) + , m_Count(0) +{ + // RESET_COMMAND_BUFFER_BIT allows command buffers to be reset individually. + VkCommandPoolCreateInfo info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + info.queueFamilyIndex = graphicsQueueIndex; + info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + K3D_VK_VERIFY(vkCreateCommandPool(m_Device, &info, nullptr, &m_Pool)); +} + +CommandBufferManager::~CommandBufferManager() +{ + Destroy(); +} + +void CommandBufferManager::Destroy() +{ + if (!m_Pool) + return; + vkDeviceWaitIdle(m_Device); + VKLOG(Info, "CommandBufferManager destroy. -- 0x%0x.", m_Pool); + vkFreeCommandBuffers(m_Device, m_Pool, m_Buffers.size(), m_Buffers.data()); + vkDestroyCommandPool(m_Device, m_Pool, nullptr); + m_Pool = VK_NULL_HANDLE; +} + +void CommandBufferManager::BeginFrame() +{ + m_Count = 0; +} + +VkCommandBuffer CommandBufferManager::RequestCommandBuffer() +{ + // Either we recycle a previously allocated command buffer, or create a new one. + VkCommandBuffer ret = VK_NULL_HANDLE; + if (m_Count < m_Buffers.size()) + { + ret = m_Buffers[m_Count++]; + K3D_VK_VERIFY(vkResetCommandBuffer(ret, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT)); + } + else + { + VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + info.commandPool = m_Pool; + info.level = m_CommandBufferLevel; + info.commandBufferCount = 1; + K3D_VK_VERIFY(vkAllocateCommandBuffers(m_Device, &info, &ret)); + m_Buffers.push_back(ret); + + m_Count++; + } + + return ret; +} + +Gpu::Gpu(VkPhysicalDevice const& gpu, InstanceRef const& pInst) + : m_Inst(pInst) + , m_LogicalDevice(VK_NULL_HANDLE) + , m_PhysicalGpu(gpu) +{ + vkGetPhysicalDeviceProperties(m_PhysicalGpu, &m_Prop); + vkGetPhysicalDeviceMemoryProperties(m_PhysicalGpu, &m_MemProp); + VKLOG(Info, "Gpu: %s", m_Prop.deviceName); + QuerySupportQueues(); +} + +void Gpu::QuerySupportQueues() +{ + uint32 queueCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalGpu, &queueCount, NULL); + if (queueCount < 1) + return; + m_QueueProps.Resize(queueCount); + vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalGpu, &queueCount, m_QueueProps.Data()); + uint32 qId = 0; + for (qId = 0; qId < queueCount; qId++) + { + if (m_QueueProps[qId].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + m_GraphicsQueueIndex = qId; + VKLOG(Info, "Device::graphicsQueueIndex(%d) queueFlags(%d).", m_GraphicsQueueIndex, m_QueueProps[qId].queueFlags); + break; + } + } + for (qId = 0; qId < queueCount; qId++) + { + if (m_QueueProps[qId].queueFlags & VK_QUEUE_COMPUTE_BIT) + { + m_ComputeQueueIndex = qId; + VKLOG(Info, "Device::ComputeQueueIndex(%d).", m_ComputeQueueIndex); + break; + } + } + for (qId = 0; qId < queueCount; qId++) + { + if (m_QueueProps[qId].queueFlags & VK_QUEUE_TRANSFER_BIT) + { + m_CopyQueueIndex = qId; + VKLOG(Info, "Device::CopyQueueIndex(%d).", m_CopyQueueIndex); + break; + } + } +} + +#define __VK_GET_DEVICE_PROC__(name, getDeviceProc, device) \ +if(!vk##name) \ +{\ +vk##name = (PFN_vk##name)getDeviceProc(device, "vk" K3D_STRINGIFY(name)); \ +if (!vk##name) \ +{\ +VKLOG(Fatal, "LoadDeviceProcs::" K3D_STRINGIFY(name) " not exist!" );\ +exit(-1);\ +}\ +} + +void Gpu::LoadDeviceProcs() +{ +#ifdef VK_NO_PROTOTYPES + if (!fpDestroyDevice) + { + fpDestroyDevice = (PFN_vkDestroyDevice)m_Inst->fpGetDeviceProcAddr(m_LogicalDevice, "vkDestroyDevice"); + } + if (!fpFreeCommandBuffers) + { + fpFreeCommandBuffers = (PFN_vkFreeCommandBuffers)m_Inst->fpGetDeviceProcAddr(m_LogicalDevice, "vkFreeCommandBuffers"); + } + if (!fpCreateCommandPool) + { + fpCreateCommandPool = (PFN_vkCreateCommandPool)m_Inst->fpGetDeviceProcAddr(m_LogicalDevice, "vkCreateCommandPool"); + } + if (!fpAllocateCommandBuffers) + { + fpAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)m_Inst->fpGetDeviceProcAddr(m_LogicalDevice, "vkAllocateCommandBuffers"); + } + __VK_GET_DEVICE_PROC__(DestroyDevice, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetDeviceQueue, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(QueueSubmit, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(QueueWaitIdle, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(QueuePresentKHR, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DeviceWaitIdle, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(AllocateMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(FreeMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(MapMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(UnmapMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(FlushMappedMemoryRanges, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(InvalidateMappedMemoryRanges, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetDeviceMemoryCommitment, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(BindBufferMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(BindImageMemory, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetBufferMemoryRequirements, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetImageMemoryRequirements, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetImageSparseMemoryRequirements, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(QueueBindSparse, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateFence, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyFence, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(ResetFences, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetFenceStatus, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(WaitForFences, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateSemaphore, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroySemaphore, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetEventStatus, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(SetEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(ResetEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateQueryPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyQueryPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetQueryPoolResults, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateBufferView, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyBufferView, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetImageSubresourceLayout, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateImageView, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyImageView, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateShaderModule, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyShaderModule, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreatePipelineCache, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyPipelineCache, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetPipelineCacheData, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(MergePipelineCaches, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateGraphicsPipelines, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateComputePipelines, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyPipeline, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreatePipelineLayout, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyPipelineLayout, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateSampler, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroySampler, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateDescriptorSetLayout, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyDescriptorSetLayout, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateDescriptorPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyDescriptorPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(ResetDescriptorPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(AllocateDescriptorSets, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(FreeDescriptorSets, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(UpdateDescriptorSets, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateFramebuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyFramebuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateRenderPass, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyRenderPass, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetRenderAreaGranularity, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateCommandPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroyCommandPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(ResetCommandPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(AllocateCommandBuffers, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(FreeCommandBuffers, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(BeginCommandBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(EndCommandBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(ResetCommandBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBindPipeline, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetViewport, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetScissor, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetLineWidth, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetDepthBias, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetBlendConstants, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetDepthBounds, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetStencilCompareMask, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetStencilWriteMask, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetStencilReference, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBindDescriptorSets, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBindIndexBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBindVertexBuffers, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDraw, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDrawIndexed, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDrawIndirect, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDrawIndexedIndirect, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDispatch, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdDispatchIndirect, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdCopyBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdCopyImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBlitImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdCopyBufferToImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdCopyImageToBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdUpdateBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdFillBuffer, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdClearColorImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdClearDepthStencilImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdClearAttachments, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdResolveImage, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdSetEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdResetEvent, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdWaitEvents, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdPipelineBarrier, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBeginQuery, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdEndQuery, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdResetQueryPool, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdWriteTimestamp, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdCopyQueryPoolResults, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdPushConstants, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdBeginRenderPass, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdNextSubpass, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdEndRenderPass, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CmdExecuteCommands, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(AcquireNextImageKHR, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(CreateSwapchainKHR, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(DestroySwapchainKHR, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); + __VK_GET_DEVICE_PROC__(GetSwapchainImagesKHR, m_Inst->fpGetDeviceProcAddr, m_LogicalDevice); +#endif +} + +Gpu::~Gpu() +{ + VKLOG(Info, "Gpu Destroyed...."); + if (m_PhysicalGpu) + { + m_PhysicalGpu = VK_NULL_HANDLE; + } +} + +VkDevice Gpu::CreateLogicDevice(bool enableValidation) +{ + if (!m_LogicalDevice) + { + std::array queuePriorities = { 0.0f }; + VkDeviceQueueCreateInfo queueCreateInfo = {}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = m_GraphicsQueueIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = queuePriorities.data(); + + std::vector enabledExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; + VkDeviceCreateInfo deviceCreateInfo = {}; + deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCreateInfo.pNext = NULL; + deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; + deviceCreateInfo.pEnabledFeatures = NULL; + + if (enableValidation) + { + deviceCreateInfo.enabledLayerCount = 1; + deviceCreateInfo.ppEnabledLayerNames = g_ValidationLayerNames; + } + + if (enabledExtensions.size() > 0) + { + deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledExtensions.size(); + deviceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data(); + } + K3D_VK_VERIFY(vkCreateDevice(m_PhysicalGpu, &deviceCreateInfo, nullptr, &m_LogicalDevice)); + + LoadDeviceProcs(); + } + return m_LogicalDevice; +} + +VkBool32 Gpu::GetSupportedDepthFormat(VkFormat * depthFormat) +{ + // Since all depth formats may be optional, we need to find a suitable depth format to use + // Start with the highest precision packed format + std::vector depthFormats = { + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM + }; + + for (auto& format : depthFormats) + { + VkFormatProperties formatProps; + vkGetPhysicalDeviceFormatProperties(m_PhysicalGpu, format, &formatProps); + // Format must support depth stencil attachment for optimal tiling + if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + { + *depthFormat = format; + return true; + } + } + + return false; +} + +VkResult Gpu::GetSurfaceSupportKHR(uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 * pSupported) +{ + return vkGetPhysicalDeviceSurfaceSupportKHR(m_PhysicalGpu, queueFamilyIndex, surface, pSupported); +} + +VkResult Gpu::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR * pSurfaceCapabilities) +{ + return vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_PhysicalGpu, surface, pSurfaceCapabilities); +} + +VkResult Gpu::GetSurfaceFormatsKHR(VkSurfaceKHR surface, uint32_t * pSurfaceFormatCount, VkSurfaceFormatKHR * pSurfaceFormats) +{ + return vkGetPhysicalDeviceSurfaceFormatsKHR(m_PhysicalGpu, surface, pSurfaceFormatCount, pSurfaceFormats); +} + +VkResult Gpu::GetSurfacePresentModesKHR(VkSurfaceKHR surface, uint32_t * pPresentModeCount, VkPresentModeKHR * pPresentModes) +{ + return vkGetPhysicalDeviceSurfacePresentModesKHR(m_PhysicalGpu, surface, pPresentModeCount, pPresentModes); +} + +void Gpu::DestroyDevice() +{ + vkDestroyDevice(m_LogicalDevice, nullptr); +} + +void Gpu::FreeCommandBuffers(VkCommandPool pool, uint32 count, VkCommandBuffer * cmd) +{ + vkFreeCommandBuffers(m_LogicalDevice, pool, count, cmd); +} + +VkResult Gpu::CreateCommdPool(const VkCommandPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkCommandPool * pCommandPool) +{ + return vkCreateCommandPool(m_LogicalDevice, pCreateInfo, pAllocator, pCommandPool); +} + +VkResult Gpu::AllocateCommandBuffers(const VkCommandBufferAllocateInfo * pAllocateInfo, VkCommandBuffer * pCommandBuffers) +{ + return vkAllocateCommandBuffers(m_LogicalDevice, pAllocateInfo, pCommandBuffers); +} + + +#if K3DPLATFORM_OS_WIN +#define PLATFORM_SURFACE_EXT VK_KHR_WIN32_SURFACE_EXTENSION_NAME +#elif defined(K3DPLATFORM_OS_LINUX) && !defined(K3DPLATFORM_OS_ANDROID) +#define PLATFORM_SURFACE_EXT VK_KHR_XCB_SURFACE_EXTENSION_NAME +#elif defined(K3DPLATFORM_OS_ANDROID) +#define PLATFORM_SURFACE_EXT VK_KHR_ANDROID_SURFACE_EXTENSION_NAME +#endif + +::k3d::DynArray gVkLayerProps; +::k3d::DynArray gVkExtProps; + + +Instance::Instance(const::k3d::String & engineName, const::k3d::String & appName, bool enableValidation) + : m_EnableValidation(enableValidation) + , m_Instance(VK_NULL_HANDLE) + , m_DebugMsgCallback(VK_NULL_HANDLE) +{ + LoadGlobalProcs(); + EnumExtsAndLayers(); + ExtractEnabledExtsAndLayers(); + + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = appName.CStr(); + appInfo.pEngineName = engineName.CStr(); + appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 1); + appInfo.engineVersion = 1; + appInfo.applicationVersion = 0; + + VkInstanceCreateInfo instanceCreateInfo = {}; + instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceCreateInfo.pNext = NULL; + instanceCreateInfo.pApplicationInfo = &appInfo; + instanceCreateInfo.enabledExtensionCount = m_EnabledExtsRaw.Count(); + instanceCreateInfo.ppEnabledExtensionNames = m_EnabledExtsRaw.Data(); + instanceCreateInfo.enabledLayerCount = m_EnabledLayersRaw.Count(); + instanceCreateInfo.ppEnabledLayerNames = m_EnabledLayersRaw.Data(); + + VkResult err = vkCreateInstance(&instanceCreateInfo, nullptr, &m_Instance); + if (err == VK_ERROR_INCOMPATIBLE_DRIVER) + { + VKLOG(Error, "Cannot find a compatible Vulkan installable client driver: vkCreateInstance Failure"); + } + else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) + { + VKLOG(Error, "Cannot find a specified extension library: vkCreateInstance Failure"); + } + else + { + LoadInstanceProcs(); + EnumGpus(); + } +} + +Instance::~Instance() +{ + VKLOG(Info, "Instance Destroying... -- %0x. (tid:%d)", m_Instance, Os::Thread::GetId()); + //if (!m_Gpus.empty()) + //{ + // m_Gpus.~DynArray(); + //} + //if (!m_GpuAdapters.empty()) + //{ + // m_GpuAdapters.~DynArray(); + //} + //if (!m_LogicDevices.empty()) + //{ + // m_LogicDevices.~DynArray(); + //} + if (m_Instance) + { + FreeDebugCallback(); + vkDestroyInstance(m_Instance, nullptr); + VKLOG(Info, "Instance Destroyed . -- %0x.", m_Instance); + m_Instance = VK_NULL_HANDLE; + } +} + +#define __VK_GLOBAL_PROC_GET__(name, functor) gp##name = reinterpret_cast(functor("vk" K3D_STRINGIFY(name))) + +void Instance::LoadGlobalProcs() +{ +#ifdef K3DPLATFORM_OS_WIN + static const char* LIBVULKAN = "vulkan-1.dll"; +#elif defined(K3DPLATFORM_OS_MAC) + static const char* LIBVULKAN = "libvulkan.dylib"; +#else + static const char* LIBVULKAN = "libvulkan.so"; +#endif + +#ifdef VK_NO_PROTOTYPES + m_VulkanLib = MakeShared(LIBVULKAN); + // load global functions + __VK_GLOBAL_PROC_GET__(CreateInstance, m_VulkanLib->ResolveEntry); + __VK_GLOBAL_PROC_GET__(DestroyInstance, m_VulkanLib->ResolveEntry); + __VK_GLOBAL_PROC_GET__(EnumerateInstanceExtensionProperties, m_VulkanLib->ResolveEntry); + __VK_GLOBAL_PROC_GET__(EnumerateInstanceLayerProperties, m_VulkanLib->ResolveEntry); + __VK_GLOBAL_PROC_GET__(GetInstanceProcAddr, m_VulkanLib->ResolveEntry); +#endif +} + +void Instance::EnumExtsAndLayers() +{ + uint32 layerCount = 0; + K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, nullptr)); + if (layerCount > 0) + { + gVkLayerProps.Resize(layerCount); + K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, gVkLayerProps.Data())); + } + uint32 extCount = 0; + K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr)); + if (extCount > 0) + { + gVkExtProps.Resize(extCount); + K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extCount, gVkExtProps.Data())); + } + VKLOG(Info, ">> Instance::EnumLayersAndExts <<\n\n" + "=================================>> layerCount = %d.\n" + "=================================>> extensionCount = %d.\n", layerCount, extCount); +} + +void Instance::ExtractEnabledExtsAndLayers() +{ + VkBool32 surfaceExtFound = 0; + VkBool32 platformSurfaceExtFound = 0; + + for (uint32_t i = 0; i < gVkExtProps.Count(); i++) + { + if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, gVkExtProps[i].extensionName)) + { + surfaceExtFound = 1; + m_EnabledExts.Append(VK_KHR_SURFACE_EXTENSION_NAME); + m_EnabledExtsRaw.Append(VK_KHR_SURFACE_EXTENSION_NAME); + } + if (!strcmp(PLATFORM_SURFACE_EXT, gVkExtProps[i].extensionName)) + { + platformSurfaceExtFound = 1; + m_EnabledExts.Append(PLATFORM_SURFACE_EXT); + m_EnabledExtsRaw.Append(PLATFORM_SURFACE_EXT); + } + if (m_EnableValidation) + { + m_EnabledExts.Append(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + m_EnabledExtsRaw.Append(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + } + VKLOG(Info, "available extension : %s .", gVkExtProps[i].extensionName); + } + if (!surfaceExtFound) + { + VKLOG(Error, "vkEnumerateInstanceExtensionProperties failed to find the " VK_KHR_SURFACE_EXTENSION_NAME" extension."); + } + if (!platformSurfaceExtFound) + { + VKLOG(Error, "vkEnumerateInstanceExtensionProperties failed to find the " PLATFORM_SURFACE_EXT " extension."); + } + + if (m_EnableValidation && !gVkLayerProps.empty()) + { + for (auto prop : gVkLayerProps) + { + if (strcmp(prop.layerName, g_ValidationLayerNames[0]) == 0 /*|| strcmp(prop.layerName, g_ValidationLayerNames[1])==0*/) + { + m_EnabledLayers.Append(prop.layerName); + m_EnabledLayersRaw.Append(g_ValidationLayerNames[0]); + VKLOG(Info, "enable validation layer [%s].", prop.layerName); + break; + } + } + } + +} + +void Instance::LoadInstanceProcs() +{ +#ifdef VK_NO_PROTOTYPES + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceSurfaceSupportKHR); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceSurfaceCapabilitiesKHR); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceSurfaceFormatsKHR); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceSurfacePresentModesKHR); + + GET_INSTANCE_PROC_ADDR(m_Instance, EnumeratePhysicalDevices); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceFeatures); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceProperties); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceMemoryProperties); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceFormatProperties); + GET_INSTANCE_PROC_ADDR(m_Instance, GetPhysicalDeviceQueueFamilyProperties); + GET_INSTANCE_PROC_ADDR(m_Instance, CreateDevice); + GET_INSTANCE_PROC_ADDR(m_Instance, GetDeviceProcAddr); + +#if K3DPLATFORM_OS_WIN + GET_INSTANCE_PROC_ADDR(m_Instance, CreateWin32SurfaceKHR); +#elif K3DPLATFORM_OS_ANDROID + GET_INSTANCE_PROC_ADDR(m_Instance, CreateAndroidSurfaceKHR); +#endif + GET_INSTANCE_PROC_ADDR(m_Instance, DestroySurfaceKHR); +#endif +} + +K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkObjects.h b/Source/RHI/Vulkan/Private/VkObjects.h index fed88f2..1063792 100755 --- a/Source/RHI/Vulkan/Private/VkObjects.h +++ b/Source/RHI/Vulkan/Private/VkObjects.h @@ -5,8 +5,50 @@ K3D_VK_BEGIN +template +struct ResTrait +{ +}; + +template <> +struct ResTrait +{ + typedef VkBufferView View; + typedef VkBufferUsageFlags UsageFlags; + typedef VkBufferCreateInfo CreateInfo; + typedef VkBufferViewCreateInfo ViewCreateInfo; + typedef VkDescriptorBufferInfo DescriptorInfo; + static decltype(vkCreateBufferView)* CreateView; + static decltype(vkDestroyBufferView)* DestroyView; + static decltype(vkCreateBuffer)* Create; + static decltype(vkDestroyBuffer)* Destroy; + static decltype(vkGetBufferMemoryRequirements)* GetMemoryInfo; + static decltype(vkBindBufferMemory)* BindMemory; +}; + +template <> +struct ResTrait +{ + typedef VkImageView View; + typedef VkImageUsageFlags UsageFlags; + typedef VkImageCreateInfo CreateInfo; + typedef VkImageViewCreateInfo ViewCreateInfo; + typedef VkDescriptorImageInfo DescriptorInfo; + static decltype(vkCreateImageView)* CreateView; + static decltype(vkDestroyImageView)* DestroyView; + static decltype(vkCreateImage)* Create; + static decltype(vkDestroyImage)* Destroy; + static decltype(vkGetImageMemoryRequirements)* GetMemoryInfo; + static decltype(vkBindImageMemory)* BindMemory; +}; + struct ImageInfo; +class Gpu; +using GpuRef = SharedPtr; +class Instance; +using InstanceRef = SharedPtr; + class RenderTargetLayout { public: @@ -386,6 +428,9 @@ class ImageViewInfo : public VkImageViewCreateInfo static std::pair CreateColorImageView( VkDevice device, VkFormat colorFmt, VkImage colorImage, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + static std::pair CreateColorImageView( + GpuRef device, VkFormat colorFmt, VkImage colorImage, + VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); static ImageViewInfo CreateDepthStencilImageInfo( VkFormat format, VkImage image, @@ -541,6 +586,341 @@ struct ImageInfo : VkImageCreateInfo static ImageInfo FromRHI(rhi::TextureDesc const & desc); }; +class VkObjectAllocator +{ +public: + + inline operator VkAllocationCallbacks() const + { + VkAllocationCallbacks result; + result.pUserData = (void*)this; +// result.pfnAllocation = VkObjectAllocator::Allocation; +// result.pfnReallocation = VkObjectAllocator::Reallocation; +// result.pfnFree = VkObjectAllocator::Free; + result.pfnInternalAllocation = nullptr; + result.pfnInternalFree = nullptr; + return result; + }; + +private: + static void* VKAPI_CALL Allocation( void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope); + static void* VKAPI_CALL Reallocation( void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope); + static void VKAPI_CALL Free( void* pUserData, void* pMemory); + void* Allocation( size_t size, size_t alignment, VkSystemAllocationScope allocationScope); + void* Reallocation(void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope); + void Free(void* pMemory); +}; + +class CommandBufferManager +{ +public: + CommandBufferManager(VkDevice pDevice, VkCommandBufferLevel bufferLevel, unsigned graphicsQueueIndex); + ~CommandBufferManager(); + void Destroy(); + VkCommandBuffer RequestCommandBuffer(); + void BeginFrame(); + +private: + VkDevice m_Device = VK_NULL_HANDLE; + VkCommandPool m_Pool = VK_NULL_HANDLE; + std::vector m_Buffers; + VkCommandBufferLevel m_CommandBufferLevel; + uint32 m_Count = 0; +}; + +using CmdBufManagerRef = SharedPtr; + +extern ::k3d::DynArray gVkLayerProps; +extern ::k3d::DynArray gVkExtProps; + +class Instance; + +#define __VK_DEVICE_PROC__(name) PFN_vk##name vk##name = NULL + +class Gpu : public EnableSharedFromThis +{ +public: + ~Gpu(); + + VkDevice CreateLogicDevice(bool enableValidation); + VkBool32 GetSupportedDepthFormat(VkFormat * depthFormat); + + VkResult GetSurfaceSupportKHR(uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); + VkResult GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); + VkResult GetSurfaceFormatsKHR(VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); + VkResult GetSurfacePresentModesKHR(VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); + + void DestroyDevice(); + void FreeCommandBuffers(VkCommandPool,uint32,VkCommandBuffer*); + VkResult CreateCommdPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); + VkResult AllocateCommandBuffers(const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); + + InstanceRef GetInstance() const { return m_Inst; } + +#ifdef VK_NO_PROTOTYPES + __VK_DEVICE_PROC__(DestroyDevice); + __VK_DEVICE_PROC__(GetDeviceQueue); + __VK_DEVICE_PROC__(QueueSubmit); + __VK_DEVICE_PROC__(QueueWaitIdle); + __VK_DEVICE_PROC__(QueuePresentKHR); + __VK_DEVICE_PROC__(DeviceWaitIdle); + __VK_DEVICE_PROC__(AllocateMemory); + __VK_DEVICE_PROC__(FreeMemory); + __VK_DEVICE_PROC__(MapMemory); + __VK_DEVICE_PROC__(UnmapMemory); + __VK_DEVICE_PROC__(FlushMappedMemoryRanges); + __VK_DEVICE_PROC__(InvalidateMappedMemoryRanges); + __VK_DEVICE_PROC__(GetDeviceMemoryCommitment); + __VK_DEVICE_PROC__(BindBufferMemory); + __VK_DEVICE_PROC__(BindImageMemory); + __VK_DEVICE_PROC__(GetBufferMemoryRequirements); + __VK_DEVICE_PROC__(GetImageMemoryRequirements); + __VK_DEVICE_PROC__(GetImageSparseMemoryRequirements); + __VK_DEVICE_PROC__(QueueBindSparse); + __VK_DEVICE_PROC__(CreateFence); + __VK_DEVICE_PROC__(DestroyFence); + __VK_DEVICE_PROC__(ResetFences); + __VK_DEVICE_PROC__(GetFenceStatus); + __VK_DEVICE_PROC__(WaitForFences); + __VK_DEVICE_PROC__(CreateSemaphore); + __VK_DEVICE_PROC__(DestroySemaphore); + __VK_DEVICE_PROC__(CreateEvent); + __VK_DEVICE_PROC__(DestroyEvent); + __VK_DEVICE_PROC__(GetEventStatus); + __VK_DEVICE_PROC__(SetEvent); + __VK_DEVICE_PROC__(ResetEvent); + __VK_DEVICE_PROC__(CreateQueryPool); + __VK_DEVICE_PROC__(DestroyQueryPool); + __VK_DEVICE_PROC__(GetQueryPoolResults); + __VK_DEVICE_PROC__(CreateBuffer); + __VK_DEVICE_PROC__(DestroyBuffer); + __VK_DEVICE_PROC__(CreateBufferView); + __VK_DEVICE_PROC__(DestroyBufferView); + __VK_DEVICE_PROC__(CreateImage); + __VK_DEVICE_PROC__(DestroyImage); + __VK_DEVICE_PROC__(GetImageSubresourceLayout); + __VK_DEVICE_PROC__(CreateImageView); + __VK_DEVICE_PROC__(DestroyImageView); + __VK_DEVICE_PROC__(CreateShaderModule); + __VK_DEVICE_PROC__(DestroyShaderModule); + __VK_DEVICE_PROC__(CreatePipelineCache); + __VK_DEVICE_PROC__(DestroyPipelineCache); + __VK_DEVICE_PROC__(GetPipelineCacheData); + __VK_DEVICE_PROC__(MergePipelineCaches); + __VK_DEVICE_PROC__(CreateGraphicsPipelines); + __VK_DEVICE_PROC__(CreateComputePipelines); + __VK_DEVICE_PROC__(DestroyPipeline); + __VK_DEVICE_PROC__(CreatePipelineLayout); + __VK_DEVICE_PROC__(DestroyPipelineLayout); + __VK_DEVICE_PROC__(CreateSampler); + __VK_DEVICE_PROC__(DestroySampler); + __VK_DEVICE_PROC__(CreateDescriptorSetLayout); + __VK_DEVICE_PROC__(DestroyDescriptorSetLayout); + __VK_DEVICE_PROC__(CreateDescriptorPool); + __VK_DEVICE_PROC__(DestroyDescriptorPool); + __VK_DEVICE_PROC__(ResetDescriptorPool); + __VK_DEVICE_PROC__(AllocateDescriptorSets); + __VK_DEVICE_PROC__(FreeDescriptorSets); + __VK_DEVICE_PROC__(UpdateDescriptorSets); + __VK_DEVICE_PROC__(CreateFramebuffer); + __VK_DEVICE_PROC__(DestroyFramebuffer); + __VK_DEVICE_PROC__(CreateRenderPass); + __VK_DEVICE_PROC__(DestroyRenderPass); + __VK_DEVICE_PROC__(GetRenderAreaGranularity); + __VK_DEVICE_PROC__(CreateCommandPool); + __VK_DEVICE_PROC__(DestroyCommandPool); + __VK_DEVICE_PROC__(ResetCommandPool); + __VK_DEVICE_PROC__(AllocateCommandBuffers); + __VK_DEVICE_PROC__(FreeCommandBuffers); + __VK_DEVICE_PROC__(BeginCommandBuffer); + __VK_DEVICE_PROC__(EndCommandBuffer); + __VK_DEVICE_PROC__(ResetCommandBuffer); + __VK_DEVICE_PROC__(CmdBindPipeline); + __VK_DEVICE_PROC__(CmdSetViewport); + __VK_DEVICE_PROC__(CmdSetScissor); + __VK_DEVICE_PROC__(CmdSetLineWidth); + __VK_DEVICE_PROC__(CmdSetDepthBias); + __VK_DEVICE_PROC__(CmdSetBlendConstants); + __VK_DEVICE_PROC__(CmdSetDepthBounds); + __VK_DEVICE_PROC__(CmdSetStencilCompareMask); + __VK_DEVICE_PROC__(CmdSetStencilWriteMask); + __VK_DEVICE_PROC__(CmdSetStencilReference); + __VK_DEVICE_PROC__(CmdBindDescriptorSets); + __VK_DEVICE_PROC__(CmdBindIndexBuffer); + __VK_DEVICE_PROC__(CmdBindVertexBuffers); + __VK_DEVICE_PROC__(CmdDraw); + __VK_DEVICE_PROC__(CmdDrawIndexed); + __VK_DEVICE_PROC__(CmdDrawIndirect); + __VK_DEVICE_PROC__(CmdDrawIndexedIndirect); + __VK_DEVICE_PROC__(CmdDispatch); + __VK_DEVICE_PROC__(CmdDispatchIndirect); + __VK_DEVICE_PROC__(CmdCopyBuffer); + __VK_DEVICE_PROC__(CmdCopyImage); + __VK_DEVICE_PROC__(CmdBlitImage); + __VK_DEVICE_PROC__(CmdCopyBufferToImage); + __VK_DEVICE_PROC__(CmdCopyImageToBuffer); + __VK_DEVICE_PROC__(CmdUpdateBuffer); + __VK_DEVICE_PROC__(CmdFillBuffer); + __VK_DEVICE_PROC__(CmdClearColorImage); + __VK_DEVICE_PROC__(CmdClearDepthStencilImage); + __VK_DEVICE_PROC__(CmdClearAttachments); + __VK_DEVICE_PROC__(CmdResolveImage); + __VK_DEVICE_PROC__(CmdSetEvent); + __VK_DEVICE_PROC__(CmdResetEvent); + __VK_DEVICE_PROC__(CmdWaitEvents); + __VK_DEVICE_PROC__(CmdPipelineBarrier); + __VK_DEVICE_PROC__(CmdBeginQuery); + __VK_DEVICE_PROC__(CmdEndQuery); + __VK_DEVICE_PROC__(CmdResetQueryPool); + __VK_DEVICE_PROC__(CmdWriteTimestamp); + __VK_DEVICE_PROC__(CmdCopyQueryPoolResults); + __VK_DEVICE_PROC__(CmdPushConstants); + __VK_DEVICE_PROC__(CmdBeginRenderPass); + __VK_DEVICE_PROC__(CmdNextSubpass); + __VK_DEVICE_PROC__(CmdEndRenderPass); + __VK_DEVICE_PROC__(CmdExecuteCommands); + __VK_DEVICE_PROC__(AcquireNextImageKHR); + __VK_DEVICE_PROC__(CreateSwapchainKHR); + __VK_DEVICE_PROC__(DestroySwapchainKHR); + __VK_DEVICE_PROC__(GetSwapchainImagesKHR); + + PFN_vkDestroyDevice fpDestroyDevice = NULL; + PFN_vkFreeCommandBuffers fpFreeCommandBuffers = NULL; + PFN_vkCreateCommandPool fpCreateCommandPool = NULL; + PFN_vkAllocateCommandBuffers fpAllocateCommandBuffers = NULL; +#endif + + VkDevice m_LogicalDevice; + +private: + friend class Instance; + friend class Device; + friend class DeviceAdapter; + + Gpu(VkPhysicalDevice const&, InstanceRef const& inst); + + void QuerySupportQueues(); + void LoadDeviceProcs(); + + InstanceRef m_Inst; + VkPhysicalDevice m_PhysicalGpu; + VkPhysicalDeviceProperties m_Prop; + VkPhysicalDeviceMemoryProperties m_MemProp; + uint32 m_GraphicsQueueIndex = 0; + uint32 m_ComputeQueueIndex = 0; + uint32 m_CopyQueueIndex = 0; + DynArray m_QueueProps; +}; + +VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, size_t location, int32_t messageCode, + const char * pLayerPrefix, + const char * pMessage, void * pUserData); + +#define __VK_GLOBAL_LEVEL_PROC__(name) PFN_vk##name gp##name = NULL; +#define __VK_INSTANCE_LEVEL_PROC__(name) PFN_vk##name fp##name = NULL + +class Instance : public EnableSharedFromThis +{ +public: + Instance(const ::k3d::String& engineName, const ::k3d::String& appName, bool enableValidation = true); + ~Instance(); + + //uint32 GetHostGpuCount() const { return m_Gpus.Count(); } + //GpuRef GetHostGpuByIndex(uint32 i) const { return m_Gpus[i]; } + //rhi::DeviceRef GetDeviceByIndex(uint32 i) const { return m_LogicDevices[i]; } + + void SetupDebugging(VkDebugReportFlagsEXT flags, PFN_vkDebugReportCallbackEXT callBack); + void FreeDebugCallback(); + + bool WithValidation() const { return m_EnableValidation; } + //void AppendLogicalDevice(rhi::DeviceRef logicalDevice); + + ::k3d::DynArray EnumGpus(); + +#ifdef VK_NO_PROTOTYPES + VkResult CreateSurfaceKHR(const +#if K3DPLATFORM_OS_WIN + VkWin32SurfaceCreateInfoKHR +#elif K3DPLATFORM_OS_ANDROID + VkAndroidSurfaceCreateInfoKHR +#endif + * pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) + { +#if K3DPLATFORM_OS_WIN + return fpCreateWin32SurfaceKHR(m_Instance, pCreateInfo, pAllocator, pSurface); +#elif K3DPLATFORM_OS_ANDROID + return fpCreateAndroidSurfaceKHR(m_Instance, pCreateInfo, pAllocator, pSurface); +#endif + } + + void DestroySurfaceKHR(VkSurfaceKHR surface, VkAllocationCallbacks* pAllocator) + { + fpDestroySurfaceKHR(m_Instance, surface, pAllocator); + } +#endif + + friend class Gpu; + friend class Device; + friend class SwapChain; + friend struct RHIRoot; + +private: + void LoadGlobalProcs(); + void EnumExtsAndLayers(); + void ExtractEnabledExtsAndLayers(); + void LoadInstanceProcs(); + + bool m_EnableValidation; + ::k3d::DynArray<::k3d::String> m_EnabledExts; + ::k3d::DynArray m_EnabledExtsRaw; + ::k3d::DynArray<::k3d::String> m_EnabledLayers; + ::k3d::DynArray m_EnabledLayersRaw; + + VkInstance m_Instance; + VkDebugReportCallbackEXT m_DebugMsgCallback; + //::k3d::DynArray m_Gpus; + //::k3d::DynArray m_GpuAdapters; + //::k3d::DynArray m_LogicDevices; + +#ifdef VK_NO_PROTOTYPES + + PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR; + + __VK_GLOBAL_LEVEL_PROC__(CreateInstance); + __VK_GLOBAL_LEVEL_PROC__(EnumerateInstanceExtensionProperties); + __VK_GLOBAL_LEVEL_PROC__(EnumerateInstanceLayerProperties); + __VK_GLOBAL_LEVEL_PROC__(GetInstanceProcAddr); + __VK_GLOBAL_LEVEL_PROC__(DestroyInstance); + + __VK_INSTANCE_LEVEL_PROC__(CreateDebugReportCallbackEXT); + __VK_INSTANCE_LEVEL_PROC__(DestroyDebugReportCallbackEXT); + +#if K3DPLATFORM_OS_WIN + __VK_INSTANCE_LEVEL_PROC__(CreateWin32SurfaceKHR); +#elif K3DPLATFORM_OS_ANDROID + __VK_INSTANCE_LEVEL_PROC__(CreateAndroidSurfaceKHR); +#endif + __VK_INSTANCE_LEVEL_PROC__(DestroySurfaceKHR); + + __VK_INSTANCE_LEVEL_PROC__(EnumeratePhysicalDevices); + __VK_INSTANCE_LEVEL_PROC__(GetPhysicalDeviceProperties); + __VK_INSTANCE_LEVEL_PROC__(GetPhysicalDeviceFeatures); + __VK_INSTANCE_LEVEL_PROC__(GetPhysicalDeviceMemoryProperties); + __VK_INSTANCE_LEVEL_PROC__(GetPhysicalDeviceQueueFamilyProperties); + __VK_INSTANCE_LEVEL_PROC__(GetPhysicalDeviceFormatProperties); + __VK_INSTANCE_LEVEL_PROC__(CreateDevice); + __VK_INSTANCE_LEVEL_PROC__(GetDeviceProcAddr); + + dynlib::LibRef m_VulkanLib; +#endif +}; + K3D_VK_END #endif \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkPipelineLayout.cpp b/Source/RHI/Vulkan/Private/VkPipelineLayout.cpp deleted file mode 100755 index 8d27a52..0000000 --- a/Source/RHI/Vulkan/Private/VkPipelineLayout.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "VkCommon.h" -#include "VkRHI.h" -#include "Private/VkUtils.h" - -K3D_VK_BEGIN - -PipelineLayout::PipelineLayout(Device::Ptr pDevice, rhi::PipelineLayoutDesc const & desc) - : DeviceChild(pDevice) - , m_PipelineLayout(VK_NULL_HANDLE) - , m_DescSetLayout(nullptr) - , m_DescSet() -{ - InitWithDesc(desc); -} - -PipelineLayout::~PipelineLayout() -{ - Destroy(); -} - -void PipelineLayout::Destroy() -{ - if (m_PipelineLayout == VK_NULL_HANDLE) - return; - vkDestroyPipelineLayout(GetRawDevice(), m_PipelineLayout, nullptr); - VKLOG(Info, "PipelineLayout-destroying vkPipelineLayout..."); -} - -void PipelineLayout::InitWithDesc(rhi::PipelineLayoutDesc const & desc) -{ - DescriptorAllocator::Options options; - BindingArray array; - for (auto & rhibinding : desc.Bindings) - { - array.Append(RHIBinding2VkBinding(rhibinding)); - } - - DescriptorAllocator* alloc = GetDevice()->NewDescriptorAllocator(16, array); - m_DescSetLayout = GetDevice()->NewDescriptorSetLayout(array); - m_DescSet = rhi::DescriptorRef( DescriptorSet::CreateDescSet(alloc, m_DescSetLayout->GetNativeHandle(), array, GetDevice()) ); - - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {}; - pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pPipelineLayoutCreateInfo.pNext = NULL; - pPipelineLayoutCreateInfo.setLayoutCount = 1; - pPipelineLayoutCreateInfo.pSetLayouts = &m_DescSetLayout->m_DescriptorSetLayout; - K3D_VK_VERIFY(vkCreatePipelineLayout(GetRawDevice(), &pPipelineLayoutCreateInfo, nullptr, &m_PipelineLayout)); -} - -K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkPipelineState.cpp b/Source/RHI/Vulkan/Private/VkPipelineState.cpp index f3179bc..4c654ab 100755 --- a/Source/RHI/Vulkan/Private/VkPipelineState.cpp +++ b/Source/RHI/Vulkan/Private/VkPipelineState.cpp @@ -2,8 +2,13 @@ #include "VkRHI.h" #include "VkEnums.h" #include "VkUtils.h" +#include #include +#include + +using namespace rhi::shc; +using namespace std; K3D_VK_BEGIN @@ -22,7 +27,7 @@ PipelineStateObject::PipelineStateObject(Device::Ptr pDevice, rhi::PipelineDesc /** * @class PipelineStateObject */ -PipelineStateObject::PipelineStateObject(Device* pDevice) +PipelineStateObject::PipelineStateObject(Device::Ptr pDevice) : DeviceChild(pDevice) , m_Pipeline(VK_NULL_HANDLE) , m_PipelineCache(VK_NULL_HANDLE) @@ -58,7 +63,7 @@ VkShaderModule CreateShaderModule(VkDevice Device, rhi::IDataBlob * ShaderBytes) return shaderModule; } -VkShaderModule CreateShaderModule(VkDevice Device, String ShaderBytes) +VkShaderModule CreateShaderModule(GpuRef Device, String ShaderBytes) { VkShaderModule shaderModule; VkShaderModuleCreateInfo moduleCreateInfo; @@ -69,13 +74,13 @@ VkShaderModule CreateShaderModule(VkDevice Device, String ShaderBytes) moduleCreateInfo.codeSize = ShaderBytes.Length(); moduleCreateInfo.pCode = (const uint32_t*)ShaderBytes.Data(); moduleCreateInfo.flags = 0; - K3D_VK_VERIFY(vkCreateShaderModule(Device, &moduleCreateInfo, NULL, &shaderModule)); + K3D_VK_VERIFY(vkCreateShaderModule(Device->m_LogicalDevice, &moduleCreateInfo, NULL, &shaderModule)); return shaderModule; } void PipelineStateObject::SetShader(rhi::EShaderType ShaderType, rhi::ShaderBundle const& ShaderBytes) { - auto sm = CreateShaderModule(GetRawDevice(), ShaderBytes.RawData); + auto sm = CreateShaderModule(GetGpuRef(), ShaderBytes.RawData); VkPipelineShaderStageCreateInfo shaderStage = {}; shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStage.stage = g_ShaderType[ShaderType]; @@ -94,12 +99,12 @@ void PipelineStateObject::Finalize() { if (VK_NULL_HANDLE != m_Pipeline) return; - /*VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - K3D_VK_VERIFY(vkCreatePipelineCache(GetRawDevice(), &pipelineCacheCreateInfo, nullptr, &m_PipelineCache));*/ + K3D_VK_VERIFY(vkCreatePipelineCache(GetRawDevice(), &pipelineCacheCreateInfo, nullptr, &m_PipelineCache)); if (GetType() == rhi::EPSO_Graphics) { - K3D_VK_VERIFY(vkCmd::CreateGraphicsPipelines(GetRawDevice(), VK_NULL_HANDLE, 1, &m_GfxCreateInfo, nullptr, &m_Pipeline)); + K3D_VK_VERIFY(vkCreateGraphicsPipelines(GetRawDevice(), m_PipelineCache, 1, &m_GfxCreateInfo, nullptr, &m_Pipeline)); } else { @@ -108,6 +113,33 @@ void PipelineStateObject::Finalize() } } +void PipelineStateObject::SavePSO(const char * path) +{ + size_t szPSO = 0; + K3D_VK_VERIFY(vkGetPipelineCacheData(GetRawDevice(), m_PipelineCache, &szPSO, nullptr)); + if (!szPSO || !path) + return; + DynArray dataBlob; + dataBlob.Resize(szPSO); + vkGetPipelineCacheData(GetRawDevice(), m_PipelineCache, &szPSO, dataBlob.Data()); + Os::File psoCacheFile(path); + psoCacheFile.Open(IOWrite); + psoCacheFile.Write(dataBlob.Data(), szPSO); + psoCacheFile.Close(); +} + +void PipelineStateObject::LoadPSO(const char * path) +{ + Os::MemMapFile psoFile; + if(!path || !psoFile.Open(path, IORead)) + return; + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; + pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + pipelineCacheCreateInfo.pInitialData = psoFile.FileData(); + pipelineCacheCreateInfo.initialDataSize = psoFile.GetSize(); + K3D_VK_VERIFY(vkCreatePipelineCache(GetRawDevice(), &pipelineCacheCreateInfo, nullptr, &m_PipelineCache)); +} + void PipelineStateObject::SetRasterizerState(const rhi::RasterizerState& rasterState) { m_RasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; @@ -190,7 +222,7 @@ void PipelineStateObject::SetRenderTargetFormat(const rhi::RenderTargetFormat &) // Init Shaders std::vector -GetShaderStageInfo(VkDevice device, rhi::PipelineDesc const & desc) +GetShaderStageInfo(GpuRef device, rhi::PipelineDesc const & desc) { std::vector infos; for (uint32 i = 0; i < rhi::EShaderType::ShaderTypeNum; i++) @@ -209,9 +241,35 @@ GetShaderStageInfo(VkDevice device, rhi::PipelineDesc const & desc) return infos; } +DynArray RHIInputAttribs(rhi::VertexInputState ia) +{ + DynArray iad; + for(uint32 i = 0; i RHIInputLayouts(rhi::VertexInputState const& ia) +{ + DynArray ibd; + for(uint32 i = 0; iGetRenderPass(); this->m_GfxCreateInfo.renderPass = m_RenderPass; - this->m_GfxCreateInfo.layout = m_PipelineLayout->m_PipelineLayout; + this->m_GfxCreateInfo.layout = m_PipelineLayout->NativeHandle(); // Finalize Finalize(); @@ -318,9 +378,96 @@ void PipelineStateObject::Destroy() vkDestroyShaderModule(GetRawDevice(), iter.module, nullptr); } } - //vkDestroyPipelineCache(GetRawDevice(), m_PipelineCache, nullptr); - vkDestroyPipeline(GetRawDevice(), m_Pipeline, nullptr); - VKLOG(Info, "PipelineStateObject-Destroyed.."); + if (m_PipelineCache) + { + vkDestroyPipelineCache(GetRawDevice(), m_PipelineCache, nullptr); + VKLOG(Info, "PipelineCache Destroyed.. -- %0x.", m_PipelineCache); + m_PipelineCache = VK_NULL_HANDLE; + } + if (m_Pipeline) + { + vkDestroyPipeline(GetRawDevice(), m_Pipeline, nullptr); + VKLOG(Info, "PipelineStateObject Destroyed.. -- %0x.", m_Pipeline); + m_Pipeline = VK_NULL_HANDLE; + } +} + +PipelineLayout::PipelineLayout(Device::Ptr pDevice, rhi::PipelineLayoutDesc const & desc) + : PipelineLayout::ThisObj(pDevice) + , m_DescSetLayout(nullptr) + , m_DescSet() +{ + InitWithDesc(desc); +} + +PipelineLayout::~PipelineLayout() +{ + Destroy(); +} + +void PipelineLayout::Destroy() +{ + if (m_NativeObj == VK_NULL_HANDLE) + return; + vkDestroyPipelineLayout(NativeDevice(), m_NativeObj, nullptr); + VKLOG(Info, "PipelineLayout Destroyed . -- %0x.", m_NativeObj); + m_NativeObj = VK_NULL_HANDLE; +} + +uint64 BindingHash(Binding const& binding) +{ + return (uint64)(1 << (3 + binding.VarNumber)) | binding.VarStage; +} + +bool operator<(Binding const &lhs, Binding const &rhs) +{ + return rhs.VarStage < lhs.VarStage && rhs.VarNumber < lhs.VarNumber; +} + +BindingArray ExtractBindingsFromTable(::k3d::DynArray const& bindings) +{ + // merge image sampler + std::map bindingMap; + for (auto const & binding : bindings) + { + uint64 hash = BindingHash(binding); + if (bindingMap.find(hash) == bindingMap.end()) + { + bindingMap.insert({ hash, binding }); + } + else // binding slot override + { + auto & overrideBinding = bindingMap[hash]; + if (EBindType((uint32)overrideBinding.VarType | (uint32)binding.VarType) + == EBindType::ESamplerImageCombine) + { + overrideBinding.VarType = EBindType::ESamplerImageCombine; + } + } + } + + BindingArray array; + for (auto & p : bindingMap) + { + array.Append(RHIBinding2VkBinding(p.second)); + } + return array; +} + +void PipelineLayout::InitWithDesc(rhi::PipelineLayoutDesc const & desc) +{ + DescriptorAllocator::Options options; + BindingArray array = ExtractBindingsFromTable(desc.Bindings); + auto alloc = m_Device->NewDescriptorAllocator(16, array); + m_DescSetLayout = m_Device->NewDescriptorSetLayout(array); + m_DescSet = rhi::DescriptorRef(DescriptorSet::CreateDescSet(alloc, m_DescSetLayout->GetNativeHandle(), array, m_Device)); + + VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {}; + pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pPipelineLayoutCreateInfo.pNext = NULL; + pPipelineLayoutCreateInfo.setLayoutCount = 1; + pPipelineLayoutCreateInfo.pSetLayouts = &m_DescSetLayout->m_DescriptorSetLayout; + K3D_VK_VERIFY(vkCreatePipelineLayout(NativeDevice(), &pPipelineLayoutCreateInfo, nullptr, &m_NativeObj)); } K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkRHI.cpp b/Source/RHI/Vulkan/Private/VkRHI.cpp index 5da4798..fc0e58a 100755 --- a/Source/RHI/Vulkan/Private/VkRHI.cpp +++ b/Source/RHI/Vulkan/Private/VkRHI.cpp @@ -20,225 +20,117 @@ namespace k3d namespace vk { -//void EnumAllDeviceAdapter(rhi::IDeviceAdapter** & adapterList, uint32* count) -//{ -// *count = (uint32)RHIRoot::GetPhysicDevices().size(); -// adapterList = new rhi::IDeviceAdapter*[*count]; -// for (size_t i = 0; i < *count; i++) -// { -// VkPhysicalDeviceProperties properties; -// vkGetPhysicalDeviceProperties(RHIRoot::GetPhysicDevices()[i], &properties); -// adapterList[i] = new DeviceAdapter(&(RHIRoot::GetPhysicDevices()[i])); -// VKLOG(Info, "DeviceName is %s, VendorId is %d.", properties.deviceName, properties.vendorID); -// } -//} +InstanceRef RHIRoot::s_InstanceRef; +DynArray RHIRoot::s_GpuRefs; +DynArray RHIRoot::s_DeviceRefs; +RenderViewportSp RHIRoot::s_Vp; -void EnumAndInitAllDeviceAdapter(rhi::IDeviceAdapter** & adapterList, uint32* count, bool debug) +void dFunc(void*) { - *count = (uint32)RHIRoot::GetPhysicDevices().size(); - adapterList = new rhi::IDeviceAdapter*[*count]; - for (size_t i = 0; i < *count; i++) + RHIRoot::Destroy(); +} + +void RHIRoot::Initialize(const char * appName, bool debug) +{ + // create instance + s_InstanceRef = InstanceRef(new vk::Instance(appName, appName, debug)); + s_GpuRefs = s_InstanceRef->EnumGpus(); + for (auto & gpu : s_GpuRefs) { - auto& gpu = RHIRoot::GetPhysicDevices()[i]; - VkPhysicalDeviceProperties properties = {}; - vkGetPhysicalDeviceProperties(gpu, &properties); - auto da = new DeviceAdapter(&gpu); - adapterList[i] = da; - auto dev = da->GetDevice(); - auto ret = dev->Create(da, debug); - K3D_ASSERT(ret == rhi::IDevice::DeviceFound); - VKLOG(Info, "DeviceName is %s, VendorId is %d.", properties.deviceName, properties.vendorID); + auto pDevice = new Device; + pDevice->Create(gpu->SharedFromThis(), s_InstanceRef->WithValidation()); + s_DeviceRefs.Append(rhi::DeviceRef( pDevice )); } } -std::vector RHIRoot::s_LayerProps; -std::vector RHIRoot::s_LayerNames; -RenderViewport * RHIRoot::s_Vp = nullptr; -VkInstance RHIRoot::Instance; -RHIRoot::DeviceList RHIRoot::PhysicalDevices; - -void RHIRoot::Initialize(const char * appName, bool debug) +void RHIRoot::Destroy() { - vkCreateInstance = reinterpret_cast(dynlib::GetVulkanLib().ResolveEntry("vkCreateInstance")); - vkDestroyInstance = reinterpret_cast(dynlib::GetVulkanLib().ResolveEntry("vkDestroyInstance")); - vkEnumeratePhysicalDevices = reinterpret_cast(dynlib::GetVulkanLib().ResolveEntry("vkEnumeratePhysicalDevices")); - vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties)dynlib::GetVulkanLib().ResolveEntry("vkEnumerateInstanceLayerProperties"); - vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)dynlib::GetVulkanLib().ResolveEntry("vkEnumerateInstanceExtensionProperties"); - vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)dynlib::GetVulkanLib().ResolveEntry("vkGetPhysicalDeviceProperties"); - vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)dynlib::GetVulkanLib().ResolveEntry("vkGetPhysicalDeviceMemoryProperties"); - vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)dynlib::GetVulkanLib().ResolveEntry("vkGetPhysicalDeviceQueueFamilyProperties"); - vkCreateDevice = (PFN_vkCreateDevice)dynlib::GetVulkanLib().ResolveEntry("vkCreateDevice"); - - EnumLayers(); + VKLOG(Info, "RHIRoot::Destroy"); +} - VkResult err = CreateInstance(debug, appName); - if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { - VKLOG(Error, "Cannot find a compatible Vulkan installable client driver: vkCreateInstance Failure"); - } - else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) { - VKLOG(Error, "Cannot find a specified extension library: vkCreateInstance Failure"); - } - else { - K3D_VK_VERIFY(err); +void RHIRoot::SetupDebug(VkDebugReportFlagsEXT flags, PFN_vkDebugReportCallbackEXT callBack) +{ + if (s_InstanceRef) + { + s_InstanceRef->SetupDebugging(flags, callBack); } +} - uint32_t gpuCount = 0; - K3D_VK_VERIFY(vkEnumeratePhysicalDevices(Instance, &gpuCount, nullptr)); - VKLOG(Info, "RHIRoot::Initializer Device Count : %u .", gpuCount); - std::vector deviceList(gpuCount); - err = vkEnumeratePhysicalDevices(Instance, &gpuCount, deviceList.data()); - VkPhysicalDeviceProperties physicalDeviceProperties = {}; - vkGetPhysicalDeviceProperties(deviceList[0], &physicalDeviceProperties); - VKLOG(Info, "Vulkan First Device: %s", physicalDeviceProperties.deviceName); - PhysicalDevices.swap(deviceList); +uint32 RHIRoot::GetHostGpuCount() +{ + return s_GpuRefs.Count(); +} +GpuRef RHIRoot::GetHostGpuById(uint32 id) +{ + return s_GpuRefs[id]; } -void RHIRoot::Destroy() +VkInstance RHIRoot::GetInstance() { -#if _DEBUG - FreeDebugCallback(Instance); -#endif - vkDestroyInstance(Instance, nullptr); - VKLOG(Info, "RHIRoot: Destroy Instance."); + return s_InstanceRef ? s_InstanceRef->m_Instance : VK_NULL_HANDLE; } -void RHIRoot::AddViewport(RenderViewport * vp) +rhi::DeviceRef RHIRoot::GetDeviceById(uint32 id) +{ + return s_DeviceRefs[id]; +} + +void RHIRoot::AddViewport(RenderViewportSp vp) { s_Vp = vp; } -RenderViewport * RHIRoot::GetViewport(int index) +RenderViewportSp +RHIRoot::GetViewport(int index) { return s_Vp; } -void RHIRoot::EnumLayers() +void RHIRoot::EnumLayersAndExts() { + // Enum Layers uint32 layerCount = 0; K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, nullptr)); - if(layerCount>0) - { - s_LayerProps.resize(layerCount); - K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, s_LayerProps.data())); - } - VKLOG(Info, "layerCount = %d. ", layerCount); -} - -VkResult RHIRoot::CreateInstance(bool enableValidation, std::string name) -{ -#if K3DPLATFORM_OS_WIN -#define PLATFORM_SURFACE_EXT VK_KHR_WIN32_SURFACE_EXTENSION_NAME -#elif defined(K3DPLATFORM_OS_LINUX) && !defined(K3DPLATFORM_OS_ANDROID) -#define PLATFORM_SURFACE_EXT VK_KHR_XCB_SURFACE_EXTENSION_NAME -#elif defined(K3DPLATFORM_OS_ANDROID) -#define PLATFORM_SURFACE_EXT VK_KHR_ANDROID_SURFACE_EXTENSION_NAME -#endif - uint32_t instanceExtensionCount = 0; - K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr)); - VKLOG(Info, "extension num : %d.", instanceExtensionCount); - VkBool32 surfaceExtFound = 0; - VkBool32 platformSurfaceExtFound = 0; - VkExtensionProperties* instanceExtensions = new VkExtensionProperties[instanceExtensionCount]; - K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, instanceExtensions)); - std::vector enabledExtensions; - for (uint32_t i = 0; i < instanceExtensionCount; i++) { - if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, instanceExtensions[i].extensionName)) - { - surfaceExtFound = 1; - enabledExtensions.push_back( VK_KHR_SURFACE_EXTENSION_NAME ); - } - if (!strcmp(PLATFORM_SURFACE_EXT, instanceExtensions[i].extensionName)) - { - platformSurfaceExtFound = 1; - enabledExtensions.push_back( PLATFORM_SURFACE_EXT ); - } - if (enableValidation) - { - enabledExtensions.push_back( VK_EXT_DEBUG_REPORT_EXTENSION_NAME ); - } - VKLOG(Info, "available extension : %s .", instanceExtensions[i].extensionName); - } - if (!surfaceExtFound) - { - VKLOG(Error, "vkEnumerateInstanceExtensionProperties failed to find the " VK_KHR_SURFACE_EXTENSION_NAME" extension."); - } - if (!platformSurfaceExtFound) + if(layerCount > 0) { - VKLOG(Error, "vkEnumerateInstanceExtensionProperties failed to find the " PLATFORM_SURFACE_EXT " extension."); + gVkLayerProps.Resize(layerCount); + K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, gVkLayerProps.Data())); } - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = name.c_str(); - appInfo.pEngineName = name.c_str(); - appInfo.apiVersion = VK_MAKE_VERSION(1,0,1); - appInfo.engineVersion = 1; - appInfo.applicationVersion = 0; - - VkInstanceCreateInfo instanceCreateInfo = {}; - instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instanceCreateInfo.pNext = NULL; - instanceCreateInfo.pApplicationInfo = &appInfo; - instanceCreateInfo.enabledExtensionCount = (uint32_t)enabledExtensions.size(); - instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data(); - if (enableValidation && !s_LayerProps.empty()) + // Enum Extensions + uint32 extCount = 0; + K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr)); + if (extCount > 0) { - for (auto prop : s_LayerProps) - { - if (strcmp(prop.layerName, g_ValidationLayerNames[0]) == 0 /*|| strcmp(prop.layerName, g_ValidationLayerNames[1])==0*/) - { - s_LayerNames.push_back(prop.layerName); - instanceCreateInfo.enabledLayerCount = s_LayerNames.size(); - instanceCreateInfo.ppEnabledLayerNames = s_LayerNames.data(); - VKLOG(Info, "enable validation layer [%s].", prop.layerName); - break; - } - } + gVkExtProps.Resize(extCount); + K3D_VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extCount, gVkExtProps.Data())); } - return vkCreateInstance(&instanceCreateInfo, nullptr, &Instance); -} - -// Macro to get a procedure address based on a vulkan instance -#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \ -{ \ - fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \ - if (fp##entrypoint == NULL) \ - { \ - exit(1); \ - } \ + VKLOG(Info, ">> RHIRoot::EnumLayersAndExts <<\n\n" + "=================================>> layerCount = %d.\n" + "=================================>> extensionCount = %d.\n", layerCount, extCount); } -// Macro to get a procedure address based on a vulkan device -#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \ -{ \ - fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \ - if (fp##entrypoint == NULL) \ - { \ - exit(1); \ - } \ -} +} // End NS -- vk -void SwapChain::InitProcs() -{ - GET_INSTANCE_PROC_ADDR(RHIRoot::GetInstance(), GetPhysicalDeviceSurfaceSupportKHR); - GET_INSTANCE_PROC_ADDR(RHIRoot::GetInstance(), GetPhysicalDeviceSurfaceCapabilitiesKHR); - GET_INSTANCE_PROC_ADDR(RHIRoot::GetInstance(), GetPhysicalDeviceSurfaceFormatsKHR); - GET_INSTANCE_PROC_ADDR(RHIRoot::GetInstance(), GetPhysicalDeviceSurfacePresentModesKHR); - GET_DEVICE_PROC_ADDR(GetRawDevice(), CreateSwapchainKHR); - GET_DEVICE_PROC_ADDR(GetRawDevice(), DestroySwapchainKHR); - GET_DEVICE_PROC_ADDR(GetRawDevice(), GetSwapchainImagesKHR); - GET_DEVICE_PROC_ADDR(GetRawDevice(), AcquireNextImageKHR); - GET_DEVICE_PROC_ADDR(GetRawDevice(), QueuePresentKHR); -} -} // End NS -- vk +#ifdef K3DPLATFORM_OS_WIN +static const char* LIBVULKAN = "vulkan-1.dll"; +#elif defined(K3DPLATFORM_OS_MAC) +static const char* LIBVULKAN = "libvulkan.dylib"; +#else +static const char* LIBVULKAN = "libvulkan.so"; +#endif class VkRHI : public IVkRHI { public: - VkRHI() {} - ~VkRHI() override {} + VkRHI()/* : m_VkLib(LIBVULKAN) */{} + ~VkRHI() override + { + VKLOG(Info, "Destroying.."); + Shutdown(); + } void Initialize(const char* appName, bool debug) override { @@ -252,20 +144,14 @@ class VkRHI : public IVkRHI rhi::DeviceRef GetPrimaryDevice() override { - if (!m_pMainDevice && m_ppAdapters && GetDeviceCount() > 0) - { - m_pMainDevice = m_ppAdapters[0]->GetDevice(); - } - return m_pMainDevice; + return GetDeviceById(0); } uint32 GetDeviceCount() override { return m_DeviceCount; } rhi::DeviceRef GetDeviceById(uint32 id) override { - if (!m_ppAdapters || id >= m_DeviceCount) - return nullptr; - return m_ppAdapters[id]->GetDevice(); + return vk::RHIRoot::GetDeviceById(id); } void Destroy() override @@ -280,22 +166,21 @@ class VkRHI : public IVkRHI VKLOG(Fatal, "RHI Module uninitialized!! You should call Initialize first!"); return; } - k3d::vk::EnumAndInitAllDeviceAdapter(m_ppAdapters, &m_DeviceCount, m_ConfigDebug); } void Shutdown() override { + KLOG(Info, VKRHI, "Shuting down..."); Destroy(); } const char * Name() { return "RHI_Vulkan"; } private: + //dynlib::Lib m_VkLib; bool m_IsInitialized = false; uint32 m_DeviceCount = 0; - rhi::IDeviceAdapter ** m_ppAdapters = nullptr; - rhi::DeviceRef m_pMainDevice = nullptr; bool m_ConfigDebug = false; }; diff --git a/Source/RHI/Vulkan/Private/VkRHI.h b/Source/RHI/Vulkan/Private/VkRHI.h index b493f6b..ce1b626 100755 --- a/Source/RHI/Vulkan/Private/VkRHI.h +++ b/Source/RHI/Vulkan/Private/VkRHI.h @@ -23,6 +23,7 @@ namespace k3d K3D_VK_BEGIN class Device; +using VkDeviceRef = SharedPtr; using RefDevice = std::shared_ptr; class ResourceManager; @@ -73,58 +74,67 @@ class Sampler; class ShaderResourceView; using BindingArray = DynArray; -//extern K3D_API void EnumAllDeviceAdapter(rhi::IDeviceAdapter** &, uint32*); -extern K3D_API void EnumAndInitAllDeviceAdapter(rhi::IDeviceAdapter** &, uint32*, bool debug); +class DescriptorAllocator; +using DescriptorAllocRef = SharedPtr; + +class DescriptorSetLayout; +using DescriptorSetLayoutRef = SharedPtr; + +class DescriptorSet; +using DescriptorSetRef = SharedPtr; + +class RenderViewport; +using RenderViewportSp = SharedPtr; + +typedef std::map MapPipelineLayout; +typedef std::unordered_map MapDescriptorSetLayout; +typedef std::unordered_map MapDescriptorAlloc; struct RHIRoot { - using DeviceList = std::vector; - static void Initialize(const char* appName, bool debug); static void Destroy(); + static void SetupDebug(VkDebugReportFlagsEXT flags, PFN_vkDebugReportCallbackEXT callBack); + static uint32 GetHostGpuCount(); + static GpuRef GetHostGpuById(uint32 id); + static VkInstance GetInstance(); - static DeviceList& GetPhysicDevices() { return PhysicalDevices; } - static VkInstance& GetInstance() { return Instance; } - - static void AddViewport(RenderViewport *); - static RenderViewport * GetViewport(int index); - - using LayerNames = std::vector; - static LayerNames s_LayerNames; + static rhi::DeviceRef GetDeviceById(uint32 id); + static void AddViewport(RenderViewportSp); + static RenderViewportSp GetViewport(int index); private: - static RenderViewport* s_Vp; - using LayerProps = std::vector; + static InstanceRef s_InstanceRef; + static DynArray s_GpuRefs; + static DynArray s_DeviceRefs; + static RenderViewportSp s_Vp; - static void EnumLayers(); - static VkResult CreateInstance(bool enableValidation, std::string name); - - static LayerProps s_LayerProps; - static VkInstance Instance; - static DeviceList PhysicalDevices; - friend class Device; -}; - -class DeviceAdapter : public rhi::IDeviceAdapter -{ - friend class Device; -public: - explicit DeviceAdapter(VkPhysicalDevice * pDevice) : m_pGpu(pDevice) {} - rhi::DeviceRef GetDevice() override; -private: - friend K3D_API void EnumAndInitAllDeviceAdapter(rhi::IDeviceAdapter** &, uint32*, bool debug); - VkPhysicalDevice * m_pGpu = nullptr; - rhi::DeviceRef m_pDevice; + static void EnumLayersAndExts(); + friend class Device; }; -class Device : public rhi::IDevice +//class DeviceAdapter : public rhi::IDeviceAdapter +//{ +// friend class Device; +//public: +// typedef SharedPtr Ptr; +// explicit DeviceAdapter(GpuRef const& gpu); +// ~DeviceAdapter() override; +// rhi::DeviceRef GetDevice() override; +//private: +// GpuRef m_Gpu; +// rhi::DeviceRef m_pDevice; +//}; + +class Device : public rhi::IDevice, public k3d::EnableSharedFromThis { public: - typedef Device * Ptr; + typedef k3d::SharedPtr Ptr; Device(); ~Device() override; Result Create(rhi::IDeviceAdapter *, bool withDebug) override; + Result Create(GpuRef const& gpu, bool withDebug); void Destroy(); rhi::CommandContextRef NewCommandContext(rhi::ECommandType)override; @@ -134,8 +144,8 @@ class Device : public rhi::IDevice rhi::PipelineLayoutRef NewPipelineLayout(rhi::PipelineLayoutDesc const & table) override; - DescriptorAllocator* NewDescriptorAllocator(uint32 maxSets, BindingArray const& bindings); - DescriptorSetLayout* NewDescriptorSetLayout(BindingArray const& bindings); + DescriptorAllocRef NewDescriptorAllocator(uint32 maxSets, BindingArray const& bindings); + DescriptorSetLayoutRef NewDescriptorSetLayout(BindingArray const& bindings); rhi::PipelineStateObjectRef NewPipelineState(rhi::PipelineDesc const & desc, rhi::PipelineLayoutRef ppl,rhi::EPipelineType)override; rhi::PipelineStateObjectRef CreatePipelineStateObject(rhi::PipelineDesc const & desc, rhi::PipelineLayoutRef ppl); @@ -143,23 +153,20 @@ class Device : public rhi::IDevice rhi::SyncFenceRef NewFence()override; rhi::IDescriptorPool * NewDescriptorPool() override; rhi::RenderViewportRef NewRenderViewport(void * winHandle, rhi::GfxSetting&) override; - void QueryTextureSubResourceLayout(rhi::GpuResourceRef, rhi::TextureResourceSpec const& spec, rhi::SubResourceLayout *) override; + void QueryTextureSubResourceLayout(rhi::TextureRef, rhi::TextureResourceSpec const& spec, rhi::SubResourceLayout *) override; SwapChainRef NewSwapChain(rhi::GfxSetting const& setting); - //VkQueue const& GetRawDeviceQueue() const { return m_DefaultQueue; } SpCmdQueue const& GetDefaultCmdQueue() const { return m_DefCmdQueue; } VkDevice const& GetRawDevice() const { return m_Device; } - VkPhysicalDevice const* GetGpuRef() const { return m_pGpu; } - PtrResManager const & GetMemoryManager() const { return m_ResourceManager; } + //PtrResManager const & GetMemoryManager() const { return m_ResourceManager; } PtrCmdAlloc NewCommandAllocator(bool transient); + bool FindMemoryType(uint32 typeBits, VkFlags requirementsMask, uint32 *typeIndex) const; PtrSemaphore NewSemaphore(); void WaitIdle() override { vkDeviceWaitIdle(m_Device); } - bool FindMemoryType(uint32_t typeBits, VkFlags requirementsMask, uint32 *typeIndex) const; - - uint32 GetQueueCount() const { return m_QueueCount; } + uint32 GetQueueCount() const { return m_Gpu->m_QueueProps.Count(); } SpRenderpass const & GetTopPass() const { return m_PendingPass.back(); } void PushRenderPass(SpRenderpass renderPass) { m_PendingPass.push_back(renderPass); } @@ -172,46 +179,33 @@ class Device : public rhi::IDevice SpCmdQueue InitCmdQueue(VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex); private: - - VkResult CreateDevice(VkPhysicalDevice gpu, bool withDebug, VkDevice * pDevice); - bool GetDeviceQueueProps(VkPhysicalDevice gpu); - - typedef std::map CachePipelineLayout; - - PtrResManager m_ResourceManager; - std::unique_ptr m_ContextPool; + CmdBufManagerRef m_CmdBufManager; + //PtrResManager m_ResourceManager; + //std::unique_ptr m_ContextPool; std::vector m_PendingPass; - CachePipelineLayout m_CachedPipelineLayout; - std::map m_CachedDescriptorPool; - std::map m_CachedDescriptorSetLayout; + //MapPipelineLayout m_CachedPipelineLayout; + //MapDescriptorAlloc m_CachedDescriptorPool; + //MapDescriptorSetLayout m_CachedDescriptorSetLayout; private: - // following is init params - std::vector queueProps; - VkPhysicalDeviceMemoryProperties m_MemoryProperties = {}; - VkPhysicalDeviceProperties m_PhysicalDeviceProperties = {}; + SpCmdQueue m_DefCmdQueue; SpCmdQueue m_ComputeCmdQueue; VkDevice m_Device = VK_NULL_HANDLE; - VkPhysicalDevice * m_pGpu = nullptr; - uint32 m_GraphicsQueueIndex = 0; - uint32 m_ComputeQueueIndex = 0; - uint32 m_CopyQueueIndex = 0; - uint32 m_QueueCount = 0; + GpuRef m_Gpu; }; class DeviceChild { public: - explicit DeviceChild(Device *pDevice) : m_pDevice(pDevice) {} - virtual ~DeviceChild() {} + explicit DeviceChild(Device::Ptr pDevice) : m_pDevice(pDevice) {} + virtual ~DeviceChild() { } VkDevice const & GetRawDevice() const { return m_pDevice->GetRawDevice(); } - VkPhysicalDevice const & GetPhysicalDevice() const { return *(m_pDevice->GetGpuRef()); } - //VkQueue const & GetRawQueue() const { return m_pDevice->GetRawDeviceQueue(); } + GpuRef GetGpuRef() const { return m_pDevice->m_Gpu; } Device::Ptr const GetDevice() const { return m_pDevice; } SpCmdQueue const& GetImmCmdQueue() const { return m_pDevice->GetDefaultCmdQueue(); } @@ -220,6 +214,25 @@ class DeviceChild Device::Ptr m_pDevice; }; +template +class TVkRHIObjectBase : public RHIRoot, public TRHIObj +{ +public: + using ThisObj = TVkRHIObjectBase; + + explicit TVkRHIObjectBase(VkDeviceRef const& refDevice) + : m_Device(refDevice), m_NativeObj(VK_NULL_HANDLE) {} + + virtual ~TVkRHIObjectBase() {} + + TVkObj NativeHandle() const { return m_NativeObj; } + VkDevice NativeDevice() const { return m_Device->GetRawDevice(); } + +protected: + SharedPtr m_Device; + TVkObj m_NativeObj; +}; + #define DEVICE_CHILD_CONSTRUCT(className) \ explicit className(Device::Ptr ptr) : DeviceChild(ptr) {} #define DEVICE_CHILD_CONSTRUCT_DECLARE(className) \ @@ -228,37 +241,57 @@ class DeviceChild /** * Fences are signaled by the system when work invoked by vkQueueSubmit completes. */ -class Fence : public rhi::ISyncFence, public DeviceChild +class Fence : public TVkRHIObjectBase { public: Fence(Device::Ptr pDevice, VkFenceCreateInfo const & info = FenceCreateInfo::Create()) - : DeviceChild(pDevice) + : ThisObj(pDevice) { if (pDevice) { - K3D_VK_VERIFY(vkCreateFence(GetRawDevice(), &info, nullptr, &m_Fence)); + K3D_VK_VERIFY(vkCreateFence(NativeDevice(), &info, nullptr, &m_NativeObj)); } } - ~Fence() override { vkDestroyFence(GetRawDevice(), m_Fence, nullptr); } + ~Fence() override + { + if (m_NativeObj) + { + vkDestroyFence(NativeDevice(), m_NativeObj, nullptr); + VKLOG(Info, "Fence Destroyed. -- %0x.", m_NativeObj); + m_NativeObj = VK_NULL_HANDLE; + } + } void Signal(int32 val) override {} bool IsSignaled() { - return VK_SUCCESS==vkGetFenceStatus(GetRawDevice(), m_Fence); + return VK_SUCCESS== vkGetFenceStatus(NativeDevice(), m_NativeObj); } - void Reset() override { vkResetFences(GetRawDevice(), 1, &m_Fence); } + void Reset() override { vkResetFences(NativeDevice(), 1, &m_NativeObj); } + void WaitFor(uint64 time) override { - vkWaitForFences(GetRawDevice(), 1, &m_Fence, VK_TRUE, time); + vkWaitForFences(NativeDevice(), 1, &m_NativeObj, VK_TRUE, time); } + private: friend class SwapChain; friend class CommandContext; +}; + +class Sampler : public TVkRHIObjectBase +{ +public: + explicit Sampler(Device::Ptr pDevice, rhi::SamplerState const & sampleDesc); + ~Sampler() override; + rhi::SamplerState GetSamplerDesc() const; - VkFence m_Fence = VK_NULL_HANDLE; +protected: + VkSamplerCreateInfo m_SamplerCreateInfo = {}; + rhi::SamplerState m_SamplerState; }; /** @@ -318,16 +351,18 @@ class DescriptorSetLayout : public DeviceChild class DescriptorSet : public DeviceChild, public rhi::IDescriptor { public: - static DescriptorSet* CreateDescSet(DescriptorAllocator *descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice); + static DescriptorSet* CreateDescSet(DescriptorAllocRef descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice); virtual ~DescriptorSet(); + void Update(uint32 bindSet, rhi::SamplerRef) override; void Update(uint32 bindSet, rhi::GpuResourceRef) override; + uint32 GetSlotNum() const override; VkDescriptorSet GetNativeHandle() const { return m_DescriptorSet; } private: - DescriptorSet( DescriptorAllocator *descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice ); + DescriptorSet( DescriptorAllocRef descriptorPool, VkDescriptorSetLayout layout, BindingArray const & bindings, Device::Ptr pDevice ); VkDescriptorSet m_DescriptorSet = VK_NULL_HANDLE; - DescriptorAllocator* m_DescriptorAllocator = nullptr; + DescriptorAllocRef m_DescriptorAllocator = nullptr; BindingArray m_Bindings; std::vector m_BoundDescriptorSet; @@ -335,7 +370,6 @@ class DescriptorSet : public DeviceChild, public rhi::IDescriptor void Destroy(); }; - class Resource : virtual public rhi::IGpuResource, public DeviceChild { public: @@ -350,9 +384,9 @@ class Resource : virtual public rhi::IGpuResource, public DeviceChild VkDeviceMemory GetDeviceMemory() const { return m_DeviceMem; } Resource::Ptr Map(uint64 offset, uint64 size) override; - void UnMap() override { vkUnmapMemory(GetRawDevice(), m_DeviceMem); } - uint64 GetResourceSize() const override { return m_Size; } - rhi::ResourceDesc GetResourceDesc() const override { return m_Desc; } + void UnMap() override { vkUnmapMemory(GetRawDevice(), m_DeviceMem); } + uint64 GetSize() const override { return m_Size; } + rhi::ResourceDesc GetDesc() const override { return m_Desc; } protected: VkMemoryAllocateInfo m_MemAllocInfo; @@ -366,32 +400,124 @@ class Resource : virtual public rhi::IGpuResource, public DeviceChild rhi::ResourceDesc m_Desc; }; -class Buffer : public Resource +template +class TResource : public TVkRHIObjectBase +{ +public: + using ThisResourceType = TResource; + using TVkRHIObjectBase::m_NativeObj; + using TVkRHIObjectBase::NativeDevice; + using TVkRHIObjectBase::m_Device; + + explicit TResource(VkDeviceRef const & refDevice) + : TVkRHIObjectBase(refDevice) + , m_MemAllocInfo{} + , m_HostMemAddr(nullptr) + , m_DeviceMem{ VK_NULL_HANDLE } + , m_ResView(VK_NULL_HANDLE) + , m_ResDesc{} + {} + + TResource(VkDeviceRef const & refDevice, rhi::ResourceDesc const &desc) + : TVkRHIObjectBase(refDevice) + , m_MemAllocInfo{} + , m_HostMemAddr(nullptr) + , m_DeviceMem{} + , m_ResView(VK_NULL_HANDLE) + , m_ResDesc(desc) + {} + + virtual ~TResource() + { + if (VK_NULL_HANDLE != m_ResView) + { + ResTrait::DestroyView(NativeDevice(), m_ResView, nullptr); + VKLOG(Info, "TResourceView Destroying.. -- %p.", m_ResView); + m_ResView = VK_NULL_HANDLE; + } + if (VK_NULL_HANDLE != m_NativeObj) + { + VKLOG(Info, "TResource Destroying.. -- %p.", m_NativeObj); + ResTrait::Destroy(NativeDevice(), m_NativeObj, nullptr); + m_NativeObj = VK_NULL_HANDLE; + } + if (VK_NULL_HANDLE != m_DeviceMem) + { + VKLOG(Info, "TResource Freeing Memory. -- 0x%0x, tid:%d", m_DeviceMem, Os::Thread::GetId()); + vkFreeMemory(NativeDevice(), m_DeviceMem, nullptr); + m_DeviceMem = VK_NULL_HANDLE; + } + } + + void* Map(uint64 offset, uint64 size) + { + K3D_VK_VERIFY(vkMapMemory(NativeDevice(), m_DeviceMem, offset, size, 0, &m_HostMemAddr)); + return m_HostMemAddr; + } + + void UnMap() + { + vkUnmapMemory(NativeDevice(), m_DeviceMem); + } + +protected: + typedef typename ResTrait::CreateInfo CreateInfo; + typedef typename ResTrait::View ResourceView; + typedef typename ResTrait::DescriptorInfo ResourceDescriptorInfo; + typedef typename ResTrait::UsageFlags ResourceUsageFlags; + + VkMemoryAllocateInfo m_MemAllocInfo; + VkMemoryRequirements m_MemReq; + VkDeviceMemory m_DeviceMem; + VkMemoryPropertyFlags m_MemoryBits = 0; + void* m_HostMemAddr; + ResourceView m_ResView; + ResourceUsageFlags m_ResUsageFlags = 0; + ResourceDescriptorInfo m_ResDescInfo{}; + rhi::ResourceDesc m_ResDesc; + +protected: + + void Allocate(CreateInfo const& info) + { + K3D_VK_VERIFY(ResTrait::Create(NativeDevice(), &info, nullptr, &m_NativeObj)); + m_MemAllocInfo = {}; + m_MemAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + ResTrait::GetMemoryInfo(NativeDevice(), m_NativeObj, &m_MemReq); + + m_MemAllocInfo.allocationSize = m_MemReq.size; + m_Device->FindMemoryType(m_MemReq.memoryTypeBits, m_MemoryBits, &m_MemAllocInfo.memoryTypeIndex); + K3D_VK_VERIFY(vkAllocateMemory(NativeDevice(), &m_MemAllocInfo, nullptr, &m_DeviceMem)); + m_MemAllocInfo.allocationSize; + + /*K3D_VK_VERIFY(vkBindBufferMemory(NativeDevice(), m_Buffer, m_DeviceMem, m_AllocationOffset));*/ + } +}; + +class Buffer : public TResource { public: typedef Buffer * Ptr; - explicit Buffer(Device::Ptr pDevice) : Resource(pDevice) {} + explicit Buffer(Device::Ptr pDevice) : ThisResourceType(pDevice) {} Buffer(Device::Ptr pDevice, rhi::ResourceDesc const & desc); virtual ~Buffer(); void Create(size_t size); - uint64 GetResourceLocation() const override { return (uint64)m_Buffer; } - rhi::EGpuResourceType GetResourceType() const override { return rhi::EGT_Buffer; } -private: - VkDescriptorBufferInfo m_BufferInfo; - VkBufferView m_BufferView = VK_NULL_HANDLE; - VkBuffer m_Buffer = VK_NULL_HANDLE; - VkBufferUsageFlags m_Usage = 0; - VkMemoryPropertyFlags m_MemoryBits = 0; + uint64 GetLocation() const override { return (uint64)m_NativeObj; } + uint64 GetSize() const override { return m_MemAllocInfo.allocationSize; } + rhi::ResourceDesc GetDesc() const override { return m_ResDesc; } + + void* Map(uint64 offset, uint64 size) override { return ThisResourceType::Map(offset, size); } + void UnMap() override { return ThisResourceType::UnMap(); } }; -class Texture : public rhi::ITexture, public Resource +class Texture : public TResource { public: typedef ::k3d::SharedPtr TextureRef; - explicit Texture(Device::Ptr pDevice) : Resource(pDevice) {} + explicit Texture(Device::Ptr pDevice) : ThisResourceType(pDevice) {} Texture(Device::Ptr pDevice, rhi::ResourceDesc const&); Texture(VkImage image, VkImageView imageView, VkImageViewCreateInfo info, Device::Ptr pDevice, bool selfOwnShip = true); ~Texture() override; @@ -399,13 +525,17 @@ class Texture : public rhi::ITexture, public Resource static TextureRef CreateFromSwapChain(VkImage image, VkImageView view, VkImageViewCreateInfo info, Device::Ptr pDevice); const VkImageViewCreateInfo&GetViewInfo() const { return m_ImageViewInfo; } - const VkImageView & GetView() const { return m_ImageView; } - const VkImage& Get() const { return m_Image; } + const VkImageView & GetView() const { return m_ResView; } + const VkImage& Get() const { return m_NativeObj; } VkImageLayout GetImageLayout() const { return m_ImageLayout; } VkImageSubresourceRange GetSubResourceRange() const { return m_SubResRange; } - uint64 GetResourceLocation() const override { return (uint64)m_Image; } - rhi::EResourceState GetUsageState() const override { return m_UsageState; } + uint64 GetLocation() const override { return (uint64)m_NativeObj; } + uint64 GetSize() const override { return m_MemAllocInfo.allocationSize; } + rhi::EResourceState GetState() const override { return m_UsageState; } + rhi::ResourceDesc GetDesc() const override { return m_ResDesc; } + void* Map(uint64 offset, uint64 size) override { return ThisResourceType::Map(offset, size); } + void UnMap() override { return ThisResourceType::UnMap(); } void BindSampler(rhi::SamplerRef sampler) override; rhi::SamplerCRef GetSampler() const override; @@ -431,14 +561,13 @@ class Texture : public rhi::ITexture, public Resource ::k3d::SharedPtr m_ImageSampler; VkImageViewCreateInfo m_ImageViewInfo = {}; rhi::ShaderResourceViewRef m_SRV; - VkImageView m_ImageView = VK_NULL_HANDLE; + //VkImageView m_ImageView = VK_NULL_HANDLE; ImageInfo m_ImageInfo; - VkImage m_Image = VK_NULL_HANDLE; + //VkImage m_Image = VK_NULL_HANDLE; rhi::EResourceState m_UsageState = rhi::ERS_Unknown; VkImageLayout m_ImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageMemoryBarrier m_Barrier; - VkImageUsageFlags m_ImageUsage = 0; - VkMemoryPropertyFlags m_MemoryBits = 0; + VkSubresourceLayout m_SubResourceLayout = {}; VkImageSubresourceRange m_SubResRange = {}; bool m_SelfOwn = true; @@ -536,7 +665,7 @@ class CommandContextPool : public DeviceChild CommandContextPool(Device::Ptr pDevice); ~CommandContextPool() override; - CommandContext* RequestContext(rhi::ECommandType type); + rhi::CommandContextRef RequestContext(rhi::ECommandType type); PtrCmdAlloc RequestCommandAllocator(); @@ -656,7 +785,7 @@ class CommandContext : public rhi::ICommandContext, public DeviceChild protected: VkCommandBuffer m_CommandBuffer; - VkCommandPool m_CommandPool; + //VkCommandPool m_CommandPool; VkRenderPass m_RenderPass; bool m_IsRenderPassActive = false; RenderTarget* m_CurrentRenderTarget = nullptr; @@ -665,10 +794,10 @@ class CommandContext : public rhi::ICommandContext, public DeviceChild void InitCommandBufferPool(); }; -class CommandQueue : public DeviceChild +class CommandQueue { public: - CommandQueue(Device::Ptr pDevice, VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex); + CommandQueue(VkDevice pDevice, VkQueueFlags queueTypes, uint32 queueFamilyIndex, uint32 queueIndex); virtual ~CommandQueue(); void Submit( @@ -689,6 +818,7 @@ class CommandQueue : public DeviceChild void Destroy(); private: + VkDevice m_Device = VK_NULL_HANDLE; VkQueue m_Queue = VK_NULL_HANDLE; VkQueueFlags m_QueueTypes = 0; uint32 m_QueueFamilyIndex = UINT32_MAX; @@ -736,21 +866,7 @@ class SwapChain : public DeviceChild VkFormat m_ColorAttachFmt = VK_FORMAT_UNDEFINED; private: - - void InitProcs(); - void Destroy(); - - /** private functions */ - PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR; - PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR; - PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR; - PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR; - PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR; - PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR; - PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR; - PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR; - PFN_vkQueuePresentKHR fpQueuePresentKHR; }; class RenderViewport : public rhi::IRenderViewport, public DeviceChild @@ -882,7 +998,7 @@ class RenderPass : public DeviceChild class PipelineStateObject : public rhi::IPipelineStateObject, public DeviceChild { public: - explicit PipelineStateObject(Device* pDevice); + explicit PipelineStateObject(Device::Ptr pDevice); PipelineStateObject(Device::Ptr pDevice, rhi::PipelineDesc const& desc, PipelineLayout * ppl); virtual ~PipelineStateObject(); @@ -900,6 +1016,8 @@ class PipelineStateObject : public rhi::IPipelineStateObject, public DeviceChild VkPipeline GetPipeline() const { return m_Pipeline; } void Finalize() override; + void SavePSO(const char* path) override; + void LoadPSO(const char* path) override; /** * TOFIX @@ -938,28 +1056,27 @@ class PipelineStateObject : public rhi::IPipelineStateObject, public DeviceChild PipelineLayout * m_PipelineLayout; }; -class ShaderResourceView : public rhi::IShaderResourceView +class ShaderResourceView : public TVkRHIObjectBase { public: - ShaderResourceView(rhi::ResourceViewDesc const &desc, rhi::IGpuResource * pGpuResource); - ~ShaderResourceView(); - rhi::GpuResourceRef GetResource() const override { return m_Resource; } + ShaderResourceView(Device::Ptr pDevice, rhi::ResourceViewDesc const &desc, rhi::GpuResourceRef gpuResource); + ~ShaderResourceView() override; + rhi::GpuResourceRef GetResource() const override { return rhi::GpuResourceRef(m_WeakResource); } rhi::ResourceViewDesc GetDesc() const override { return m_Desc; } - VkImageView NativeImageView() const { return m_TextureView; } + VkImageView NativeImageView() const { return m_NativeObj; } private: - rhi::GpuResourceRef m_Resource; + //rhi::GpuResourceRef m_Resource; + WeakPtr m_WeakResource; rhi::ResourceViewDesc m_Desc; VkImageViewCreateInfo m_TextureViewInfo; - VkImageView m_TextureView; }; -class PipelineLayout : public rhi::IPipelineLayout, public DeviceChild +class PipelineLayout : public TVkRHIObjectBase { public: PipelineLayout(Device::Ptr pDevice, rhi::PipelineLayoutDesc const &desc); - ~PipelineLayout()override; + ~PipelineLayout() override; - VkPipelineLayout GetNativeLayout() const { return m_PipelineLayout; } VkDescriptorSet GetNativeDescriptorSet() const { return static_cast(m_DescSet.Get())->GetNativeHandle(); } rhi::DescriptorRef GetDescriptorSet()const override{ return m_DescSet; } @@ -970,21 +1087,7 @@ class PipelineLayout : public rhi::IPipelineLayout, public DeviceChild friend class PipelineStateObject; private: rhi::DescriptorRef m_DescSet; - DescriptorSetLayout * m_DescSetLayout; - VkPipelineLayout m_PipelineLayout; -}; - -class Sampler : public rhi::ISampler, public DeviceChild -{ -public: - explicit Sampler(Device::Ptr pDevice, rhi::SamplerState const & sampleDesc); - ~Sampler() override; - rhi::SamplerState GetSamplerDesc() const; - VkSampler NativePtr() const { return m_Sampler; } -protected: - VkSampler m_Sampler = VK_NULL_HANDLE; - VkSamplerCreateInfo m_SamplerCreateInfo = {}; - rhi::SamplerState m_SamplerState; + DescriptorSetLayoutRef m_DescSetLayout; }; K3D_VK_END diff --git a/Source/RHI/Vulkan/Private/VkRenderPass.cpp b/Source/RHI/Vulkan/Private/VkRenderPass.cpp index 5d237a2..6b07804 100755 --- a/Source/RHI/Vulkan/Private/VkRenderPass.cpp +++ b/Source/RHI/Vulkan/Private/VkRenderPass.cpp @@ -2,6 +2,8 @@ #include "VkRHI.h" #include "VkUtils.h" +//#include "Public/VkCommandWrapper.hpp" + K3D_VK_BEGIN RenderPass::RenderPass(Device::Ptr pDevice, RenderpassOptions const & options) @@ -207,8 +209,71 @@ void RenderPass::Destroy() { return; } + VKLOG(Info, "RenderPass destroy... -- %0x.", m_RenderPass); vkDestroyRenderPass(GetRawDevice(), m_RenderPass, nullptr); m_RenderPass = VK_NULL_HANDLE; } +FrameBuffer::FrameBuffer(Device::Ptr pDevice, VkRenderPass renderPass, FrameBuffer::Option const& op) + : DeviceChild(pDevice) + , m_RenderPass(renderPass) + , m_Width(op.Width) + , m_Height(op.Height) +{ + VKRHI_METHOD_TRACE + for (auto& elem : op.Attachments) + { + if (elem.ImageAttachment) + { + continue; + } + } + + std::vector attachments; + for (const auto& elem : op.Attachments) { + attachments.push_back(elem.ImageAttachment); + } + + VkFramebufferCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.renderPass = m_RenderPass; + createInfo.attachmentCount = static_cast(op.Attachments.size()); + createInfo.pAttachments = attachments.data(); + createInfo.width = m_Width; + createInfo.height = m_Height; + createInfo.layers = 1; + createInfo.flags = 0; + K3D_VK_VERIFY(vkCreateFramebuffer(GetRawDevice(), &createInfo, nullptr, &m_FrameBuffer)); +} + +FrameBuffer::FrameBuffer(Device::Ptr pDevice, RenderPass * renderPass, RenderTargetLayout const &) + : DeviceChild(pDevice) +{ +} + +FrameBuffer::~FrameBuffer() +{ + if (VK_NULL_HANDLE == m_FrameBuffer) + { + return; + } + VKLOG(Info, "FrameBuffer destroy... -- %0x.", m_FrameBuffer); + vkDestroyFramebuffer(GetRawDevice(), m_FrameBuffer, nullptr); + m_FrameBuffer = VK_NULL_HANDLE; +} + +FrameBuffer::Attachment::Attachment(VkFormat format, VkSampleCountFlagBits samples) +{ + VkImageAspectFlags aspectMask = DetermineAspectMask(Format); + if (VK_IMAGE_ASPECT_COLOR_BIT == aspectMask) + { + FormatFeatures = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + } + else + { + FormatFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + } +} + K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkRenderViewport.cpp b/Source/RHI/Vulkan/Private/VkRenderViewport.cpp index f54a0cb..b268441 100755 --- a/Source/RHI/Vulkan/Private/VkRenderViewport.cpp +++ b/Source/RHI/Vulkan/Private/VkRenderViewport.cpp @@ -9,7 +9,7 @@ K3D_VK_BEGIN RenderViewport::RenderViewport( - Device * pDevice, + Device::Ptr pDevice, void * windowHandle, rhi::GfxSetting & setting) : m_NumBufferCount(-1) @@ -25,7 +25,6 @@ RenderViewport::RenderViewport( setting.Width, setting.Height, m_NumBufferCount); m_PresentSemaphore = GetDevice()->NewSemaphore(); m_RenderSemaphore = GetDevice()->NewSemaphore(); - RHIRoot::AddViewport(this); } } @@ -95,7 +94,7 @@ void RenderViewport::AllocateDefaultRenderPass(rhi::GfxSetting & gfxSetting) if (gfxSetting.HasDepth) { VkFormat depthFormat = g_FormatTable[gfxSetting.DepthStencilFormat]; - GetSupportedDepthFormat(GetPhysicalDevice(), &depthFormat); + GetGpuRef()->GetSupportedDepthFormat(&depthFormat); RenderpassAttachment depthAttach = RenderpassAttachment::CreateDepthStencil(depthFormat); depthAttach.GetDescription().InitialLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) @@ -112,7 +111,7 @@ void RenderViewport::AllocateRenderTargets(rhi::GfxSetting & gfxSetting) if (m_RenderPass) { VkFormat depthFormat = g_FormatTable[gfxSetting.DepthStencilFormat]; - GetSupportedDepthFormat(GetPhysicalDevice(), &depthFormat); + GetGpuRef()->GetSupportedDepthFormat(&depthFormat); VkImage depthImage; VkImageCreateInfo image = {}; image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -173,7 +172,7 @@ void RenderViewport::AllocateRenderTargets(rhi::GfxSetting & gfxSetting) for (uint32_t i = 0; i < m_NumBufferCount; ++i) { VkImage colorImage = m_pSwapChain->GetBackImage(i); - auto colorImageInfo = ImageViewInfo::CreateColorImageView(GetRawDevice(), colorFmt, colorImage); + auto colorImageInfo = ImageViewInfo::CreateColorImageView(GetGpuRef(), colorFmt, colorImage); VKLOG(Info, "swapchain imageView created . (0x%0x).", colorImageInfo.first); colorImageInfo.second.components = { VK_COMPONENT_SWIZZLE_R, diff --git a/Source/RHI/Vulkan/Private/VkResource.cpp b/Source/RHI/Vulkan/Private/VkResource.cpp index 700a7d5..46db774 100755 --- a/Source/RHI/Vulkan/Private/VkResource.cpp +++ b/Source/RHI/Vulkan/Private/VkResource.cpp @@ -17,23 +17,26 @@ Resource::Ptr Resource::Map(uint64 offset, uint64 size) Resource::~Resource() { - VKLOG(Info, "Resource-Destroying Resource.."); - //vkFreeMemory(GetRawDevice(), m_DeviceMem, nullptr); + if (!m_DeviceMem) + return; + VKLOG(Info, "Resource freeing gpu memory. -- 0x%0x, tid:%d", m_DeviceMem, Os::Thread::GetId()); + vkFreeMemory(GetRawDevice(), m_DeviceMem, nullptr); + m_DeviceMem = VK_NULL_HANDLE; } Buffer::Buffer(Device::Ptr pDevice, rhi::ResourceDesc const &desc) -: Resource(pDevice, desc) +: TResource(pDevice, desc) { - m_Usage = g_ResourceViewFlag[desc.ViewType]; + m_ResUsageFlags = g_ResourceViewFlag[desc.ViewType]; if (desc.CreationFlag & rhi::EGRCF_TransferSrc) { - m_Usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + m_ResUsageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; } if (desc.CreationFlag & rhi::EGRCF_TransferDst) { - m_Usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + m_ResUsageFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; } if (desc.Flag & rhi::EGRAF_HostVisible) @@ -53,17 +56,7 @@ Buffer::Buffer(Device::Ptr pDevice, rhi::ResourceDesc const &desc) Buffer::~Buffer() { - VKLOG(Info, "Buffer-Destroying Resource.."); - if (VK_NULL_HANDLE != m_BufferView) - { - vkDestroyBufferView(GetRawDevice(), m_BufferView, nullptr); - m_BufferView = VK_NULL_HANDLE; - } - if (VK_NULL_HANDLE != m_Buffer) - { - vkDestroyBuffer(GetRawDevice(), m_Buffer, nullptr); - m_Buffer = VK_NULL_HANDLE; - } + VKLOG(Info, "Buffer Destroying.."); } void Buffer::Create(size_t size) @@ -72,42 +65,27 @@ void Buffer::Create(size_t size) createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; createInfo.pNext = nullptr; createInfo.size = size; - createInfo.usage = m_Usage; + createInfo.usage = m_ResUsageFlags; createInfo.flags = 0; createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.queueFamilyIndexCount = 0; createInfo.pQueueFamilyIndices = nullptr; - K3D_VK_VERIFY(vkCreateBuffer(GetRawDevice(), &createInfo, nullptr, &m_Buffer)); - ResourceManager::Allocation alloc = GetDevice()->GetMemoryManager()->AllocateBuffer(m_Buffer, false, m_MemoryBits); - K3D_ASSERT(VK_NULL_HANDLE != alloc.Memory); - m_DeviceMem = alloc.Memory; - m_AllocationOffset = alloc.Offset; - m_AllocationSize = alloc.Size; - m_Size = size; + TResource::Allocate(createInfo); - VKLOG(Info, "Buffer reqSize:(%d) allocated:(%d) offset:(%d) address:(0x%0x).", - m_Size, m_AllocationSize, m_AllocationOffset, m_DeviceMem); - - m_BufferInfo.buffer = m_Buffer; - m_BufferInfo.offset = 0; - m_BufferInfo.range = m_Size; + m_ResDescInfo.buffer = m_NativeObj; + m_ResDescInfo.offset = 0; + m_ResDescInfo.range = m_MemAllocInfo.allocationSize; - K3D_VK_VERIFY(vkCmd::BindBufferMemory(GetRawDevice(), m_Buffer, m_DeviceMem, m_AllocationOffset)); + K3D_VK_VERIFY(vkBindBufferMemory(NativeDevice(), m_NativeObj, m_DeviceMem, 0)); } -/*Texture::Texture(Device::Ptr pDevice, rhi::TextureDesc const &desc) -: Resource(pDevice) -{ - Create(desc); -}*/ - Texture::Texture(Device::Ptr pDevice, rhi::ResourceDesc const & desc) - : Resource(pDevice, desc) + : Texture::ThisResourceType(pDevice, desc) { if (desc.CreationFlag & rhi::EGRCF_TransferDst) { - m_ImageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + m_ResUsageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; } if (desc.Flag & rhi::EGRAF_HostVisible) { @@ -139,9 +117,7 @@ Texture::Texture(Device::Ptr pDevice, rhi::ResourceDesc const & desc) } Texture::Texture(VkImage image, VkImageView imageView, VkImageViewCreateInfo info, Device::Ptr pDevice, bool selfOwnShip) - : Resource(pDevice) - , m_ImageView(imageView) - , m_Image(image) + : Texture::ThisResourceType(pDevice) , m_ImageViewInfo(info) , m_SelfOwn(selfOwnShip) { @@ -160,27 +136,21 @@ SamplerCRef Texture::GetSampler() const void Texture::CreateResourceView() { - m_ImageViewInfo = ImageViewInfo::From(m_ImageInfo, m_Image); - K3D_VK_VERIFY(vkCreateImageView(GetRawDevice(), &m_ImageViewInfo, nullptr, &m_ImageView)); + m_ImageViewInfo = ImageViewInfo::From(m_ImageInfo, m_NativeObj); + K3D_VK_VERIFY(vkCreateImageView(NativeDevice(), &m_ImageViewInfo, nullptr, &m_ResView)); } void Texture::CreateRenderTexture(TextureDesc const & desc) { m_ImageInfo = ImageInfo::FromRHI(desc); - K3D_VK_VERIFY(vkCreateImage(GetRawDevice(), &m_ImageInfo, nullptr, &m_Image)); + m_MemoryBits = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - ResourceManager::Allocation alloc = GetDevice()->GetMemoryManager()->AllocateImage(m_Image, false, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - K3D_ASSERT(VK_NULL_HANDLE != alloc.Memory); + ThisResourceType::Allocate(m_ImageInfo); - m_DeviceMem = alloc.Memory; - m_AllocationOffset = alloc.Offset; - m_AllocationSize = alloc.Size; - m_Size = alloc.Size; + K3D_VK_VERIFY(vkBindImageMemory(NativeDevice(), m_NativeObj, m_DeviceMem, 0)); - K3D_VK_VERIFY(vkBindImageMemory(GetRawDevice(), m_Image, m_DeviceMem, m_AllocationOffset)); - - m_ImageViewInfo = ImageViewInfo::From(m_ImageInfo, m_Image); - K3D_VK_VERIFY(vkCreateImageView(GetRawDevice(), &m_ImageViewInfo, nullptr, &m_ImageView)); + m_ImageViewInfo = ImageViewInfo::From(m_ImageInfo, m_NativeObj); + K3D_VK_VERIFY(vkCreateImageView(NativeDevice(), &m_ImageViewInfo, nullptr, &m_ResView)); VkImageSubresource subres; subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -189,7 +159,7 @@ void Texture::CreateRenderTexture(TextureDesc const & desc) // query texture memory layout info here // image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR // The aspectMask member of pSubresource must only have a single bit set - vkGetImageSubresourceLayout(GetRawDevice(), m_Image, &subres, &m_SubResourceLayout); + vkGetImageSubresourceLayout(NativeDevice(), m_NativeObj, &subres, &m_SubResourceLayout); } void Texture::CreateDepthStencilTexture(TextureDesc const & desc) @@ -199,40 +169,27 @@ void Texture::CreateDepthStencilTexture(TextureDesc const & desc) void Texture::CreateSampledTexture(TextureDesc const & desc) { m_ImageInfo = ImageInfo::FromRHI(desc); - m_ImageInfo.usage = m_ImageUsage | VK_IMAGE_USAGE_SAMPLED_BIT; - m_ImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - m_ImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + m_ImageInfo.usage = m_ResUsageFlags | VK_IMAGE_USAGE_SAMPLED_BIT; + if (m_ResUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) // texture upload use staging + { + m_ImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + m_ImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + else // directly upload + { + m_ImageInfo.tiling = VK_IMAGE_TILING_LINEAR; + m_ImageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + } m_SubResRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, desc.MipLevels, 0, desc.Layers }; - K3D_VK_VERIFY(vkCreateImage(GetRawDevice(), &m_ImageInfo, nullptr, &m_Image)); - - ResourceManager::Allocation alloc = GetDevice()->GetMemoryManager()->AllocateImage(m_Image, false, m_MemoryBits); - K3D_ASSERT(VK_NULL_HANDLE != alloc.Memory); - - m_DeviceMem = alloc.Memory; - m_AllocationOffset = alloc.Offset; - m_AllocationSize = alloc.Size; - m_Size = alloc.Size; + ThisResourceType::Allocate(m_ImageInfo); - K3D_VK_VERIFY(vkBindImageMemory(GetRawDevice(), m_Image, m_DeviceMem, m_AllocationOffset)); + K3D_VK_VERIFY(vkBindImageMemory(NativeDevice(), m_NativeObj, m_DeviceMem, 0)); } Texture::~Texture() { - if (GetRawDevice() == VK_NULL_HANDLE) - return; - if (VK_NULL_HANDLE != m_ImageView) - { - vkDestroyImageView(GetRawDevice(), m_ImageView, nullptr); - m_ImageView = VK_NULL_HANDLE; - } - if (VK_NULL_HANDLE != m_Image && m_SelfOwn) - { - vkDestroyImage(GetRawDevice(), m_Image, nullptr); - m_Image = VK_NULL_HANDLE; - } - VKLOG(Info, "Texture-Destroyed.."); } Texture::TextureRef Texture::CreateFromSwapChain(VkImage image, VkImageView view, VkImageViewCreateInfo info, Device::Ptr pDevice) @@ -240,31 +197,85 @@ Texture::TextureRef Texture::CreateFromSwapChain(VkImage image, VkImageView view return k3d::MakeShared(image, view, info, pDevice, false); } -ShaderResourceView::ShaderResourceView(rhi::ResourceViewDesc const &desc, rhi::IGpuResource * pGpuResource) - : m_Desc(desc), m_Resource(pGpuResource), m_TextureViewInfo{}, m_TextureView(VK_NULL_HANDLE) +ShaderResourceView::ShaderResourceView(Device::Ptr pDevice, rhi::ResourceViewDesc const &desc, rhi::GpuResourceRef pGpuResource) + : ShaderResourceView::ThisObj(pDevice) + , m_Desc(desc), m_WeakResource(pGpuResource), m_TextureViewInfo{} { - auto resourceDesc = m_Resource->GetResourceDesc(); + auto resourceDesc = m_WeakResource->GetDesc(); + m_TextureViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + m_TextureViewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; switch(resourceDesc.Type) { + case rhi::EGT_Texture1D: + m_TextureViewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D; + break; case rhi::EGT_Texture2D: - m_TextureViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - m_TextureViewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; m_TextureViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - m_TextureViewInfo.format = g_FormatTable[resourceDesc.TextureDesc.Format]; - m_TextureViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_TextureViewInfo.subresourceRange.baseMipLevel = 0; - m_TextureViewInfo.subresourceRange.baseArrayLayer = 0; - m_TextureViewInfo.subresourceRange.layerCount = 1; - m_TextureViewInfo.subresourceRange.levelCount = resourceDesc.TextureDesc.MipLevels; - m_TextureViewInfo.image = (VkImage)m_Resource->GetResourceLocation(); - K3D_VK_VERIFY(vkCreateImageView(dynamic_cast(m_Resource.Get())->GetRawDevice(), &m_TextureViewInfo, nullptr, &m_TextureView)); + break; + case rhi::EGT_Texture3D: + m_TextureViewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D; + break; + case rhi::EGT_Texture2DArray: + m_TextureViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; } + m_TextureViewInfo.format = g_FormatTable[resourceDesc.TextureDesc.Format]; + m_TextureViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + m_TextureViewInfo.subresourceRange.baseMipLevel = 0; + m_TextureViewInfo.subresourceRange.baseArrayLayer = 0; + m_TextureViewInfo.subresourceRange.layerCount = 1; + m_TextureViewInfo.subresourceRange.levelCount = resourceDesc.TextureDesc.MipLevels; + m_TextureViewInfo.image = (VkImage)m_WeakResource->GetLocation(); + + K3D_VK_VERIFY(vkCreateImageView(NativeDevice(), &m_TextureViewInfo, nullptr, &m_NativeObj)); } ShaderResourceView::~ShaderResourceView() { // destroy view + VKLOG(Info, "ShaderResourceView destroying..."); + if (m_NativeObj) + { + vkDestroyImageView(NativeDevice(), m_NativeObj, nullptr); + m_NativeObj = VK_NULL_HANDLE; + } +} + +Sampler::Sampler(Device::Ptr pDevice, rhi::SamplerState const & samplerDesc) + : ThisObj(pDevice) + , m_SamplerState(samplerDesc) +{ + if (pDevice) + { + m_SamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + m_SamplerCreateInfo.magFilter = g_Filters[samplerDesc.Filter.MagFilter]; + m_SamplerCreateInfo.minFilter = g_Filters[samplerDesc.Filter.MinFilter]; + m_SamplerCreateInfo.mipmapMode = g_MipMapModes[samplerDesc.Filter.MipMapFilter]; + m_SamplerCreateInfo.addressModeU = g_AddressModes[samplerDesc.U]; + m_SamplerCreateInfo.addressModeV = g_AddressModes[samplerDesc.V]; + m_SamplerCreateInfo.addressModeW = g_AddressModes[samplerDesc.W]; + m_SamplerCreateInfo.mipLodBias = samplerDesc.MipLODBias; + m_SamplerCreateInfo.compareOp = g_ComparisonFunc[samplerDesc.ComparisonFunc]; + m_SamplerCreateInfo.minLod = samplerDesc.MinLOD; + // Max level-of-detail should match mip level count + m_SamplerCreateInfo.maxLod = samplerDesc.MaxLOD; + // Enable anisotropic filtering + m_SamplerCreateInfo.maxAnisotropy = samplerDesc.MaxAnistropy; + m_SamplerCreateInfo.anisotropyEnable = VK_TRUE; + m_SamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; // cannot convert... + vkCreateSampler(NativeDevice(), &m_SamplerCreateInfo, nullptr, &m_NativeObj); + } +} + +Sampler::~Sampler() +{ + VKLOG(Info, "Sampler Destroying %p...", m_NativeObj); + vkDestroySampler(NativeDevice(), m_NativeObj, nullptr); +} + +rhi::SamplerState Sampler::GetSamplerDesc() const +{ + return m_SamplerState; } template @@ -338,6 +349,8 @@ ResourceManager::PoolManager::~PoolManager() template void ResourceManager::PoolManager::Destroy() { + if (!GetRawDevice()) + return; ::Os::Mutex::AutoLock lock(&m_Mutex); for (auto& pool : m_Pools) { vkFreeMemory(GetRawDevice(), pool->m_Memory, nullptr); diff --git a/Source/RHI/Vulkan/Private/VkSampler.cpp b/Source/RHI/Vulkan/Private/VkSampler.cpp deleted file mode 100755 index f59a134..0000000 --- a/Source/RHI/Vulkan/Private/VkSampler.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "VkCommon.h" -#include "VkRHI.h" -#include "VkEnums.h" - -K3D_VK_BEGIN - -Sampler::Sampler(Device::Ptr pDevice, rhi::SamplerState const & samplerDesc) - : DeviceChild(pDevice) - , m_SamplerState(samplerDesc) -{ - if (pDevice) - { - m_SamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - m_SamplerCreateInfo.magFilter = g_Filters[samplerDesc.Filter.MagFilter]; - m_SamplerCreateInfo.minFilter = g_Filters[samplerDesc.Filter.MinFilter]; - m_SamplerCreateInfo.mipmapMode = g_MipMapModes[samplerDesc.Filter.MipMapFilter]; - m_SamplerCreateInfo.addressModeU = g_AddressModes[samplerDesc.U]; - m_SamplerCreateInfo.addressModeV = g_AddressModes[samplerDesc.V]; - m_SamplerCreateInfo.addressModeW = g_AddressModes[samplerDesc.W]; - m_SamplerCreateInfo.mipLodBias = samplerDesc.MipLODBias; - m_SamplerCreateInfo.compareOp = g_ComparisonFunc[samplerDesc.ComparisonFunc]; - m_SamplerCreateInfo.minLod = samplerDesc.MinLOD; - // Max level-of-detail should match mip level count - m_SamplerCreateInfo.maxLod = samplerDesc.MaxLOD; - // Enable anisotropic filtering - m_SamplerCreateInfo.maxAnisotropy = samplerDesc.MaxAnistropy; - m_SamplerCreateInfo.anisotropyEnable = VK_TRUE; - m_SamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; // cannot convert... - vkCreateSampler(GetRawDevice(), &m_SamplerCreateInfo, nullptr, &m_Sampler); - } -} - -Sampler::~Sampler() -{ - VKLOG(Info, "Sampler-Destroying ..."); - vkDestroySampler(GetRawDevice(), m_Sampler, nullptr); -} - -rhi::SamplerState Sampler::GetSamplerDesc() const -{ - return m_SamplerState; -} - -K3D_VK_END \ No newline at end of file diff --git a/Source/RHI/Vulkan/Private/VkSwapChain.cpp b/Source/RHI/Vulkan/Private/VkSwapChain.cpp index d3e3dc9..6deb0b2 100755 --- a/Source/RHI/Vulkan/Private/VkSwapChain.cpp +++ b/Source/RHI/Vulkan/Private/VkSwapChain.cpp @@ -7,10 +7,6 @@ K3D_VK_BEGIN SwapChain::SwapChain(Device::Ptr pDevice) : DeviceChild(pDevice), m_ReserveBackBufferCount(0) { - if(pDevice) - { - InitProcs(); - } } SwapChain::~SwapChain() @@ -26,7 +22,7 @@ void SwapChain::Initialize(void * WindowHandle, rhi::GfxSetting & gfxSetting) m_SelectedPresentQueueFamilyIndex = ChooseQueueIndex(); m_SwapchainExtent = { gfxSetting.Width, gfxSetting.Height }; VkSurfaceCapabilitiesKHR surfProperties; - K3D_VK_VERIFY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(GetPhysicalDevice(), m_Surface, &surfProperties)); + K3D_VK_VERIFY(GetGpuRef()->GetSurfaceCapabilitiesKHR(m_Surface, &surfProperties)); m_SwapchainExtent = surfProperties.currentExtent; /*gfxSetting.Width = m_SwapchainExtent.width; gfxSetting.Height = m_SwapchainExtent.height;*/ @@ -36,9 +32,9 @@ void SwapChain::Initialize(void * WindowHandle, rhi::GfxSetting & gfxSetting) surfProperties.maxImageCount); m_DesiredBackBufferCount = desiredNumBuffers; InitSwapChain(m_DesiredBackBufferCount, chosenFormat, swapchainPresentMode, surfProperties.currentTransform); - K3D_VK_VERIFY(fpGetSwapchainImagesKHR(GetRawDevice(), m_SwapChain, &m_ReserveBackBufferCount, nullptr)); + K3D_VK_VERIFY(vkGetSwapchainImagesKHR(GetRawDevice(), m_SwapChain, &m_ReserveBackBufferCount, nullptr)); m_ColorImages.resize(m_ReserveBackBufferCount); - K3D_VK_VERIFY(fpGetSwapchainImagesKHR(GetRawDevice(), m_SwapChain, &m_ReserveBackBufferCount, m_ColorImages.data())); + K3D_VK_VERIFY(vkGetSwapchainImagesKHR(GetRawDevice(), m_SwapChain, &m_ReserveBackBufferCount, m_ColorImages.data())); gfxSetting.BackBufferCount = m_ReserveBackBufferCount; VKLOG(Info, "[SwapChain::Initialize] desired imageCount=%d, reserved imageCount = %d.", m_DesiredBackBufferCount, m_ReserveBackBufferCount); } @@ -46,9 +42,9 @@ void SwapChain::Initialize(void * WindowHandle, rhi::GfxSetting & gfxSetting) uint32 SwapChain::AcquireNextImage(PtrSemaphore presentSemaphore, PtrFence pFence) { uint32 imageIndex; - VkResult result = fpAcquireNextImageKHR(GetRawDevice(), m_SwapChain, UINT64_MAX, + VkResult result = vkAcquireNextImageKHR(GetRawDevice(), m_SwapChain, UINT64_MAX, presentSemaphore ? presentSemaphore->m_Semaphore:VK_NULL_HANDLE, - pFence ? pFence->m_Fence : VK_NULL_HANDLE, + pFence ? pFence->NativeHandle() : VK_NULL_HANDLE, &imageIndex); switch (result) { @@ -73,7 +69,7 @@ VkResult SwapChain::Present(uint32 imageIndex, PtrSemaphore renderingFinishSemap presentInfo.pSwapchains = &m_SwapChain; presentInfo.waitSemaphoreCount = renderSem ? 1 : 0; presentInfo.pWaitSemaphores = &renderSem; - return fpQueuePresentKHR(GetImmCmdQueue()->GetNativeHandle(), &presentInfo); + return vkQueuePresentKHR(GetImmCmdQueue()->GetNativeHandle(), &presentInfo); } void SwapChain::InitSurface(void * WindowHandle) @@ -83,21 +79,21 @@ void SwapChain::InitSurface(void * WindowHandle) SurfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; SurfaceCreateInfo.hinstance = GetModuleHandle(nullptr); SurfaceCreateInfo.hwnd = (HWND)WindowHandle; - K3D_VK_VERIFY(vkCreateWin32SurfaceKHR(RHIRoot::GetInstance(), &SurfaceCreateInfo, nullptr, &m_Surface)); + K3D_VK_VERIFY(vkCreateWin32SurfaceKHR(GetGpuRef()->GetInstance()->m_Instance, &SurfaceCreateInfo, nullptr, &m_Surface)); #elif K3DPLATFORM_OS_ANDROID VkAndroidSurfaceCreateInfoKHR SurfaceCreateInfo = {}; SurfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; SurfaceCreateInfo.window = (ANativeWindow*)WindowHandle; - K3D_VK_VERIFY(vkCreateAndroidSurfaceKHR(RHIRoot::GetInstance(), &SurfaceCreateInfo, nullptr, &m_Surface)); + K3D_VK_VERIFY(vkCreateAndroidSurfaceKHR(GetGpuRef()->GetInstance()->m_Instance, &SurfaceCreateInfo, nullptr, &m_Surface)); #endif } VkPresentModeKHR SwapChain::ChoosePresentMode() { uint32_t presentModeCount; - K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, NULL)); + K3D_VK_VERIFY(GetGpuRef()->GetSurfacePresentModesKHR(m_Surface, &presentModeCount, NULL)); std::vector presentModes(presentModeCount); - K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, presentModes.data())); + K3D_VK_VERIFY(GetGpuRef()->GetSurfacePresentModesKHR(m_Surface, &presentModeCount, presentModes.data())); VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; for (size_t i = 0; i < presentModeCount; i++) { @@ -117,9 +113,9 @@ VkPresentModeKHR SwapChain::ChoosePresentMode() std::pair SwapChain::ChooseFormat(rhi::GfxSetting & gfxSetting) { uint32_t formatCount; - K3D_VK_VERIFY(fpGetPhysicalDeviceSurfaceFormatsKHR(GetPhysicalDevice(), m_Surface, &formatCount, NULL)); + K3D_VK_VERIFY(GetGpuRef()->GetSurfaceFormatsKHR(m_Surface, &formatCount, NULL)); std::vector surfFormats(formatCount); - K3D_VK_VERIFY(fpGetPhysicalDeviceSurfaceFormatsKHR(GetPhysicalDevice(), m_Surface, &formatCount, surfFormats.data())); + K3D_VK_VERIFY(GetGpuRef()->GetSurfaceFormatsKHR(m_Surface, &formatCount, surfFormats.data())); VkFormat colorFormat; VkColorSpaceKHR colorSpace; if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) @@ -142,7 +138,7 @@ int SwapChain::ChooseQueueIndex() for (uint32_t i = 0; i < GetDevice()->GetQueueCount(); ++i) { - vkGetPhysicalDeviceSurfaceSupportKHR(GetPhysicalDevice(), i, m_Surface, &queuePresentSupport[i]); + GetGpuRef()->GetSurfaceSupportKHR(i, m_Surface, &queuePresentSupport[i]); if (queuePresentSupport[i]) { chosenIndex = i; @@ -172,20 +168,21 @@ void SwapChain::InitSwapChain(uint32 numBuffers, std::pairGetInstance()->m_Instance, m_Surface, nullptr); m_Surface = VK_NULL_HANDLE; } } diff --git a/Source/RHI/Vulkan/Private/VkUtils.cpp b/Source/RHI/Vulkan/Private/VkUtils.cpp index 6047a62..2b7ee4c 100755 --- a/Source/RHI/Vulkan/Private/VkUtils.cpp +++ b/Source/RHI/Vulkan/Private/VkUtils.cpp @@ -4,6 +4,21 @@ K3D_VK_BEGIN +// Buffer functors +decltype(vkCreateBufferView)* ResTrait::CreateView = &vkCreateBufferView; +decltype(vkDestroyBufferView)* ResTrait::DestroyView = &vkDestroyBufferView; +decltype(vkCreateBuffer)* ResTrait::Create = &vkCreateBuffer; +decltype(vkDestroyBuffer)* ResTrait::Destroy = &vkDestroyBuffer; +decltype(vkGetBufferMemoryRequirements)* ResTrait::GetMemoryInfo = &vkGetBufferMemoryRequirements; +decltype(vkBindBufferMemory)* ResTrait::BindMemory = &vkBindBufferMemory; + +decltype(vkCreateImageView)* ResTrait::CreateView = &vkCreateImageView; +decltype(vkDestroyImageView)* ResTrait::DestroyView = &vkDestroyImageView; +decltype(vkCreateImage)* ResTrait::Create = &vkCreateImage; +decltype(vkDestroyImage)* ResTrait::Destroy = &vkDestroyImage; +decltype(vkGetImageMemoryRequirements)* ResTrait::GetMemoryInfo = &vkGetImageMemoryRequirements; +decltype(vkBindImageMemory)* ResTrait::BindMemory = &vkBindImageMemory; + VkDeviceSize CalcAlignedOffset(VkDeviceSize offset, VkDeviceSize align) { VkDeviceSize n = offset / align; @@ -137,10 +152,11 @@ void CommandAllocator::Initialize() void CommandAllocator::Destroy() { - if (VK_NULL_HANDLE == m_Pool) + if (VK_NULL_HANDLE == m_Pool || !GetRawDevice() ) { return; } + VKLOG(Info, "CommandAllocator destroy.. -- %d. (device:0x%0x)", m_Pool, GetRawDevice()); vkDestroyCommandPool(GetRawDevice(), m_Pool, nullptr); m_Pool = VK_NULL_HANDLE; } diff --git a/Source/RHI/Vulkan/Private/VkUtils.h b/Source/RHI/Vulkan/Private/VkUtils.h index 329aad8..1c56b9e 100755 --- a/Source/RHI/Vulkan/Private/VkUtils.h +++ b/Source/RHI/Vulkan/Private/VkUtils.h @@ -9,8 +9,7 @@ extern K3D_API VkDeviceSize CalcAlignedOffset(VkDeviceSize offset, VkDeviceSi extern K3D_API VkImageAspectFlags DetermineAspectMask(VkFormat format); extern K3D_API std::string ErrorString(VkResult errorCode); extern K3D_API VkBool32 GetSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat * depthFormat); -extern K3D_API void SetupDebugging(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportCallbackEXT callBack); -extern K3D_API void FreeDebugCallback(VkInstance instance); + extern K3D_API rhi::PipelineLayoutKey HashPipelineLayoutDesc(rhi::PipelineLayoutDesc const& desc); class CommandAllocator; @@ -27,9 +26,11 @@ class CommandAllocator : public DeviceChild ~CommandAllocator(); VkCommandPool GetCommandPool() const { return m_Pool; } + + void Destroy(); + protected: void Initialize(); - void Destroy(); private: CommandAllocator(uint32 queueFamilyIndex, bool transient, Device::Ptr device); @@ -48,7 +49,11 @@ class Semaphore : public DeviceChild K3D_VK_VERIFY(vkCreateSemaphore(GetRawDevice(), &info, nullptr, &m_Semaphore)); VKLOG(Info, "Semaphore Created. (0x%0x).", m_Semaphore); } - ~Semaphore() { vkDestroySemaphore(GetRawDevice(), m_Semaphore, nullptr); } + ~Semaphore() + { + VKLOG(Info, "Semaphore Destroyed. (0x%0x).", m_Semaphore); + vkDestroySemaphore(GetRawDevice(), m_Semaphore, nullptr); + } VkSemaphore GetNativeHandle() const { return m_Semaphore; } diff --git a/Source/RHI/Vulkan/Public/IVkRHI.h b/Source/RHI/Vulkan/Public/IVkRHI.h index 19905e9..30aa758 100755 --- a/Source/RHI/Vulkan/Public/IVkRHI.h +++ b/Source/RHI/Vulkan/Public/IVkRHI.h @@ -1,7 +1,7 @@ #ifndef __IVkRHI_h__ #define __IVkRHI_h__ #include -#include +#include namespace k3d { @@ -21,4 +21,8 @@ namespace k3d }; } +#if BUILD_STATIC_PLUGIN +K3D_STATIC_MODULE_DECLARE(RHI_Vulkan); +#endif + #endif \ No newline at end of file diff --git a/Source/RHI/Vulkan/VkCommon.h b/Source/RHI/Vulkan/VkCommon.h index 166746e..fbb4062 100755 --- a/Source/RHI/Vulkan/VkCommon.h +++ b/Source/RHI/Vulkan/VkCommon.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Source/Renderer/CMakeLists.txt b/Source/Renderer/CMakeLists.txt index 506f9b2..0a30434 100755 --- a/Source/Renderer/CMakeLists.txt +++ b/Source/Renderer/CMakeLists.txt @@ -5,10 +5,6 @@ ${DXSDK_INCLUDE_DIR} ${V8_INCLUDE_DIR} ) -if(BUILD_SHARED) - add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) -endif() - set(RENDER_SRCS Render.h Render.cpp @@ -16,6 +12,10 @@ MeshRender.cpp RenderContext.cpp ) +if(BUILD_SHARED) + add_definitions(-DBUILD_WITH_PLUGIN) +endif() + source_group(Render FILES ${RENDER_SRCS}) set(RENDER_DEPLIB Core) @@ -27,13 +27,14 @@ if(HAS_FREETYPE) set(RENDER_DEPLIB ${RENDER_DEPLIB} ${FREETYPE2_LIBRARY}) endif() -add_library(Render ${LIB_TYPE} ${RENDER_SRCS}) -target_link_libraries(Render ${RENDER_DEPLIB}) -set_target_properties(Render PROPERTIES FOLDER "Runtime") +k3d_add_lib(Render SRCS ${RENDER_SRCS} LIBS ${RENDER_DEPLIB} FOLDER "Runtime") -if(WIN32) - install(TARGETS Render ARCHIVE DESTINATION lib) -elseif(MACOS) - add_custom_command(TARGET Render POST_BUILD COMMAND - ${CMAKE_INSTALL_NAME_TOOL} -id "@loader_path/../Frameworks/libRender.dylib" $) +if(MACOS AND BUILD_SHARED) + add_custom_command(TARGET Render POST_BUILD COMMAND + ${CMAKE_INSTALL_NAME_TOOL} -id "@loader_path/../Frameworks/libRender.dylib" $) endif() + +install(TARGETS Render + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) \ No newline at end of file diff --git a/Source/Renderer/FontRenderer.cpp b/Source/Renderer/FontRenderer.cpp index 9b98fa0..7698815 100755 --- a/Source/Renderer/FontRenderer.cpp +++ b/Source/Renderer/FontRenderer.cpp @@ -1 +1,200 @@ -#include "FontRenderer.h" \ No newline at end of file +#include "Kaleido3D.h" +#include "FontRenderer.h" +#include +#include +#include FT_FREETYPE_H + +namespace render +{ + FontManager::FontManager() + : m_PixelSize(0) + , m_Color(0xffffffff) + , m_pFontLib(nullptr) + , m_pFontFace(nullptr) + { + FT_Init_FreeType((FT_Library*)&m_pFontLib); + } + + FontManager::~FontManager() + { + if (m_pFontFace) + { + FT_Done_Face((FT_Face)m_pFontFace); + m_pFontFace = nullptr; + } + if (m_pFontLib) + { + FT_Done_FreeType((FT_Library)m_pFontLib); + m_pFontLib = nullptr; + } + } + + void FontManager::LoadLib(const char * fontPath) + { + if (m_pFontFace) + { + FT_Done_Face((FT_Face)m_pFontFace); + m_pFontFace = nullptr; + } + FT_New_Face((FT_Library)m_pFontLib, fontPath, 0, (FT_Face*)&m_pFontFace); + } + + void FontManager::ChangeFontSize(int height) + { + FT_Set_Pixel_Sizes((FT_Face)m_pFontFace, 0, height); + m_PixelSize = height; + } + + void FontManager::SetPaintColor(int color) + { + m_Color = color; + } + + unsigned int* GlyphTexture(const FT_Bitmap& bitmap, const unsigned int& color) + { + unsigned int* buffer = new unsigned int[bitmap.width * bitmap.rows * 4]; + for (int y = 0; y< bitmap.rows; y++) + { + for (int x = 0; x < bitmap.width; x++) + { + unsigned int pixel = (color & 0xffffff00); + unsigned int alpha = bitmap.buffer[(y * bitmap.pitch) + x]; + pixel |= alpha; + buffer[(y*bitmap.width) + x] = pixel; + } + } + return buffer; + } + + TextQuads FontManager::AcquireText(const::k3d::String & text) + { + if(text.Length()==0 || !m_pFontFace) + return TextQuads(); + FT_Face face = (FT_Face)m_pFontFace; + TextQuads quadlist; + for (unsigned int i = 0; i < text.Length(); i++) + { + FT_Load_Char(face, text[i], FT_LOAD_RENDER | FT_LOAD_NO_HINTING); + unsigned int *bytes = GlyphTexture(face->glyph->bitmap, m_Color); + int width = face->glyph->bitmap.width; + int height = face->glyph->bitmap.rows; + int x = face->glyph->metrics.horiBearingX / m_PixelSize; + int y = face->glyph->metrics.horiBearingY / m_PixelSize; + int next = face->glyph->metrics.horiAdvance / m_PixelSize; + quadlist.Append({ x,y, width, height, next, bytes}); + } + return quadlist; + } + + CharTexture::CharTexture(rhi::DeviceRef device, TextQuad const & quad) + { + rhi::ResourceDesc texDesc; + texDesc.Type = rhi::EGT_Texture2D; + texDesc.ViewType = rhi::EGpuMemViewType::EGVT_SRV; + texDesc.Flag = rhi::EGpuResourceAccessFlag::EGRAF_HostVisible; + texDesc.TextureDesc.Format = rhi::EPF_RGBA8Unorm; // TODO font color fmt inconsistent + texDesc.TextureDesc.Width = quad.W; + texDesc.TextureDesc.Height = quad.H; + texDesc.TextureDesc.Layers = 1; + texDesc.TextureDesc.MipLevels = 1; + texDesc.TextureDesc.Depth = 1; + m_Texture = ::k3d::DynamicPointerCast(device->NewGpuResource(texDesc)); + + uint64 sz = m_Texture->GetSize(); + void * pData = m_Texture->Map(0, sz); + rhi::SubResourceLayout layout = {}; + rhi::TextureResourceSpec spec = { rhi::ETAF_COLOR,0,0 }; + device->QueryTextureSubResourceLayout(m_Texture, spec, &layout); + if (quad.W * 4 == layout.RowPitch) + { + memcpy(pData, quad.Pixels, sz); + } + else + { + for (int y = 0; y < quad.H; y++) + { + uint32_t *row = (uint32_t *)((char *)pData + layout.RowPitch * y); + for (int x = 0; x < quad.W; x++) + { + row[x] = quad.Pixels[x + y * quad.W]; + } + } + } + m_Texture->UnMap(); + + auto cmd = device->NewCommandContext(rhi::ECMD_Graphics); + cmd->Begin(); + cmd->TransitionResourceBarrier(m_Texture, rhi::ERS_ShaderResource); + cmd->End(); + cmd->Execute(false); + } + + short CharRenderer::s_Indices[] = { 0, 1, 3, 2 }; + + float CharRenderer::s_Vertices[] = { + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // 0 + 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 1 + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 3 + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f // 2 + }; + + CharRenderer::CharRenderer() + { + } + + CharRenderer::~CharRenderer() + { + } + + + void CharRenderer::InitVertexBuffers(rhi::DeviceRef const & device) + { + rhi::ResourceDesc vboDesc; + vboDesc.ViewType = rhi::EGpuMemViewType::EGVT_VBV; + vboDesc.Flag = (rhi::EGpuResourceAccessFlag) (rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible); + vboDesc.Size = sizeof(s_Vertices); + m_VertexBuffer = device->NewGpuResource(vboDesc); + void * ptr = m_VertexBuffer->Map(0, vboDesc.Size); + memcpy(ptr, s_Vertices, vboDesc.Size); + m_VertexBuffer->UnMap(); + + rhi::ResourceDesc iboDesc; + iboDesc.ViewType = rhi::EGpuMemViewType::EGVT_IBV; + iboDesc.Flag = (rhi::EGpuResourceAccessFlag) (rhi::EGpuResourceAccessFlag::EGRAF_HostCoherent | rhi::EGpuResourceAccessFlag::EGRAF_HostVisible); + iboDesc.Size = sizeof(s_Indices); + m_IndexBuffer = device->NewGpuResource(iboDesc); + ptr = m_IndexBuffer->Map(0, iboDesc.Size); + memcpy(ptr, s_Indices, iboDesc.Size); + m_IndexBuffer->UnMap(); + } + + CharTexture::~CharTexture() + { + } + + FontRenderer::FontRenderer(rhi::DeviceRef const& device) + : m_Device(device) + { + } + + FontRenderer::~FontRenderer() + { + } + + void FontRenderer::InitPSO() + { + auto shMod = k3d::StaticPointerCast(ACQUIRE_PLUGIN(ShaderCompiler)); + if (!shMod) + return; + auto glslc = shMod->CreateShaderCompiler(rhi::ERHI_Vulkan); + } + + void FontRenderer::DrawText2D(rhi::CommandContextRef const & cmd, const::k3d::String & text, float x, float y) + { + auto quads = m_FontManager.AcquireText(text); + for (auto quad : quads) + { + CharTexture * tex = new CharTexture(m_Device, quad); + } + } +} \ No newline at end of file diff --git a/Source/Renderer/FontRenderer.h b/Source/Renderer/FontRenderer.h index 6f70f09..1c4026d 100755 --- a/Source/Renderer/FontRenderer.h +++ b/Source/Renderer/FontRenderer.h @@ -1 +1,85 @@ #pragma once +#include +#include +#include + +#include + +namespace render +{ + class TextQuad + { + public: + int X; + int Y; + int W; + int H; + int HSpace; + unsigned int* Pixels; + }; + + typedef ::k3d::DynArray TextQuads; + + class K3D_API FontManager + { + public: + FontManager(); + ~FontManager(); + + void LoadLib(const char * fontPath); + void ChangeFontSize(int height); + void SetPaintColor(int color); + + TextQuads AcquireText(const ::k3d::String & text); + + private: + int m_PixelSize; + int m_Color; + void* m_pFontLib; + void* m_pFontFace; + // Cache + }; + + class CharTexture + { + public: + CharTexture(rhi::DeviceRef device, TextQuad const& quad); + ~CharTexture(); + rhi::TextureRef GetTexture() const { return m_Texture; } + private: + rhi::TextureRef m_Texture; + }; + + class CharRenderer + { + public: + CharRenderer(); + ~CharRenderer(); + + void InitVertexBuffers(rhi::DeviceRef const& device); + + private: + static short s_Indices[]; + static float s_Vertices[]; + static float s_CharTexCoords[]; + + private: + rhi::GpuResourceRef m_VertexBuffer; + rhi::GpuResourceRef m_IndexBuffer; + }; + + class FontRenderer + { + public: + explicit FontRenderer(rhi::DeviceRef const & device); + ~FontRenderer(); + void InitPSO(); + void DrawText2D(rhi::CommandContextRef const& cmd, const ::k3d::String & text, float x, float y); + + private: + rhi::DeviceRef m_Device; + rhi::PipelineStateObjectRef m_TextRenderPSO; + FontManager m_FontManager; + std::unordered_map m_TexCache; + }; +} \ No newline at end of file diff --git a/Source/Renderer/Render.h b/Source/Renderer/Render.h index 8c1eb2d..9cccc02 100755 --- a/Source/Renderer/Render.h +++ b/Source/Renderer/Render.h @@ -1,6 +1,6 @@ #pragma once #include "Engine/SceneManager.h" -#include "RHI/IRHI.h" +#include #include #include #include diff --git a/Source/Renderer/RenderContext.cpp b/Source/Renderer/RenderContext.cpp index dbab4fc..fd6ae06 100755 --- a/Source/Renderer/RenderContext.cpp +++ b/Source/Renderer/RenderContext.cpp @@ -3,7 +3,7 @@ #if K3DPLATFORM_OS_WIN #include #include -#elif K3DPLATFORM_OS_MAC +#elif K3DPLATFORM_OS_MAC||K3DPLATFORM_OS_IOS #include #include #else @@ -29,13 +29,13 @@ namespace render m_Width = w; m_Height = h; m_RhiType = type; -#ifndef K3DPLATFORM_OS_MAC - IVkRHI* pVkRHI = (IVkRHI*)GlobalModuleManager.FindModule("RHI_Vulkan"); +#if !(K3DPLATFORM_OS_MAC || K3DPLATFORM_OS_IOS) + auto pVkRHI = k3d::StaticPointerCast(ACQUIRE_PLUGIN(RHI_Vulkan)); pVkRHI->Initialize("RenderContext", true); pVkRHI->Start(); m_pDevice = pVkRHI->GetPrimaryDevice(); #else - IMetalRHI* pMtlRHI = (IMetalRHI*)GlobalModuleManager.FindModule("RHI_Metal"); + auto pMtlRHI = k3d::StaticPointerCast(ACQUIRE_PLUGIN(RHI_Metal)); if(pMtlRHI) { pMtlRHI->Start(); @@ -77,6 +77,7 @@ namespace render void RenderContext::Destroy() { + m_pDevice->WaitIdle(); KLOG(Info, "RenderContext", "Destroyed Render Context."); } diff --git a/Source/Tools/MayaDCC/DCTranslator.h b/Source/Tools/MayaDCC/DCTranslator.h index 665d3f2..7ed8e9f 100755 --- a/Source/Tools/MayaDCC/DCTranslator.h +++ b/Source/Tools/MayaDCC/DCTranslator.h @@ -5,7 +5,7 @@ #include "MayaCommon.h" #include -#include +#include #include #include #include diff --git a/Source/Tools/ShaderGen/CMakeLists.txt b/Source/Tools/ShaderGen/CMakeLists.txt index fbe4adc..ba5a9f5 100755 --- a/Source/Tools/ShaderGen/CMakeLists.txt +++ b/Source/Tools/ShaderGen/CMakeLists.txt @@ -1,7 +1,6 @@ -add_definitions(-DUSE_GLSLANG=1) - +add_definitions(-DUSE_GLSLANG=1 -DAMD_EXTENSIONS) include_directories(${DXSDK_INCLUDE_DIR} .) -ADD_DEFINITIONS(-DAMD_EXTENSIONS) + set(COMPILER_SRCS Private/ShaderCompiler.cc Private/DXCompiler.cc Private/GLSLCompiler.cc Private/DXCompiler.h Private/GLSLCompiler.h @@ -14,10 +13,17 @@ source_group("Compiler\\Private" FILES ${COMPILER_SRCS}) set(PUB_SRCS Public/ShaderCompiler.h) source_group("Compiler\\Public" FILES ${PUB_SRCS}) -add_plugin(ShaderCompiler "Tools" ${COMPILER_SRCS} ${PUB_SRCS}) -target_link_libraries(ShaderCompiler ${GLSLANG_LIBRARIES} ${SPIRV2CROSS_LIBRARY}) +add_plugin(ShaderCompiler + FOLDER "Tools" + SRCS ${COMPILER_SRCS} ${PUB_SRCS} + LIBS ${GLSLANG_LIBRARIES} ${SPIRV2CROSS_LIBRARY}) -if(MACOS) +if(MACOS AND BUILD_SHARED) add_custom_command(TARGET ShaderCompiler POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -id "@loader_path/../Frameworks/libShaderCompiler.dylib" $) endif() + +install(TARGETS ShaderCompiler + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) diff --git a/Source/Tools/ShaderGen/Private/GLSLCompiler.cc b/Source/Tools/ShaderGen/Private/GLSLCompiler.cc index d8d9604..32b4417 100755 --- a/Source/Tools/ShaderGen/Private/GLSLCompiler.cc +++ b/Source/Tools/ShaderGen/Private/GLSLCompiler.cc @@ -34,28 +34,6 @@ namespace k3d { return ESemantic::ENumSemanics; } - - static void sInitializeGlSlang() - { -#if USE_GLSLANG - static bool sGlSlangIntialized = false; - if (!sGlSlangIntialized) { - glslang::InitializeProcess(); - sGlSlangIntialized = true; - } -#endif - } - - static void sFinializeGlSlang() - { -#if USE_GLSLANG - static bool sGlSlangFinalized = false; - if (!sGlSlangFinalized) { - glslang::FinalizeProcess(); - //sGlSlangFinalized = true; - } -#endif - } GLSLangCompiler::GLSLangCompiler() { diff --git a/Source/Tools/ShaderGen/Private/GLSLangUtils.cc b/Source/Tools/ShaderGen/Private/GLSLangUtils.cc index ea03776..a6478be 100755 --- a/Source/Tools/ShaderGen/Private/GLSLangUtils.cc +++ b/Source/Tools/ShaderGen/Private/GLSLangUtils.cc @@ -4,6 +4,28 @@ using namespace ::glslang; +void sInitializeGlSlang() +{ +#if USE_GLSLANG + static bool sGlSlangIntialized = false; + if (!sGlSlangIntialized) { + glslang::InitializeProcess(); + sGlSlangIntialized = true; + } +#endif +} + +void sFinializeGlSlang() +{ +#if USE_GLSLANG + static bool sGlSlangFinalized = false; + if (!sGlSlangFinalized) { + glslang::FinalizeProcess(); + sGlSlangFinalized = true; + } +#endif +} + rhi::shc::EDataType glTypeToRHIAttribType(int glType) { using namespace rhi::shc; @@ -315,7 +337,25 @@ void ExtractUniformData(rhi::EShaderType const& stype, const glslang::TProgram& auto qualifier = type->getQualifier(); if (qualifier.hasBinding()) { - outUniformLayout.AddBinding({ glslangTypeToRHIType(baseType), name, stype, qualifier.layoutBinding }); + rhi::shc::EBindType bind = glslangTypeToRHIType(baseType); + if (baseType == EbtSampler) + { + if (type->getSampler().isCombined()) + { + bind = rhi::shc::EBindType::ESamplerImageCombine; + } + switch (type->getSampler().dim) + { + case Esd1D: + case Esd2D: + case Esd3D: + case EsdCube: + case EsdRect: + bind = rhi::shc::EBindType::ESampledImage; + break; + } + } + outUniformLayout.AddBinding({ bind, name, stype, qualifier.layoutBinding }); } if (qualifier.hasSet()) { @@ -356,4 +396,4 @@ void ExtractUniformData(rhi::EShaderType const& stype, const glslang::TProgram& break; } } -} \ No newline at end of file +} diff --git a/Source/Tools/ShaderGen/Private/GLSLangUtils.h b/Source/Tools/ShaderGen/Private/GLSLangUtils.h index 15b8f12..9a31827 100755 --- a/Source/Tools/ShaderGen/Private/GLSLangUtils.h +++ b/Source/Tools/ShaderGen/Private/GLSLangUtils.h @@ -1,7 +1,10 @@ #pragma once -#include +#include #include +void sInitializeGlSlang(); +void sFinializeGlSlang(); + void initResources(TBuiltInResource &resources); EShLanguage findLanguage(const rhi::EShaderType shader_type); rhi::shc::EDataType glTypeToRHIAttribType(int glType); @@ -10,4 +13,4 @@ rhi::shc::EDataType glslangDataTypeToRHIDataType(const glslang::TType& type); rhi::shc::EBindType glslangTypeToRHIType(const glslang::TBasicType& type); void ExtractAttributeData(const glslang::TProgram& program, rhi::shc::Attributes& shAttributes); -void ExtractUniformData(rhi::EShaderType const& type, const glslang::TProgram& program, rhi::shc::BindingTable& outUniformLayout); \ No newline at end of file +void ExtractUniformData(rhi::EShaderType const& type, const glslang::TProgram& program, rhi::shc::BindingTable& outUniformLayout); diff --git a/Source/Tools/ShaderGen/Private/MetalCompiler.cc b/Source/Tools/ShaderGen/Private/MetalCompiler.cc index 1e80071..aad39b5 100755 --- a/Source/Tools/ShaderGen/Private/MetalCompiler.cc +++ b/Source/Tools/ShaderGen/Private/MetalCompiler.cc @@ -19,6 +19,16 @@ namespace k3d { EResult mtlCompile(string const& source, String & metalIR); + MetalCompiler::MetalCompiler() + { + sInitializeGlSlang(); + } + + MetalCompiler::~MetalCompiler() + { + sFinializeGlSlang(); + } + EResult MetalCompiler::Compile(String const& src, rhi::ShaderDesc const& inOp, rhi::ShaderBundle & bundle) { if(inOp.Format == rhi::EShFmt_Text) @@ -87,10 +97,46 @@ namespace k3d } std::vector spirv; glslang::GlslangToSpv(*program.getIntermediate(stage), spirv); - + + if(program.buildReflection()) + { + ExtractAttributeData(program, bundle.Attributes); + ExtractUniformData(inOp.Stage, program, bundle.BindingTable); + } + else + { + return rhi::shc::E_Failed; + } + uint32 bufferLoc = 0; + std::vector vertAttrs; + for(auto & attr : bundle.Attributes) + { + spirv_cross::MSLVertexAttr vAttrib; + vAttrib.location = attr.VarLocation; + vAttrib.msl_buffer = attr.VarBindingPoint; + vertAttrs.push_back(vAttrib); + bufferLoc = attr.VarBindingPoint; + } + std::vector resBindings; + for(auto & binding : bundle.BindingTable.Bindings) + { + if(binding.VarType == EBindType::EBlock) + { + bufferLoc ++; + spirv_cross::MSLResourceBinding resBind; + resBind.stage = rhiShaderStageToSpvModel(binding.VarStage); + resBind.desc_set = 0; + resBind.binding = binding.VarNumber; + resBind.msl_buffer = bufferLoc; + resBindings.push_back(resBind); + } + } auto metalc = make_unique(spirv); - auto result = metalc->compile(); - + spirv_cross::MSLConfiguration config; + config.flip_vert_y = false; + config.flip_frag_y = false; + config.entry_point_name = inOp.EntryFunction.CStr(); + auto result = metalc->compile(config, &vertAttrs, &resBindings); if(m_IsMac) { auto ret = mtlCompile(result, bundle.RawData); @@ -162,7 +208,7 @@ namespace k3d bcFile.Open(tmpLib.c_str(), IORead); metalIR = { bcFile.FileData(), (size_t)bcFile.GetSize() }; bcFile.Close(); - Os::Remove(intermediate.c_str()); + //Os::Remove(intermediate.c_str()); #endif return E_Ok; } diff --git a/Source/Tools/ShaderGen/Private/MetalCompiler.h b/Source/Tools/ShaderGen/Private/MetalCompiler.h index bd3d945..5da68e5 100755 --- a/Source/Tools/ShaderGen/Private/MetalCompiler.h +++ b/Source/Tools/ShaderGen/Private/MetalCompiler.h @@ -7,8 +7,8 @@ namespace k3d class MetalCompiler : public rhi::IShCompiler { public: - MetalCompiler() {} - ~MetalCompiler() override {} + MetalCompiler(); + ~MetalCompiler() override; rhi::shc::EResult Compile(String const& src, rhi::ShaderDesc const& inOp, rhi::ShaderBundle & bundle) override; diff --git a/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.cc b/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.cc index 0bfcf18..f2d47b3 100755 --- a/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.cc +++ b/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.cc @@ -61,6 +61,17 @@ rhi::shc::EDataType spirTypeToRHIAttribType(const spirv_cross::SPIRType& spirTyp return result; } +spv::ExecutionModel rhiShaderStageToSpvModel(rhi::EShaderType const& type) +{ + switch(type) + { + case rhi::ES_Vertex: + return spv::ExecutionModelVertex; + case rhi::ES_Fragment: + return spv::ExecutionModelFragment; + } + return spv::ExecutionModelVertex; +} rhi::shc::EDataType spirTypeToGlslUniformDataType(const spirv_cross::SPIRType& spirType) { diff --git a/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.h b/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.h index 98a09e8..d2f94c3 100755 --- a/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.h +++ b/Source/Tools/ShaderGen/Private/SPIRVCrossUtils.h @@ -1,11 +1,11 @@ #pragma once -#include +#include #include #include #include rhi::shc::EDataType spirTypeToRHIAttribType(const spirv_cross::SPIRType& spirType); rhi::shc::EDataType spirTypeToGlslUniformDataType(const spirv_cross::SPIRType& spirType); - +spv::ExecutionModel rhiShaderStageToSpvModel(rhi::EShaderType const& type); void ExtractAttributeData(spirv_cross::CompilerGLSL const& backCompiler, rhi::shc::Attributes & outShaderAttributes); void ExtractUniformData(rhi::EShaderType shaderStage, spirv_cross::CompilerGLSL const& backCompiler, rhi::shc::BindingTable& outUniformLayout); \ No newline at end of file diff --git a/Source/Tools/ShaderGen/Private/ShaderCompiler.cc b/Source/Tools/ShaderGen/Private/ShaderCompiler.cc index d1bf903..fe7f1e9 100755 --- a/Source/Tools/ShaderGen/Private/ShaderCompiler.cc +++ b/Source/Tools/ShaderGen/Private/ShaderCompiler.cc @@ -1,4 +1,6 @@ +#include #include "Public/ShaderCompiler.h" +#include #include "GLSLCompiler.h" #if _WIN32 #include "DXCompiler.h" @@ -12,7 +14,10 @@ class ShaderCompilerModule : public rhi::IShModule { public: ShaderCompilerModule() {} - ~ShaderCompilerModule() override {} + ~ShaderCompilerModule() override + { + KLOG(Info, ShaderCompilerModule, "Destroying.."); + } void Start() override {} void Shutdown() override {} diff --git a/Source/Tools/ShaderGen/Public/ShaderCompiler.h b/Source/Tools/ShaderGen/Public/ShaderCompiler.h index 5324392..0bb2230 100755 --- a/Source/Tools/ShaderGen/Public/ShaderCompiler.h +++ b/Source/Tools/ShaderGen/Public/ShaderCompiler.h @@ -1,8 +1,8 @@ #ifndef __ShaderGen_h__ #define __ShaderGen_h__ -#include -#include +#include +#include #include #include diff --git a/Source/UnitTest/1.Device/UnitTestRHIDevice.cpp b/Source/UnitTest/1.Device/UnitTestRHIDevice.cpp deleted file mode 100755 index 810579a..0000000 --- a/Source/UnitTest/1.Device/UnitTestRHIDevice.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "UnitTestRHIDevice.h" -#include -#include -#include - -K3D_APP_MAIN(UnitTestRHIDevice); - -using namespace rhi; -using namespace k3d; - -bool UnitTestRHIDevice::OnInit() -{ - App::OnInit(); -#if K3DPLATFORM_OS_WIN || K3DPLATFORM_OS_ANDROID - IVkRHI* pVkRHI = (IVkRHI*)GlobalModuleManager.FindModule("RHI_Vulkan"); - pVkRHI->Initialize("UnitTestRHIDevice", false); - pVkRHI->Start(); - m_TestDevice = pVkRHI->GetPrimaryDevice(); -#else - IMetalRHI* pMtlRHI = (IMetalRHI*)GlobalModuleManager.FindModule("RHI_Metal"); - if(pMtlRHI) - { - pMtlRHI->Start(); - m_TestDevice = pMtlRHI->GetPrimaryDevice(); - } -#endif - return true; -} - -void UnitTestRHIDevice::OnDestroy() -{ - App::OnDestroy(); -} - -void UnitTestRHIDevice::OnProcess(Message & msg) -{ -} diff --git a/Source/UnitTest/1.Device/UnitTestRHIDevice.h b/Source/UnitTest/1.Device/UnitTestRHIDevice.h deleted file mode 100755 index e1b21b9..0000000 --- a/Source/UnitTest/1.Device/UnitTestRHIDevice.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include -#include -#include - -using namespace k3d; - -class UnitTestRHIDevice : public App -{ -public: - explicit UnitTestRHIDevice(kString const & appName) - : App(appName, 1920, 1080) - {} - - bool OnInit() override; - void OnDestroy() override; - void OnProcess(Message & msg) override; - -private: - - rhi::DeviceRef m_TestDevice; -}; \ No newline at end of file diff --git a/Source/UnitTest/Base/Common.h b/Source/UnitTest/Base/Common.h deleted file mode 100755 index 0f19794..0000000 --- a/Source/UnitTest/Base/Common.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -using threadptr = std::shared_ptr; - -#define JOIN_TESTS(...) \ -threadptr tests[] = { __VA_ARGS__ }; \ -for (auto t : tests) \ -{ \ - t->join(); \ -} - - -extern threadptr TestBundle(); - -extern threadptr TestOs(); - -extern threadptr TestString(); - -extern threadptr TestWebSocket(); - -extern threadptr TestShaderCompiler(); - -extern threadptr TestSharedPtr(); - -extern threadptr TestDynArrray(); diff --git a/Source/UnitTest/Base/Main.cpp b/Source/UnitTest/Base/Main.cpp deleted file mode 100755 index 6b6cc64..0000000 --- a/Source/UnitTest/Base/Main.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "Common.h" - -#if K3DPLATFORM_OS_WIN -#pragma comment(linker,"/subsystem:console") -#endif - -int main(int argc, char**argv) -{ - JOIN_TESTS(TestBundle(), TestOs(), TestShaderCompiler(), TestWebSocket(), TestSharedPtr(), TestString(), TestDynArrray()); - return 0; -} diff --git a/Source/UnitTest/Base/UTCore.Os.cpp b/Source/UnitTest/Base/UTCore.Os.cpp deleted file mode 100755 index 5045f62..0000000 --- a/Source/UnitTest/Base/UTCore.Os.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Common.h" - -using namespace k3d; - -threadptr TestOs() -{ - auto ret = std::make_shared([]() { - K3D_ASSERT(Os::MakeDir(KT("./TestOs"))); - K3D_ASSERT(Os::Remove(KT("./TestOs"))); - }); - return ret; -} diff --git a/Source/UnitTest/Base/UTCore.String.cpp b/Source/UnitTest/Base/UTCore.String.cpp deleted file mode 100755 index c729fa9..0000000 --- a/Source/UnitTest/Base/UTCore.String.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "Common.h" - -using namespace k3d; -using namespace std; - -String toBeRemoved("Love you later."); - -threadptr TestString() -{ - auto ret = std::make_shared([]() { - String testString("HeyYou!"); - cout << testString.CStr() << endl; - String testStringBaby("BabyGirl!!"); - testStringBaby.Swap(testString); - cout << testString.CStr() << endl; - - testString += toBeRemoved; - testString += ".."; - cout << testString.CStr() << endl; - - testString.AppendSprintf("%d %s", 5, "fhdsfjdhjkfdhksfhdkjshfjkdshfk"); - cout << testString.CStr() << endl; - - //Archive ar; - //ar << testString; - - String testMoveString(Move(toBeRemoved)); - cout << "testMove:" << testMoveString.CStr() - << " original:" << (toBeRemoved.CStr()?toBeRemoved.CStr():"null") << endl; - }); - return ret; -} diff --git a/Source/UnitTest/Base/UTKTL.DynArray.cpp b/Source/UnitTest/Base/UTKTL.DynArray.cpp deleted file mode 100755 index 658f9c3..0000000 --- a/Source/UnitTest/Base/UTKTL.DynArray.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "Common.h" - -using namespace std; -using namespace k3d; - -struct B -{ - B() : msg_(nullptr) - { - std::cout << "construct" << std::endl; - } - B(const char* msg) : msg_(msg) - { - std::cout << msg << std::endl; - } - - B& operator=(const B& rhs) - { - std::cout << "rhs " << rhs.msg_ - << " assigned to " << std::endl; - this->msg_ = rhs.msg_; - return *this; - } - - ~B() - { - std::cout << "deconstructB " << msg_ << std::endl; - } - const char *msg_; -}; - -threadptr TestDynArrray() -{ - auto ret = std::make_shared([]() { - B b1{ "b1" }, b3{ "b3" }; - DynArray ints; - ints.Append(5).Append(6).Append(7).Append(0).Append(8); - std::cout << ints[3] << std::endl; - ints[3] = 0; - - std::cout << "for begin - end test start-----" << std::endl; - for (auto& iter : ints) - { - std::cout << iter << std::endl; - } - std::cout << "for begin - end test end-----" << std::endl; - - std::cout << ints[3] << std::endl; - std::cout << ints.Count() << std::endl; - { - B b2{ "b2" }; - DynArray bs; - bs.Append(b1) - .Append(std::move(b2)) - .Append(b3); - bs[2] = B("B modified"); - } - { - DynArray bs; - bs.Append(B("A1")) - .Append(B("A2")) - .Append(B("A3")) - .Append(B("A4")) - .Append(B("A5")); - } - }); - return ret; -} diff --git a/Source/UnitTest/Base/UTKTL.SharedPtr.cpp b/Source/UnitTest/Base/UTKTL.SharedPtr.cpp deleted file mode 100755 index f6cffbd..0000000 --- a/Source/UnitTest/Base/UTKTL.SharedPtr.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "Common.h" -#include -#include -#include - -using namespace std; -using namespace k3d; - -class SharedTest -{ -public: - SharedTest() - { - - } - ~SharedTest() - { - cout << "SharedTest Destroy. " << endl; - } -}; - -threadptr TestSharedPtr() -{ - auto ret = std::make_shared([]() { - SharedPtr spFile(new Os::File); - cout << "file:" << spFile.UseCount() << endl; - - SharedPtr spCam(new CameraData); - spCam.UseCount(); - spCam->SetName("TestSharedPtr"); - - SharedPtr spTest(new SharedTest); - cout << "SharedTest:" << spTest.UseCount() << endl; - - SharedPtr ioFile = spFile; - K3D_ASSERT(ioFile.UseCount()==2); - - auto makeShared = MakeShared(); - makeShared->Open(KT("TestSharedPtr"), IOWrite); - - auto refMakeShared = makeShared; - cout << "refMakeShared:" << refMakeShared.UseCount() << endl; - - refMakeShared->Close(); - }); - return ret; -} diff --git a/Source/UnitTest/Base/UTTools.ShaderCompiler.cpp b/Source/UnitTest/Base/UTTools.ShaderCompiler.cpp deleted file mode 100755 index 7b8285a..0000000 --- a/Source/UnitTest/Base/UTTools.ShaderCompiler.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "Common.h" -#include -#include - -using namespace std; -using namespace k3d; - -threadptr TestShaderCompiler() -{ - auto ret = std::make_shared([]() { - - Os::MemMapFile vShFile; - vShFile.Open("../../Data/Test/testCompiler.glsl", IOFlag::IORead); - String vertexSource((const char*)vShFile.FileData()); - vShFile.Close(); - - rhi::IShModule* shMod = (rhi::IShModule*)GlobalModuleManager.FindModule("ShaderCompiler"); - if (shMod) - { - // test compile - SharedPtr vkCompiler = shMod->CreateShaderCompiler(rhi::ERHI_Vulkan); - if (vkCompiler) - { - rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; - rhi::ShaderBundle bundle; - auto ret = vkCompiler->Compile(vertexSource, desc, bundle); - K3D_ASSERT(ret == rhi::shc::E_Ok); - - // test shader serialize - Os::File shBundle; - shBundle.Open(KT("shaderbundle.sh"), IOWrite); - Archive ar; - ar.SetIODevice(&shBundle); - ar << bundle; - shBundle.Close(); - - // write spirv to file - Os::File spirvFile; - spirvFile.Open(KT("triangle.spv"), IOWrite); - spirvFile.Write(bundle.RawData.Data(), bundle.RawData.Length()); - spirvFile.Close(); - - // test shader deserialize; - Os::File shBundleRead; - rhi::ShaderBundle bundleRead; - shBundleRead.Open(KT("shaderbundle.sh"), IORead); - Archive readar; - readar.SetIODevice(&shBundleRead); - readar >> bundleRead; - shBundleRead.Close(); - - // test hlsl compile - rhi::ShaderBundle hlslBundle; - Os::MemMapFile hlslVertFile; - hlslVertFile.Open("../../Data/Test/TestMaterial.hlsl", IOFlag::IORead); - rhi::ShaderDesc hlsldesc = { rhi::EShFmt_Text, rhi::EShLang_HLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; - auto hlslret = vkCompiler->Compile(String((const char*)hlslVertFile.FileData()), hlsldesc, hlslBundle); - K3D_ASSERT(hlslret == rhi::shc::E_Ok); - - // test spirv reflect - Os::MemMapFile spirvFileRead; - rhi::ShaderBundle spirvBundle; - spirvFileRead.Open(KT("triangle.spv"), IORead); - rhi::ShaderDesc spirvDesc = { rhi::EShFmt_ByteCode, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; - auto spirvRet = vkCompiler->Compile(String(spirvFileRead.FileData(), spirvFileRead.GetSize()), spirvDesc, spirvBundle); - K3D_ASSERT(spirvRet == rhi::shc::E_Ok); - } - - SharedPtr mtlCompiler = shMod->CreateShaderCompiler(rhi::ERHI_Metal); - if(mtlCompiler) - { - rhi::ShaderDesc desc = { rhi::EShFmt_Text, rhi::EShLang_GLSL, rhi::EShProfile_Modern, rhi::ES_Vertex, "main" }; - rhi::ShaderBundle bundle; - auto ret = mtlCompiler->Compile(vertexSource, desc, bundle); - K3D_ASSERT(ret == rhi::shc::E_Ok); - - // test shader serialize - Os::File shBundle; - shBundle.Open(KT("metalshaderbundle.sh"), IOWrite); - Archive ar; - ar.SetIODevice(&shBundle); - ar << bundle; - shBundle.Close(); - } - } - }); - return ret; -} diff --git a/Source/UnitTest/CMakeLists.txt b/Source/UnitTest/CMakeLists.txt deleted file mode 100755 index d891cc0..0000000 --- a/Source/UnitTest/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -add_definitions(-DBUILD_SHARED_LIB -DBUILD_WITH_PLUGIN) - -################################## Unit Test For RHI ##################################### - -add_unittest( - 1.Device - 1.Device/UnitTestRHIDevice.h - 1.Device/UnitTestRHIDevice.cpp -) - -add_unittest( - 2.SwapChainPresent - 2.SwapChain/SwapChainPresent.cpp -) - -add_unittest( - 3.Triangle - 3.Triangle/Triangle.cpp -) - -add_unittest( - 4.TexturedCube - 4.TexturedCube/TexturedCube.cpp - 4.TexturedCube/TextureObject.h - 4.TexturedCube/TextureObject.cpp -) - -add_unittest( - 0.BaseComponents - Base/Common.h - Base/UTCore.Bundle.cpp - Base/UTCore.Os.cpp - Base/UTCore.WebSocket.cpp - Base/UTTools.ShaderCompiler.cpp - Base/UTKTL.SharedPtr.cpp - Base/UTKTL.DynArray.cpp - Base/UTCore.String.cpp - Base/Main.cpp -) diff --git a/Source/UnitTest/RHI_Metal/Assets.xcassets/AppIcon.appiconset/Contents.json b/Source/UnitTest/RHI_Metal/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100755 index 2db2b1c..0000000 --- a/Source/UnitTest/RHI_Metal/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Source/UnitTest/RHI_Metal/Base.lproj/MainMenu.xib b/Source/UnitTest/RHI_Metal/Base.lproj/MainMenu.xib deleted file mode 100755 index e084772..0000000 --- a/Source/UnitTest/RHI_Metal/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,686 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Source/UnitTest/RHI_Metal/Info.plist b/Source/UnitTest/RHI_Metal/Info.plist deleted file mode 100755 index 6b49211..0000000 --- a/Source/UnitTest/RHI_Metal/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2015年 TsinStudio. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Source/UnitTest/RHI_Metal/Shaders.metal b/Source/UnitTest/RHI_Metal/Shaders.metal deleted file mode 100755 index 65b71ea..0000000 --- a/Source/UnitTest/RHI_Metal/Shaders.metal +++ /dev/null @@ -1,52 +0,0 @@ -// -// Shaders.metal -// mdemo -// -// Created by QinZhou on 15/9/1. -// Copyright (c) 2015年 TsinStudio. All rights reserved. -// - -#include -#include -#include "SharedStructures.h" - -using namespace metal; - -// Variables in constant address space -constant float3 light_position = float3(0.0, 1.0, -1.0); -constant float4 ambient_color = float4(0.18, 0.24, 0.8, 1.0); -constant float4 diffuse_color = float4(0.4, 0.4, 1.0, 1.0); - -typedef struct -{ - float3 position [[attribute(0)]]; - float3 normal [[attribute(1)]]; -} vertex_t; - -typedef struct { - float4 position [[position]]; - half4 color; -} ColorInOut; - -// Vertex shader function -vertex ColorInOut lighting_vertex(vertex_t vertex_array [[stage_in]], - constant uniforms_t& uniforms [[ buffer(1) ]]) -{ - ColorInOut out; - - float4 in_position = float4(vertex_array.position, 1.0); - out.position = uniforms.modelview_projection_matrix * in_position; - - float4 eye_normal = normalize(uniforms.normal_matrix * float4(vertex_array.normal, 0.0)); - float n_dot_l = dot(eye_normal.rgb, normalize(light_position)); - n_dot_l = fmax(0.0, n_dot_l); - - out.color = half4(ambient_color + diffuse_color * n_dot_l); - return out; -} - -// Fragment shader function -fragment half4 lighting_fragment(ColorInOut in [[stage_in]]) -{ - return in.color; -} \ No newline at end of file diff --git a/Source/UnitTest/RHI_Metal/SharedStructures.h b/Source/UnitTest/RHI_Metal/SharedStructures.h deleted file mode 100755 index 7ebee47..0000000 --- a/Source/UnitTest/RHI_Metal/SharedStructures.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// SharedStructures.h -// mdemo -// -// Created by QinZhou on 15/9/1. -// Copyright (c) 2015年 TsinStudio. All rights reserved. -// - -#ifndef SharedStructures_h -#define SharedStructures_h - -#include - -typedef struct __attribute__((__aligned__(256))) -{ - matrix_float4x4 modelview_projection_matrix; - matrix_float4x4 normal_matrix; -} uniforms_t; - -#endif /* SharedStructures_h */ - diff --git a/Source/UnitTest/RHI_Metal/UnitTestRHICommandContext.mm b/Source/UnitTest/RHI_Metal/UnitTestRHICommandContext.mm deleted file mode 100755 index 9700e7d..0000000 --- a/Source/UnitTest/RHI_Metal/UnitTestRHICommandContext.mm +++ /dev/null @@ -1,6 +0,0 @@ -#import -#include - -int main(int argc, const char * argv[]) { - return NSApplicationMain(argc, argv); -} diff --git a/Source/UnitTest/RHI_Metal/premake5.lua b/Source/UnitTest/RHI_Metal/premake5.lua deleted file mode 100755 index 62769ad..0000000 --- a/Source/UnitTest/RHI_Metal/premake5.lua +++ /dev/null @@ -1,31 +0,0 @@ -project "UnitTestRHICommandContext" - - language "C++" - - kind "WindowedApp" - - includedirs { - ".", - "../..", - "../../RHI", - "../../../Include" - } - - libdirs { - "../../../Bin" - } - - links { - "Core", "RHI_Metal" - } - - targetdir "../../../Bin" - - files { - "Info.plist", - "Base.lproj/MainMenu.xib", - "**.metal", - "**.mm", - "**.h" - } - linkoptions { "-framework MetalKit", "-framework Cocoa", "-framework Metal", "-framework ModelIO" } \ No newline at end of file diff --git a/Tools/VisualStudioVisualizer/kaleido3d.natvis b/Tools/VisualStudioVisualizer/kaleido3d.natvis new file mode 100644 index 0000000..c26ad51 --- /dev/null +++ b/Tools/VisualStudioVisualizer/kaleido3d.natvis @@ -0,0 +1,17 @@ + + + + {{ size={m_ElementCount} capacity={m_Capacity} }} + + m_Capacity + m_Allocator + + m_ElementCount + m_pElement + + + + + {m_pStringData} + + \ No newline at end of file diff --git a/Tools/WebConsole/index.html b/Tools/WebConsole/index.html new file mode 100644 index 0000000..05c531d --- /dev/null +++ b/Tools/WebConsole/index.html @@ -0,0 +1,22 @@ + + + + + WebConsole - Kaleido3D + + + + + + + + + + + + + +
+
+ + \ No newline at end of file diff --git a/circle.yml b/circle.yml index 775357a..b204505 100755 --- a/circle.yml +++ b/circle.yml @@ -17,7 +17,6 @@ dependencies: - unzip cmake.zip -d /usr/local/android-sdk-linux/cmake - /usr/local/android-sdk-linux/cmake/bin/cmake --version - git clone https://github.com/TsinStudio/android-ndk.git /usr/local/android-sdk-linux/ndk-bundle - - git clone https://github.com/Tomicyo/kaleido3d_dep_prebuilt.git -b android_arm_debug Source/ThirdParty_Prebuilt/Android_ARM_Debug - export ANDROID_NDK_HOME=/usr/local/android-sdk-linux/ndk-bundle - export NDK=/usr/local/android-sdk-linux/ndk-bundle - echo y | android update sdk --no-ui --all --filter tools,platform-tools,build-tools-23.0.2,android-23,extra-google-m2repository,extra-android-support diff --git a/make.cmd b/make.cmd index 9d7130b..9e6e839 100755 --- a/make.cmd +++ b/make.cmd @@ -8,7 +8,7 @@ goto BUILD_BY_CMAKE :CHECK_DEPENDENCIES echo Checkout Dependencies From Github -git clone https://github.com/Tomicyo/kaleido3d_dep_prebuilt.git -b win64_debug Source\ThirdParty_Prebuilt\Win64_Debug +git clone https://github.com/Tomicyo/kaleido3d_dep_prebuilt.git -b win64_Debug Source\ThirdParty_Prebuilt\Win64\Debug goto BUILD_BY_CMAKE @@ -30,30 +30,20 @@ pause exit :BUILD_BY_CMAKE -echo Now build by CMake -if not exist BuildCMakeProj mkdir BuildCMakeProj -pushd %~dp0 -cd BuildCMakeProj - -if defined VS140COMNTOOLS (goto MS2015Build) -if defined VS120COMNTOOLS (goto MS2013Build) else (goto NotSupport) - -:MS2015Build -echo Build By Visual Studio 2015 -cmake -G"Visual Studio 14 2015 Win64" ..\Source -DCMAKE_BUILD_TYPE=Debug -call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 -msbuild Kaleido3D.sln -goto End +echo Now Generate Project by CMake (VS 2017) +cmake -G"Visual Studio 15 2017 Win64" -HSource -BBuild\Win64\Debug -DCMAKE_BUILD_TYPE=Debug +if "%ERRORLEVEL%"=="0" (goto BUILD_CMAKE) +RD /S /Q Build + +echo Now Generate Project by CMake (VS 2015) +cmake -G"Visual Studio 14 2015 Win64" -HSource -BBuild\Win64\Debug -DCMAKE_BUILD_TYPE=Debug +if "%ERRORLEVEL%"=="0" (goto BUILD_CMAKE) else (goto NotSupport) -:MS2013Build -echo Build By Visual Studio 2013 -cmake -G"Visual Studio 12 2013 Win64" ..\Source -call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 -msbuild Kaleido3D.sln +:BUILD_CMAKE +cmake --build Build\Win64\Debug --config Debug goto End :NotSupport echo Visual Studio Version not supported! -:End -popd \ No newline at end of file +:End \ No newline at end of file diff --git a/make_android.cmd b/make_android.cmd new file mode 100644 index 0000000..22c5cf3 --- /dev/null +++ b/make_android.cmd @@ -0,0 +1,15 @@ +for /f %%i in ('dir /b %ANDROID_HOME%\cmake') do set CMAKE_DIR=%ANDROID_HOME%\cmake\%%i +set CMAKE_BIN=%CMAKE_DIR%\bin\cmake +set CMAKE_NINJA=%CMAKE_DIR%\bin\ninja +set CMAKE_TOOLCHAIN=%ANDROID_NDK_HOME%\build\cmake\android.toolchain.cmake +set STL=gnustl_shared +set CMAKE_NDK_DEFINES=-DANDROID_NDK=%ANDROID_NDK_HOME% +set CMAKE_ANDROID_DEFINES=%CMAKE_NDK_DEFINES% -DCMAKE_MAKE_PROGRAM=%CMAKE_NINJA% -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=24 -DANDROID_PLATFORM=android-24 -DANDROID_TOOLCHAIN=clang -DANDROID_STL=%STL% -DANDROID_CPP_FEATURES=rtti;exceptions + +call :Build Debug +exit /b %errorlevel% + +:Build +%CMAKE_BIN% -G"Android Gradle - Ninja" -DCMAKE_TOOLCHAIN_FILE=%CMAKE_TOOLCHAIN% -HSource -BBuild\Android\%~1\%STL% -DCMAKE_BUILD_TYPE=%~1 %CMAKE_ANDROID_DEFINES% +%CMAKE_BIN% --build Build\Android\%~1\%STL% --config %~1 +:End diff --git a/make_android.sh b/make_android.sh new file mode 100755 index 0000000..f1f8485 --- /dev/null +++ b/make_android.sh @@ -0,0 +1,17 @@ +CMAKE_VERSION=`ls $android_home/cmake` +CMAKE_DIR=$android_home/cmake/$CMAKE_VERSION +CMAKE_BIN=$CMAKE_DIR/bin/cmake +CMAKE_NINJA=$CMAKE_DIR/bin/ninja +CMAKE_TOOLCHAIN=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake +STL=gnustl_shared +CMAKE_NDK_DEFINES="-DANDROID_NDK=$ANDROID_NDK_HOME" +CMAKE_ANDROID_DEFINES="$CMAKE_NDK_DEFINES -DCMAKE_MAKE_PROGRAM=$CMAKE_NINJA -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=24 -DANDROID_PLATFORM=android-24 -DANDROID_TOOLCHAIN=clang -DANDROID_STL=$STL -DANDROID_CPP_FEATURES=rtti;exceptions" + +function build() +{ + set -e + $CMAKE_BIN -G"Android Gradle - Ninja" -DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN -DCMAKE_BUILD_TYPE=$1 $CMAKE_ANDROID_DEFINES -HSource -BBuild/Android/$STL/$1 -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=STL_$1 + $CMAKE_BIN --build Build/Android/$STL/$1 --config $1 --target RHI-UnitTest-3.Triangle +} + +build Debug; \ No newline at end of file diff --git a/make_ios.sh b/make_ios.sh new file mode 100755 index 0000000..302dedf --- /dev/null +++ b/make_ios.sh @@ -0,0 +1,3 @@ +# build projects +cmake -DCMAKE_TOOLCHAIN_FILE=../Project/ios.cmake -DIOS_PLATFORM=OS -HSource -BBuild/IOS/Debug -GXcode -DCMAKE_BUILD_TYPE=Debug +cmake --build Build/IOS/Debug --config Debug \ No newline at end of file diff --git a/make_macos.sh b/make_macos.sh index 5106bca..57bfb17 100755 --- a/make_macos.sh +++ b/make_macos.sh @@ -1,6 +1,2 @@ -if [ ! -d Build ]; then - mkdir Build -fi -cd Build -cmake -G"Xcode" ../Source -DCMAKE_BUILD_TYPE=Debug -xcodebuild \ No newline at end of file +cmake -HSource -BBuild/Mac/Debug -GXcode -DCMAKE_BUILD_TYPE=Debug +cmake --build Build/Mac/Debug --config Debug \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f87c20a..5f03016 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ include ':Project' -include ':Source:UnitTest:Android:Triangle' -include ':Source:UnitTest:Android:TexturedCube' \ No newline at end of file +include ':Source:RHI:UnitTest:Android:Triangle' +include ':Source:RHI:UnitTest:Android:TexturedCube' \ No newline at end of file

DOX>! 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