diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 63fda17212cf97f2857ac1891dfad9dd052cbe6a..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,125 +0,0 @@ -variables: - RUN: - value: "all" - description: "The tests that should run. Possible values: ubuntu, win-msvc, win-mingw, mac, all." - GIT_DEPTH: 15 - -stages: - - build - - deploy - -build_ubuntu_gcc: - only: - variables: - - $RUN =~ /\bubuntu.*/i || $RUN =~ /\ball.*/i - stage: build - tags: - - ubuntu-gcc-cached - variables: - GIT_SUBMODULE_STRATEGY: recursive - timeout: 15m - retry: 1 - script: - - mkdir debug - - cd debug - - cmake -DCMAKE_BUILD_TYPE=Debug .. - - cmake --build . -j 4 - artifacts: - name: "Documentation - $CI_PIPELINE_ID" - paths: - - doc/html - - doc/latex - expire_in: never - -build_win10_msvc: - only: - variables: - - $RUN =~ /\bwin-msvc.*/i || $RUN =~ /\ball.*/i - stage: build - tags: - - win10-msvc-cached - variables: - GIT_SUBMODULE_STRATEGY: recursive - timeout: 15m - retry: 0 - script: - - cd 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\' - - .\Launch-VsDevShell.ps1 - - cd $CI_PROJECT_DIR - - mkdir debug - - cd debug - - cmake -DCMAKE_BUILD_TYPE=Debug .. - - cmake --build . -j 4 - -build_win10_mingw: - only: - variables: - - $RUN =~ /\bwin-mingw.*/i || $RUN =~ /\ball.*/i - stage: build - tags: - - win10-mingw-cached - variables: - GIT_SUBMODULE_STRATEGY: recursive - timeout: 15m - retry: 0 - script: - - mkdir debug - - cd debug - - cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-g++.exe .. -G "Unix Makefiles" - - cmake --build . -j 4 - -build_mac_clang: - only: - variables: - - $RUN =~ /\bmac.*/i || $RUN =~ /\ball.*/i - stage: build - tags: - - catalina-clang-cached - variables: - GIT_SUBMODULE_STRATEGY: recursive - timeout: 15m - retry: 1 - script: - - mkdir debug - - cd debug - - export LDFLAGS="-L/usr/local/opt/llvm/lib" - - export CPPFLAGS="-I/usr/local/opt/llvm/include" - - cmake -DCMAKE_C_COMPILER="/usr/local/opt/llvm/bin/clang" -DCMAKE_CXX_COMPILER="/usr/local/opt/llvm/bin/clang++" -DCMAKE_BUILD_TYPE=Debug .. - - cmake --build . -j 4 - -deploy_doc_develop: - only: - variables: - - $RUN =~ /\bubuntu.*/i || $RUN =~ /\ball.*/i - refs: - - develop - stage: deploy - needs: ["build_ubuntu_gcc"] - dependencies: - - build_ubuntu_gcc - tags: - - webserver - variables: - GIT_STRATEGY: none - script: - - rsync -avh doc/html/ /var/www/html/develop --delete - - echo "Check it out at https://vkcv.de/develop" - -deploy_doc_branch: - only: - variables: - - $RUN =~ /\bubuntu.*/i || $RUN =~ /\ball.*/i - except: - refs: - - develop - stage: deploy - needs: ["build_ubuntu_gcc"] - dependencies: - - build_ubuntu_gcc - tags: - - webserver - variables: - GIT_STRATEGY: none - script: - - rsync -avh doc/html/ /var/www/html/branch/$CI_COMMIT_BRANCH --delete - - echo "Check it out at https://vkcv.de/branch/$CI_COMMIT_BRANCH" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..3e2cfbfed372f4d7aa182b6129c34f2bc6abccb6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,43 @@ +# Changelog + +## [0.1.0](https://gitlab.uni-koblenz.de/vulkan2021/vkcv-framework/tree/0.1.0) (2021-12-07) + +** Platform support:** + + - Linux support (GCC and CLang) + - MacOS support (Apple CLang) + - Windows support (MSVC and MinGW-GCC experimentally) + +** New modules:** + + - [Asset-Loader](modules/asset_loader/README.md): A VkCV module to load basic assets like models, materials and images + - [Camera](modules/asset_loader/README.md): A VkCV module to manage cameras and their handle view and projection matrices + - [GUI](modules/gui/README.md): A VkCV module to integrate GUI rendering to your application as additional pass + - [Material](modules/material/README.md): A VkCV module to abstract typical kinds of materials for rendering + - [Meshlet](modules/meshlet/README.md): A VkCV module to divide vertex data of a mesh into meshlets + - [Scene](modules/scene/README.md): A VkCV module to load and manage a scene, simplify its rendering and potentially optimize it + - [Shader-Compiler](modules/shader_compiler/README.md): A VkCV module to compile shaders at runtime + - [Upscaling](modules/upscaling/README.md): A VkCV module to upscale images in realtime + +** New features:** + + - Resizable windows + - Multiple windows and multiple swapchains (window management) + - Dynamically requesting Vulkan features and extensions + - Shader reflection and runtime shader compilation (various shader stages) + - Realtime ray tracing + - Mesh shaders + - Indirect dispatch + - Compute pipelines and compute shaders + - Multiple queues and graphic pipelines + - Bindless textures + - ImGUI support + - Mipmapping + - Logging + - Command buffer synchronization + - Doxygen source code documentation + - Buffer, sampler and image management + - Camera management with gamepad support + - Input event synchronization + - Resource management with handles + diff --git a/CMakeLists.txt b/CMakeLists.txt index e3a8d930f061b25631dff84ba8ed425d780f9055..121d499fb2cd337c28524b89ecf1ab9d12607bdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,8 +33,13 @@ if (CMAKE_BUILD_TYPE) set(vkcv_build_${_vkcv_build_type} 1) endif() +if (EXISTS "/usr/bin/mold") + set(CMAKE_LINKER "/usr/bin/mold") +endif() + message(STATUS "Language: [ C++ " ${CMAKE_CXX_STANDARD} " ]") message(STATUS "Compiler: [ " ${CMAKE_CXX_COMPILER_ID} " " ${CMAKE_CXX_COMPILER_VERSION} " ]") +message(STATUS "Linker: [ " ${CMAKE_LINKER} " ]") if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")) message(FATAL_ERROR "Upgrade your compiler! GCC 9.0+ is required!") diff --git a/config/Libraries.cmake b/config/Libraries.cmake index 512669ce85a96f8cc94d8181994cfe458fa8b604..ca2af95ef5533ffaf36cbd439f58cf9bd8e28854 100644 --- a/config/Libraries.cmake +++ b/config/Libraries.cmake @@ -16,6 +16,9 @@ if(NOT WIN32) list(APPEND vkcv_flags -fopenmp) endif() +# add custom functions to check for git submodules +include(${vkcv_config_ext}/Git.cmake) + list(APPEND vkcv_definitions _USE_MATH_DEFINES) # some formatted printing diff --git a/config/ext/Git.cmake b/config/ext/Git.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a943ce02ab3a170a67fae7394fa6f616239ab5b4 --- /dev/null +++ b/config/ext/Git.cmake @@ -0,0 +1,15 @@ + +function(use_git_submodule submodule_path submodule_status) + file(GLOB path_glob "${submodule_path}/*") + list(LENGTH path_glob glob_len) + + if(glob_len GREATER 0) + set(${submodule_status} TRUE PARENT_SCOPE) + return() + endif() + + get_filename_component(submodule_name ${submodule_path} NAME) + + message(WARNING "${submodule_name} is required..! Update the submodules!") + set(${submodule_status} FALSE PARENT_SCOPE) +endfunction() diff --git a/config/ext/ProjectFix.cmake b/config/ext/ProjectFix.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d3f26b4a5323f473868d87cc94d39b52eafd4313 --- /dev/null +++ b/config/ext/ProjectFix.cmake @@ -0,0 +1,13 @@ + +# the first argument should be the project's target +macro(fix_project) + # this should fix the execution path to load local files from the project (for MSVC) + if(MSVC) + set_target_properties(${ARGV1} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set_target_properties(${ARGV1} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + # in addition to setting the output directory, the working directory has to be set + # by default visual studio sets the working directory to the build directory, when using the debugger + set_target_properties(${ARGV1} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + endif() +endmacro() diff --git a/config/lib/GLFW.cmake b/config/lib/GLFW.cmake index 9668694de5b6887c163f74b626c71873e3f611f8..977eabc8c3916da694420eb8b069e058b94c15f2 100644 --- a/config/lib/GLFW.cmake +++ b/config/lib/GLFW.cmake @@ -6,14 +6,14 @@ if (glfw3_FOUND) message(${vkcv_config_msg} " GLFW - " ${glfw3_VERSION}) else() - if (EXISTS "${vkcv_lib_path}/glfw") + use_git_submodule("${vkcv_lib_path}/glfw" glfw_status) + + if (${glfw_status}) add_subdirectory(${vkcv_lib}/glfw) list(APPEND vkcv_libraries glfw) list(APPEND vkcv_includes ${vkcv_lib_path}/glfw/include) message(${vkcv_config_msg} " GLFW - " ${glfw3_VERSION}) - else() - message(WARNING "GLFW is required..! Update the submodules!") endif () endif () diff --git a/config/lib/SPIRV_Cross.cmake b/config/lib/SPIRV_Cross.cmake index 00ae45527d0f49c5632d71e19509871d437ae691..ce4b2e437467436daa7e1bc04975be4fa9609fef 100644 --- a/config/lib/SPIRV_Cross.cmake +++ b/config/lib/SPIRV_Cross.cmake @@ -5,7 +5,9 @@ if (spirv-cross_FOUND) message(${vkcv_config_msg} " SPIRV Cross - " ${SPIRV_CROSS_VERSION}) else() - if (EXISTS "${vkcv_lib_path}/SPIRV-Cross") + use_git_submodule("${vkcv_lib_path}/SPIRV-Cross" spirv_cross_status) + + if (${spirv_cross_status}) set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF CACHE INTERNAL "") set(SPIRV_CROSS_SHARED OFF CACHE INTERNAL "") set(SPIRV_CROSS_STATIC ON CACHE INTERNAL "") @@ -28,7 +30,5 @@ else() list(APPEND vkcv_includes ${vkcv_lib_path}/SPIV-Cross/include) message(${vkcv_config_msg} " SPIRV Cross - " ${SPIRV_CROSS_VERSION}) - else() - message(WARNING "SPIRV-Cross is required..! Update the submodules!") endif () endif () \ No newline at end of file diff --git a/config/lib/VulkanMemoryAllocator.cmake b/config/lib/VulkanMemoryAllocator.cmake index 5f670ff04633e1747accb8f1598fee028a287168..fcde834d920e80f8ba47f8eaea0416127ee0347b 100644 --- a/config/lib/VulkanMemoryAllocator.cmake +++ b/config/lib/VulkanMemoryAllocator.cmake @@ -1,6 +1,12 @@ -if (EXISTS "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp") - set(VMA_HPP_PATH "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp" CACHE INTERNAL "") +use_git_submodule("${vkcv_lib_path}/VulkanMemoryAllocator-Hpp" vma_hpp_status) + +if (${vma_hpp_status}) + if (EXISTS "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp/include") + set(VMA_HPP_PATH "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp/include" CACHE INTERNAL "") + else() + set(VMA_HPP_PATH "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp" CACHE INTERNAL "") + endif() set(VMA_RECORDING_ENABLED OFF CACHE INTERNAL "") set(VMA_USE_STL_CONTAINERS OFF CACHE INTERNAL "") @@ -14,9 +20,7 @@ if (EXISTS "${vkcv_lib_path}/VulkanMemoryAllocator-Hpp") add_subdirectory(${vkcv_config_lib}/vma) list(APPEND vkcv_libraries VulkanMemoryAllocator) - list(APPEND vkcv_includes ${vkcv_lib_path}/VulkanMemoryAllocator-Hpp) + list(APPEND vkcv_includes ${VMA_HPP_PATH}) message(${vkcv_config_msg} " VMA - ") -else() - message(WARNING "VulkanMemoryAllocator is required..! Update the submodules!") endif () diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp index 38e9e6da5db7dc42f4acd408d961f87183f8a1cc..e3157f7a4e688fb2b33397b713cdb93e1cacfcaf 100644 --- a/include/vkcv/ComputePipelineConfig.hpp +++ b/include/vkcv/ComputePipelineConfig.hpp @@ -7,13 +7,14 @@ #include <vector> +#include "Handles.hpp" #include "ShaderProgram.hpp" namespace vkcv { struct ComputePipelineConfig { ShaderProgram& m_ShaderProgram; - std::vector<vk::DescriptorSetLayout> m_DescriptorSetLayouts; + std::vector<DescriptorSetLayoutHandle> m_DescriptorSetLayouts; }; } \ No newline at end of file diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 228513227e42d7c4073a988d522b0fd8da463423..e34b625bf182647a90b8376a66546ef7645aa5c4 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -28,6 +28,9 @@ #include "DrawcallRecording.hpp" #include "CommandRecordingFunctionTypes.hpp" +#define VKCV_FRAMEWORK_NAME "VkCV" +#define VKCV_FRAMEWORK_VERSION (VK_MAKE_VERSION(0, 1, 0)) + namespace vkcv { @@ -208,7 +211,7 @@ namespace vkcv [[nodiscard]] SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, - float mipLodBias = 0.0f); + float mipLodBias = 0.0f, SamplerBorderColor borderColor = SamplerBorderColor::INT_ZERO_OPAQUE); /** * Creates an #Image with a given format, width, height and depth. diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp index 1bd90354b8fb2a775c791c4866bcc51362a63af1..244508b4c4c2677f608573275b32a25fef435951 100644 --- a/include/vkcv/DrawcallRecording.hpp +++ b/include/vkcv/DrawcallRecording.hpp @@ -10,6 +10,7 @@ #include "Handles.hpp" #include "DescriptorConfig.hpp" #include "PushConstants.hpp" + #include "Buffer.hpp" namespace vkcv { @@ -28,12 +29,12 @@ namespace vkcv { }; struct DescriptorSetUsage { - inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle, + inline DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle descriptorSet, const std::vector<uint32_t>& dynamicOffsets = {}) noexcept - : setLocation(setLocation), vulkanHandle(vulkanHandle), dynamicOffsets(dynamicOffsets) {} + : setLocation(setLocation), descriptorSet(descriptorSet), dynamicOffsets(dynamicOffsets) {} const uint32_t setLocation; - const vk::DescriptorSet vulkanHandle; + const DescriptorSetHandle descriptorSet; const std::vector<uint32_t> dynamicOffsets; }; @@ -59,8 +60,6 @@ namespace vkcv { }; - vk::IndexType getIndexType(IndexBitCount indexByteCount); - struct DrawcallInfo { inline DrawcallInfo(const Mesh& mesh, const std::vector<DescriptorSetUsage>& descriptorSets, const uint32_t instanceCount = 1) : mesh(mesh), descriptorSets(descriptorSets), instanceCount(instanceCount){} @@ -70,22 +69,6 @@ namespace vkcv { uint32_t instanceCount; }; - void recordDrawcall( - const DrawcallInfo &drawcall, - vk::CommandBuffer cmdBuffer, - vk::PipelineLayout pipelineLayout, - const PushConstants &pushConstants, - const size_t drawcallIndex); - - void recordIndirectDrawcall( - const DrawcallInfo &drawcall, - vk::CommandBuffer cmdBuffer, - const vkcv::Buffer<vk::DrawIndexedIndirectCommand> &drawBuffer, - const uint32_t drawCount, - vk::PipelineLayout pipelineLayout, - const PushConstants &pushConstants, - const size_t drawcallIndex); - void InitMeshShaderDrawFunctions(vk::Device device); struct MeshShaderDrawcall { @@ -97,9 +80,10 @@ namespace vkcv { }; void recordMeshShaderDrawcall( + const Core& core, vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, - const PushConstants& pushConstantData, + const PushConstants& pushConstantData, const uint32_t pushConstantOffset, const MeshShaderDrawcall& drawcall, const uint32_t firstTask); diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index 136972fda74c0db835fbf43ebb6f4a3db7ab3a0c..0e7fb2a5265a91b961328546aba9ba8f335e73e9 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -224,6 +224,12 @@ namespace vkcv { [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV& features, bool required) const; + [[nodiscard]] + bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT& features, bool required) const; + + [[nodiscard]] + bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT& features, bool required) const; + /** * @brief Checks support of the @p vk::PhysicalDeviceVulkan12Features. * @param features The features diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp index a9f0996b3e8e64d4922a09af930ef6ab093e70c6..3efde5bcbb80cd98df964f1bc7e03798d440ad02 100644 --- a/include/vkcv/GraphicsPipelineConfig.hpp +++ b/include/vkcv/GraphicsPipelineConfig.hpp @@ -15,7 +15,7 @@ namespace vkcv { - enum class PrimitiveTopology{PointList, LineList, TriangleList }; + enum class PrimitiveTopology{PointList, LineList, TriangleList, PatchList }; enum class CullMode{ None, Front, Back }; enum class DepthTest { None, Less, LessEqual, Greater, GreatherEqual, Equal }; @@ -29,7 +29,7 @@ namespace vkcv { uint32_t m_Height; PassHandle m_PassHandle; VertexLayout m_VertexLayout; - std::vector<vk::DescriptorSetLayout> m_DescriptorLayouts; + std::vector<DescriptorSetLayoutHandle> m_DescriptorLayouts; bool m_UseDynamicViewport; bool m_UseConservativeRasterization = false; PrimitiveTopology m_PrimitiveTopology = PrimitiveTopology::TriangleList; @@ -40,6 +40,7 @@ namespace vkcv { DepthTest m_depthTest = DepthTest::LessEqual; bool m_depthWrite = true; bool m_alphaToCoverage = false; + uint32_t m_tessellationControlPoints = 0; }; } \ No newline at end of file diff --git a/include/vkcv/Sampler.hpp b/include/vkcv/Sampler.hpp index ad2ba8bd6c4769c1d882d940dbde323ef6623365..891a96f869c03f5f4a064116bff603acbf2d47e3 100644 --- a/include/vkcv/Sampler.hpp +++ b/include/vkcv/Sampler.hpp @@ -21,7 +21,19 @@ namespace vkcv { REPEAT = 1, MIRRORED_REPEAT = 2, CLAMP_TO_EDGE = 3, - MIRROR_CLAMP_TO_EDGE = 4 + MIRROR_CLAMP_TO_EDGE = 4, + CLAMP_TO_BORDER = 5 + }; + + enum class SamplerBorderColor { + INT_ZERO_OPAQUE = 1, + INT_ZERO_TRANSPARENT = 2, + + FLOAT_ZERO_OPAQUE = 3, + FLOAT_ZERO_TRANSPARENT = 4, + + INT_ONE_OPAQUE = 5, + FLOAT_ONE_OPAQUE = 6 }; } diff --git a/include/vkcv/ShaderStage.hpp b/include/vkcv/ShaderStage.hpp index 83446bd0717cd6beaa010aca4673c44f0e294d7d..b964c63fa93e4c9483affa091a2b2aadcd16f903 100644 --- a/include/vkcv/ShaderStage.hpp +++ b/include/vkcv/ShaderStage.hpp @@ -8,26 +8,56 @@ #include <vulkan/vulkan.hpp> namespace vkcv { - + enum class ShaderStage : VkShaderStageFlags { - VERTEX = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eVertex), - TESS_CONTROL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl), - TESS_EVAL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationEvaluation), - GEOMETRY = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eGeometry), - FRAGMENT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eFragment), - COMPUTE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCompute), - TASK = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTaskNV), - MESH = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMeshNV), - RAY_GEN = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eRaygenKHR), // RTX - RAY_ANY_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eAnyHitKHR), // RTX - RAY_CLOSEST_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eClosestHitKHR), // RTX - RAY_MISS = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMissKHR), // RTX - RAY_INTERSECTION = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eIntersectionKHR), // RTX - RAY_CALLABLE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCallableKHR) // RTX + VERTEX = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eVertex), + TESS_CONTROL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl), + TESS_EVAL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationEvaluation), + GEOMETRY = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eGeometry), + FRAGMENT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eFragment), + COMPUTE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCompute), + TASK = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTaskNV), + MESH = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMeshNV), + RAY_GEN = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eRaygenKHR), + RAY_ANY_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eAnyHitKHR), + RAY_CLOSEST_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eClosestHitKHR), + RAY_MISS = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMissKHR), + RAY_INTERSECTION = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eIntersectionKHR), + RAY_CALLABLE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCallableKHR) }; using ShaderStages = vk::Flags<ShaderStage>; +} + +namespace vk { + + template<> + struct [[maybe_unused]] FlagTraits<vkcv::ShaderStage> { + enum : VkFlags { + allFlags [[maybe_unused]] = ( + VkFlags( vkcv::ShaderStage::VERTEX ) | + VkFlags( vkcv::ShaderStage::TESS_CONTROL ) | + VkFlags( vkcv::ShaderStage::TESS_EVAL ) | + VkFlags( vkcv::ShaderStage::GEOMETRY ) | + VkFlags( vkcv::ShaderStage::FRAGMENT ) | + VkFlags( vkcv::ShaderStage::COMPUTE ) | + VkFlags( vkcv::ShaderStage::TASK ) | + VkFlags( vkcv::ShaderStage::MESH ) | + VkFlags( vkcv::ShaderStage::RAY_GEN ) | + VkFlags( vkcv::ShaderStage::RAY_ANY_HIT ) | + VkFlags( vkcv::ShaderStage::RAY_CLOSEST_HIT ) | + VkFlags( vkcv::ShaderStage::RAY_MISS ) | + VkFlags( vkcv::ShaderStage::RAY_INTERSECTION ) | + VkFlags( vkcv::ShaderStage::RAY_CALLABLE ) + ) + }; + }; + +} + +namespace vkcv { + constexpr vk::ShaderStageFlags getShaderStageFlags(ShaderStages shaderStages) noexcept { return vk::ShaderStageFlags(static_cast<VkShaderStageFlags>(shaderStages)); } diff --git a/lib/SPIRV-Cross b/lib/SPIRV-Cross index ff61890722a91e97c44940494be5b6eed0d5ff5b..6a67891418a3f08be63f92726e049dc788e46f5b 160000 --- a/lib/SPIRV-Cross +++ b/lib/SPIRV-Cross @@ -1 +1 @@ -Subproject commit ff61890722a91e97c44940494be5b6eed0d5ff5b +Subproject commit 6a67891418a3f08be63f92726e049dc788e46f5b diff --git a/lib/VulkanMemoryAllocator-Hpp b/lib/VulkanMemoryAllocator-Hpp index 3a61240a5354ce56c222969a69825aabb6ba0a21..c6c3c665b6a29ae546bdec60606a3ef0757ea108 160000 --- a/lib/VulkanMemoryAllocator-Hpp +++ b/lib/VulkanMemoryAllocator-Hpp @@ -1 +1 @@ -Subproject commit 3a61240a5354ce56c222969a69825aabb6ba0a21 +Subproject commit c6c3c665b6a29ae546bdec60606a3ef0757ea108 diff --git a/lib/glfw b/lib/glfw index 0e9ec7788b4985a0df698080258e4091d18dcc3b..4cb36872a5fe448c205d0b46f0e8c8b57530cfe0 160000 --- a/lib/glfw +++ b/lib/glfw @@ -1 +1 @@ -Subproject commit 0e9ec7788b4985a0df698080258e4091d18dcc3b +Subproject commit 4cb36872a5fe448c205d0b46f0e8c8b57530cfe0 diff --git a/modules/asset_loader/config/FX_GLTF.cmake b/modules/asset_loader/config/FX_GLTF.cmake index 37cd162422d8277022067498f5d5ba3e26e2ae1b..4164c2786d9ada53c979b98bf23f973113edfda5 100644 --- a/modules/asset_loader/config/FX_GLTF.cmake +++ b/modules/asset_loader/config/FX_GLTF.cmake @@ -1,5 +1,7 @@ -if (EXISTS "${vkcv_asset_loader_lib_path}/fx-gltf") +use_git_submodule("${vkcv_asset_loader_lib_path}/fx-gltf" fx_gltf_status) + +if (${fx_gltf_status}) set(FX_GLTF_INSTALL OFF CACHE INTERNAL "") set(FX_GLTF_USE_INSTALLED_DEPS OFF CACHE INTERNAL "") set(BUILD_TESTING OFF CACHE INTERNAL "") @@ -7,6 +9,4 @@ if (EXISTS "${vkcv_asset_loader_lib_path}/fx-gltf") add_subdirectory(${vkcv_asset_loader_lib}/fx-gltf) list(APPEND vkcv_asset_loader_libraries fx-gltf) -else() - message(WARNING "FX-GLTF is required..! Update the submodules!") endif () diff --git a/modules/asset_loader/config/NLOHMANN_JSON.cmake b/modules/asset_loader/config/NLOHMANN_JSON.cmake index 018f6a19809fd3e53e6e790a6fe6447348e43c09..4bd7f4475ef1e748e109814d440762e27948f495 100644 --- a/modules/asset_loader/config/NLOHMANN_JSON.cmake +++ b/modules/asset_loader/config/NLOHMANN_JSON.cmake @@ -1,10 +1,10 @@ -if (EXISTS "${vkcv_asset_loader_lib_path}/json") +use_git_submodule("${vkcv_asset_loader_lib_path}/json" json_status) + +if (${json_status}) set(JSON_BuildTests OFF CACHE INTERNAL "") add_subdirectory(${vkcv_asset_loader_lib}/json) list(APPEND vkcv_asset_loader_libraries nlohmann_json::nlohmann_json) -else() - message(WARNING "NLOHMANN_JSON is required..! Update the submodules!") endif () diff --git a/modules/asset_loader/config/STB.cmake b/modules/asset_loader/config/STB.cmake index 1287d0a9ddda559e061ddd680bc815e24b3e2075..61b7cc929b2b5ae96fbbbe479f6e9d48d9db5c69 100644 --- a/modules/asset_loader/config/STB.cmake +++ b/modules/asset_loader/config/STB.cmake @@ -1,10 +1,10 @@ -if (EXISTS "${vkcv_asset_loader_lib_path}/stb") +use_git_submodule("${vkcv_asset_loader_lib_path}/stb" stb_status) + +if (${stb_status}) list(APPEND vkcv_asset_loader_includes ${vkcv_asset_loader_lib}/stb) list(APPEND vkcv_asset_loader_definitions STB_IMAGE_IMPLEMENTATION) list(APPEND vkcv_asset_loader_definitions STBI_ONLY_JPEG) list(APPEND vkcv_asset_loader_definitions STBI_ONLY_PNG) -else() - message(WARNING "STB is required..! Update the submodules!") endif () diff --git a/modules/asset_loader/lib/fx-gltf b/modules/asset_loader/lib/fx-gltf index f4f18f2017a049a23748c9c9aad42ba2de20bfd5..7766c237ea81c0bb3759e78e5c0f22854843eef8 160000 --- a/modules/asset_loader/lib/fx-gltf +++ b/modules/asset_loader/lib/fx-gltf @@ -1 +1 @@ -Subproject commit f4f18f2017a049a23748c9c9aad42ba2de20bfd5 +Subproject commit 7766c237ea81c0bb3759e78e5c0f22854843eef8 diff --git a/modules/asset_loader/lib/json b/modules/asset_loader/lib/json index 0972f7ff0e651f09a306dba791cc42024b8642c1..4f8fba14066156b73f1189a2b8bd568bde5284c5 160000 --- a/modules/asset_loader/lib/json +++ b/modules/asset_loader/lib/json @@ -1 +1 @@ -Subproject commit 0972f7ff0e651f09a306dba791cc42024b8642c1 +Subproject commit 4f8fba14066156b73f1189a2b8bd568bde5284c5 diff --git a/modules/asset_loader/lib/stb b/modules/asset_loader/lib/stb index c9064e317699d2e495f36ba4f9ac037e88ee371a..af1a5bc352164740c1cc1354942b1c6b72eacb8a 160000 --- a/modules/asset_loader/lib/stb +++ b/modules/asset_loader/lib/stb @@ -1 +1 @@ -Subproject commit c9064e317699d2e495f36ba4f9ac037e88ee371a +Subproject commit af1a5bc352164740c1cc1354942b1c6b72eacb8a diff --git a/modules/camera/config/GLM.cmake b/modules/camera/config/GLM.cmake index f256ccade8c4f44a89744bb7875371324cf2369d..53960241b8c147f522afd7afa3bfedb20f4f0761 100644 --- a/modules/camera/config/GLM.cmake +++ b/modules/camera/config/GLM.cmake @@ -5,13 +5,13 @@ if (glm_FOUND) list(APPEND vkcv_camera_includes ${GLM_INCLUDE_DIRS}) list(APPEND vkcv_camera_libraries glm) else() - if (EXISTS "${vkcv_camera_lib_path}/glm") + use_git_submodule("${vkcv_camera_lib_path}/glm" glm_status) + + if (${glm_status}) add_subdirectory(${vkcv_camera_lib}/glm) list(APPEND vkcv_camera_includes ${vkcv_camera_lib_path}/glm) list(APPEND vkcv_camera_libraries glm) - else() - message(WARNING "GLM is required..! Update the submodules!") endif () endif () diff --git a/modules/camera/lib/glm b/modules/camera/lib/glm index 66062497b104ca7c297321bd0e970869b1e6ece5..6ad79aae3eb5bf809c30bf1168171e9e55857e45 160000 --- a/modules/camera/lib/glm +++ b/modules/camera/lib/glm @@ -1 +1 @@ -Subproject commit 66062497b104ca7c297321bd0e970869b1e6ece5 +Subproject commit 6ad79aae3eb5bf809c30bf1168171e9e55857e45 diff --git a/modules/gui/config/ImGui.cmake b/modules/gui/config/ImGui.cmake index 90cdafdeee355af9e63723632572799e135b04da..624ea7701e245ab8c20731d2b226896667c18f89 100644 --- a/modules/gui/config/ImGui.cmake +++ b/modules/gui/config/ImGui.cmake @@ -1,5 +1,7 @@ -if (EXISTS "${vkcv_gui_lib_path}/imgui") +use_git_submodule("${vkcv_gui_lib_path}/imgui" imgui_status) + +if (${imgui_status}) list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_glfw.cpp) list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_glfw.h) list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_vulkan.cpp) @@ -22,6 +24,4 @@ if (EXISTS "${vkcv_gui_lib_path}/imgui") list(APPEND vkcv_gui_include ${vkcv_gui_lib}) list(APPEND vkcv_gui_defines IMGUI_DISABLE_WIN32_FUNCTIONS=1) -else() - message(WARNING "IMGUI is required..! Update the submodules!") endif () diff --git a/modules/gui/lib/imgui b/modules/gui/lib/imgui index d5828cd988db525f27128edeadb1a689cd2d7461..eda7792b151d138e15df951578253b821ceed5a3 160000 --- a/modules/gui/lib/imgui +++ b/modules/gui/lib/imgui @@ -1 +1 @@ -Subproject commit d5828cd988db525f27128edeadb1a689cd2d7461 +Subproject commit eda7792b151d138e15df951578253b821ceed5a3 diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp index 437cd44534cee0066e3b9b4fdab924ea9cde7ca8..f9c87f0a0587bd8a897e42d5b8536fe07c61c749 100644 --- a/modules/scene/src/vkcv/scene/MeshPart.cpp +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -70,11 +70,10 @@ namespace vkcv::scene { if (*this) { const auto& material = getMaterial(); - const auto& descriptorSet = core.getDescriptorSet(material.getDescriptorSet()); drawcalls.push_back(DrawcallInfo( vkcv::Mesh(m_vertexBindings, indexBuffer.getVulkanHandle(), m_indexCount), - { DescriptorSetUsage(0, descriptorSet.vulkanHandle) } + { DescriptorSetUsage(0, material.getDescriptorSet()) } )); } } diff --git a/modules/shader_compiler/config/GLSLANG.cmake b/modules/shader_compiler/config/GLSLANG.cmake index 50b9fd46bd0db9421c632aa0b80fb8df7e3f2123..98bd45497f9d7ed5196dbed486921f8e6ada12da 100644 --- a/modules/shader_compiler/config/GLSLANG.cmake +++ b/modules/shader_compiler/config/GLSLANG.cmake @@ -1,5 +1,7 @@ -if (EXISTS "${vkcv_shader_compiler_lib_path}/glslang") +use_git_submodule("${vkcv_shader_compiler_lib_path}/glslang" glslang_status) + +if (${glslang_status}) set(SKIP_GLSLANG_INSTALL ON CACHE INTERNAL "") set(ENABLE_SPVREMAPPER OFF CACHE INTERNAL "") set(ENABLE_GLSLANG_BINARIES OFF CACHE INTERNAL "") @@ -23,6 +25,4 @@ if (EXISTS "${vkcv_shader_compiler_lib_path}/glslang") list(APPEND vkcv_shader_compiler_libraries glslang SPIRV) list(APPEND vkcv_shader_compiler_includes ${vkcv_shader_compiler_lib}) -else() - message(WARNING "GLSLANG is required..! Update the submodules!") endif () diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp index ddaaf3d995397dbf7b6b25e2ddd675c5d52a1b47..937c43ef58227d6c2ed29a7ac66681f9afadd025 100644 --- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp @@ -6,6 +6,7 @@ #include <vkcv/Event.hpp> #include <vkcv/ShaderStage.hpp> +#include <vkcv/ShaderProgram.hpp> namespace vkcv::shader { @@ -19,8 +20,13 @@ namespace vkcv::shader { * An event function type to be called on compilation completion. */ typedef typename event_function<ShaderStage, const std::filesystem::path&>::type ShaderCompiledFunction; - - /** + + /** + * An event function type to be called on program compilation completion. + */ + typedef typename event_function<ShaderProgram&>::type ShaderProgramCompiledFunction; + + /** * An abstract class to handle runtime shader compilation. */ class Compiler { @@ -58,8 +64,23 @@ namespace vkcv::shader { virtual void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath, const ShaderCompiledFunction& compiled, const std::filesystem::path& includePath, bool update) = 0; - - /** + + /** + * Compile a shader program from a specific map of given file paths for + * target pipeline stages with a custom shader include path and an event + * function called if the compilation completes. + * @param[in,out] program Shader program + * @param[in] stages Shader pipeline stages + * @param[in] compiled Shader program compilation event + * @param[in] includePath Include path for shaders + * @param[in] update Flag to update shaders during runtime + */ + void compileProgram(ShaderProgram& program, + const std::unordered_map<ShaderStage, const std::filesystem::path>& stages, + const ShaderProgramCompiledFunction& compiled, + const std::filesystem::path& includePath = "", bool update = false); + + /** * Return the definition value of a macro for shader compilation. * @param[in] name Macro definition name * @return Macro definition value diff --git a/modules/shader_compiler/lib/glslang b/modules/shader_compiler/lib/glslang index fe15158676657bf965e41c32e15ae5db7ea2ab6a..48fd6c82b3fefb38e59dd799d8b12fddddf8e63c 160000 --- a/modules/shader_compiler/lib/glslang +++ b/modules/shader_compiler/lib/glslang @@ -1 +1 @@ -Subproject commit fe15158676657bf965e41c32e15ae5db7ea2ab6a +Subproject commit 48fd6c82b3fefb38e59dd799d8b12fddddf8e63c diff --git a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp index f5ec0435ca8b82dc5f328921f43a39338d1be456..1467bf22616764e00399ada69d5f866b929416d5 100644 --- a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp @@ -3,6 +3,27 @@ namespace vkcv::shader { + void Compiler::compileProgram(ShaderProgram& program, + const std::unordered_map<ShaderStage, const std::filesystem::path>& stages, + const ShaderProgramCompiledFunction& compiled, + const std::filesystem::path& includePath, bool update) { + for (const auto& stage : stages) { + compile( + stage.first, + stage.second, + [&program](ShaderStage shaderStage, const std::filesystem::path& path) { + program.addShader(shaderStage, path); + }, + includePath, + update + ); + } + + if (compiled) { + compiled(program); + } + } + std::string Compiler::getDefine(const std::string &name) const { return m_defines.at(name); } diff --git a/modules/upscaling/config/FidelityFX_FSR.cmake b/modules/upscaling/config/FidelityFX_FSR.cmake index cc52b4189f781f534a933feb7b782b6bec333e5a..780f1d441abe2a567db7491ce5e2f4821a396b89 100644 --- a/modules/upscaling/config/FidelityFX_FSR.cmake +++ b/modules/upscaling/config/FidelityFX_FSR.cmake @@ -1,5 +1,7 @@ -if (EXISTS "${vkcv_upscaling_lib_path}/FidelityFX-FSR") +use_git_submodule("${vkcv_upscaling_lib_path}/FidelityFX-FSR" ffx_fsr_status) + +if (${ffx_fsr_status}) include_shader(${vkcv_upscaling_lib_path}/FidelityFX-FSR/ffx-fsr/ffx_a.h ${vkcv_upscaling_include} ${vkcv_upscaling_source}) include_shader(${vkcv_upscaling_lib_path}/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h ${vkcv_upscaling_include} ${vkcv_upscaling_source}) include_shader(${vkcv_upscaling_lib_path}/FidelityFX-FSR/sample/src/VK/FSR_Pass.glsl ${vkcv_upscaling_include} ${vkcv_upscaling_source}) @@ -13,6 +15,4 @@ if (EXISTS "${vkcv_upscaling_lib_path}/FidelityFX-FSR") list(APPEND vkcv_upscaling_sources ${vkcv_upscaling_include}/ffx_a.h.hxx) list(APPEND vkcv_upscaling_sources ${vkcv_upscaling_include}/ffx_fsr1.h.hxx) list(APPEND vkcv_upscaling_sources ${vkcv_upscaling_include}/FSR_Pass.glsl.hxx) -else() - message(WARNING "FidelityFX-FSR is required..! Update the submodules!") endif () diff --git a/modules/upscaling/lib/FidelityFX-FSR b/modules/upscaling/lib/FidelityFX-FSR index bcffc8171efb80e265991301a49670ed755088dd..a21ffb8f6c13233ba336352bdff293894c706575 160000 --- a/modules/upscaling/lib/FidelityFX-FSR +++ b/modules/upscaling/lib/FidelityFX-FSR @@ -1 +1 @@ -Subproject commit bcffc8171efb80e265991301a49670ed755088dd +Subproject commit a21ffb8f6c13233ba336352bdff293894c706575 diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp index eef49ef8d1617239a362f2790e69e8f358883bc1..752d81e65eeb1fc901abf498b8330b7ae6102c80 100644 --- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp +++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp @@ -232,9 +232,9 @@ namespace vkcv::upscaling { program.addShader(shaderStage, path); }); - m_easuPipeline = m_core.createComputePipeline({ program, - {m_core.getDescriptorSetLayout(m_easuDescriptorSetLayout).vulkanHandle} - }); + m_easuPipeline = m_core.createComputePipeline({program,{ + m_easuDescriptorSetLayout + }}); DescriptorWrites writes; @@ -255,7 +255,7 @@ namespace vkcv::upscaling { }); m_rcasPipeline = m_core.createComputePipeline({ program, { - m_core.getDescriptorSetLayout(m_rcasDescriptorSetLayout).vulkanHandle + m_rcasDescriptorSetLayout }}); DescriptorWrites writes; @@ -344,9 +344,7 @@ namespace vkcv::upscaling { cmdStream, m_easuPipeline, dispatch, - {DescriptorSetUsage(0, m_core.getDescriptorSet( - m_easuDescriptorSet - ).vulkanHandle, { 0 })}, + {DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })}, PushConstants(0) ); @@ -366,9 +364,7 @@ namespace vkcv::upscaling { cmdStream, m_rcasPipeline, dispatch, - {DescriptorSetUsage(0, m_core.getDescriptorSet( - m_rcasDescriptorSet - ).vulkanHandle, { 0 })}, + {DescriptorSetUsage(0,m_rcasDescriptorSet, { 0 })}, PushConstants(0) ); @@ -386,9 +382,7 @@ namespace vkcv::upscaling { cmdStream, m_easuPipeline, dispatch, - {DescriptorSetUsage(0, m_core.getDescriptorSet( - m_easuDescriptorSet - ).vulkanHandle, { 0 })}, + {DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })}, PushConstants(0) ); } diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index 9cf1ff1c9327114d28871f11694a2fb88bc00735..ffe8546c961697869354993539697b118fa8d6be 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -1,4 +1,6 @@ +include(${vkcv_config_ext}/ProjectFix.cmake) + # Add new projects/examples here: add_subdirectory(first_triangle) add_subdirectory(first_mesh) @@ -12,4 +14,5 @@ add_subdirectory(indirect_draw) add_subdirectory(bindless_textures) add_subdirectory(saf_r) add_subdirectory(indirect_dispatch) -add_subdirectory(path_tracer) \ No newline at end of file +add_subdirectory(path_tracer) +add_subdirectory(wobble_bobble) \ No newline at end of file diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp index 555e3dc65016b0e383fc57ebc3618a35485e9519..6aa0a9d6106dd06c08dd5219c9570430b49ce229 100644 --- a/projects/bindless_textures/src/main.cpp +++ b/projects/bindless_textures/src/main.cpp @@ -123,18 +123,12 @@ int main(int argc, const char** argv) { vkcv::ShaderProgram firstMeshProgram; vkcv::shader::GLSLCompiler compiler; - compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"), - [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - firstMeshProgram.addShader(shaderStage, path); - }); - - compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"), - [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - firstMeshProgram.addShader(shaderStage, path); - }); + compiler.compileProgram(firstMeshProgram, { + { vkcv::ShaderStage::VERTEX, "resources/shaders/shader.vert" }, + { vkcv::ShaderStage::FRAGMENT, "resources/shaders/shader.frag" } + }, nullptr); auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); @@ -162,7 +156,7 @@ int main(int argc, const char** argv) { UINT32_MAX, firstMeshPass, {firstMeshLayout}, - { core.getDescriptorSetLayout(descriptorSetLayout).vulkanHandle }, + { descriptorSetLayout }, true }; vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); @@ -218,7 +212,7 @@ int main(int argc, const char** argv) { const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices); - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1); vkcv::camera::CameraManager cameraManager(core.getWindow(windowHandle)); diff --git a/projects/first_mesh/CMakeLists.txt b/projects/first_mesh/CMakeLists.txt index 345324ac1d2c836b174c90d16c710491ee477f93..946031f922d7f6b4e2fc5db43c2ef92d48de2691 100644 --- a/projects/first_mesh/CMakeLists.txt +++ b/projects/first_mesh/CMakeLists.txt @@ -10,16 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # adding source files to the project add_executable(first_mesh src/main.cpp) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(first_mesh PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(first_mesh PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(first_mesh PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(first_mesh) # including headers of dependencies and the VkCV framework target_include_directories(first_mesh SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include}) diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 0871631827b87539bbe9b0050420088e199a39af..3f4378a6a2187ba33b7965fd6d008577541f7351 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -73,18 +73,12 @@ int main(int argc, const char** argv) { vkcv::ShaderProgram firstMeshProgram; vkcv::shader::GLSLCompiler compiler; - compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"), - [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - firstMeshProgram.addShader(shaderStage, path); - }); - - compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"), - [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - firstMeshProgram.addShader(shaderStage, path); - }); + compiler.compileProgram(firstMeshProgram, { + { vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" }, + { vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" } + }, nullptr); auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); @@ -115,7 +109,7 @@ int main(int argc, const char** argv) { UINT32_MAX, firstMeshPass, {firstMeshLayout}, - { core.getDescriptorSetLayout(setLayoutHandle).vulkanHandle }, + { setLayoutHandle }, true }; vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); @@ -167,7 +161,7 @@ int main(int argc, const char** argv) { const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices); - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1); vkcv::camera::CameraManager cameraManager(core.getWindow(windowHandle)); diff --git a/projects/first_scene/CMakeLists.txt b/projects/first_scene/CMakeLists.txt index d55476f5fa62639aeaec7a3859f2f63f9c937aed..3d0a5ee7e32ea1ad4cfdd0744e00ad15d69a7541 100644 --- a/projects/first_scene/CMakeLists.txt +++ b/projects/first_scene/CMakeLists.txt @@ -10,16 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # adding source files to the project add_executable(first_scene src/main.cpp) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(first_scene PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(first_scene PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(first_scene PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(first_scene) # including headers of dependencies and the VkCV framework target_include_directories(first_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_scene_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index a078776eb4b7688f51d45cecb7e08d5ba9d0d973..3dd6fc40d516c6f1ae3358d60c02fc4ed219245a 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -61,15 +61,10 @@ int main(int argc, const char** argv) { vkcv::ShaderProgram sceneShaderProgram; vkcv::shader::GLSLCompiler compiler; - compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"), - [&sceneShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - sceneShaderProgram.addShader(shaderStage, path); - }); - - compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"), - [&sceneShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - sceneShaderProgram.addShader(shaderStage, path); - }); + compiler.compileProgram(sceneShaderProgram, { + { vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" }, + { vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" } + }, nullptr); const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments(); std::vector<vkcv::VertexBinding> bindings; @@ -87,8 +82,9 @@ int main(int argc, const char** argv) { UINT32_MAX, scenePass, {sceneLayout}, - { core.getDescriptorSetLayout(material0.getDescriptorSetLayout()).vulkanHandle }, - true }; + { material0.getDescriptorSetLayout() }, + true + }; vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition); if (!scenePipeline) { diff --git a/projects/first_triangle/CMakeLists.txt b/projects/first_triangle/CMakeLists.txt index cf1fdb9022fc8332210a44946911fbfab3f5559a..793c2bc37db08c9fe744a56c97f474e1e2d17c4f 100644 --- a/projects/first_triangle/CMakeLists.txt +++ b/projects/first_triangle/CMakeLists.txt @@ -10,16 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # adding source files to the project add_executable(first_triangle src/main.cpp) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(first_triangle PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(first_triangle PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(first_triangle PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(first_triangle) # including headers of dependencies and the VkCV framework target_include_directories(first_triangle SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 1725b5c84dea931fe785880e3cd423cbb5f04a46..b4ba9046e07ecd3534844b493642098aa5847307 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -47,15 +47,10 @@ int main(int argc, const char** argv) { vkcv::ShaderProgram triangleShaderProgram; vkcv::shader::GLSLCompiler compiler; - compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"), - [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - triangleShaderProgram.addShader(shaderStage, path); - }); - - compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"), - [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - triangleShaderProgram.addShader(shaderStage, path); - }); + compiler.compileProgram(triangleShaderProgram, { + {vkcv::ShaderStage::VERTEX, "shaders/shader.vert"}, + { vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" } + }, nullptr); const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); diff --git a/projects/indirect_dispatch/CMakeLists.txt b/projects/indirect_dispatch/CMakeLists.txt index ac8501f17b65212f87d00998dbf9bc4d5c044619..18a89c8e1966b1e0ee509afd716c1410d9d671d8 100644 --- a/projects/indirect_dispatch/CMakeLists.txt +++ b/projects/indirect_dispatch/CMakeLists.txt @@ -26,16 +26,8 @@ target_sources(indirect_dispatch PRIVATE src/MotionBlurSetup.hpp src/MotionBlurSetup.cpp) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(indirect_dispatch PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(indirect_dispatch PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(indirect_dispatch PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() + +fix_project(indirect_dispatch) # including headers of dependencies and the VkCV framework target_include_directories(indirect_dispatch SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index 532cef11db5b2bb8b5d741f6505507ff23fa4163..cc897e68651de65c7122188b52598535e6637335 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -261,7 +261,7 @@ void App::run() { for (const Object& obj : sceneObjects) { forwardSceneDrawcalls.push_back(vkcv::DrawcallInfo( obj.meshResources.mesh, - { vkcv::DescriptorSetUsage(0, m_core.getDescriptorSet(m_meshPass.descriptorSet).vulkanHandle) })); + { vkcv::DescriptorSetUsage(0, m_meshPass.descriptorSet) })); } m_core.recordDrawcallsToCmdStream( @@ -338,7 +338,7 @@ void App::run() { cmdStream, m_gammaCorrectionPass.pipeline, fullScreenImageDispatch, - { vkcv::DescriptorSetUsage(0, m_core.getDescriptorSet(m_gammaCorrectionPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_gammaCorrectionPass.descriptorSet) }, vkcv::PushConstants(0)); m_core.prepareSwapchainImageForPresent(cmdStream); diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp index e1b29ad5990d371535794fa72a1d80e2b653045b..1d40204b1ab7c6cd49a0c7924fa1fdbf6c2cc24e 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -122,12 +122,12 @@ bool loadGraphicPass( const auto descriptorBindings = shaderProgram.getReflectedDescriptors(); const bool hasDescriptor = descriptorBindings.size() > 0; - std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = {}; + std::vector<vkcv::DescriptorSetLayoutHandle> descriptorSetLayouts = {}; if (hasDescriptor) { outPassHandles->descriptorSetLayout = core.createDescriptorSetLayout(descriptorBindings.at(0)); outPassHandles->descriptorSet = core.createDescriptorSet(outPassHandles->descriptorSetLayout); - descriptorSetLayouts.push_back(core.getDescriptorSetLayout(outPassHandles->descriptorSetLayout).vulkanHandle); + descriptorSetLayouts.push_back(outPassHandles->descriptorSetLayout); } @@ -138,7 +138,8 @@ bool loadGraphicPass( outPassHandles->renderPass, { vertexLayout }, descriptorSetLayouts, - true }; + true + }; pipelineConfig.m_depthTest = depthTest; outPassHandles->pipeline = core.createGraphicsPipeline(pipelineConfig); @@ -260,7 +261,7 @@ bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, Comput outComputePass->descriptorSet = core.createDescriptorSet(outComputePass->descriptorSetLayout); outComputePass->pipeline = core.createComputePipeline({ shaderProgram, - { core.getDescriptorSetLayout(outComputePass->descriptorSetLayout).vulkanHandle }}); + { outComputePass->descriptorSetLayout }}); if (!outComputePass->pipeline) { vkcv_log(vkcv::LogLevel::ERROR, "Compute shader pipeline creation failed"); diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp index fea5b1d6f726851ad1d88e71301bffb0f6d71f4a..30116c84b79ae71c683ee865dbf93dd1a37923e9 100644 --- a/projects/indirect_dispatch/src/MotionBlur.cpp +++ b/projects/indirect_dispatch/src/MotionBlur.cpp @@ -120,7 +120,7 @@ vkcv::ImageHandle MotionBlur::render( cmdStream, m_tileResetPass.pipeline, dispatchSizeOne, - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_tileResetPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_tileResetPass.descriptorSet) }, vkcv::PushConstants(0)); m_core->recordBufferMemoryBarrier(cmdStream, m_fullPathWorkTileBuffer); @@ -166,7 +166,7 @@ vkcv::ImageHandle MotionBlur::render( cmdStream, m_tileClassificationPass.pipeline, tileClassificationDispatch.data(), - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_tileClassificationPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_tileClassificationPass.descriptorSet) }, classificationPushConstants); m_core->recordBufferMemoryBarrier(cmdStream, m_fullPathWorkTileBuffer); @@ -254,7 +254,7 @@ vkcv::ImageHandle MotionBlur::render( m_motionBlurPass.pipeline, m_fullPathWorkTileBuffer, 0, - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_motionBlurPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_motionBlurPass.descriptorSet) }, motionBlurPushConstants); m_core->recordComputeIndirectDispatchToCmdStream( @@ -262,7 +262,7 @@ vkcv::ImageHandle MotionBlur::render( m_colorCopyPass.pipeline, m_copyPathWorkTileBuffer, 0, - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_colorCopyPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_colorCopyPass.descriptorSet) }, vkcv::PushConstants(0)); m_core->recordComputeIndirectDispatchToCmdStream( @@ -270,7 +270,7 @@ vkcv::ImageHandle MotionBlur::render( m_motionBlurFastPathPass.pipeline, m_fastPathWorkTileBuffer, 0, - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_motionBlurFastPathPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_motionBlurFastPathPass.descriptorSet) }, fastPathPushConstants); } else if(mode == eMotionBlurMode::Disabled) { @@ -305,7 +305,7 @@ vkcv::ImageHandle MotionBlur::render( cmdStream, m_tileVisualisationPass.pipeline, dispatchCounts, - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_tileVisualisationPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_tileVisualisationPass.descriptorSet) }, vkcv::PushConstants(0)); } else { @@ -371,7 +371,7 @@ vkcv::ImageHandle MotionBlur::renderMotionVectorVisualisation( cmdStream, m_motionVectorVisualisationPass.pipeline, dispatchSizes.data(), - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_motionVectorVisualisationPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_motionVectorVisualisationPass.descriptorSet) }, motionVectorVisualisationPushConstants); return m_renderTargets.outputColor; @@ -406,7 +406,7 @@ void MotionBlur::computeMotionTiles( cmdStream, m_motionVectorMinMaxPass.pipeline, motionTileDispatchCounts.data(), - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_motionVectorMinMaxPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_motionVectorMinMaxPass.descriptorSet) }, vkcv::PushConstants(0)); // motion vector min max neighbourhood @@ -432,6 +432,6 @@ void MotionBlur::computeMotionTiles( cmdStream, m_motionVectorMinMaxNeighbourhoodPass.pipeline, motionTileDispatchCounts.data(), - { vkcv::DescriptorSetUsage(0, m_core->getDescriptorSet(m_motionVectorMinMaxNeighbourhoodPass.descriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_motionVectorMinMaxNeighbourhoodPass.descriptorSet) }, vkcv::PushConstants(0)); } \ No newline at end of file diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp index 88e7005f2912bb448980bd4c1219245481f1559a..9b062ab56245c44e5021f164b9e06fed8edd15c3 100644 --- a/projects/indirect_draw/src/main.cpp +++ b/projects/indirect_draw/src/main.cpp @@ -467,7 +467,7 @@ int main(int argc, const char** argv) { UINT32_MAX, passHandle, {sponzaVertexLayout}, - { core.getDescriptorSetLayout(descriptorSetLayout).vulkanHandle }, + { descriptorSetLayout }, true }; vkcv::GraphicsPipelineHandle sponzaPipelineHandle = core.createGraphicsPipeline(sponzaPipelineConfig); @@ -512,7 +512,7 @@ int main(int argc, const char** argv) { const vkcv::ComputePipelineConfig computeCullingConfig { cullingProgram, - {core.getDescriptorSetLayout(cullingSetLayout).vulkanHandle} + {cullingSetLayout} }; vkcv::ComputePipelineHandle cullingPipelineHandle = core.createComputePipeline(computeCullingConfig); if (!cullingPipelineHandle) { @@ -536,7 +536,7 @@ int main(int argc, const char** argv) { const uint32_t dispatchCount[3] = {static_cast<uint32_t>(ceiledDispatchCount), 1, 1}; - vkcv::DescriptorSetUsage cullingUsage(0, core.getDescriptorSet(cullingDescSet).vulkanHandle, {}); + vkcv::DescriptorSetUsage cullingUsage(0, cullingDescSet, {}); vkcv::PushConstants emptyPushConstant(0); bool updateFrustumPlanes = true; diff --git a/projects/mesh_shader/CMakeLists.txt b/projects/mesh_shader/CMakeLists.txt index 9e132e555136a7dfdd7d8fc15e06547d8059aff5..0eb0ca2e45daa7486a80ea897a2397c1d3ac1ba3 100644 --- a/projects/mesh_shader/CMakeLists.txt +++ b/projects/mesh_shader/CMakeLists.txt @@ -10,18 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # adding source files to the project add_executable(mesh_shader src/main.cpp) - -target_sources(mesh_shader PRIVATE) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(mesh_shader PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(mesh_shader PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(mesh_shader PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(mesh_shader) # including headers of dependencies and the VkCV framework target_include_directories(mesh_shader SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_meshlet_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 0ee16b99822e0c8fbeaf58af57f02255493b0fb5..0a9914abf0a28f82eee06c5d2a67067faaff4109 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -211,7 +211,7 @@ int main(int argc, const char** argv) { swapchainExtent.height, renderPass, { bunnyLayout }, - { core.getDescriptorSetLayout(vertexShaderDescriptorSetLayout).vulkanHandle }, + { vertexShaderDescriptorSetLayout }, false }; @@ -261,7 +261,7 @@ int main(int argc, const char** argv) { swapchainExtent.height, renderPass, {meshShaderLayout}, - {core.getDescriptorSetLayout(meshShaderDescriptorSetLayout).vulkanHandle}, + {meshShaderDescriptorSetLayout}, false }; @@ -354,7 +354,7 @@ int main(int argc, const char** argv) { if (useMeshShader) { - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(meshShaderDescriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, meshShaderDescriptorSet); const uint32_t taskCount = (meshShaderModelData.meshlets.size() + 31) / 32; core.recordMeshShaderDrawcalls( @@ -368,7 +368,7 @@ int main(int argc, const char** argv) { } else { - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(vertexShaderDescriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, vertexShaderDescriptorSet); core.recordDrawcallsToCmdStream( cmdStream, diff --git a/projects/particle_simulation/CMakeLists.txt b/projects/particle_simulation/CMakeLists.txt index 41ce6ca2f4042285ad42d81e79f04d7b53c837e7..2ff6aaf62c6a9842c3d1b9669286becfd79d92ca 100644 --- a/projects/particle_simulation/CMakeLists.txt +++ b/projects/particle_simulation/CMakeLists.txt @@ -18,15 +18,7 @@ add_executable(particle_simulation src/BloomAndFlares.hpp src/BloomAndFlares.cpp) -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(particle_simulation PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(particle_simulation PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(particle_simulation PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(particle_simulation) # including headers of dependencies and the VkCV framework target_include_directories(particle_simulation SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include}) diff --git a/projects/particle_simulation/src/BloomAndFlares.cpp b/projects/particle_simulation/src/BloomAndFlares.cpp index d0f25122c443eef847ce190c099eef95e8ecc0c8..6ab0a8deff3d5fe906567562cb86d75a1cc2c09b 100644 --- a/projects/particle_simulation/src/BloomAndFlares.cpp +++ b/projects/particle_simulation/src/BloomAndFlares.cpp @@ -38,7 +38,8 @@ BloomAndFlares::BloomAndFlares( } m_DownsamplePipe = p_Core->createComputePipeline({ - dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }}); + dsProg, m_DownsampleDescSetLayouts + }); // UPSAMPLE vkcv::ShaderProgram usProg; @@ -57,7 +58,8 @@ BloomAndFlares::BloomAndFlares( } m_UpsamplePipe = p_Core->createComputePipeline({ - usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }}); + usProg, m_UpsampleDescSetLayouts + }); // LENS FEATURES vkcv::ShaderProgram lensProg; @@ -71,7 +73,8 @@ BloomAndFlares::BloomAndFlares( m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0)); m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout); m_LensFlarePipe = p_Core->createComputePipeline({ - lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle }}); + lensProg, { m_LensFlareDescSetLayout } + }); // COMPOSITE vkcv::ShaderProgram compProg; @@ -85,7 +88,8 @@ BloomAndFlares::BloomAndFlares( m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0)); m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout); m_CompositePipe = p_Core->createComputePipeline({ - compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle }}); + compProg, { m_CompositeDescSetLayout } + }); } void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream, @@ -114,7 +118,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, initialDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[0])}, vkcv::PushConstants(0)); // downsample dispatches of blur buffer's mip maps @@ -149,7 +153,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, mipDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[mipLevel])}, vkcv::PushConstants(0)); // image barrier between mips @@ -194,7 +198,7 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream cmdStream, m_UpsamplePipe, upsampleDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_UpsampleDescSets[mipLevel])}, vkcv::PushConstants(0) ); // image barrier between mips @@ -226,7 +230,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr cmdStream, m_LensFlarePipe, lensFeatureDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_LensFlareDescSet)}, vkcv::PushConstants(0)); } @@ -259,7 +263,7 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea cmdStream, m_CompositePipe, compositeDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_CompositeDescSet)}, vkcv::PushConstants(0)); } diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index ae3c6795a66cdc81297986acb224a63055d02c44..6637041e5ea9c8f1dd3dadf0303049d2a3b749e9 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -121,8 +121,9 @@ int main(int argc, const char **argv) { UINT32_MAX, particlePass, {particleLayout}, - {core.getDescriptorSetLayout(descriptorSetLayout).vulkanHandle}, - true}; + {descriptorSetLayout}, + true + }; particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive; const std::vector<glm::vec3> vertices = {glm::vec3(-0.012, 0.012, 0), @@ -133,7 +134,9 @@ int main(int argc, const char **argv) { vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition); - vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline({ computeShaderProgram, {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} }); + vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline({ + computeShaderProgram, {computeDescriptorSetLayout} + }); vkcv::Buffer<glm::vec4> color = core.createBuffer<glm::vec4>( vkcv::BufferType::UNIFORM, @@ -177,7 +180,7 @@ int main(int argc, const char **argv) { const vkcv::Mesh renderMesh({vertexBufferBindings}, particleIndexBuffer.getVulkanHandle(), particleIndexBuffer.getCount()); - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); auto pos = glm::vec2(0.f); auto spawnPosition = glm::vec3(0.f); @@ -238,7 +241,8 @@ int main(int argc, const char **argv) { vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout); vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({ tonemappingShader, - { core.getDescriptorSetLayout(tonemappingDescriptorLayout).vulkanHandle }}); + { tonemappingDescriptorLayout } + }); std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; @@ -279,7 +283,7 @@ int main(int argc, const char **argv) { core.recordComputeDispatchToCmdStream(cmdStream, computePipeline, computeDispatchCount, - {vkcv::DescriptorSetUsage(0,core.getDescriptorSet(computeDescriptorSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, computeDescriptorSet)}, pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer.getHandle()); @@ -317,7 +321,7 @@ int main(int argc, const char **argv) { cmdStream, tonemappingPipe, tonemappingDispatchCount, - {vkcv::DescriptorSetUsage(0, core.getDescriptorSet(tonemappingDescriptor).vulkanHandle) }, + {vkcv::DescriptorSetUsage(0, tonemappingDescriptor) }, vkcv::PushConstants(0)); core.prepareSwapchainImageForPresent(cmdStream); diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp index c49bb7ed7f2cd65345ef273d0b17273101a92df0..b76244b035d8d24e1abd665b82d09bd413a14a09 100644 --- a/projects/path_tracer/src/main.cpp +++ b/projects/path_tracer/src/main.cpp @@ -104,7 +104,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle imageCombineDescriptorSet = core.createDescriptorSet(imageCombineDescriptorSetLayout); vkcv::ComputePipelineHandle imageCombinePipeline = core.createComputePipeline({ imageCombineShaderProgram, - { core.getDescriptorSetLayout(imageCombineDescriptorSetLayout).vulkanHandle } + { imageCombineDescriptorSetLayout } }); vkcv::DescriptorWrites imageCombineDescriptorWrites; @@ -126,7 +126,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle presentDescriptorSet = core.createDescriptorSet(presentDescriptorSetLayout); vkcv::ComputePipelineHandle presentPipeline = core.createComputePipeline({ presentShaderProgram, - { core.getDescriptorSetLayout(presentDescriptorSetLayout).vulkanHandle } + { presentDescriptorSetLayout } }); // clear shader @@ -141,7 +141,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle imageClearDescriptorSet = core.createDescriptorSet(imageClearDescriptorSetLayout); vkcv::ComputePipelineHandle imageClearPipeline = core.createComputePipeline({ clearShaderProgram, - { core.getDescriptorSetLayout(imageClearDescriptorSetLayout).vulkanHandle } + { imageClearDescriptorSetLayout } }); vkcv::DescriptorWrites imageClearDescriptorWrites; @@ -204,7 +204,7 @@ int main(int argc, const char** argv) { vkcv::ComputePipelineHandle tracePipeline = core.createComputePipeline({ traceShaderProgram, - { core.getDescriptorSetLayout(traceDescriptorSetLayout).vulkanHandle } + { traceDescriptorSetLayout } }); if (!tracePipeline) @@ -343,7 +343,7 @@ int main(int argc, const char** argv) { core.recordComputeDispatchToCmdStream(cmdStream, imageClearPipeline, fullscreenDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(imageClearDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, imageClearDescriptorSet) }, vkcv::PushConstants(0)); clearMeanImage = false; @@ -378,7 +378,7 @@ int main(int argc, const char** argv) { core.recordComputeDispatchToCmdStream(cmdStream, tracePipeline, traceDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(traceDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, traceDescriptorSet) }, pushConstantsCompute); core.prepareImageForStorage(cmdStream, meanImage); @@ -388,7 +388,7 @@ int main(int argc, const char** argv) { core.recordComputeDispatchToCmdStream(cmdStream, imageCombinePipeline, fullscreenDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(imageCombineDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, imageCombineDescriptorSet) }, vkcv::PushConstants(0)); core.recordImageMemoryBarrier(cmdStream, meanImage); @@ -407,7 +407,7 @@ int main(int argc, const char** argv) { core.recordComputeDispatchToCmdStream(cmdStream, presentPipeline, fullscreenDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(presentDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, presentDescriptorSet) }, vkcv::PushConstants(0)); core.prepareSwapchainImageForPresent(cmdStream); diff --git a/projects/rtx_ambient_occlusion/src/RTX/ASManager.cpp b/projects/rtx_ambient_occlusion/src/RTX/ASManager.cpp index 186379a63a5844bf43bdf0e9d1ee7572d8077f52..8e19caaeda878d8b37b24069bbf752bae6dc41d0 100644 --- a/projects/rtx_ambient_occlusion/src/RTX/ASManager.cpp +++ b/projects/rtx_ambient_occlusion/src/RTX/ASManager.cpp @@ -323,7 +323,9 @@ namespace vkcv::rtx { bufferInstances.bufferType = RTXBufferType::GPU; bufferInstances.deviceSize = sizeof(accelerationStructureInstanceKhr); bufferInstances.bufferUsageFlagBits = vk::BufferUsageFlagBits::eShaderDeviceAddress - | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eTransferSrc; + | vk::BufferUsageFlagBits::eTransferDst + | vk::BufferUsageFlagBits::eTransferSrc + | vk::BufferUsageFlagBits::eAccelerationStructureBuildInputReadOnlyKHR; bufferInstances.memoryPropertyFlagBits = vk::MemoryPropertyFlagBits::eDeviceLocal; createBuffer(bufferInstances); diff --git a/projects/rtx_ambient_occlusion/src/RTX/RTXExtensions.cpp b/projects/rtx_ambient_occlusion/src/RTX/RTXExtensions.cpp index 133bd8b888f62a56a35c997d2ea75374fbf203a7..0bc6a4d3dff358bdeab74d9d5da695f81c3675c7 100644 --- a/projects/rtx_ambient_occlusion/src/RTX/RTXExtensions.cpp +++ b/projects/rtx_ambient_occlusion/src/RTX/RTXExtensions.cpp @@ -11,12 +11,8 @@ RTXExtensions::RTXExtensions() }; m_deviceExtensions = { VK_KHR_MAINTENANCE3_EXTENSION_NAME, - VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, - VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, - VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_SPIRV_1_4_EXTENSION_NAME, - VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME }; @@ -24,91 +20,32 @@ RTXExtensions::RTXExtensions() for (auto deviceExtension : m_deviceExtensions) { m_features.requireExtension(deviceExtension); } - - /* FIXME: We must disable features that will be mentioned as "not supported" by the FeatureManager. If every unsupported feature is disabled, this should work. - * Maybe we find a better workaround... - */ - m_features.requireFeature<vk::PhysicalDeviceVulkan12Features>( - [](vk::PhysicalDeviceVulkan12Features& features) { - features.setSamplerMirrorClampToEdge(true); - features.setDrawIndirectCount(true); - features.setStorageBuffer8BitAccess(true); - features.setUniformAndStorageBuffer8BitAccess(true); - features.setStoragePushConstant8(true); - features.setShaderBufferInt64Atomics(true); - features.setShaderSharedInt64Atomics(true); - features.setShaderFloat16(true); - features.setShaderInt8(true); - features.setDescriptorIndexing(true); - features.setShaderInputAttachmentArrayDynamicIndexing(true); - features.setShaderUniformTexelBufferArrayDynamicIndexing(true); - features.setShaderStorageTexelBufferArrayDynamicIndexing(true); - features.setShaderUniformBufferArrayNonUniformIndexing(true); - features.setShaderSampledImageArrayNonUniformIndexing(true); - features.setShaderStorageBufferArrayNonUniformIndexing(true); - features.setShaderStorageImageArrayNonUniformIndexing(true); - features.setShaderInputAttachmentArrayNonUniformIndexing(true); - features.setShaderUniformTexelBufferArrayNonUniformIndexing(true); - features.setShaderStorageTexelBufferArrayNonUniformIndexing(true); - features.setDescriptorBindingUniformBufferUpdateAfterBind(true); - features.setDescriptorBindingSampledImageUpdateAfterBind(true); - features.setDescriptorBindingStorageImageUpdateAfterBind(true); - features.setDescriptorBindingStorageBufferUpdateAfterBind(true); - features.setDescriptorBindingUniformTexelBufferUpdateAfterBind(true); - features.setDescriptorBindingStorageTexelBufferUpdateAfterBind(true); - features.setDescriptorBindingUpdateUnusedWhilePending(true); - features.setDescriptorBindingPartiallyBound(true); - features.setDescriptorBindingVariableDescriptorCount(true); - features.setRuntimeDescriptorArray(true); - features.setSamplerFilterMinmax(true); - features.setScalarBlockLayout(true); - features.setImagelessFramebuffer(true); - features.setUniformBufferStandardLayout(true); - features.setShaderSubgroupExtendedTypes(true); - features.setSeparateDepthStencilLayouts(true); - features.setHostQueryReset(true); - features.setTimelineSemaphore(true); - features.setBufferDeviceAddress(true); - features.setBufferDeviceAddressCaptureReplay(true); - features.setBufferDeviceAddressMultiDevice(true); - features.setVulkanMemoryModel(true); - features.setVulkanMemoryModelDeviceScope(true); - features.setVulkanMemoryModelAvailabilityVisibilityChains(true); - features.setShaderOutputViewportIndex(true); - features.setShaderOutputLayer(true); - features.setSubgroupBroadcastDynamicId(true); - }); - m_features.requireFeature<vk::PhysicalDeviceVulkan11Features>( - [](vk::PhysicalDeviceVulkan11Features& features) { - features.setMultiview(true); - features.setMultiviewGeometryShader(true); - features.setMultiviewTessellationShader(true); - // features.setProtectedMemory(true); // not supported - features.setSamplerYcbcrConversion(true); - features.setShaderDrawParameters(true); - features.setStorageBuffer16BitAccess(true); - // features.setStorageInputOutput16(true); // not supported - features.setStoragePushConstant16(true); - features.setUniformAndStorageBuffer16BitAccess(true); - features.setVariablePointers(true); - features.setVariablePointersStorageBuffer(true); - }); - m_features.requireFeature<vk::PhysicalDeviceAccelerationStructureFeaturesKHR>( - [](vk::PhysicalDeviceAccelerationStructureFeaturesKHR& features) { - features.setAccelerationStructure(true); - features.setAccelerationStructureCaptureReplay(true); - // features.setAccelerationStructureIndirectBuild(true); // not supported - // features.setAccelerationStructureHostCommands(true); // not supported - features.setDescriptorBindingAccelerationStructureUpdateAfterBind(true); - }); + + m_features.requireExtensionFeature<vk::PhysicalDeviceDescriptorIndexingFeatures>( + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, + [](vk::PhysicalDeviceDescriptorIndexingFeatures& features) {} + ); + + m_features.requireExtensionFeature<vk::PhysicalDeviceBufferDeviceAddressFeatures>( + VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, + [](vk::PhysicalDeviceBufferDeviceAddressFeatures& features) { + features.setBufferDeviceAddress(true); + } + ); + + m_features.requireExtensionFeature<vk::PhysicalDeviceAccelerationStructureFeaturesKHR>( + VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, + [](vk::PhysicalDeviceAccelerationStructureFeaturesKHR& features) { + features.setAccelerationStructure(true); + } + ); + m_features.requireExtensionFeature<vk::PhysicalDeviceRayTracingPipelineFeaturesKHR>( - VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, [](vk::PhysicalDeviceRayTracingPipelineFeaturesKHR& features) { - features.setRayTracingPipeline(true); - // features.setRayTracingPipelineShaderGroupHandleCaptureReplay(true); // not supported - // features.setRayTracingPipelineShaderGroupHandleCaptureReplayMixed(true); // not supported - features.setRayTracingPipelineTraceRaysIndirect(true); - features.setRayTraversalPrimitiveCulling(true); - }); + VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, + [](vk::PhysicalDeviceRayTracingPipelineFeaturesKHR& features) { + features.setRayTracingPipeline(true); + } + ); } std::vector<const char*> RTXExtensions::getInstanceExtensions() diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp index bac1fe367031e43cf2fc53d4be23c208f4fb682d..d4c8ec2cac8e26f70da346738da04de16a766a26 100644 --- a/projects/rtx_ambient_occlusion/src/main.cpp +++ b/projects/rtx_ambient_occlusion/src/main.cpp @@ -148,7 +148,7 @@ int main(int argc, const char** argv) { rtxRegions.rmissRegion, rtxRegions.rchitRegion, rtxRegions.rcallRegion, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(rtxShaderDescriptorSet).vulkanHandle)}, + { vkcv::DescriptorSetUsage(0, rtxShaderDescriptorSet)}, pushConstantsRTX, windowHandle); diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp index c206fbffed7c9f5295fa0d5387ec5bfc9185d34a..ea5378406b092a92a1f8ee8149630f72059ca391 100644 --- a/projects/saf_r/src/main.cpp +++ b/projects/saf_r/src/main.cpp @@ -175,7 +175,7 @@ int main(int argc, const char** argv) { (uint32_t)windowHeight, safrPass, {}, - { core.getDescriptorSetLayout(descriptorSetLayout).vulkanHandle }, + { descriptorSetLayout }, false }; @@ -183,7 +183,7 @@ int main(int argc, const char** argv) { const vkcv::ComputePipelineConfig computePipelineConfig{ computeShaderProgram, - {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} + {computeDescriptorSetLayout} }; vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline(computePipelineConfig); @@ -197,7 +197,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); const vkcv::Mesh renderMesh({}, safrIndexBuffer.getVulkanHandle(), 3); - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage }, 1); //create the camera @@ -279,7 +279,7 @@ int main(int argc, const char** argv) { core.recordComputeDispatchToCmdStream(cmdStream, computePipeline, computeDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(computeDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, computeDescriptorSet) }, pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, lightsBuffer.getHandle()); diff --git a/projects/sph/shaders/force.comp b/projects/sph/shaders/force.comp index ea9b378b48a23fd0208ab18d884dbccda5ab21f4..694ddbdf7009d4e493a5f8dd8ba462e42d1e8b68 100644 --- a/projects/sph/shaders/force.comp +++ b/projects/sph/shaders/force.comp @@ -40,56 +40,113 @@ layout( push_constant ) uniform constants{ float particleCount; }; -float spiky(float r) -{ - return (15.f / (PI * pow(h, 6)) * pow((h-r), 3)) * int(0<=r && r<=h); -} - float grad_spiky(float r) { - return -45.f / (PI * pow(h, 6)) * pow((h-r), 2) * int(0<=r && r<=h); + return -45.f / (PI * pow(h, 6)) * pow((h-r), 2); } - - float laplacian(float r) { - return (45.f / (PI * pow(h,6)) * (h - r)) * int(0<=r && r<=h); + return (45.f / (PI * pow(h,6)) * (h - r)); } vec3 pressureForce = vec3(0, 0, 0); vec3 viscosityForce = vec3(0, 0, 0); vec3 externalForce = vec3(0, 0, 0); -void main() { +struct ParticleData +{ + vec3 position; + float density; + vec3 velocity; + float pressure; +}; + +shared ParticleData particle_data [256]; +void main() { uint id = gl_GlobalInvocationID.x; - if(id >= int(particleCount)) - { - return; + if (id >= int(particleCount)) { + particle_data[gl_LocalInvocationIndex].position = vec3(0.0f); + particle_data[gl_LocalInvocationIndex].density = 0.0f; + particle_data[gl_LocalInvocationIndex].velocity = vec3(0.0f); + particle_data[gl_LocalInvocationIndex].pressure = 0.0f; + } else { + particle_data[gl_LocalInvocationIndex].position = inParticle[id].position; + particle_data[gl_LocalInvocationIndex].density = inParticle[id].density; + particle_data[gl_LocalInvocationIndex].velocity = inParticle[id].velocity; + particle_data[gl_LocalInvocationIndex].pressure = inParticle[id].pressure; + } + + uint index_offset = gl_WorkGroupID.x * gl_WorkGroupSize.x; + uint group_size = min(index_offset + gl_WorkGroupSize.x, int(particleCount)) - index_offset; + + memoryBarrierShared(); + barrier(); + + const float h6 = pow(h, 6); + externalForce = particle_data[gl_LocalInvocationIndex].density * gravity * vec3(-gravityDir.x,gravityDir.y,gravityDir.z); + + for(uint j = 1; j < group_size; j++) { + uint i = (gl_LocalInvocationIndex + j) % group_size; + + vec3 dir = particle_data[gl_LocalInvocationIndex].position - particle_data[i].position; + float dist = length(dir); + + if ((dist > 0.0f) && (dist <= h)) + { + const float h_dist = (h - dist); + + float laplacian = 45.f / (PI * h6) * h_dist; + float grad_spiky = -1.0f * laplacian * h_dist; + + pressureForce += mass * -(particle_data[gl_LocalInvocationIndex].pressure + particle_data[i].pressure)/(2.f * particle_data[i].density) * grad_spiky * normalize(dir); + viscosityForce += mass * (particle_data[i].velocity - particle_data[gl_LocalInvocationIndex].velocity)/particle_data[i].density * laplacian; + } } - externalForce = inParticle[id].density * gravity * vec3(-gravityDir.x,gravityDir.y,gravityDir.z); + for(uint i = 0; i < index_offset; i++) + { + vec3 dir = particle_data[gl_LocalInvocationIndex].position - inParticle[i].position; + float dist = length(dir); + + if ((dist > 0.0f) && (dist <= h)) + { + const float h_dist = (h - dist); - for(uint i = 0; i < int(particleCount); i++) + float laplacian = 45.f / (PI * h6) * h_dist; + float grad_spiky = -1.0f * laplacian * h_dist; + + pressureForce += mass * -(particle_data[gl_LocalInvocationIndex].pressure + inParticle[i].pressure)/(2.f * inParticle[i].density) * grad_spiky * normalize(dir); + viscosityForce += mass * (inParticle[i].velocity - particle_data[gl_LocalInvocationIndex].velocity)/inParticle[i].density * laplacian; + } + } + + for(uint i = index_offset + group_size; i < int(particleCount); i++) { - if (id != i) + vec3 dir = particle_data[gl_LocalInvocationIndex].position - inParticle[i].position; + float dist = length(dir); + + if ((dist > 0.0f) && (dist <= h)) { - vec3 dir = inParticle[id].position - inParticle[i].position; - float dist = length(dir); - if(dist != 0) - { - pressureForce += mass * -(inParticle[id].pressure + inParticle[i].pressure)/(2.f * inParticle[i].density) * grad_spiky(dist) * normalize(dir); - viscosityForce += mass * (inParticle[i].velocity - inParticle[id].velocity)/inParticle[i].density * laplacian(dist); - } + const float h_dist = (h - dist); + + float laplacian = 45.f / (PI * h6) * h_dist; + float grad_spiky = -1.0f * laplacian * h_dist; + + pressureForce += mass * -(particle_data[gl_LocalInvocationIndex].pressure + inParticle[i].pressure)/(2.f * inParticle[i].density) * grad_spiky * normalize(dir); + viscosityForce += mass * (inParticle[i].velocity - particle_data[gl_LocalInvocationIndex].velocity)/inParticle[i].density * laplacian; } } + viscosityForce *= viscosity; - outParticle[id].force = externalForce + pressureForce + viscosityForce; - outParticle[id].density = inParticle[id].density; - outParticle[id].pressure = inParticle[id].pressure; - outParticle[id].position = inParticle[id].position; - outParticle[id].velocity = inParticle[id].velocity; + if (id < int(particleCount)) { + outParticle[id].force = externalForce + pressureForce + viscosityForce; + outParticle[id].density = particle_data[gl_LocalInvocationIndex].density; + outParticle[id].pressure = particle_data[gl_LocalInvocationIndex].pressure; + outParticle[id].position = particle_data[gl_LocalInvocationIndex].position; + outParticle[id].velocity = particle_data[gl_LocalInvocationIndex].velocity; + } } diff --git a/projects/sph/shaders/pressure.comp b/projects/sph/shaders/pressure.comp index 05b3af3afb490b427cc1297f21a82a779d4c8ecb..8fa2e4762bddb3b9b28d8a3c184ceaaf7ab4421c 100644 --- a/projects/sph/shaders/pressure.comp +++ b/projects/sph/shaders/pressure.comp @@ -42,31 +42,53 @@ layout( push_constant ) uniform constants{ float poly6(float r) { - return (315.f * pow((pow(h,2)-pow(r,2)), 3)/(64.f*PI*pow(h, 9))) * int(0<=r && r<=h); + return (315.f * pow((pow(h,2)-pow(r,2)), 3)/(64.f*PI*pow(h, 9))) * int(r<=h); } float densitySum = 0.f; +shared vec3 position_data [256]; + void main() { uint id = gl_GlobalInvocationID.x; - if(id >= int(particleCount)) + if (id >= int(particleCount)) { + position_data[gl_LocalInvocationIndex] = vec3(0.0f); + } else { + position_data[gl_LocalInvocationIndex] = inParticle[id].position; + } + + uint index_offset = gl_WorkGroupID.x * gl_WorkGroupSize.x; + uint group_size = min(index_offset + gl_WorkGroupSize.x, int(particleCount)) - index_offset; + + memoryBarrierShared(); + barrier(); + + for(uint j = 1; j < group_size; j++) { + uint i = (gl_LocalInvocationIndex + j) % group_size; + + float dist = distance(position_data[gl_LocalInvocationIndex], position_data[i]); + densitySum += mass * poly6(dist); + } + + for(uint i = 0; i < index_offset; i++) { - return; + float dist = distance(position_data[gl_LocalInvocationIndex], inParticle[i].position); + densitySum += mass * poly6(dist); } - for(uint i = 0; i < int(particleCount); i++) + for(uint i = index_offset + group_size; i < int(particleCount); i++) { - if (id != i) - { - float dist = distance(inParticle[id].position, inParticle[i].position); - densitySum += mass * poly6(dist); - } + float dist = distance(position_data[gl_LocalInvocationIndex], inParticle[i].position); + densitySum += mass * poly6(dist); + } + + if (id < int(particleCount)) { + outParticle[id].density = max(densitySum, 0.0000001f); + outParticle[id].pressure = max((densitySum - offset), 0.0000001f) * gasConstant; + outParticle[id].position = position_data[gl_LocalInvocationIndex]; + outParticle[id].velocity = inParticle[id].velocity; + outParticle[id].force = inParticle[id].force; } - outParticle[id].density = max(densitySum,0.0000001f); - outParticle[id].pressure = max((densitySum - offset), 0.0000001f) * gasConstant; - outParticle[id].position = inParticle[id].position; - outParticle[id].velocity = inParticle[id].velocity; - outParticle[id].force = inParticle[id].force; } diff --git a/projects/sph/src/BloomAndFlares.cpp b/projects/sph/src/BloomAndFlares.cpp index 09534815afcd8ab238b79da5c6bbceb6672b043a..200c0dea16a0b1483a8b20786902b38a43b5f825 100644 --- a/projects/sph/src/BloomAndFlares.cpp +++ b/projects/sph/src/BloomAndFlares.cpp @@ -37,7 +37,8 @@ BloomAndFlares::BloomAndFlares( p_Core->createDescriptorSet(m_DownsampleDescSetLayouts.back())); } m_DownsamplePipe = p_Core->createComputePipeline({ - dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle } }); + dsProg, m_DownsampleDescSetLayouts + }); // UPSAMPLE vkcv::ShaderProgram usProg; @@ -55,7 +56,8 @@ BloomAndFlares::BloomAndFlares( p_Core->createDescriptorSet(m_UpsampleDescSetLayouts.back())); } m_UpsamplePipe = p_Core->createComputePipeline({ - usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle } }); + usProg, m_UpsampleDescSetLayouts + }); // LENS FEATURES vkcv::ShaderProgram lensProg; @@ -68,7 +70,8 @@ BloomAndFlares::BloomAndFlares( m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0)); m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout); m_LensFlarePipe = p_Core->createComputePipeline({ - lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle } }); + lensProg, { m_LensFlareDescSetLayout } + }); // COMPOSITE vkcv::ShaderProgram compProg; @@ -81,7 +84,8 @@ BloomAndFlares::BloomAndFlares( m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0)); m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout); m_CompositePipe = p_Core->createComputePipeline({ - compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle } }); + compProg, { m_CompositeDescSetLayout } + }); } void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream, @@ -110,7 +114,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, initialDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[0])}, vkcv::PushConstants(0)); // downsample dispatches of blur buffer's mip maps @@ -145,7 +149,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, mipDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[mipLevel])}, vkcv::PushConstants(0)); // image barrier between mips @@ -190,7 +194,7 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream cmdStream, m_UpsamplePipe, upsampleDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_UpsampleDescSets[mipLevel])}, vkcv::PushConstants(0) ); // image barrier between mips @@ -222,7 +226,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr cmdStream, m_LensFlarePipe, lensFeatureDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_LensFlareDescSet)}, vkcv::PushConstants(0)); } @@ -255,7 +259,7 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea cmdStream, m_CompositePipe, compositeDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_CompositeDescSet)}, vkcv::PushConstants(0)); } diff --git a/projects/sph/src/PipelineInit.cpp b/projects/sph/src/PipelineInit.cpp index 6cf941fa0d8f8716b7d05daf9b6fb618b0fa7d85..052c983cb094114853d19dac3e76149db99116db 100644 --- a/projects/sph/src/PipelineInit.cpp +++ b/projects/sph/src/PipelineInit.cpp @@ -21,7 +21,8 @@ vkcv::DescriptorSetHandle PipelineInit::ComputePipelineInit(vkcv::Core *pCore, v pipeline = pCore->createComputePipeline({ shaderProgram, - { pCore->getDescriptorSetLayout(descriptorSetLayout).vulkanHandle } }); + { descriptorSetLayout } + }); return descriptorSet; } \ No newline at end of file diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp index 738d7699b4bcfa34ce70ca19864a3eb9724c7e27..c3305fdd335115ef108ca87a8065da3f5302e7a0 100644 --- a/projects/sph/src/main.cpp +++ b/projects/sph/src/main.cpp @@ -122,8 +122,9 @@ int main(int argc, const char **argv) { UINT32_MAX, particlePass, {particleLayout}, - {core.getDescriptorSetLayout(descriptorSetLayout).vulkanHandle}, - true}; + {descriptorSetLayout}, + true + }; particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive; const std::vector<glm::vec3> vertices = {glm::vec3(-0.012, 0.012, 0), @@ -206,7 +207,7 @@ int main(int argc, const char **argv) { const vkcv::Mesh renderMesh({vertexBufferBindings}, particleIndexBuffer.getVulkanHandle(), particleIndexBuffer.getCount()); - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); auto pos = glm::vec2(0.f); @@ -332,7 +333,7 @@ int main(int argc, const char **argv) { core.recordComputeDispatchToCmdStream(cmdStream, pressurePipeline, computeDispatchCount, - {vkcv::DescriptorSetUsage(0,core.getDescriptorSet(pressureDescriptorSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, pressureDescriptorSet)}, pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle()); @@ -340,10 +341,10 @@ int main(int argc, const char **argv) { // computing force pipeline core.recordComputeDispatchToCmdStream(cmdStream, - forcePipeline, - computeDispatchCount, - {vkcv::DescriptorSetUsage(0,core.getDescriptorSet(forceDescriptorSet).vulkanHandle)}, - pushConstantsCompute); + forcePipeline, + computeDispatchCount, + {vkcv::DescriptorSetUsage(0, forceDescriptorSet)}, + pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle()); core.recordBufferMemoryBarrier(cmdStream, particleBuffer2.getHandle()); @@ -352,7 +353,7 @@ int main(int argc, const char **argv) { core.recordComputeDispatchToCmdStream(cmdStream, updateDataPipeline, computeDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(updateDataDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, updateDataDescriptorSet) }, pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle()); @@ -362,7 +363,7 @@ int main(int argc, const char **argv) { core.recordComputeDispatchToCmdStream(cmdStream, flipPipeline, computeDispatchCount, - { vkcv::DescriptorSetUsage(0,core.getDescriptorSet(flipDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, flipDescriptorSet) }, pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle()); @@ -403,7 +404,7 @@ int main(int argc, const char **argv) { cmdStream, tonemappingPipe, tonemappingDispatchCount, - {vkcv::DescriptorSetUsage(0, core.getDescriptorSet(tonemappingDescriptor).vulkanHandle) }, + {vkcv::DescriptorSetUsage(0, tonemappingDescriptor) }, vkcv::PushConstants(0)); core.prepareSwapchainImageForPresent(cmdStream); diff --git a/projects/voxelization/CMakeLists.txt b/projects/voxelization/CMakeLists.txt index 9597f9493b91ef48a5932fb22da7dce791dc450c..ba3c467766377d22925ac9c90acffee7fe324332 100644 --- a/projects/voxelization/CMakeLists.txt +++ b/projects/voxelization/CMakeLists.txt @@ -19,15 +19,7 @@ target_sources(voxelization PRIVATE src/BloomAndFlares.hpp src/BloomAndFlares.cpp) -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(voxelization PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(voxelization PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(voxelization PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() +fix_project(voxelization) # including headers of dependencies and the VkCV framework target_include_directories(voxelization SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include} ${vkcv_upscaling_include}) diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp index 2014d7a0219141ec6363b38a5311cb924b6b6a45..ddb1326ae83c8bd596ce61dc1c47b81b5ddb17be 100644 --- a/projects/voxelization/src/BloomAndFlares.cpp +++ b/projects/voxelization/src/BloomAndFlares.cpp @@ -51,7 +51,7 @@ BloomAndFlares::BloomAndFlares( } m_DownsamplePipe = p_Core->createComputePipeline({ - dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle } + dsProg, m_DownsampleDescSetLayouts }); // UPSAMPLE @@ -77,7 +77,7 @@ BloomAndFlares::BloomAndFlares( } m_UpsamplePipe = p_Core->createComputePipeline({ - usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle } + usProg, m_UpsampleDescSetLayouts }); // LENS FEATURES @@ -92,7 +92,8 @@ BloomAndFlares::BloomAndFlares( m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0)); m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout); m_LensFlarePipe = p_Core->createComputePipeline( - { lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle } }); + { lensProg, { m_LensFlareDescSetLayout } + }); // COMPOSITE @@ -107,7 +108,8 @@ BloomAndFlares::BloomAndFlares( m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0)); m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout); m_CompositePipe = p_Core->createComputePipeline( - { compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle } }); + { compProg, { m_CompositeDescSetLayout } + }); // radial LUT const auto texture = vkcv::asset::loadTexture("assets/RadialLUT.png"); @@ -143,7 +145,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, initialDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[0])}, vkcv::PushConstants(0)); // downsample dispatches of blur buffer's mip maps @@ -178,7 +180,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre cmdStream, m_DownsamplePipe, mipDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_DownsampleDescSets[mipLevel])}, vkcv::PushConstants(0)); // image barrier between mips @@ -227,7 +229,7 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream cmdStream, m_UpsamplePipe, upsampleDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_UpsampleDescSets[mipLevel])}, vkcv::PushConstants(0) ); // image barrier between mips @@ -266,7 +268,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr cmdStream, m_LensFlarePipe, lensFeatureDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_LensFlareDescSet)}, vkcv::PushConstants(0)); // upsample dispatch @@ -299,7 +301,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr cmdStream, m_UpsamplePipe, upsampleDispatchCount, - { vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleLensFlareDescSets[i]).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_UpsampleLensFlareDescSets[i]) }, vkcv::PushConstants(0) ); // image barrier between mips @@ -346,7 +348,7 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea cmdStream, m_CompositePipe, compositeDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, + {vkcv::DescriptorSetUsage(0, m_CompositeDescSet)}, pushConstants); p_Core->recordEndDebugLabel(cmdStream); diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index ce4261ff2403139d10b9d677e7aa216a3e41178f..5ae7eb6047200b2cdb7a3ac38ce8512cdcaa3d53 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -192,7 +192,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert m_depthToMomentsDescriptorSetLayout = corePtr->createDescriptorSetLayout(depthToMomentsShader.getReflectedDescriptors().at(0)); m_depthToMomentsDescriptorSet = corePtr->createDescriptorSet(m_depthToMomentsDescriptorSetLayout); - m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { corePtr->getDescriptorSetLayout(m_depthToMomentsDescriptorSetLayout).vulkanHandle }}); + m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { m_depthToMomentsDescriptorSetLayout }}); vkcv::DescriptorWrites depthToMomentDescriptorWrites; depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) }; @@ -204,7 +204,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::ShaderProgram shadowBlurXShader = loadShadowBlurXShader(); m_shadowBlurXDescriptorSetLayout = corePtr->createDescriptorSetLayout(shadowBlurXShader.getReflectedDescriptors().at(0)); m_shadowBlurXDescriptorSet = corePtr->createDescriptorSet(m_shadowBlurXDescriptorSetLayout); - m_shadowBlurXPipe = corePtr->createComputePipeline({ shadowBlurXShader, { corePtr->getDescriptorSetLayout(m_shadowBlurXDescriptorSetLayout).vulkanHandle }}); + m_shadowBlurXPipe = corePtr->createComputePipeline({ shadowBlurXShader, { m_shadowBlurXDescriptorSetLayout }}); vkcv::DescriptorWrites shadowBlurXDescriptorWrites; shadowBlurXDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) }; @@ -216,7 +216,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::ShaderProgram shadowBlurYShader = loadShadowBlurYShader(); m_shadowBlurYDescriptorSetLayout = corePtr->createDescriptorSetLayout(shadowBlurYShader.getReflectedDescriptors().at(0)); m_shadowBlurYDescriptorSet = corePtr->createDescriptorSet(m_shadowBlurYDescriptorSetLayout); - m_shadowBlurYPipe = corePtr->createComputePipeline({ shadowBlurYShader, { corePtr->getDescriptorSetLayout(m_shadowBlurYDescriptorSetLayout).vulkanHandle }}); + m_shadowBlurYPipe = corePtr->createComputePipeline({ shadowBlurYShader, { m_shadowBlurYDescriptorSetLayout }}); vkcv::DescriptorWrites shadowBlurYDescriptorWrites; shadowBlurYDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) }; @@ -296,7 +296,7 @@ void ShadowMapping::recordShadowMapRendering( cmdStream, m_depthToMomentsPipe, dispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_depthToMomentsDescriptorSet) }, msaaPushConstants); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); m_corePtr->recordEndDebugLabel(cmdStream); @@ -309,7 +309,7 @@ void ShadowMapping::recordShadowMapRendering( cmdStream, m_shadowBlurXPipe, dispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurXDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_shadowBlurXDescriptorSet) }, vkcv::PushConstants(0)); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapIntermediate.getHandle()); @@ -319,7 +319,7 @@ void ShadowMapping::recordShadowMapRendering( cmdStream, m_shadowBlurYPipe, dispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurYDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_shadowBlurYDescriptorSet) }, vkcv::PushConstants(0)); m_shadowMap.recordMipChainGeneration(cmdStream); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index c023af21c673651984e945ab03d16280c18f0768..faa03d38127d5a23c931fdef0470c1e24131d206 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -110,11 +110,10 @@ Voxelization::Voxelization( voxelResolution, m_voxelizationPass, dependencies.vertexLayout, - { - m_corePtr->getDescriptorSetLayout(m_voxelizationDescriptorSetLayout).vulkanHandle, - m_corePtr->getDescriptorSetLayout(dummyPerMeshDescriptorSetLayout).vulkanHandle}, + { m_voxelizationDescriptorSetLayout, dummyPerMeshDescriptorSetLayout }, false, - true }; + true + }; m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig); vkcv::DescriptorWrites voxelizationDescriptorWrites; @@ -156,10 +155,11 @@ Voxelization::Voxelization( 0, m_visualisationPass, {}, - { m_corePtr->getDescriptorSetLayout(m_visualisationDescriptorSetLayout).vulkanHandle }, + { m_visualisationDescriptorSetLayout }, true, false, - vkcv::PrimitiveTopology::PointList }; // points are extended to cubes in the geometry shader + vkcv::PrimitiveTopology::PointList + }; // points are extended to cubes in the geometry shader voxelVisualisationPipeConfig.m_multisampling = msaa; m_visualisationPipe = m_corePtr->createGraphicsPipeline(voxelVisualisationPipeConfig); @@ -168,7 +168,7 @@ Voxelization::Voxelization( voxelIndexData.push_back(static_cast<uint16_t>(i)); } - const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle); + const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_visualisationDescriptorSet); vkcv::ShaderProgram resetVoxelShader = loadVoxelResetShader(); @@ -176,7 +176,8 @@ Voxelization::Voxelization( m_voxelResetDescriptorSet = m_corePtr->createDescriptorSet(m_voxelResetDescriptorSetLayout); m_voxelResetPipe = m_corePtr->createComputePipeline({ resetVoxelShader, - { m_corePtr->getDescriptorSetLayout(m_voxelResetDescriptorSetLayout).vulkanHandle }}); + { m_voxelResetDescriptorSetLayout } + }); vkcv::DescriptorWrites resetVoxelWrites; resetVoxelWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; @@ -189,7 +190,8 @@ Voxelization::Voxelization( m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(m_bufferToImageDescriptorSetLayout); m_bufferToImagePipe = m_corePtr->createComputePipeline({ bufferToImageShader, - { m_corePtr->getDescriptorSetLayout(m_bufferToImageDescriptorSetLayout).vulkanHandle }}); + { m_bufferToImageDescriptorSetLayout } + }); vkcv::DescriptorWrites bufferToImageDescriptorWrites; bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; @@ -203,7 +205,8 @@ Voxelization::Voxelization( m_secondaryBounceDescriptorSet = m_corePtr->createDescriptorSet(m_secondaryBounceDescriptorSetLayout); m_secondaryBouncePipe = m_corePtr->createComputePipeline({ secondaryBounceShader, - { m_corePtr->getDescriptorSetLayout(m_secondaryBounceDescriptorSetLayout).vulkanHandle }}); + { m_secondaryBounceDescriptorSetLayout } + }); vkcv::DescriptorWrites secondaryBounceDescriptorWrites; secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; @@ -256,7 +259,7 @@ void Voxelization::voxelizeMeshes( cmdStream, m_voxelResetPipe, resetVoxelDispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_voxelResetDescriptorSet) }, voxelCountPushConstants); m_corePtr->recordBufferMemoryBarrier(cmdStream, m_voxelBuffer.getHandle()); m_corePtr->recordEndDebugLabel(cmdStream); @@ -267,8 +270,8 @@ void Voxelization::voxelizeMeshes( drawcalls.push_back(vkcv::DrawcallInfo( meshes[i], { - vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle), - vkcv::DescriptorSetUsage(1, m_corePtr->getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) + vkcv::DescriptorSetUsage(0, m_voxelizationDescriptorSet), + vkcv::DescriptorSetUsage(1, perMeshDescriptorSets[i]) },1)); } @@ -296,7 +299,7 @@ void Voxelization::voxelizeMeshes( cmdStream, m_bufferToImagePipe, bufferToImageDispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_bufferToImageDescriptorSet) }, vkcv::PushConstants(0)); m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImageIntermediate.getHandle()); @@ -315,7 +318,7 @@ void Voxelization::voxelizeMeshes( cmdStream, m_secondaryBouncePipe, bufferToImageDispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_secondaryBounceDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_secondaryBounceDescriptorSet) }, vkcv::PushConstants(0)); m_voxelImage.recordMipChainGeneration(cmdStream); m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); @@ -352,7 +355,7 @@ void Voxelization::renderVoxelVisualisation( const auto drawcall = vkcv::DrawcallInfo( vkcv::Mesh({}, nullptr, drawVoxelCount), - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle) },1); + { vkcv::DescriptorSetUsage(0, m_visualisationDescriptorSet) },1); m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel visualisation", { 1, 1, 1, 1 }); m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle()); diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index a4ffb668e74d0a0829bb3c436ed5b992695b6ecf..2245419f87d196e913ba27e8e78ffff73aab04b6 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -317,10 +317,9 @@ int main(int argc, const char** argv) { swapchainExtent.height, prepassPass, vertexLayout, - { - core.getDescriptorSetLayout(prepassDescriptorSetLayout).vulkanHandle, - core.getDescriptorSetLayout(perMeshDescriptorSetLayouts[0]).vulkanHandle }, - true }; + { prepassDescriptorSetLayout, perMeshDescriptorSetLayouts[0] }, + true + }; prepassPipelineConfig.m_culling = vkcv::CullMode::Back; prepassPipelineConfig.m_multisampling = msaa; prepassPipelineConfig.m_depthTest = vkcv::DepthTest::LessEqual; @@ -335,9 +334,7 @@ int main(int argc, const char** argv) { swapchainExtent.height, forwardPass, vertexLayout, - { - core.getDescriptorSetLayout(forwardShadingDescriptorSetLayout).vulkanHandle, - core.getDescriptorSetLayout(perMeshDescriptorSetLayouts[0]).vulkanHandle }, + { forwardShadingDescriptorSetLayout, perMeshDescriptorSetLayouts[0] }, true }; forwardPipelineConfig.m_culling = vkcv::CullMode::Back; @@ -468,7 +465,8 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle tonemappingDescriptorSet = core.createDescriptorSet(tonemappingDescriptorSetLayout); vkcv::ComputePipelineHandle tonemappingPipeline = core.createComputePipeline({ tonemappingProgram, - { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }}); + { tonemappingDescriptorSetLayout } + }); // tonemapping compute shader vkcv::ShaderProgram postEffectsProgram; @@ -482,7 +480,8 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle postEffectsDescriptorSet = core.createDescriptorSet(postEffectsDescriptorSetLayout); vkcv::ComputePipelineHandle postEffectsPipeline = core.createComputePipeline({ postEffectsProgram, - { core.getDescriptorSetLayout(postEffectsDescriptorSetLayout).vulkanHandle }}); + { postEffectsDescriptorSetLayout } + }); // resolve compute shader vkcv::ShaderProgram resolveProgram; @@ -496,7 +495,8 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle resolveDescriptorSet = core.createDescriptorSet(resolveDescriptorSetLayout); vkcv::ComputePipelineHandle resolvePipeline = core.createComputePipeline({ resolveProgram, - { core.getDescriptorSetLayout(resolveDescriptorSetLayout).vulkanHandle }}); + { resolveDescriptorSetLayout } + }); vkcv::SamplerHandle resolveSampler = core.createSampler( vkcv::SamplerFilterType::NEAREST, @@ -527,11 +527,11 @@ int main(int argc, const char** argv) { for (size_t i = 0; i < meshes.size(); i++) { drawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { - vkcv::DescriptorSetUsage(0, core.getDescriptorSet(forwardShadingDescriptorSet).vulkanHandle), - vkcv::DescriptorSetUsage(1, core.getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) })); + vkcv::DescriptorSetUsage(0, forwardShadingDescriptorSet), + vkcv::DescriptorSetUsage(1, perMeshDescriptorSets[i]) })); prepassDrawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { - vkcv::DescriptorSetUsage(0, core.getDescriptorSet(prepassDescriptorSet).vulkanHandle), - vkcv::DescriptorSetUsage(1, core.getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) })); + vkcv::DescriptorSetUsage(0, prepassDescriptorSet), + vkcv::DescriptorSetUsage(1, perMeshDescriptorSets[i]) })); } vkcv::SamplerHandle voxelSampler = core.createSampler( @@ -859,7 +859,7 @@ int main(int argc, const char** argv) { cmdStream, resolvePipeline, fulsscreenDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(resolveDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, resolveDescriptorSet) }, vkcv::PushConstants(0)); core.recordImageMemoryBarrier(cmdStream, resolvedColorBuffer); @@ -882,9 +882,7 @@ int main(int argc, const char** argv) { cmdStream, tonemappingPipeline, fulsscreenDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet( - tonemappingDescriptorSet - ).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, tonemappingDescriptorSet) }, vkcv::PushConstants(0) ); @@ -920,9 +918,7 @@ int main(int argc, const char** argv) { cmdStream, postEffectsPipeline, fulsscreenDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet( - postEffectsDescriptorSet - ).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, postEffectsDescriptorSet) }, timePushConstants ); core.recordEndDebugLabel(cmdStream); @@ -1001,7 +997,8 @@ int main(int argc, const char** argv) { vkcv::ComputePipelineHandle newPipeline = core.createComputePipeline({ newProgram, - { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }}); + { tonemappingDescriptorSetLayout } + }); if (newPipeline) { tonemappingPipeline = newPipeline; diff --git a/projects/wobble_bobble/.gitignore b/projects/wobble_bobble/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7ed07ed409373206a95d74e6dbdc27a4cb391fea --- /dev/null +++ b/projects/wobble_bobble/.gitignore @@ -0,0 +1 @@ +wobble_bobble diff --git a/projects/wobble_bobble/CMakeLists.txt b/projects/wobble_bobble/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9842b13b1038d61414de5c2cf2a9107604b6fe16 --- /dev/null +++ b/projects/wobble_bobble/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.16) +project(wobble_bobble) + +# setting c++ standard for the project +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# this should fix the execution path to load local files from the project +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +# adding source files to the project +add_executable(wobble_bobble + src/main.cpp) + +fix_project(wobble_bobble) + +# including headers of dependencies and the VkCV framework +target_include_directories(wobble_bobble SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_camera_include} ${vkcv_gui_include} ${vkcv_shader_compiler_include}) + +# linking with libraries from all dependencies and the VkCV framework +target_link_libraries(wobble_bobble vkcv vkcv_camera vkcv_gui vkcv_shader_compiler) diff --git a/projects/wobble_bobble/shaders/.gitignore b/projects/wobble_bobble/shaders/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/projects/wobble_bobble/shaders/grid.frag b/projects/wobble_bobble/shaders/grid.frag new file mode 100644 index 0000000000000000000000000000000000000000..8eb2fbc2173bbddb5bdc44c52ce81d2e5d52d389 --- /dev/null +++ b/projects/wobble_bobble/shaders/grid.frag @@ -0,0 +1,30 @@ +#version 450 + +layout(location = 0) in vec2 passPos; +layout(location = 1) in vec3 passVelocity; +layout(location = 2) in float passMass; + +layout(location = 0) out vec3 outColor; + +void main() { + if (passMass <= 0.0f) { + discard; + } + + const float value = length(passPos); + + float z = sqrt(0.25 - value * value); + + if (value < 0.5f) { + vec3 surface = vec3(passPos.x + 0.5f, passPos.y + 0.5f, z * 2.0f); + vec3 velocity = vec3(0.5f); + + if (length(passVelocity) > 0.0f) { + velocity = vec3(0.5f) + 0.5f * normalize(passVelocity.xyz); + } + + outColor = velocity; + } else { + discard; + } +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/grid.vert b/projects/wobble_bobble/shaders/grid.vert new file mode 100644 index 0000000000000000000000000000000000000000..54de3f3e1da43e3ea3d018e5c54003b83e055c4c --- /dev/null +++ b/projects/wobble_bobble/shaders/grid.vert @@ -0,0 +1,58 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "particle.inc" + +layout(set=0, binding=0) uniform texture3D gridImage; +layout(set=0, binding=1) uniform sampler gridSampler; + +layout(set=0, binding=2) uniform simulationBlock { + Simulation simulation; +}; + +layout(location = 0) in vec2 vertexPos; + +layout(location = 0) out vec2 passPos; +layout(location = 1) out vec3 passVelocity; +layout(location = 2) out float passMass; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +ivec3 actual_mod(ivec3 x, ivec3 y) { + return x - y * (x/y); +} + +void main() { + ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0); + + ivec3 gridID = ivec3( + gl_InstanceIndex, + gl_InstanceIndex / gridResolution.x, + gl_InstanceIndex / gridResolution.x / gridResolution.y + ); + + gridID = actual_mod(gridID, gridResolution); + + vec3 position = (vec3(gridID) + vec3(0.5f)) / gridResolution; + + vec3 size = vec3(1.0f) / vec3(gridResolution); + float volume = size.x * size.y * size.z; + float radius = cube_radius(volume); + + vec4 gridData = texture(sampler3D(gridImage, gridSampler), position); + + float mass = gridData.w; + float density = mass / volume; + + float alpha = clamp(density / simulation.density, 0.0f, 1.0f); + + passPos = vertexPos; + passVelocity = gridData.xyz; + passMass = mass; + + // align voxel to face camera + gl_Position = mvp * vec4(position, 1); // transform position into projected view space + gl_Position.xy += vertexPos * (radius * 2.0f) * alpha; // move position directly in view space +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/init_particle_weights.comp b/projects/wobble_bobble/shaders/init_particle_weights.comp new file mode 100644 index 0000000000000000000000000000000000000000..9b821e88fc7cc3fcea87b7eb6de0f8f6d629d911 --- /dev/null +++ b/projects/wobble_bobble/shaders/init_particle_weights.comp @@ -0,0 +1,43 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#include "particle.inc" + +layout(set=0, binding=0, std430) restrict buffer particleBuffer { + Particle particles []; +}; + +layout(set=1, binding=0) uniform texture3D gridImage; +layout(set=1, binding=1) uniform sampler gridSampler; + +void main() { + if (gl_GlobalInvocationID.x < particles.length()) { + ParticleMinimal minimal = particles[gl_GlobalInvocationID.x].minimal; + + minimal.weight_sum = 1.0f; + + ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0); + ivec3 gridWindow = ivec3(minimal.size * 2.0f * gridResolution); + + float weight_sum = 0.0f; + + int i, j, k; + + for (i = -gridWindow.x; i <= gridWindow.x; i++) { + for (j = -gridWindow.y; j <= gridWindow.y; j++) { + for (k = -gridWindow.z; k <= gridWindow.z; k++) { + vec3 offset = vec3(i, j, k) / gridResolution; + vec3 voxel = minimal.position + offset; + + weight_sum += voxel_particle_weight(voxel, minimal); + } + } + } + + if (weight_sum > 0.0f) { + particles[gl_GlobalInvocationID.x].minimal.weight_sum = weight_sum; + } + } +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/lines.frag b/projects/wobble_bobble/shaders/lines.frag new file mode 100644 index 0000000000000000000000000000000000000000..37d79d30d2ce751a59b1b467764b2fe464aa5c17 --- /dev/null +++ b/projects/wobble_bobble/shaders/lines.frag @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 0) out vec3 outColor; + +void main() { + outColor = vec3(1.0f); +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/lines.vert b/projects/wobble_bobble/shaders/lines.vert new file mode 100644 index 0000000000000000000000000000000000000000..b8e3b01c67986156ad980899697ffea05409b752 --- /dev/null +++ b/projects/wobble_bobble/shaders/lines.vert @@ -0,0 +1,11 @@ +#version 450 + +layout(location = 0) in vec3 vertexPos; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +void main() { + gl_Position = mvp * vec4(vertexPos, 1); +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/particle.frag b/projects/wobble_bobble/shaders/particle.frag new file mode 100644 index 0000000000000000000000000000000000000000..81c0a3594359e816a28b5e3f0301b47ce74a3cd7 --- /dev/null +++ b/projects/wobble_bobble/shaders/particle.frag @@ -0,0 +1,18 @@ +#version 450 + +layout(location = 0) in vec2 passPos; +layout(location = 1) in float passMass; + +layout(location = 0) out vec3 outColor; + +void main() { + const float value = length(passPos); + + float z = sqrt(0.25 - value * value); + + if (value < 0.5f) { + outColor = vec3(passPos.x + 0.5f, passPos.y + 0.5f, z * 2.0f); + } else { + discard; + } +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/particle.inc b/projects/wobble_bobble/shaders/particle.inc new file mode 100644 index 0000000000000000000000000000000000000000..a622485eab5bbcafdc51c030281e53b1cc1c5f11 --- /dev/null +++ b/projects/wobble_bobble/shaders/particle.inc @@ -0,0 +1,118 @@ +#ifndef PARTICLE_INC +#define PARTICLE_INC + +#define EPSILON 0.00000001f + +struct ParticleMinimal { + vec3 position; + float size; + vec3 velocity; + float mass; + + vec3 pad; + float weight_sum; +}; + +struct Particle { + ParticleMinimal minimal; + mat4 deformation; + mat4 mls; +}; + +#define SIM_FORM_SPHERE 0 +#define SIM_FORM_CUBE 1 + +#define SIM_TYPE_HYPERELASTIC 0 +#define SIM_TYPE_FLUID 1 + +#define SIM_MODE_RANDOM 0 +#define SIM_MODE_ORDERED 1 + +struct Simulation { + float density; + float size; + float lame1; + float lame2; + + int form; + int type; + float K; + float E; + + float gamma; + int mode; + float gravity; + int count; +}; + +const float PI = 3.1415926535897932384626433832795; + +float sphere_volume(float radius) { + return 4.0f * (radius * radius * radius) * PI / 3.0f; +} + +float sphere_radius(float volume) { + return pow(volume * 3.0f / 4.0f / PI, 1.0f / 3.0f); +} + +float cube_volume(float radius) { + return 8.0f * (radius * radius * radius); +} + +float cube_radius(float volume) { + return pow(volume / 8.0f, 1.0f / 3.0f); +} + +float weight_A(float x) { + return max(1.0f - x, 0.0f); +} + +float weight_B(float x) { + if (x < 0.5f) { + return 0.75f - x * x; + } else + if (x < 1.5f) { + float y = (1.5f - x); + return 0.5f * y * y; + } else { + return 0.0f; + } +} + +float weight_C(float x) { + if (x < 1.0f) { + return (0.5f * x - 1.0f) * x*x + 2.0f / 3.0f; + } else + if (x < 2.0f) { + float y = (2.0f - x); + return 0.5f / 3.0f * y * y * y; + } else { + return 0.0f; + } +} + +float voxel_particle_weight(vec3 voxel, ParticleMinimal particle) { + vec3 delta = abs(particle.position - voxel) / particle.size; + + if (any(isnan(delta)) || any(isinf(delta))) { + return 0.0f; + } + + vec3 weight = vec3( + weight_C(delta.x), + weight_C(delta.y), + weight_C(delta.z) + ); + + float result = ( + weight.x * weight.y * weight.z + ) / particle.weight_sum; + + if ((isnan(result)) || (isinf(result))) { + return 0.0f; + } else { + return result; + } +} + +#endif // PARTICLE_INC \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/particle.vert b/projects/wobble_bobble/shaders/particle.vert new file mode 100644 index 0000000000000000000000000000000000000000..a8f697e79eacba361d80b5858405add675e761bb --- /dev/null +++ b/projects/wobble_bobble/shaders/particle.vert @@ -0,0 +1,31 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "particle.inc" + +layout(set=0, binding=0, std430) readonly buffer particleBuffer { + Particle particles []; +}; + +layout(location = 0) in vec2 vertexPos; + +layout(location = 0) out vec2 passPos; +layout(location = 1) out float passMass; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +void main() { + vec3 position = particles[gl_InstanceIndex].minimal.position; + float size = particles[gl_InstanceIndex].minimal.size; + + float mass = particles[gl_InstanceIndex].minimal.mass; + + passPos = vertexPos; + passMass = mass; + + // align particle to face camera + gl_Position = mvp * vec4(position, 1); // transform position into projected view space + gl_Position.xy += vertexPos * size * 2.0f; // move position directly in view space +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/transform_particles_to_grid.comp b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp new file mode 100644 index 0000000000000000000000000000000000000000..1be18c41303ab2208c8cb4a8c33f41b350315d63 --- /dev/null +++ b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp @@ -0,0 +1,101 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; + +#include "particle.inc" + +layout(set=0, binding=0, std430) readonly buffer particleBuffer { + Particle particles []; +}; + +layout(set=1, binding=0) uniform simulationBlock { + Simulation simulation; +}; + +layout(set=2, binding=0, rgba16f) restrict writeonly uniform image3D gridImage; + +layout( push_constant ) uniform constants { + float t; + float dt; + float speedfactor; +}; + +#define SHARED_PARTICLES_BATCH_SIZE 64 + +shared ParticleMinimal shared_particles [SHARED_PARTICLES_BATCH_SIZE]; + +void main() { + const vec3 position = (vec3(gl_GlobalInvocationID) + vec3(0.5f)) / imageSize(gridImage); + + float dts = dt * speedfactor; + + vec4 gridValue = vec4(0.0f); + + uint offset = 0; + + for (offset = 0; offset < particles.length(); offset += SHARED_PARTICLES_BATCH_SIZE) { + uint localOffset = offset + gl_LocalInvocationIndex; + + if (localOffset < particles.length()) { + shared_particles[gl_LocalInvocationIndex] = particles[localOffset].minimal; + + shared_particles[gl_LocalInvocationIndex].pad = ( + mat3(particles[localOffset].mls) * + (position - shared_particles[gl_LocalInvocationIndex].position) + ) + ( + shared_particles[gl_LocalInvocationIndex].velocity * + shared_particles[gl_LocalInvocationIndex].mass + ); + } else { + shared_particles[gl_LocalInvocationIndex].position = vec3(0.0f); + shared_particles[gl_LocalInvocationIndex].size = 0.0f; + shared_particles[gl_LocalInvocationIndex].velocity = vec3(0.0f); + shared_particles[gl_LocalInvocationIndex].mass = 0.0f; + + shared_particles[gl_LocalInvocationIndex].pad = vec3(0.0f); + shared_particles[gl_LocalInvocationIndex].weight_sum = 1.0f; + } + + barrier(); + memoryBarrierShared(); + + for (uint i = 0; i < SHARED_PARTICLES_BATCH_SIZE; i++) { + float weight = voxel_particle_weight(position, shared_particles[i]); + + gridValue += vec4( + shared_particles[i].pad * weight, + shared_particles[i].mass * weight + ); + } + + barrier(); + memoryBarrierShared(); + } + + if (any(isnan(gridValue.xyz)) || any(isinf(gridValue.xyz))) { + gridValue.xyz = vec3(0.0f); + } + + gridValue.xyz += vec3(0.0f, -simulation.gravity * dts * gridValue.w, 0.0f); + + bvec3 lowerID = lessThanEqual(gl_GlobalInvocationID, ivec3(0)); + bvec3 negativeVelocity = lessThan(gridValue.xyz, vec3(0.0f)); + + bvec3 greaterID = greaterThanEqual(gl_GlobalInvocationID + ivec3(1), imageSize(gridImage)); + bvec3 positiveVelocity = greaterThan(gridValue.xyz, vec3(0.0f)); + + bvec3 collision = bvec3( + (lowerID.x && negativeVelocity.x) || (greaterID.x && positiveVelocity.x), + (lowerID.y && negativeVelocity.y) || (greaterID.y && positiveVelocity.y), + (lowerID.z && negativeVelocity.z) || (greaterID.z && positiveVelocity.z) + ); + + gridValue.xyz = mix(gridValue.xyz, -gridValue.xyz, collision); + + imageStore( + gridImage, + ivec3(gl_GlobalInvocationID), + gridValue + ); +} \ No newline at end of file diff --git a/projects/wobble_bobble/shaders/update_particle_velocities.comp b/projects/wobble_bobble/shaders/update_particle_velocities.comp new file mode 100644 index 0000000000000000000000000000000000000000..4420bc9575bcde4d04d7d4f5531d0091362285c2 --- /dev/null +++ b/projects/wobble_bobble/shaders/update_particle_velocities.comp @@ -0,0 +1,161 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#include "particle.inc" + +layout(set=0, binding=0, std430) restrict buffer particleBuffer { + Particle particles []; +}; + +layout(set=1, binding=0) uniform simulationBlock { + Simulation simulation; +}; + +layout(set=2, binding=0) uniform texture3D gridImage; +layout(set=2, binding=1) uniform sampler gridSampler; + +layout( push_constant ) uniform constants { + float t; + float dt; + float speedfactor; +}; + +void main() { + float dts = dt * speedfactor; + + if (gl_GlobalInvocationID.x < particles.length()) { + Particle particle = particles[gl_GlobalInvocationID.x]; + + vec3 position = particle.minimal.position; + float size = particle.minimal.size; + float mass = particle.minimal.mass; + + ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0); + ivec3 gridWindow = ivec3(size * 2.0f * gridResolution); + + mat3 affine_D = mat3(0.0f); + mat3 affine_B = mat3(0.0f); + + vec3 velocity_pic = vec3(0.0f); + vec3 velocity_flip = vec3(particle.minimal.velocity); + + int i, j, k; + + for (i = -gridWindow.x; i <= gridWindow.x; i++) { + for (j = -gridWindow.y; j <= gridWindow.y; j++) { + for (k = -gridWindow.z; k <= gridWindow.z; k++) { + vec3 offset = vec3(i, j, k) / gridResolution; + vec3 voxel = position + offset; + + vec4 gridSample = texture(sampler3D(gridImage, gridSampler), voxel); + + float weight = voxel_particle_weight(voxel, particle.minimal); + vec3 velocity = gridSample.xyz * weight / gridSample.w; + + if (any(isnan(velocity)) || any(isinf(velocity))) { + velocity = vec3(0.0f); + } + + affine_D += outerProduct(weight * offset, offset); + affine_B += outerProduct(velocity, offset); + + velocity_pic += velocity; + } + } + } + + mat3 mls_Q = mat3(0.0f); + mat3 affine_C = mat3(0.0f); + + mat3 F = mat3(particle.deformation); + + mat3 D_inv = inverse(affine_D); + float D_det = determinant(D_inv); + + if ((isnan(D_det)) || (isinf(D_det))) { + D_inv = mat3(0.0f); + } else { + D_inv *= min(abs(D_det), 1.0f / EPSILON) / abs(D_det); + } + + float J = max(determinant(F), EPSILON); + float volume = sphere_volume(size); + + mat3 stress = mat3(0.0f); + + switch (simulation.type) { + case SIM_TYPE_HYPERELASTIC: + mat3 F_T = transpose(F); + mat3 F_T_inv = inverse(F_T); + + mat3 P_term_0 = simulation.lame2 * (F - F_T_inv); + mat3 P_term_1 = simulation.lame1 * log(J) * F_T_inv; + + mat3 P = P_term_0 + P_term_1; + + stress = P * F_T; + break; + case SIM_TYPE_FLUID: + float pressure = simulation.K * (1.0f / pow(J, simulation.gamma) - 1.0f); + + stress = mat3(-pressure * J); + break; + default: + break; + } + + mls_Q -= dts * volume * stress * D_inv; + + affine_C = affine_B * D_inv; + mls_Q += affine_C * mass; + + F = (mat3(1.0f) + dts * affine_C) * F; + + position = position + velocity_pic * dts; + + const float gridRange = (1.0f - 2.0f * size); + + for (uint i = 0; i < 3; i++) { + if (position[i] - size < 0.0f) { + float a = (size - position[i]) / gridRange; + int b = int(floor(a)); + + a = (a - b) * gridRange; + + if (b % 2 == 0) { + position[i] = size + a; + } else { + position[i] = 1.0f - size - a; + } + + if ((velocity_pic[i] < 0.0f) == (b % 2 == 0)) { + velocity_pic[i] *= -1.0f; + } + } else + if (position[i] + size > 1.0f) { + float a = (position[i] + size - 1.0f) / gridRange; + int b = int(floor(a)); + + a = (a - b) * gridRange; + + if (b % 2 == 0) { + position[i] = 1.0f - size - a; + } else { + position[i] = size + a; + } + + if ((velocity_pic[i] > 0.0f) == (b % 2 == 0)) { + velocity_pic[i] *= -1.0f; + } + } + } + + particles[gl_GlobalInvocationID.x].minimal.position = position; + particles[gl_GlobalInvocationID.x].minimal.velocity = velocity_pic; + particles[gl_GlobalInvocationID.x].deformation = mat4(F); + particles[gl_GlobalInvocationID.x].mls = mat4(mls_Q); + } +} \ No newline at end of file diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96c367f2f8e22ac65bf6ccf6a5c09eb238b5604d --- /dev/null +++ b/projects/wobble_bobble/src/main.cpp @@ -0,0 +1,905 @@ + +#include <vkcv/Core.hpp> +#include <vkcv/camera/CameraManager.hpp> +#include <vkcv/gui/GUI.hpp> +#include <vkcv/shader/GLSLCompiler.hpp> + +#include <random> + +struct Particle { + glm::vec3 position; + float size; + glm::vec3 velocity; + float mass; + + glm::vec3 pad; + float weight_sum; + + glm::mat4 deformation; + glm::mat4 mls; +}; + +#define SIM_FORM_SPHERE 0 +#define SIM_FORM_CUBE 1 + +#define SIM_TYPE_HYPERELASTIC 0 +#define SIM_TYPE_FLUID 1 + +#define SIM_MODE_RANDOM 0 +#define SIM_MODE_ORDERED 1 + +struct Simulation { + float density; + float size; + float lame1; + float lame2; + + int form; + int type; + float K; + float E; + + float gamma; + int mode; + float gravity; + int count; +}; + +struct Physics { + float t; + float dt; + float speedfactor; +}; + +float sphere_volume(float radius) { + return 4.0f * (radius * radius * radius) * M_PI / 3.0f; +} + +float sphere_radius(float volume) { + return std::pow(volume * 3.0f / 4.0f / M_PI, 1.0f / 3.0f); +} + +float cube_volume(float radius) { + return 8.0f * (radius * radius * radius); +} + +float cube_radius(float volume) { + return std::pow(volume / 8.0f, 1.0f / 3.0f); +} + +std::random_device random_dev; +std::uniform_int_distribution<int> dist(0, RAND_MAX); + +float randomFloat(float min, float max) { + return min + (max - min) * dist(random_dev) / static_cast<float>(RAND_MAX); +} + +float mod(float x, float y) { + return x - std::floor(x / y) * y; +} + +void distributeParticlesCube(Particle *particles, size_t count, const glm::vec3& center, float radius, + float mass, const glm::vec3& velocity, bool random) { + const float side = cube_radius(static_cast<float>(count)) * 2.0f; + + float volume = 0.0f; + + for (size_t i = 0; i < count; i++) { + glm::vec3 offset; + + if (random) { + offset.x = randomFloat(-1.0f, +1.0f); + offset.y = randomFloat(-1.0f, +1.0f); + offset.z = randomFloat(-1.0f, +1.0f); + } else { + const float s = static_cast<float>(i) + 0.5f; + + offset.x = 2.0f * mod(s, side) / side - 1.0f; + offset.y = 2.0f * mod(s / side, side) / side - 1.0f; + offset.z = 2.0f * mod(s / side / side, side) / side - 1.0f; + } + + offset *= radius; + + float size = 0.0f; + + if (random) { + const float ax = std::abs(offset.x); + const float ay = std::abs(offset.y); + const float az = std::abs(offset.z); + + const float a = std::max(std::max(ax, ay), az); + + size = (radius - a); + } else { + size = 2.0f * radius / side; + } + + particles[i].position = center + offset; + particles[i].size = size; + particles[i].velocity = velocity; + + volume += cube_volume(size); + } + + for (size_t i = 0; i < count; i++) { + particles[i].mass = (mass * cube_volume(particles[i].size) / volume); + particles[i].deformation = glm::mat4(1.0f); + + particles[i].pad = glm::vec3(0.0f); + particles[i].weight_sum = 1.0f; + + particles[i].mls = glm::mat4(0.0f); + } +} + +void distributeParticlesSphere(Particle *particles, size_t count, const glm::vec3& center, float radius, + float mass, const glm::vec3& velocity, bool random) { + const float side = sphere_radius(static_cast<float>(count)) * 2.0f; + + float volume = 0.0f; + + for (size_t i = 0; i < count; i++) { + glm::vec3 offset; + + if (random) { + offset.x = randomFloat(-1.0f, +1.0f); + offset.y = randomFloat(-1.0f, +1.0f); + offset.z = randomFloat(-1.0f, +1.0f); + + if (glm::length(offset) > 0.0f) + offset = glm::normalize(offset); + + offset *= randomFloat(0.0f, 1.0f); + } else { + const float range = 0.5f * side; + const float s = static_cast<float>(i) + 0.5f; + + float a = mod(s, range) / range; + float b = mod(s / range, M_PI * range); + float c = mod(s / range / M_PI / range, M_PI * range * 2.0f); + + offset.x = a * std::sin(c) * std::sin(b); + offset.y = a * std::cos(b); + offset.z = a * std::cos(c) * std::sin(b); + } + + offset *= radius; + + float size = 0.0f; + + if (random) { + size = (radius - glm::length(offset)); + } else { + size = 2.0f * radius / side; + } + + particles[i].position = center + offset; + particles[i].size = size; + particles[i].velocity = velocity; + + volume += sphere_volume(size); + } + + // Keep the same densitiy as planned! + mass *= (volume / sphere_volume(radius)); + + for (size_t i = 0; i < count; i++) { + particles[i].mass = (mass * sphere_volume(particles[i].size) / volume); + particles[i].deformation = glm::mat4(1.0f); + + particles[i].pad = glm::vec3(0.0f); + particles[i].weight_sum = 1.0f; + + particles[i].mls = glm::mat4(0.0f); + } +} + +vkcv::ComputePipelineHandle createComputePipeline(vkcv::Core& core, vkcv::shader::GLSLCompiler& compiler, + const std::string& path, + std::vector<vkcv::DescriptorSetHandle>& descriptorSets) { + vkcv::ShaderProgram shaderProgram; + + compiler.compile( + vkcv::ShaderStage::COMPUTE, + path, + [&shaderProgram](vkcv::ShaderStage stage, const std::filesystem::path& path) { + shaderProgram.addShader(stage, path); + } + ); + + const auto& descriptors = shaderProgram.getReflectedDescriptors(); + + size_t count = 0; + + for (const auto& descriptor : descriptors) { + if (descriptor.first >= count) { + count = (descriptor.first + 1); + } + } + + std::vector<vkcv::DescriptorSetLayoutHandle> descriptorSetLayouts; + + descriptorSetLayouts.resize(count); + descriptorSets.resize(count); + + for (const auto& descriptor : descriptors) { + descriptorSetLayouts[descriptor.first] = core.createDescriptorSetLayout(descriptor.second); + descriptorSets[descriptor.first] = core.createDescriptorSet(descriptorSetLayouts[descriptor.first]); + } + + vkcv::ComputePipelineConfig config { + shaderProgram, + descriptorSetLayouts + }; + + return core.createComputePipeline(config); +} + +vkcv::BufferHandle resetParticles(vkcv::Core& core, size_t count, const glm::vec3& velocity, + float density, float size, int form, int mode) { + vkcv::Buffer<Particle> particles = core.createBuffer<Particle>( + vkcv::BufferType::STORAGE, + count + ); + + std::vector<Particle> particles_vec (particles.getCount()); + + switch (form) { + case SIM_FORM_SPHERE: + distributeParticlesSphere( + particles_vec.data(), + particles_vec.size(), + glm::vec3(0.5f), + size, + density * sphere_volume(size), + velocity, + (mode == 0) + ); + break; + case SIM_FORM_CUBE: + distributeParticlesCube( + particles_vec.data(), + particles_vec.size(), + glm::vec3(0.5f), + size, + density * sphere_volume(size), + velocity, + (mode == 0) + ); + break; + default: + break; + } + + particles.fill(particles_vec); + return particles.getHandle(); +} + +int main(int argc, const char **argv) { + const char* applicationName = "Wobble Bobble"; + + uint32_t windowWidth = 800; + uint32_t windowHeight = 600; + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + + vkcv::Core core = vkcv::Core::create( + applicationName, + VK_MAKE_VERSION(0, 0, 1), + {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, + features + ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); + vkcv::Window& window = core.getWindow(windowHandle); + vkcv::camera::CameraManager cameraManager(window); + + vkcv::gui::GUI gui (core, windowHandle); + + uint32_t trackballIdx = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); + cameraManager.getCamera(trackballIdx).setCenter(glm::vec3(0.5f, 0.5f, 0.5f)); // set camera to look at the center of the particle volume + cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); + + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); + + vkcv::ImageHandle depthBuffer = core.createImage( + vk::Format::eD32Sfloat, + swapchainExtent.width, + swapchainExtent.height + ).getHandle(); + + vkcv::Image grid = core.createImage( + vk::Format::eR16G16B16A16Sfloat, + 32, + 32, + 32, + false, + true + ); + + vkcv::SamplerHandle gridSampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::NEAREST, + vkcv::SamplerAddressMode::CLAMP_TO_BORDER, + 0.0f, + vkcv::SamplerBorderColor::FLOAT_ZERO_TRANSPARENT + ); + + vkcv::Buffer<Simulation> simulation = core.createBuffer<Simulation>( + vkcv::BufferType::UNIFORM, 1, vkcv::BufferMemoryType::HOST_VISIBLE + ); + + Simulation* sim = simulation.map(); + + glm::vec3 initialVelocity (0.0f, 0.1f, 0.0f); + + sim->density = 2500.0f; + sim->size = 0.1f; + sim->lame1 = 10.0f; + sim->lame2 = 20.0f; + sim->form = SIM_FORM_SPHERE; + sim->type = SIM_TYPE_HYPERELASTIC; + sim->K = 2.2f; + sim->E = 35.0f; + sim->gamma = 1.330f; + sim->mode = SIM_MODE_RANDOM; + sim->gravity = 9.81f; + sim->count = 1024; + + vkcv::BufferHandle particlesHandle = resetParticles( + core, + sim->count, + initialVelocity, + sim->density, + sim->size, + sim->form, + sim->mode + ); + + vkcv::shader::GLSLCompiler compiler; + + std::vector<vkcv::DescriptorSetHandle> initParticleWeightsSets; + vkcv::ComputePipelineHandle initParticleWeightsPipeline = createComputePipeline( + core, compiler, + "shaders/init_particle_weights.comp", + initParticleWeightsSets + ); + + { + vkcv::DescriptorWrites writes; + writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle)); + core.writeDescriptorSet(initParticleWeightsSets[0], writes); + } + + { + vkcv::DescriptorWrites writes; + writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle())); + writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler)); + core.writeDescriptorSet(initParticleWeightsSets[1], writes); + } + + std::vector<vkcv::DescriptorSetHandle> transformParticlesToGridSets; + vkcv::ComputePipelineHandle transformParticlesToGridPipeline = createComputePipeline( + core, compiler, + "shaders/transform_particles_to_grid.comp", + transformParticlesToGridSets + ); + + { + vkcv::DescriptorWrites writes; + writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle)); + core.writeDescriptorSet(transformParticlesToGridSets[0], writes); + } + + { + vkcv::DescriptorWrites writes; + writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle())); + core.writeDescriptorSet(transformParticlesToGridSets[1], writes); + } + + { + vkcv::DescriptorWrites writes; + writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, grid.getHandle())); + core.writeDescriptorSet(transformParticlesToGridSets[2], writes); + } + + std::vector<vkcv::DescriptorSetHandle> updateParticleVelocitiesSets; + vkcv::ComputePipelineHandle updateParticleVelocitiesPipeline = createComputePipeline( + core, compiler, + "shaders/update_particle_velocities.comp", + updateParticleVelocitiesSets + ); + + { + vkcv::DescriptorWrites writes; + writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle)); + core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes); + } + + { + vkcv::DescriptorWrites writes; + writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle())); + core.writeDescriptorSet(updateParticleVelocitiesSets[1], writes); + } + + { + vkcv::DescriptorWrites writes; + writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle())); + writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler)); + core.writeDescriptorSet(updateParticleVelocitiesSets[2], writes); + } + + vkcv::ShaderProgram gfxProgramGrid; + + compiler.compileProgram(gfxProgramGrid, { + { vkcv::ShaderStage::VERTEX, "shaders/grid.vert" }, + { vkcv::ShaderStage::FRAGMENT, "shaders/grid.frag" } + }, nullptr); + + vkcv::ShaderProgram gfxProgramParticles; + + compiler.compileProgram(gfxProgramParticles, { + { vkcv::ShaderStage::VERTEX, "shaders/particle.vert" }, + { vkcv::ShaderStage::FRAGMENT, "shaders/particle.frag" } + }, nullptr); + + vkcv::ShaderProgram gfxProgramLines; + + compiler.compileProgram(gfxProgramLines, { + { vkcv::ShaderStage::VERTEX, "shaders/lines.vert" }, + { vkcv::ShaderStage::FRAGMENT, "shaders/lines.frag" } + }, nullptr); + + vkcv::PassConfig passConfigGrid ({ + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + core.getSwapchain(windowHandle).getFormat() + ), + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + vk::Format::eD32Sfloat + ) + }); + + vkcv::PassConfig passConfigParticles ({ + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + core.getSwapchain(windowHandle).getFormat() + ), + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + vk::Format::eD32Sfloat + ) + }); + + vkcv::PassConfig passConfigLines ({ + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::LOAD, + core.getSwapchain(windowHandle).getFormat() + ), + vkcv::AttachmentDescription( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::LOAD, + vk::Format::eD32Sfloat + ) + }); + + vkcv::DescriptorSetLayoutHandle gfxSetLayoutGrid = core.createDescriptorSetLayout( + gfxProgramGrid.getReflectedDescriptors().at(0) + ); + + vkcv::DescriptorSetHandle gfxSetGrid = core.createDescriptorSet(gfxSetLayoutGrid); + + { + vkcv::DescriptorWrites writes; + writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle())); + writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler)); + writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(2, simulation.getHandle())); + core.writeDescriptorSet(gfxSetGrid, writes); + } + + vkcv::DescriptorSetLayoutHandle gfxSetLayoutParticles = core.createDescriptorSetLayout( + gfxProgramParticles.getReflectedDescriptors().at(0) + ); + + vkcv::DescriptorSetHandle gfxSetParticles = core.createDescriptorSet(gfxSetLayoutParticles); + + { + vkcv::DescriptorWrites writes; + writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle)); + core.writeDescriptorSet(gfxSetParticles, writes); + } + + vkcv::PassHandle gfxPassGrid = core.createPass(passConfigGrid); + vkcv::PassHandle gfxPassParticles = core.createPass(passConfigParticles); + vkcv::PassHandle gfxPassLines = core.createPass(passConfigLines); + + vkcv::VertexLayout vertexLayoutGrid ({ + vkcv::VertexBinding(0, gfxProgramGrid.getVertexAttachments()) + }); + + vkcv::GraphicsPipelineConfig gfxPipelineConfigGrid; + gfxPipelineConfigGrid.m_ShaderProgram = gfxProgramGrid; + gfxPipelineConfigGrid.m_Width = windowWidth; + gfxPipelineConfigGrid.m_Height = windowHeight; + gfxPipelineConfigGrid.m_PassHandle = gfxPassGrid; + gfxPipelineConfigGrid.m_VertexLayout = vertexLayoutGrid; + gfxPipelineConfigGrid.m_DescriptorLayouts = { gfxSetLayoutGrid }; + gfxPipelineConfigGrid.m_UseDynamicViewport = true; + + vkcv::VertexLayout vertexLayoutParticles ({ + vkcv::VertexBinding(0, gfxProgramParticles.getVertexAttachments()) + }); + + vkcv::GraphicsPipelineConfig gfxPipelineConfigParticles; + gfxPipelineConfigParticles.m_ShaderProgram = gfxProgramParticles; + gfxPipelineConfigParticles.m_Width = windowWidth; + gfxPipelineConfigParticles.m_Height = windowHeight; + gfxPipelineConfigParticles.m_PassHandle = gfxPassParticles; + gfxPipelineConfigParticles.m_VertexLayout = vertexLayoutParticles; + gfxPipelineConfigParticles.m_DescriptorLayouts = { gfxSetLayoutParticles }; + gfxPipelineConfigParticles.m_UseDynamicViewport = true; + + vkcv::VertexLayout vertexLayoutLines ({ + vkcv::VertexBinding(0, gfxProgramLines.getVertexAttachments()) + }); + + vkcv::GraphicsPipelineConfig gfxPipelineConfigLines; + gfxPipelineConfigLines.m_ShaderProgram = gfxProgramLines; + gfxPipelineConfigLines.m_Width = windowWidth; + gfxPipelineConfigLines.m_Height = windowHeight; + gfxPipelineConfigLines.m_PassHandle = gfxPassLines; + gfxPipelineConfigLines.m_VertexLayout = vertexLayoutLines; + gfxPipelineConfigLines.m_DescriptorLayouts = {}; + gfxPipelineConfigLines.m_UseDynamicViewport = true; + gfxPipelineConfigLines.m_PrimitiveTopology = vkcv::PrimitiveTopology::LineList; + + vkcv::GraphicsPipelineHandle gfxPipelineGrid = core.createGraphicsPipeline(gfxPipelineConfigGrid); + vkcv::GraphicsPipelineHandle gfxPipelineParticles = core.createGraphicsPipeline(gfxPipelineConfigParticles); + vkcv::GraphicsPipelineHandle gfxPipelineLines = core.createGraphicsPipeline(gfxPipelineConfigLines); + + vkcv::Buffer<glm::vec2> trianglePositions = core.createBuffer<glm::vec2>(vkcv::BufferType::VERTEX, 3); + trianglePositions.fill({ + glm::vec2(-1.0f, -1.0f), + glm::vec2(+0.0f, +1.5f), + glm::vec2(+1.0f, -1.0f) + }); + + vkcv::Buffer<uint16_t> triangleIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3); + triangleIndices.fill({ + 0, 1, 2 + }); + + vkcv::Mesh triangleMesh ( + { vkcv::VertexBufferBinding(0, trianglePositions.getVulkanHandle()) }, + triangleIndices.getVulkanHandle(), + triangleIndices.getCount() + ); + + vkcv::Buffer<glm::vec3> linesPositions = core.createBuffer<glm::vec3>(vkcv::BufferType::VERTEX, 8); + linesPositions.fill({ + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), + glm::vec3(1.0f, 1.0f, 0.0f), + glm::vec3(0.0f, 0.0f, 1.0f), + glm::vec3(1.0f, 0.0f, +1.0f), + glm::vec3(0.0f, 1.0f, 1.0f), + glm::vec3(1.0f, 1.0f, 1.0f) + }); + + vkcv::Buffer<uint16_t> linesIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 24); + linesIndices.fill({ + 0, 1, + 1, 3, + 3, 2, + 2, 0, + + 4, 5, + 5, 7, + 7, 6, + 6, 4, + + 0, 4, + 1, 5, + 2, 6, + 3, 7 + }); + + vkcv::Mesh linesMesh ( + { vkcv::VertexBufferBinding(0, linesPositions.getVulkanHandle()) }, + linesIndices.getVulkanHandle(), + linesIndices.getCount() + ); + + std::vector<vkcv::DrawcallInfo> drawcallsGrid; + + drawcallsGrid.push_back(vkcv::DrawcallInfo( + triangleMesh, + { vkcv::DescriptorSetUsage(0, gfxSetGrid) }, + grid.getWidth() * grid.getHeight() * grid.getDepth() + )); + + std::vector<vkcv::DrawcallInfo> drawcallsParticles; + + drawcallsParticles.push_back(vkcv::DrawcallInfo( + triangleMesh, + { vkcv::DescriptorSetUsage(0, gfxSetParticles) }, + sim->count + )); + + std::vector<vkcv::DrawcallInfo> drawcallsLines; + + drawcallsLines.push_back(vkcv::DrawcallInfo( + linesMesh, + {}, + 1 + )); + + bool renderGrid = true; + + float speed_factor = 1.0f; + + auto start = std::chrono::system_clock::now(); + auto current = start; + + while (vkcv::Window::hasOpenWindow()) { + vkcv::Window::pollEvents(); + + if (window.getHeight() == 0 || window.getWidth() == 0) + continue; + + uint32_t swapchainWidth, swapchainHeight; + if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) { + continue; + } + + if ((swapchainWidth != swapchainExtent.width) || ((swapchainHeight != swapchainExtent.height))) { + depthBuffer = core.createImage( + vk::Format::eD32Sfloat, + swapchainWidth, + swapchainHeight + ).getHandle(); + + swapchainExtent.width = swapchainWidth; + swapchainExtent.height = swapchainHeight; + } + + auto next = std::chrono::system_clock::now(); + + auto time = std::chrono::duration_cast<std::chrono::microseconds>(next - start); + auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(next - current); + + current = next; + + Physics physics; + physics.t = static_cast<float>(0.000001 * static_cast<double>(time.count())); + physics.dt = static_cast<float>(0.000001 * static_cast<double>(deltatime.count())); + physics.speedfactor = speed_factor; + + vkcv::PushConstants physicsPushConstants(sizeof(physics)); + physicsPushConstants.appendDrawcall(physics); + + cameraManager.update(physics.dt); + + glm::mat4 mvp = cameraManager.getActiveCamera().getMVP(); + vkcv::PushConstants cameraPushConstants(sizeof(glm::mat4)); + cameraPushConstants.appendDrawcall(mvp); + + auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); + + const uint32_t dispatchSizeGrid[3] = {grid.getWidth() / 4, grid.getHeight() / 4, grid.getDepth() / 4}; + const uint32_t dispatchSizeParticles[3] = {static_cast<uint32_t>(sim->count + 63) / 64, 1, 1}; + + for (int step = 0; step < 1; step++) { + core.recordBeginDebugLabel(cmdStream, "INIT PARTICLE WEIGHTS", {0.78f, 0.89f, 0.94f, 1.0f}); + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + core.prepareImageForSampling(cmdStream, grid.getHandle()); + + core.recordComputeDispatchToCmdStream( + cmdStream, + initParticleWeightsPipeline, + dispatchSizeParticles, + { + vkcv::DescriptorSetUsage( + 0, initParticleWeightsSets[0] + ), + vkcv::DescriptorSetUsage( + 1, initParticleWeightsSets[1] + ) + }, + vkcv::PushConstants(0) + ); + + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + core.recordEndDebugLabel(cmdStream); + + core.recordBeginDebugLabel(cmdStream, "TRANSFORM PARTICLES TO GRID", {0.47f, 0.77f, 0.85f, 1.0f}); + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + core.prepareImageForStorage(cmdStream, grid.getHandle()); + + core.recordComputeDispatchToCmdStream( + cmdStream, + transformParticlesToGridPipeline, + dispatchSizeGrid, + { + vkcv::DescriptorSetUsage( + 0, transformParticlesToGridSets[0] + ), + vkcv::DescriptorSetUsage( + 1, transformParticlesToGridSets[1] + ), + vkcv::DescriptorSetUsage( + 2, transformParticlesToGridSets[2] + ) + }, + physicsPushConstants + ); + + core.recordImageMemoryBarrier(cmdStream, grid.getHandle()); + core.recordEndDebugLabel(cmdStream); + + core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE VELOCITIES", {0.78f, 0.89f, 0.94f, 1.0f}); + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + core.recordBufferMemoryBarrier(cmdStream, simulation.getHandle()); + core.prepareImageForSampling(cmdStream, grid.getHandle()); + + core.recordComputeDispatchToCmdStream( + cmdStream, + updateParticleVelocitiesPipeline, + dispatchSizeParticles, + { + vkcv::DescriptorSetUsage( + 0, updateParticleVelocitiesSets[0] + ), + vkcv::DescriptorSetUsage( + 1, updateParticleVelocitiesSets[1] + ), + vkcv::DescriptorSetUsage( + 2, updateParticleVelocitiesSets[2] + ) + }, + physicsPushConstants + ); + + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + core.recordEndDebugLabel(cmdStream); + } + + std::vector<vkcv::ImageHandle> renderTargets { + vkcv::ImageHandle::createSwapchainImageHandle(), + depthBuffer + }; + + if (renderGrid) { + core.recordBeginDebugLabel(cmdStream, "RENDER GRID", { 0.13f, 0.20f, 0.22f, 1.0f }); + core.recordBufferMemoryBarrier(cmdStream, simulation.getHandle()); + core.prepareImageForSampling(cmdStream, grid.getHandle()); + + core.recordDrawcallsToCmdStream( + cmdStream, + gfxPassGrid, + gfxPipelineGrid, + cameraPushConstants, + drawcallsGrid, + renderTargets, + windowHandle + ); + + core.recordEndDebugLabel(cmdStream); + } else { + core.recordBeginDebugLabel(cmdStream, "RENDER PARTICLES", { 0.13f, 0.20f, 0.22f, 1.0f }); + core.recordBufferMemoryBarrier(cmdStream, particlesHandle); + + core.recordDrawcallsToCmdStream( + cmdStream, + gfxPassParticles, + gfxPipelineParticles, + cameraPushConstants, + drawcallsParticles, + renderTargets, + windowHandle + ); + + core.recordEndDebugLabel(cmdStream); + } + + core.recordBeginDebugLabel(cmdStream, "RENDER LINES", { 0.13f, 0.20f, 0.22f, 1.0f }); + + core.recordDrawcallsToCmdStream( + cmdStream, + gfxPassLines, + gfxPipelineLines, + cameraPushConstants, + drawcallsLines, + renderTargets, + windowHandle + ); + + core.recordEndDebugLabel(cmdStream); + + core.prepareSwapchainImageForPresent(cmdStream); + core.submitCommandStream(cmdStream); + + gui.beginGUI(); + ImGui::Begin("Settings"); + + ImGui::BeginGroup(); + ImGui::Combo("Mode", &(sim->mode), "Random\0Ordered", 2); + ImGui::Combo("Form", &(sim->form), "Sphere\0Cube", 2); + ImGui::Combo("Type", &(sim->type), "Hyperelastic\0Fluid", 2); + ImGui::EndGroup(); + + ImGui::Spacing(); + + ImGui::SliderInt("Particle Count", &(sim->count), 1, 100000); + ImGui::SliderFloat("Density", &(sim->density), std::numeric_limits<float>::epsilon(), 5000.0f); + ImGui::SameLine(0.0f, 10.0f); + if (ImGui::SmallButton("Reset##density")) { + sim->density = 2500.0f; + } + + ImGui::SliderFloat("Radius", &(sim->size), 0.0f, 0.5f); + ImGui::SameLine(0.0f, 10.0f); + if (ImGui::SmallButton("Reset##radius")) { + sim->size = 0.1f; + } + + ImGui::Spacing(); + + ImGui::BeginGroup(); + ImGui::SliderFloat("Bulk Modulus", &(sim->K), 0.0f, 1000.0f); + ImGui::SliderFloat("Young's Modulus", &(sim->E), 0.0f, 1000.0f); + ImGui::SliderFloat("Heat Capacity Ratio", &(sim->gamma), 1.0f, 2.0f); + ImGui::SliderFloat("Lame1", &(sim->lame1), 0.0f, 1000.0f); + ImGui::SliderFloat("Lame2", &(sim->lame2), 0.0f, 1000.0f); + ImGui::EndGroup(); + + ImGui::Spacing(); + + ImGui::SliderFloat("Simulation Speed", &speed_factor, 0.0f, 2.0f); + + ImGui::Spacing(); + ImGui::Checkbox("Render Grid", &renderGrid); + + ImGui::DragFloat3("Initial Velocity", reinterpret_cast<float*>(&initialVelocity), 0.001f); + ImGui::SameLine(0.0f, 10.0f); + if (ImGui::Button("Reset##particle_velocity")) { + particlesHandle = resetParticles( + core, + sim->count, + initialVelocity, + sim->density, + sim->size, + sim->form, + sim->mode + ); + + vkcv::DescriptorWrites writes; + writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle)); + + core.writeDescriptorSet(initParticleWeightsSets[0], writes); + core.writeDescriptorSet(transformParticlesToGridSets[0], writes); + core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes); + + core.writeDescriptorSet(gfxSetParticles, writes); + } + + ImGui::SliderFloat("Gravity", &(sim->gravity), 0.0f, 10.0f); + + ImGui::End(); + gui.endGUI(); + + core.endFrame(windowHandle); + } + + simulation.unmap(); + return 0; +} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..7e41ca8e8ad62ce6667ab4d9c549f2ea613d28aa --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# Check if release or debug build +CMAKE_BUILD_DIR="build" +CMAKE_FLAGS="" +if [ "$1" = "--debug" ]; then + CMAKE_BUILD_DIR="cmake-build-debug" + CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Debug" +elif [ "$1" = "--release" ]; then + CMAKE_BUILD_DIR="cmake-build-release" + CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release" +fi + +# Navigate to the main directory of the cloned repository +cd "$(dirname "$0")" || exit +cd .. + +# Setup git lfs and the submodules +git lfs install +git submodule init +git submodule update + +# Setup build directory +mkdir $CMAKE_BUILD_DIR +cd $CMAKE_BUILD_DIR || exit +BUILD_THREADS=$(($(nproc --all) - 1)) + +if [ $BUILD_THREADS -lt 1 ]; then + BUILD_THREADS=1 +fi + +# Build process +cmake $CMAKE_FLAGS .. +make -j $BUILD_THREADS "$@" \ No newline at end of file diff --git a/scripts/generate.sh b/scripts/generate.sh new file mode 100755 index 0000000000000000000000000000000000000000..cf9ff2d607217890b6fd0586e1dddece962d59b9 --- /dev/null +++ b/scripts/generate.sh @@ -0,0 +1,58 @@ +#!/bin/sh +CMAKE_PROJECT_DIR="$(pwd)" +CMAKE_PROJECT_NAME="$(basename "$CMAKE_PROJECT_DIR")" + +# Navigate to the main directory of the cloned repository +cd "$(dirname "$0")" || exit +cd .. + +CMAKE_FRAMEWORK_DIR="$(realpath -s --relative-to="$CMAKE_PROJECT_DIR" "$(pwd)")" + +# Navigate back to the project directory +cd "$CMAKE_PROJECT_DIR" || exit + +test -f "CMakeLists.txt" && echo "WARNING: CMakeLists.txt exists already! Project generation stops!" && exit +test -f "src/main.cpp" && echo "WARNING: src/main.cpp exists already! Project generation stops!" && exit + +generate_cmake_lists() { + echo "cmake_minimum_required(VERSION 3.16)" + echo "project($CMAKE_PROJECT_NAME)" + echo + echo "set(CMAKE_CXX_STANDARD 20)" + echo "set(CMAKE_CXX_STANDARD_REQUIRED ON)" + echo + echo "set(BUILD_MODULES ON CACHE INTERNAL \"\")" + echo "set(BUILD_PROJECTS OFF CACHE INTERNAL \"\")" + echo "set(BUILD_DOXYGEN_DOCS OFF CACHE INTERNAL \"\")" + echo "set(BUILD_SHARED OFF CACHE INTERNAL \"\")" + echo "add_subdirectory($CMAKE_FRAMEWORK_DIR)" + echo + echo "add_executable($CMAKE_PROJECT_NAME src/main.cpp)" + echo + echo "target_include_directories($CMAKE_PROJECT_NAME SYSTEM BEFORE PRIVATE \${vkcv_includes})" + echo "target_link_libraries($CMAKE_PROJECT_NAME \${vkcv_libraries})" +} + +generate_main_cpp() { + echo "#include <vkcv/Core.hpp>" + echo + echo "int main(int argc, const char** argv) {" + echo " vkcv::Core core = vkcv::Core::create(" + echo " \"$CMAKE_PROJECT_NAME\"," + echo " VK_MAKE_VERSION(0, 0, 1)," + echo " { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }," + echo " { VK_KHR_SWAPCHAIN_EXTENSION_NAME }" + echo " );" + echo " " + echo " vkcv::WindowHandle windowHandle = core.createWindow(\"$CMAKE_PROJECT_NAME\", 800, 600, true);" + echo " " + echo " while (vkcv::Window::hasOpenWindow()) {" + echo " vkcv::Window::pollEvents();" + echo " }" + echo "}" +} + +generate_cmake_lists > "CMakeLists.txt" + +mkdir -p "src" +generate_main_cpp > "src/main.cpp" diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000000000000000000000000000000000000..9e4e7a6f6493a07a224054cfb84ae7b20f794e9f --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,27 @@ +#!/bin/sh +VKCV_BRANCH="$(git status | awk 'NR == 1 { print $3 }')" + +if [ "$VKCV_BRANCH" != "develop" ]; then + echo "WARNING: Please switch to origin/develop branch for preparing the next release!" + exit +fi + +VKCV_VERSION="$(cat include/vkcv/Core.hpp | grep "#define VKCV_FRAMEWORK_VERSION" | awk 'NR == 1 { $1=""; $2=""; print }' | sed -e 's/[^0-9 ]//g' -- | awk '{print $1"."$2"."$3}')" + +if [ $(git tag | grep "$VKCV_VERSION" | wc -l) -gt 0 ]; then + echo "WARNING: Please adjust the version of the framework before uploading a release! (Duplicate version: $VKCV_VERSION)" + exit +fi + +vim CHANGELOG.md +git add CHANGELOG.md + +git commit -S -s -m "========== VkCV-$VKCV_VERSION ==========" +git push + +git checkout master +git merge develop + +git tag -a "$VKCV_VERSION" -m "VkCV-$VKCV_VERSION release" +git push +git push --tags diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..2f5a32131003b8c684adb4a4d0d9219bdc8fc3d8 --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Navigate to the scripts directory +cd "$(dirname "$0")" || exit + +# Check if there is a project name as argument +if [ $# -lt 1 ]; then + echo "You need to specify a project name to run!">&2 + exit +fi + +RUN_WITH_HUD="no" +BUILD_FLAGS="" +while [ $# -gt 1 ]; do + case "$1" in + "--"*) + if [ "$1" = "--hud" ]; then + RUN_WITH_HUD="yes" + else + BUILD_FLAGS="$BUILD_FLAGS$1 " + fi + shift 1;; + *) break;; + esac +done + +PROJECT="$1" +PROJECT_DIR="../projects/$PROJECT" +shift 1 + +# Check if the project name is valid +if [ ! -d "$PROJECT_DIR" ]; then + echo "There is no project with the name '$PROJECT'!">&2 + exit +fi + +./build.sh $FLAGS "$PROJECT" +cd "$PROJECT_DIR" || exit + +if [ ! -f "$PROJECT" ]; then + echo "Building the project '$PROJECT' failed!">&2 + exit +fi + +if [ "$RUN_WITH_HUD" = "yes" ]; then + MANGOHUD=1 ./"$PROJECT" "$@" +else + ./"$PROJECT" "$@" +fi \ No newline at end of file diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp index f090b6dbe7e05f488958c072a758fbf2d2938ab5..a599001d3c60e126cfa0a52a1347abfe48b961a9 100644 --- a/src/vkcv/ComputePipelineManager.cpp +++ b/src/vkcv/ComputePipelineManager.cpp @@ -41,11 +41,12 @@ namespace vkcv return pipeline.m_layout; } - ComputePipelineHandle ComputePipelineManager::createComputePipeline(const ComputePipelineConfig& config) { + ComputePipelineHandle ComputePipelineManager::createComputePipeline(const ShaderProgram& shaderProgram, + const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) { // Temporally handing over the Shader Program instead of a pipeline config vk::ShaderModule computeModule{}; - if (createShaderModule(computeModule, config.m_ShaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess) + if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess) return ComputePipelineHandle(); vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo( @@ -56,9 +57,9 @@ namespace vkcv nullptr ); - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, config.m_DescriptorSetLayouts); + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts); - const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize(); + const size_t pushConstantSize = shaderProgram.getPushConstantSize(); vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize); if (pushConstantSize > 0) { pipelineLayoutCreateInfo.setPushConstantRangeCount(1); diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp index 527243e6ec43850d416a7d929e01351454c40086..acb50bbdef99d037374c140836d25bb161132b2b 100644 --- a/src/vkcv/ComputePipelineManager.hpp +++ b/src/vkcv/ComputePipelineManager.hpp @@ -1,7 +1,7 @@ #pragma once /** - * @authors Mark Mints + * @authors Mark Mints, Tobias Frisch * @file src/vkcv/ComputePipelineManager.hpp * @brief Creation and handling of Compute Pipelines */ @@ -49,10 +49,12 @@ namespace vkcv * Creates a Compute Pipeline based on the set shader stages in the Config Struct. * This function is wrapped in /src/vkcv/Core.cpp by Core::createComputePipeline(const ComputePipelineConfig &config). * On application level it is necessary first to fill a ComputePipelineConfig Struct. - * @param config Hands over all needed information for pipeline creation. + * @param shaderProgram Hands over all needed information for pipeline creation. + * @param descriptorSetLayouts Hands over all needed information for pipeline creation. * @return A Handler to the created Compute Pipeline Object. */ - ComputePipelineHandle createComputePipeline(const ComputePipelineConfig& config); + ComputePipelineHandle createComputePipeline(const ShaderProgram& shaderProgram, + const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts); private: struct ComputePipeline { diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index 2f3453f3ff97bd778df8fcfd36d79cc901c867ba..f7cd67eb756f353d9eb98c4768e2b0d74bbc1ab6 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -1,6 +1,7 @@ #include "vkcv/Context.hpp" #include "vkcv/Window.hpp" +#include "vkcv/Core.hpp" namespace vkcv { @@ -239,8 +240,8 @@ namespace vkcv const vk::ApplicationInfo applicationInfo( applicationName, applicationVersion, - "vkCV", - VK_MAKE_VERSION(0, 0, 1), + VKCV_FRAMEWORK_NAME, + VKCV_FRAMEWORK_VERSION, VK_HEADER_VERSION_COMPLETE ); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index bf24089e935302767f2a6b947d68748db8b0313d..6964884361ad9d3956c7e4333a7189680b9099da 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -80,12 +80,19 @@ namespace vkcv GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) { - return m_PipelineManager->createPipeline(config, *m_PassManager); + return m_PipelineManager->createPipeline(config, *m_PassManager, *m_DescriptorManager); } ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) { - return m_ComputePipelineManager->createComputePipeline(config); + std::vector<vk::DescriptorSetLayout> layouts; + layouts.resize(config.m_DescriptorSetLayouts.size()); + + for (size_t i = 0; i < layouts.size(); i++) { + layouts[i] = getDescriptorSetLayout(config.m_DescriptorSetLayouts[i]).vulkanHandle; + } + + return m_ComputePipelineManager->createComputePipeline(config.m_ShaderProgram, layouts); } PassHandle Core::createPass(const PassConfig &config) @@ -261,6 +268,56 @@ namespace vkcv cmdBuffer.setViewport(0, 1, &dynamicViewport); cmdBuffer.setScissor(0, 1, &dynamicScissor); } + + vk::IndexType getIndexType(IndexBitCount indexByteCount){ + switch (indexByteCount) { + case IndexBitCount::Bit16: return vk::IndexType::eUint16; + case IndexBitCount::Bit32: return vk::IndexType::eUint32; + default: + vkcv_log(LogLevel::ERROR, "unknown Enum"); + return vk::IndexType::eUint16; + } + } + + void recordDrawcall( + const Core &core, + const DrawcallInfo &drawcall, + vk::CommandBuffer cmdBuffer, + vk::PipelineLayout pipelineLayout, + const PushConstants &pushConstants, + const size_t drawcallIndex) { + + for (uint32_t i = 0; i < drawcall.mesh.vertexBufferBindings.size(); i++) { + const auto& vertexBinding = drawcall.mesh.vertexBufferBindings[i]; + cmdBuffer.bindVertexBuffers(i, vertexBinding.buffer, vertexBinding.offset); + } + + for (const auto& descriptorUsage : drawcall.descriptorSets) { + cmdBuffer.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + pipelineLayout, + descriptorUsage.setLocation, + core.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle, + nullptr); + } + + if (pushConstants.getSizePerDrawcall() > 0) { + cmdBuffer.pushConstants( + pipelineLayout, + vk::ShaderStageFlagBits::eAll, + 0, + pushConstants.getSizePerDrawcall(), + pushConstants.getDrawcallData(drawcallIndex)); + } + + if (drawcall.mesh.indexBuffer) { + cmdBuffer.bindIndexBuffer(drawcall.mesh.indexBuffer, 0, getIndexType(drawcall.mesh.indexBitCount)); + cmdBuffer.drawIndexed(drawcall.mesh.indexCount, drawcall.instanceCount, 0, 0, {}); + } + else { + cmdBuffer.draw(drawcall.mesh.indexCount, drawcall.instanceCount, 0, 0, {}); + } + } void Core::recordDrawcallsToCmdStream( const CommandStreamHandle& cmdStreamHandle, @@ -316,7 +373,7 @@ namespace vkcv } for (size_t i = 0; i < drawcalls.size(); i++) { - recordDrawcall(drawcalls[i], cmdBuffer, pipelineLayout, pushConstantData, i); + recordDrawcall(*this, drawcalls[i], cmdBuffer, pipelineLayout, pushConstantData, i); } cmdBuffer.endRenderPass(); @@ -483,6 +540,7 @@ namespace vkcv for (size_t i = 0; i < drawcalls.size(); i++) { const uint32_t pushConstantOffset = i * pushConstantData.getSizePerDrawcall(); recordMeshShaderDrawcall( + *this, cmdBuffer, pipelineLayout, pushConstantData, @@ -522,7 +580,7 @@ namespace vkcv vk::PipelineBindPoint::eRayTracingKHR, rtxPipelineLayout, usage.setLocation, - { usage.vulkanHandle }, + { getDescriptorSet(usage.descriptorSet).vulkanHandle }, usage.dynamicOffsets ); } @@ -563,7 +621,7 @@ namespace vkcv vk::PipelineBindPoint::eCompute, pipelineLayout, usage.setLocation, - { usage.vulkanHandle }, + { getDescriptorSet(usage.descriptorSet).vulkanHandle }, usage.dynamicOffsets ); } @@ -642,7 +700,7 @@ namespace vkcv vk::PipelineBindPoint::eCompute, pipelineLayout, usage.setLocation, - { usage.vulkanHandle }, + { getDescriptorSet(usage.descriptorSet).vulkanHandle }, usage.dynamicOffsets ); } @@ -756,8 +814,8 @@ namespace vkcv SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, - float mipLodBias) { - return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias); + float mipLodBias, SamplerBorderColor borderColor) { + return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias, borderColor); } Image Core::createImage( diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp index acc6edd9b704c377480e7acbbc40b3e763003d5f..d60a6d5c6eb1a66db07487c888505e8b3731b046 100644 --- a/src/vkcv/DescriptorManager.hpp +++ b/src/vkcv/DescriptorManager.hpp @@ -1,3 +1,5 @@ +#pragma once + /** * @authors Artur Wasmut, Susanne D�tsch, Simeon Hermann * @file src/vkcv/DescriptorManager.cpp @@ -21,7 +23,7 @@ namespace vkcv explicit DescriptorManager(vk::Device device) noexcept; ~DescriptorManager() noexcept; - DescriptorSetLayoutHandle createDescriptorSetLayout(const std::unordered_map<uint32_t, DescriptorBinding> &setBindingsMap); + DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &setBindingsMap); DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &setLayoutHandle); void writeDescriptorSet( diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp index 638df388178f79f680c3b9f797d9d435e752fe10..e13b4d24148e9d76d8be4ad7fd3db0db87249c59 100644 --- a/src/vkcv/DrawcallRecording.cpp +++ b/src/vkcv/DrawcallRecording.cpp @@ -1,67 +1,9 @@ -#include <vkcv/DrawcallRecording.hpp> -#include <vkcv/Logger.hpp> -namespace vkcv { - - vk::IndexType getIndexType(IndexBitCount indexByteCount){ - switch (indexByteCount) { - case IndexBitCount::Bit16: return vk::IndexType::eUint16; - case IndexBitCount::Bit32: return vk::IndexType::eUint32; - default: - vkcv_log(LogLevel::ERROR, "unknown Enum"); - return vk::IndexType::eUint16; - } - } - - void recordDrawcall( - const DrawcallInfo &drawcall, - vk::CommandBuffer cmdBuffer, - vk::PipelineLayout pipelineLayout, - const PushConstants &pushConstants, - const size_t drawcallIndex) { - - for (uint32_t i = 0; i < drawcall.mesh.vertexBufferBindings.size(); i++) { - const auto& vertexBinding = drawcall.mesh.vertexBufferBindings[i]; - cmdBuffer.bindVertexBuffers(i, vertexBinding.buffer, vertexBinding.offset); - } +#include "vkcv/DrawcallRecording.hpp" +#include "vkcv/Logger.hpp" +#include "vkcv/Core.hpp" - for (const auto& descriptorUsage : drawcall.descriptorSets) { - cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, - pipelineLayout, - descriptorUsage.setLocation, - descriptorUsage.vulkanHandle, - nullptr); - } - - if (pushConstants.getSizePerDrawcall() > 0) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eAll, - 0, - pushConstants.getSizePerDrawcall(), - pushConstants.getDrawcallData(drawcallIndex)); - } - - if (drawcall.mesh.indexBuffer) { - cmdBuffer.bindIndexBuffer(drawcall.mesh.indexBuffer, 0, getIndexType(drawcall.mesh.indexBitCount)); - cmdBuffer.drawIndexed(drawcall.mesh.indexCount, drawcall.instanceCount, 0, 0, {}); - } - else { - cmdBuffer.draw(drawcall.mesh.indexCount, drawcall.instanceCount, 0, 0, {}); - } - } - - void recordIndirectDrawcall( - const DrawcallInfo &drawcall, - vk::CommandBuffer cmdBuffer, - const Buffer <vk::DrawIndexedIndirectCommand> &drawBuffer, - const uint32_t drawCount, - vk::PipelineLayout pipelineLayout, - const PushConstants &pushConstants, - const size_t drawcallIndex) { - return; - } +namespace vkcv { struct MeshShaderFunctions { @@ -78,6 +20,7 @@ namespace vkcv { } void recordMeshShaderDrawcall( + const Core& core, vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, const PushConstants& pushConstantData, @@ -90,7 +33,7 @@ namespace vkcv { vk::PipelineBindPoint::eGraphics, pipelineLayout, descriptorUsage.setLocation, - descriptorUsage.vulkanHandle, + core.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle, nullptr); } diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index 4aefcb90131b5f9d6144d1f870b6fe709cd6c1e7..af4426252d840bdffd7d210d900be64d6b74f6f3 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -296,6 +296,44 @@ m_physicalDevice.getFeatures2(&query) return true; } + bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT& features, bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT); + + vkcv_check_feature(shaderBufferFloat32Atomics); + vkcv_check_feature(shaderBufferFloat32AtomicAdd); + vkcv_check_feature(shaderBufferFloat64Atomics); + vkcv_check_feature(shaderBufferFloat64AtomicAdd); + vkcv_check_feature(shaderSharedFloat32Atomics); + vkcv_check_feature(shaderSharedFloat32AtomicAdd); + vkcv_check_feature(shaderSharedFloat64Atomics); + vkcv_check_feature(shaderSharedFloat64AtomicAdd); + vkcv_check_feature(shaderImageFloat32Atomics); + vkcv_check_feature(shaderImageFloat32AtomicAdd); + vkcv_check_feature(sparseImageFloat32Atomics); + vkcv_check_feature(sparseImageFloat32AtomicAdd); + + return true; + } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT& features, bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT); + + vkcv_check_feature(shaderBufferFloat16Atomics); + vkcv_check_feature(shaderBufferFloat16AtomicAdd); + vkcv_check_feature(shaderBufferFloat16AtomicMinMax); + vkcv_check_feature(shaderBufferFloat32AtomicMinMax); + vkcv_check_feature(shaderBufferFloat64AtomicMinMax); + vkcv_check_feature(shaderSharedFloat16Atomics); + vkcv_check_feature(shaderSharedFloat16AtomicAdd); + vkcv_check_feature(shaderSharedFloat16AtomicMinMax); + vkcv_check_feature(shaderSharedFloat32AtomicMinMax); + vkcv_check_feature(shaderSharedFloat64AtomicMinMax); + vkcv_check_feature(shaderImageFloat32AtomicMinMax); + vkcv_check_feature(sparseImageFloat32AtomicMinMax); + + return true; + } + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan12Features &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceVulkan12Features); diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp index a461051f9784e7d95de7c15c965caa633d3bb35c..ab0d9f26fdf482698f679b598d5b087e3674c638 100644 --- a/src/vkcv/GraphicsPipelineManager.cpp +++ b/src/vkcv/GraphicsPipelineManager.cpp @@ -51,6 +51,8 @@ namespace vkcv return vk::PrimitiveTopology::eLineList; case(PrimitiveTopology::TriangleList): return vk::PrimitiveTopology::eTriangleList; + case(PrimitiveTopology::PatchList): + return vk::PrimitiveTopology::ePatchList; default: vkcv_log(LogLevel::ERROR, "Unknown primitive topology type"); return vk::PrimitiveTopology::eTriangleList; @@ -195,6 +197,15 @@ namespace vkcv return pipelineInputAssemblyStateCreateInfo; } + vk::PipelineTessellationStateCreateInfo createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo( + {}, + config.m_tessellationControlPoints + ); + + return pipelineTessellationStateCreateInfo; + } + /** * Creates a Pipeline Viewport State Create Info Struct with default set viewport and scissor settings. * @param config provides with and height of the output window @@ -350,7 +361,8 @@ namespace vkcv * @param config sets Push Constant Size and Descriptor Layouts. * @return Pipeline Layout Create Info Struct */ - vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(const GraphicsPipelineConfig &config, + const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) { static vk::PushConstantRange pushConstantRange; const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize(); @@ -360,7 +372,7 @@ namespace vkcv vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( {}, - (config.m_DescriptorLayouts), + (descriptorSetLayouts), (pushConstantRange) ); @@ -416,7 +428,9 @@ namespace vkcv return dynamicStateCreateInfo; } - GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager) { + GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, + const PassManager& passManager, + const DescriptorManager& descriptorManager) { const vk::RenderPass &pass = passManager.getVkPass(config.m_PassHandle); const bool existsTaskShader = config.m_ShaderProgram.existsShader(ShaderStage::TASK); @@ -424,7 +438,13 @@ namespace vkcv const bool existsVertexShader = config.m_ShaderProgram.existsShader(ShaderStage::VERTEX); const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT); const bool existsGeometryShader = config.m_ShaderProgram.existsShader(ShaderStage::GEOMETRY); - const bool validGeometryStages = existsVertexShader || (existsTaskShader && existsMeshShader); + const bool existsTessellationControlShader = config.m_ShaderProgram.existsShader(ShaderStage::TESS_CONTROL); + const bool existsTessellationEvaluationShader = config.m_ShaderProgram.existsShader(ShaderStage::TESS_EVAL); + + const bool validGeometryStages = ( + (existsVertexShader && (existsTessellationControlShader == existsTessellationEvaluationShader)) || + (existsTaskShader && existsMeshShader) + ); if (!validGeometryStages) { @@ -529,6 +549,40 @@ namespace vkcv return GraphicsPipelineHandle(); } } + + if (existsTessellationControlShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::TESS_CONTROL, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + if (existsTessellationEvaluationShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::TESS_EVAL, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } // vertex input state // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers @@ -545,6 +599,10 @@ namespace vkcv vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = createPipelineInputAssemblyStateCreateInfo(config); + // tesselation state + vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo = + createPipelineTessellationStateCreateInfo(config); + // viewport state vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = createPipelineViewportStateCreateInfo(config); @@ -570,9 +628,15 @@ namespace vkcv vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = createPipelineDynamicStateCreateInfo(config); + std::vector<vk::DescriptorSetLayout> descriptorSetLayouts; + descriptorSetLayouts.reserve(config.m_DescriptorLayouts.size()); + for (const auto& handle : config.m_DescriptorLayouts) { + descriptorSetLayouts.push_back(descriptorManager.getDescriptorSetLayout(handle).vulkanHandle); + } + // pipeline layout vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = - createPipelineLayoutCreateInfo(config); + createPipelineLayoutCreateInfo(config, descriptorSetLayouts); vk::PipelineLayout vkPipelineLayout{}; if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) { @@ -601,7 +665,7 @@ namespace vkcv shaderStages.data(), &pipelineVertexInputStateCreateInfo, &pipelineInputAssemblyStateCreateInfo, - nullptr, + &pipelineTessellationStateCreateInfo, &pipelineViewportStateCreateInfo, &pipelineRasterizationStateCreateInfo, &pipelineMultisampleStateCreateInfo, diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp index 782603ab0e1ffa9bde05fda96c5d2d259eff1953..09900c37760f07d1967aa56a75cfc8b94aa289d5 100644 --- a/src/vkcv/GraphicsPipelineManager.hpp +++ b/src/vkcv/GraphicsPipelineManager.hpp @@ -13,6 +13,7 @@ #include "vkcv/Handles.hpp" #include "vkcv/GraphicsPipelineConfig.hpp" #include "PassManager.hpp" +#include "DescriptorManager.hpp" namespace vkcv { @@ -36,9 +37,12 @@ namespace vkcv * On application level it is necessary first to fill a PipelineConfig Struct. * @param config Hands over all needed information for pipeline creation. * @param passManager Hands over the corresponding render pass. + * @param descriptorManager Hands over the corresponding descriptor set layouts * @return A Handler to the created Graphics Pipeline Object. */ - GraphicsPipelineHandle createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager); + GraphicsPipelineHandle createPipeline(const GraphicsPipelineConfig &config, + const PassManager& passManager, + const DescriptorManager& descriptorManager); /** * Returns a vk::Pipeline object by handle. diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index bde020498e19e3f9bf0667c7182ca13d11f9044f..bfee504f599d941e625e6ef5c6045805c33a29a1 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -345,7 +345,7 @@ namespace vkcv { recordImageBarrier(cmdBuffer, transitionBarrier); } - constexpr uint32_t getChannelsByFormat(vk::Format format) { + constexpr uint32_t getBytesPerPixel(vk::Format format) { switch (format) { case vk::Format::eR8Unorm: return 1; @@ -353,6 +353,10 @@ namespace vkcv { return 4; case vk::Format::eR8G8B8A8Unorm: return 4; + case vk::Format::eR16G16B16A16Sfloat: + return 8; + case vk::Format::eR32G32B32A32Sfloat: + return 16; default: std::cerr << "Unknown image format" << std::endl; return 4; @@ -379,15 +383,15 @@ namespace vkcv { handle, vk::ImageLayout::eTransferDstOptimal); - uint32_t channels = getChannelsByFormat(image.m_format); const size_t image_size = ( - image.m_width * image.m_height * image.m_depth * channels + image.m_width * image.m_height * image.m_depth * + getBytesPerPixel(image.m_format) ); const size_t max_size = std::min(size, image_size); BufferHandle bufferHandle = m_bufferManager.createBuffer( - BufferType::STAGING, max_size, BufferMemoryType::HOST_VISIBLE, false + BufferType::STAGING, max_size, BufferMemoryType::DEVICE_LOCAL, false ); m_bufferManager.fillBuffer(bufferHandle, data, max_size, 0); diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp index 78bd5808b63fee7333243db4fca640047f76eae9..b203fab4f02afcc8f51b468ab4504480a8e60e4e 100644 --- a/src/vkcv/PassConfig.cpp +++ b/src/vkcv/PassConfig.cpp @@ -11,7 +11,7 @@ namespace vkcv store_operation{store_op}, load_operation{load_op}, format(format) - {}; + {} PassConfig::PassConfig(std::vector<AttachmentDescription> attachments, Multisampling msaa) noexcept : attachments{std::move(attachments) }, msaa(msaa) diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp index 792e6f16b4a05af41a164a1eda9dd7423594857e..9a80635744e5a3dd0b6bd8db476cec841b1c317d 100644 --- a/src/vkcv/SamplerManager.cpp +++ b/src/vkcv/SamplerManager.cpp @@ -18,11 +18,13 @@ namespace vkcv { SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, - float mipLodBias) { + float mipLodBias, + SamplerBorderColor borderColor) { vk::Filter vkMagFilter; vk::Filter vkMinFilter; vk::SamplerMipmapMode vkMipmapMode; vk::SamplerAddressMode vkAddressMode; + vk::BorderColor vkBorderColor; switch (magFilter) { case SamplerFilterType::NEAREST: @@ -70,6 +72,32 @@ namespace vkcv { case SamplerAddressMode::MIRROR_CLAMP_TO_EDGE: vkAddressMode = vk::SamplerAddressMode::eMirrorClampToEdge; break; + case SamplerAddressMode::CLAMP_TO_BORDER: + vkAddressMode = vk::SamplerAddressMode::eClampToBorder; + break; + default: + return SamplerHandle(); + } + + switch (borderColor) { + case SamplerBorderColor::INT_ZERO_OPAQUE: + vkBorderColor = vk::BorderColor::eIntOpaqueBlack; + break; + case SamplerBorderColor::INT_ZERO_TRANSPARENT: + vkBorderColor = vk::BorderColor::eIntTransparentBlack; + break; + case SamplerBorderColor::FLOAT_ZERO_OPAQUE: + vkBorderColor = vk::BorderColor::eFloatOpaqueBlack; + break; + case SamplerBorderColor::FLOAT_ZERO_TRANSPARENT: + vkBorderColor = vk::BorderColor::eFloatTransparentBlack; + break; + case SamplerBorderColor::INT_ONE_OPAQUE: + vkBorderColor = vk::BorderColor::eIntOpaqueWhite; + break; + case SamplerBorderColor::FLOAT_ONE_OPAQUE: + vkBorderColor = vk::BorderColor::eFloatOpaqueWhite; + break; default: return SamplerHandle(); } @@ -89,7 +117,7 @@ namespace vkcv { vk::CompareOp::eAlways, -1000.0f, 1000.0f, - vk::BorderColor::eIntOpaqueBlack, + vkBorderColor, false ); diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp index aea47a03714b417314a09dfc0be855df31fbb557..128faa711993ac052cf774a1d31144d19362658f 100644 --- a/src/vkcv/SamplerManager.hpp +++ b/src/vkcv/SamplerManager.hpp @@ -30,10 +30,11 @@ namespace vkcv { SamplerManager& operator=(SamplerManager&& other) = delete; SamplerHandle createSampler(SamplerFilterType magFilter, - SamplerFilterType minFilter, - SamplerMipmapMode mipmapMode, - SamplerAddressMode addressMode, - float mipLodBias); + SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, + SamplerAddressMode addressMode, + float mipLodBias, + SamplerBorderColor borderColor); [[nodiscard]] vk::Sampler getVulkanSampler(const SamplerHandle& handle) const;