diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index d5cc376c9507f26c8d41b4e85c5d916e1815f827..e8ce984d7daa945c5436c51e896e797a0da22b84 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -314,6 +314,14 @@ namespace vkcv */ [[nodiscard]] uint32_t getImageHeight(const ImageHandle &image); + + /** + * Returns the image depth + * @param image handle + * @return imageDepth + */ + [[nodiscard]] + uint32_t getImageDepth(const ImageHandle &image); /** * Returns the image format of the image @@ -331,6 +339,15 @@ namespace vkcv */ [[nodiscard]] uint32_t getImageMipLevels(const ImageHandle &image); + + /** + * @brief Returns the images amount of array layers. + * + * @param image Image handle + * @return Amount of array layers + */ + [[nodiscard]] + uint32_t getImageArrayLayers(const ImageHandle &image); /** * @brief Creates a descriptor set layout handle by a set of descriptor bindings. diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp index bc2435f6246f616c907e206e4a3de62aafaebebc..8e4f3df2fad31f2a358f5f6b7f5ba4e0c14bd6e0 100644 --- a/include/vkcv/DescriptorConfig.hpp +++ b/include/vkcv/DescriptorConfig.hpp @@ -68,6 +68,7 @@ namespace vkcv uint32_t descriptorCount; ShaderStages shaderStages; bool variableCount; + bool partialBinding; bool operator ==(const DescriptorBinding &other) const; }; diff --git a/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp b/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp index 588fe9255a2f1f612e06be86a72d61a1bfb3d42a..0b5a71cd27e64acebe6afb08f7d27e40b0a9dcd0 100644 --- a/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp +++ b/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp @@ -21,7 +21,6 @@ namespace vkcv::algorithm { int numWorkGroupsPerSlice; int workGroupOffset[2]; float invInputSize[2]; - float padding[2]; }; class SinglePassDownsampler : public vkcv::Downsampler { diff --git a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp index 65ecfc85ec1ed0d7588dcb22ee4c8df4c3f235b6..6d55bfd7212e350bc4611183010ed12cbd5bde4b 100644 --- a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp +++ b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp @@ -27,7 +27,8 @@ namespace vkcv::algorithm { DescriptorType::IMAGE_STORAGE, SPD_MAX_MIP_LEVELS + 1, ShaderStage::COMPUTE, - false + false, + true }; auto binding_1 = DescriptorBinding { @@ -35,6 +36,7 @@ namespace vkcv::algorithm { DescriptorType::IMAGE_STORAGE, 1, ShaderStage::COMPUTE, + false, false }; @@ -43,6 +45,7 @@ namespace vkcv::algorithm { DescriptorType::STORAGE_BUFFER, 1, ShaderStage::COMPUTE, + false, false }; @@ -50,14 +53,18 @@ namespace vkcv::algorithm { 3, DescriptorType::IMAGE_SAMPLED, 1, - ShaderStage::COMPUTE + ShaderStage::COMPUTE, + false, + false }; auto binding_4 = DescriptorBinding{ 4, DescriptorType::SAMPLER, 1, - ShaderStage::COMPUTE + ShaderStage::COMPUTE, + false, + false }; descriptorBindings.insert(std::make_pair(0, binding_0)); @@ -195,9 +202,10 @@ namespace vkcv::algorithm { ); } - m_pipeline = m_core.createComputePipeline({program,{ - m_descriptorSetLayout - }}); + m_pipeline = m_core.createComputePipeline({ + program, + { m_descriptorSetLayout } + }); uint32_t zeroes [m_globalCounter.getCount()]; memset(zeroes, 0, m_globalCounter.getSize()); @@ -207,8 +215,11 @@ namespace vkcv::algorithm { void SinglePassDownsampler::recordDownsampling(const CommandStreamHandle &cmdStream, const ImageHandle &image) { const uint32_t mipLevels = m_core.getImageMipLevels(image); + const uint32_t depth = m_core.getImageDepth(image); + + m_core.prepareImageForSampling(cmdStream, image); - if (mipLevels < 7) { + if ((mipLevels < 4) || (depth > 1)) { m_core.getDownsampler().recordDownsampling(cmdStream, image); return; } @@ -262,7 +273,7 @@ namespace vkcv::algorithm { uint32_t dispatch [3]; dispatch[0] = dispatchThreadGroupCountXY[0]; dispatch[1] = dispatchThreadGroupCountXY[1]; - dispatch[2] = 1; // TODO: No array size supported by images yet! + dispatch[2] = m_core.getImageArrayLayers(image); vkcv::PushConstants pushConstants (m_sampler? sizeof(SPDConstantsSampler) : sizeof(SPDConstants)); diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index 2d09f8a3137816e441c0fd4cf0e46da030356c5b..a4b967b33f47110df42ca02849fbeb06b4a024f8 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -236,7 +236,8 @@ void ShadowMapping::recordShadowMapRendering( const vkcv::camera::Camera& camera, const glm::vec3& voxelVolumeOffset, float voxelVolumeExtent, - const vkcv::WindowHandle& windowHandle) { + const vkcv::WindowHandle& windowHandle, + vkcv::Downsampler& downsampler) { LightInfo lightInfo; lightInfo.sunColor = lightColor; @@ -260,7 +261,6 @@ void ShadowMapping::recordShadowMapRendering( shadowPushConstants.appendDrawcall(lightInfo.lightMatrix * m); } - std::vector<vkcv::DrawcallInfo> drawcalls; for (const auto& mesh : meshes) { drawcalls.push_back(vkcv::DrawcallInfo(mesh, {})); @@ -321,7 +321,7 @@ void ShadowMapping::recordShadowMapRendering( dispatchCount, { vkcv::DescriptorSetUsage(0, m_shadowBlurYDescriptorSet) }, vkcv::PushConstants(0)); - m_shadowMap.recordMipChainGeneration(cmdStream, m_corePtr->getDownsampler()); + m_shadowMap.recordMipChainGeneration(cmdStream, downsampler); m_corePtr->recordEndDebugLabel(cmdStream); } diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 3067307b444d4cee18caccaf58a94a13584dc774..14fef77df51632977f4c4eade4ebcdc28ba56b68 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -1,6 +1,7 @@ #pragma once #include <vkcv/Core.hpp> #include <vkcv/camera/Camera.hpp> +#include <vkcv/Downsampler.hpp> #include <glm/glm.hpp> #define GLM_ENABLE_EXPERIMENTAL // use this before inclusion, else error! @@ -29,7 +30,8 @@ public: const vkcv::camera::Camera& camera, const glm::vec3& voxelVolumeOffset, float voxelVolumeExtent, - const vkcv::WindowHandle& windowHandle); + const vkcv::WindowHandle& windowHandle, + vkcv::Downsampler& downsampler); vkcv::ImageHandle getShadowMap(); vkcv::SamplerHandle getShadowSampler(); diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index 523a7a672ba09a259c77e2ee568a06c92533832e..b30d8a7fa1e9cb56158903de4b11c24ddc503b94 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -229,7 +229,8 @@ void Voxelization::voxelizeMeshes( const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets, - const vkcv::WindowHandle& windowHandle) { + const vkcv::WindowHandle& windowHandle, + vkcv::Downsampler& downsampler) { m_voxelInfoBuffer.fill({ m_voxelInfo }); @@ -314,7 +315,7 @@ void Voxelization::voxelizeMeshes( // intermediate image mipchain m_corePtr->recordBeginDebugLabel(cmdStream, "Intermediate Voxel mipmap generation", { 1, 1, 1, 1 }); - m_voxelImageIntermediate.recordMipChainGeneration(cmdStream, m_corePtr->getDownsampler()); + m_voxelImageIntermediate.recordMipChainGeneration(cmdStream, downsampler); m_corePtr->recordEndDebugLabel(cmdStream); // secondary bounce @@ -326,12 +327,12 @@ void Voxelization::voxelizeMeshes( bufferToImageDispatchCount, { vkcv::DescriptorSetUsage(0, m_secondaryBounceDescriptorSet) }, vkcv::PushConstants(0)); - m_voxelImage.recordMipChainGeneration(cmdStream, m_corePtr->getDownsampler()); + m_voxelImage.recordMipChainGeneration(cmdStream, downsampler); m_corePtr->recordEndDebugLabel(cmdStream); // final image mipchain m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel mipmap generation", { 1, 1, 1, 1 }); - m_voxelImage.recordMipChainGeneration(cmdStream, m_corePtr->getDownsampler()); + m_voxelImage.recordMipChainGeneration(cmdStream, downsampler); m_corePtr->recordEndDebugLabel(cmdStream); } diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index d5f41123b527f2919dec678d0337ee25ea6fa2c6..866efaf47354bc0a53ebd500d06dc4a49b0ed690 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -2,6 +2,7 @@ #include <vkcv/Core.hpp> #include <glm/glm.hpp> #include <vkcv/camera/Camera.hpp> +#include <vkcv/Downsampler.hpp> class Voxelization{ public: @@ -24,7 +25,8 @@ public: const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets, - const vkcv::WindowHandle& windowHandle); + const vkcv::WindowHandle& windowHandle, + vkcv::Downsampler& downsampler); void renderVoxelVisualisation( vkcv::CommandStreamHandle cmdStream, diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 4380a23b2cdc30c007c4fceb8e137062d3a80004..4aa285deb81ead2e078fb59f3c59e852fb6c4627 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -23,6 +23,13 @@ int main(int argc, const char** argv) { vkcv::Features features; features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + features.requireExtensionFeature<vk::PhysicalDeviceDescriptorIndexingFeatures>( + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, + [](vk::PhysicalDeviceDescriptorIndexingFeatures& features) { + features.setDescriptorBindingPartiallyBound(true); + } + ); + features.tryExtensionFeature<vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures>( VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME, [](vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures& features) { @@ -251,7 +258,7 @@ int main(int argc, const char** argv) { std::vector<vkcv::DescriptorSetHandle> materialDescriptorSets; std::vector<vkcv::Image> sceneImages; - vkcv::algorithm::SinglePassDownsampler spdDownsampler (core); + vkcv::algorithm::SinglePassDownsampler spdDownsampler (core, colorSampler); vkcv::Downsampler &downsampler = core.getDownsampler(); auto mipStream = core.createCommandStream(vkcv::QueueType::Graphics); @@ -775,7 +782,9 @@ int main(int argc, const char** argv) { cameraManager.getActiveCamera(), voxelization.getVoxelOffset(), voxelization.getVoxelExtent(), - windowHandle); + windowHandle, + spdDownsampler + ); // voxelization voxelization.setVoxelExtent(voxelizationExtent); @@ -784,7 +793,9 @@ int main(int argc, const char** argv) { meshes, modelMatrices, perMeshDescriptorSets, - windowHandle); + windowHandle, + spdDownsampler + ); // depth prepass const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index df7050ccc94e3c3688f7f74dca7fd923fc4e74af..808e0c68407fdd6a2f5dd1df962af01f82c760a1 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -891,6 +891,11 @@ namespace vkcv return m_ImageManager->getImageHeight(image); } + uint32_t Core::getImageDepth(const ImageHandle& image) + { + return m_ImageManager->getImageDepth(image); + } + vk::Format Core::getImageFormat(const ImageHandle& image) { return m_ImageManager->getImageFormat(image); } @@ -898,6 +903,10 @@ namespace vkcv uint32_t Core::getImageMipLevels(const ImageHandle &image) { return m_ImageManager->getImageMipCount(image); } + + uint32_t Core::getImageArrayLayers(const ImageHandle &image) { + return m_ImageManager->getImageArrayLayers(image); + } Swapchain& Core::getSwapchainOfCurrentWindow() { return m_SwapchainManager->getSwapchain(Window::getFocusedWindow().getSwapchainHandle()); diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index 127eb8050ad1a43930013706cd721049811ce2d3..a9cabbd4b65bd8e460bc3506338497992ded890a 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -81,14 +81,15 @@ namespace vkcv nullptr ); - if (binding.variableCount) { - bindingsFlags.push_back( - vk::DescriptorBindingFlagBits::eVariableDescriptorCount | - vk::DescriptorBindingFlagBits::ePartiallyBound - ); - } else { - bindingsFlags.emplace_back(); - } + vk::DescriptorBindingFlags flags; + + if (binding.variableCount) + flags |= vk::DescriptorBindingFlagBits::eVariableDescriptorCount; + + if (binding.partialBinding) + flags |= vk::DescriptorBindingFlagBits::ePartiallyBound; + + bindingsFlags.push_back(flags); } vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo ( diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index 1e4e3a5b7dffc1891c8c60ee0db1214bf67d3280..b58fe3c56a60d3ba619b1d11859271dd198bc6b7 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -125,6 +125,10 @@ namespace vkcv { imageViewType = vk::ImageViewType::e2D; } + if (vk::ImageType::e3D == imageType) { + createFlags |= vk::ImageCreateFlagBits::e2DArrayCompatible; + } + if (!formatProperties.optimalTilingFeatures) { if (!formatProperties.linearTilingFeatures) return ImageHandle(); @@ -188,53 +192,51 @@ namespace vkcv { std::vector<vk::ImageView> arrayViews; for (uint32_t mip = 0; mip < mipCount; mip++) { - { - const vk::ImageViewCreateInfo imageViewCreateInfo( - {}, - image, - imageViewType, - format, - vk::ComponentMapping( - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity - ), - vk::ImageSubresourceRange( - aspectFlags, - mip, - mipCount - mip, - 0, - arrayLayers - ) - ); - - views.push_back(device.createImageView(imageViewCreateInfo)); - } + const vk::ImageViewCreateInfo imageViewCreateInfo( + {}, + image, + imageViewType, + format, + vk::ComponentMapping( + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity + ), + vk::ImageSubresourceRange( + aspectFlags, + mip, + mipCount - mip, + 0, + arrayLayers + ) + ); - { - const vk::ImageViewCreateInfo imageViewCreateInfo( - {}, - image, - vk::ImageViewType::e2DArray, - format, - vk::ComponentMapping( - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity - ), - vk::ImageSubresourceRange( - aspectFlags, - mip, - 1, - 0, - arrayLayers - ) - ); - - arrayViews.push_back(device.createImageView(imageViewCreateInfo)); - } + views.push_back(device.createImageView(imageViewCreateInfo)); + } + + for (uint32_t mip = 0; mip < mipCount; mip++) { + const vk::ImageViewCreateInfo imageViewCreateInfo( + {}, + image, + vk::ImageViewType::e2DArray, + format, + vk::ComponentMapping( + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity + ), + vk::ImageSubresourceRange( + aspectFlags, + mip, + 1, + 0, + arrayLayers + ) + ); + + arrayViews.push_back(device.createImageView(imageViewCreateInfo)); } const uint64_t id = m_images.size(); @@ -253,6 +255,7 @@ namespace vkcv { arrayLayers, vk::ImageLayout::eUndefined }); + return ImageHandle(id, [&](uint64_t id) { destroyImageById(id); }); } @@ -395,7 +398,9 @@ namespace vkcv { transitionBarrier ); }, - nullptr); + nullptr + ); + image.m_layout = newLayout; } @@ -760,6 +765,21 @@ namespace vkcv { return m_images[id].m_viewPerMip.size(); } + + uint32_t ImageManager::getImageArrayLayers(const ImageHandle& handle) const { + const uint64_t id = handle.getId(); + + if (handle.isSwapchainImage()) { + return m_swapchainImages[0].m_layers; + } + + if (id >= m_images.size()) { + vkcv_log(LogLevel::ERROR, "Invalid handle"); + return 0; + } + + return m_images[id].m_layers; + } void ImageManager::setCurrentSwapchainImageIndex(int index) { m_currentSwapchainInputImage = index; diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index dec46c6fff84e1b78192e2e64ecd120a8368cb77..84d41d3457d1d5a2869f08ba1401ddc3decbbc26 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -133,6 +133,9 @@ namespace vkcv { [[nodiscard]] uint32_t getImageMipCount(const ImageHandle& handle) const; + + [[nodiscard]] + uint32_t getImageArrayLayers(const ImageHandle& handle) const; void setCurrentSwapchainImageIndex(int index); diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp index 97eea880cbc38fee1a71d52a1e154471344d7758..e1af4e1bbea54024773bcf7f8d3090643d7a0186 100644 --- a/src/vkcv/ShaderProgram.cpp +++ b/src/vkcv/ShaderProgram.cpp @@ -167,11 +167,14 @@ namespace vkcv { variableCount = true; } - DescriptorBinding binding{bindingID, - DescriptorType::UNIFORM_BUFFER, - descriptorCount, - shaderStage, - variableCount}; + DescriptorBinding binding { + bindingID, + DescriptorType::UNIFORM_BUFFER, + descriptorCount, + shaderStage, + variableCount, + variableCount // partialBinding == variableCount + }; auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); if(!insertionResult.second) @@ -202,12 +205,14 @@ namespace vkcv { variableCount = true; } - DescriptorBinding binding{bindingID, - DescriptorType::STORAGE_BUFFER, - descriptorCount, - shaderStage, - variableCount}; - + DescriptorBinding binding { + bindingID, + DescriptorType::STORAGE_BUFFER, + descriptorCount, + shaderStage, + variableCount, + variableCount // partialBinding == variableCount + }; auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); if(!insertionResult.second) @@ -237,11 +242,14 @@ namespace vkcv { variableCount = true; } - DescriptorBinding binding {bindingID, - DescriptorType::SAMPLER, - descriptorCount, - shaderStage, - variableCount}; + DescriptorBinding binding { + bindingID, + DescriptorType::SAMPLER, + descriptorCount, + shaderStage, + variableCount, + variableCount // partialBinding == variableCount + }; auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); if(!insertionResult.second) @@ -271,11 +279,14 @@ namespace vkcv { variableCount = true; } - DescriptorBinding binding {bindingID, - DescriptorType::IMAGE_SAMPLED, - descriptorCount, - shaderStage, - variableCount}; + DescriptorBinding binding { + bindingID, + DescriptorType::IMAGE_SAMPLED, + descriptorCount, + shaderStage, + variableCount, + variableCount // partialBinding == variableCount + }; auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); if(!insertionResult.second) @@ -305,11 +316,14 @@ namespace vkcv { variableCount = true; } - DescriptorBinding binding {bindingID, - DescriptorType::IMAGE_STORAGE, - descriptorCount, - shaderStage, - variableCount}; + DescriptorBinding binding { + bindingID, + DescriptorType::IMAGE_STORAGE, + descriptorCount, + shaderStage, + variableCount, + variableCount // partialBinding == variableCount + }; auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); if(!insertionResult.second) @@ -333,6 +347,7 @@ namespace vkcv { DescriptorType::ACCELERATION_STRUCTURE_KHR, base_type.vecsize, shaderStage, + false, false };