From 4318961c79cc03fc052101b6e9a8bdd74cdca44a Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Thu, 17 Jun 2021 15:44:25 +0200 Subject: [PATCH] [#70] Voxelization now uses buffer in preparation for additional voxel info --- include/vkcv/BufferManager.hpp | 3 + include/vkcv/Core.hpp | 3 +- .../voxelization/resources/shaders/voxel.inc | 8 +++ .../resources/shaders/voxelBufferToImage.comp | 22 +++++++ .../resources/shaders/voxelInfo.inc | 4 -- .../resources/shaders/voxelReset.comp | 16 +++-- .../resources/shaders/voxelVisualisation.vert | 2 +- .../resources/shaders/voxelization.frag | 18 ++++-- projects/voxelization/src/Voxelization.cpp | 62 +++++++++++++++---- projects/voxelization/src/Voxelization.hpp | 11 +++- src/vkcv/BufferManager.cpp | 30 +++++++++ src/vkcv/Core.cpp | 6 ++ 12 files changed, 156 insertions(+), 29 deletions(-) create mode 100644 projects/voxelization/resources/shaders/voxel.inc create mode 100644 projects/voxelization/resources/shaders/voxelBufferToImage.comp delete mode 100644 projects/voxelization/resources/shaders/voxelInfo.inc diff --git a/include/vkcv/BufferManager.hpp b/include/vkcv/BufferManager.hpp index a390a2ff..9eb80d70 100644 --- a/include/vkcv/BufferManager.hpp +++ b/include/vkcv/BufferManager.hpp @@ -132,6 +132,9 @@ namespace vkcv */ void unmapBuffer(const BufferHandle& handle); + void recordBufferMemoryBarrier( + const BufferHandle& handle, + vk::CommandBuffer cmdBuffer); }; } diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index af186fe2..3d21e4bb 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -276,5 +276,6 @@ namespace vkcv void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image); void prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image); void recordImageMemoryBarrier(const CommandStreamHandle cmdStream, const ImageHandle image); - }; + void recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer); + }; } diff --git a/projects/voxelization/resources/shaders/voxel.inc b/projects/voxelization/resources/shaders/voxel.inc new file mode 100644 index 00000000..5e56878a --- /dev/null +++ b/projects/voxelization/resources/shaders/voxel.inc @@ -0,0 +1,8 @@ +struct VoxelInfo{ + vec3 offset; + float extent; +}; + +uint flattenVoxelUVToIndex(ivec3 UV, ivec3 voxelImageSize){ + return UV.x + UV.y * voxelImageSize.x + UV.z * voxelImageSize.x* voxelImageSize.y; +} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelBufferToImage.comp b/projects/voxelization/resources/shaders/voxelBufferToImage.comp new file mode 100644 index 00000000..4c5d73c0 --- /dev/null +++ b/projects/voxelization/resources/shaders/voxelBufferToImage.comp @@ -0,0 +1,22 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#include "voxel.inc" + +layout(set=0, binding=0) buffer voxelBuffer{ + uint isFilled[]; +}; + +layout(set=0, binding=1, r8) uniform image3D voxelImage; + +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; + +void main(){ + + ivec3 voxelImageSize = imageSize(voxelImage); + if(any(greaterThanEqual(gl_GlobalInvocationID, voxelImageSize))){ + return; + } + ivec3 UV = ivec3(gl_GlobalInvocationID); + uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); + imageStore(voxelImage, UV, vec4(isFilled[flatIndex], vec3(0))); +} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelInfo.inc b/projects/voxelization/resources/shaders/voxelInfo.inc deleted file mode 100644 index c8ef9c6c..00000000 --- a/projects/voxelization/resources/shaders/voxelInfo.inc +++ /dev/null @@ -1,4 +0,0 @@ -struct VoxelInfo{ - vec3 offset; - float extent; -}; \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelReset.comp b/projects/voxelization/resources/shaders/voxelReset.comp index ca67b74c..bbbc2965 100644 --- a/projects/voxelization/resources/shaders/voxelReset.comp +++ b/projects/voxelization/resources/shaders/voxelReset.comp @@ -1,13 +1,19 @@ -#version 440 +#version 450 -layout(set=0, binding=0, r8) uniform image3D voxelImage; +layout(set=0, binding=0) buffer voxelizationBuffer{ + uint isFilled[]; +}; -layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout( push_constant ) uniform constants{ + int voxelCount; +}; void main(){ - if(any(greaterThanEqual(gl_GlobalInvocationID, imageSize(voxelImage)))){ + if(gl_GlobalInvocationID.x> voxelCount){ return; } - imageStore(voxelImage, ivec3(gl_GlobalInvocationID), vec4(0.f)); + isFilled[gl_GlobalInvocationID.x] = 0; } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelVisualisation.vert b/projects/voxelization/resources/shaders/voxelVisualisation.vert index 9884087d..0b1bb57e 100644 --- a/projects/voxelization/resources/shaders/voxelVisualisation.vert +++ b/projects/voxelization/resources/shaders/voxelVisualisation.vert @@ -2,7 +2,7 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_GOOGLE_include_directive : enable -#include "voxelInfo.inc" +#include "voxel.inc" layout(location = 0) out float passCubeHalf; diff --git a/projects/voxelization/resources/shaders/voxelization.frag b/projects/voxelization/resources/shaders/voxelization.frag index 0b946fbb..9be9c259 100644 --- a/projects/voxelization/resources/shaders/voxelization.frag +++ b/projects/voxelization/resources/shaders/voxelization.frag @@ -2,15 +2,20 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_GOOGLE_include_directive : enable -#include "voxelInfo.inc" +#include "voxel.inc" layout(location = 0) in vec3 passPos; -layout(set=0, binding=0, r8) uniform image3D voxelImage; +layout(set=0, binding=0) buffer voxelizationBuffer{ + uint isFilled[]; +}; + layout(set=0, binding=1) uniform voxelizationInfo{ VoxelInfo voxelInfo; }; +layout(set=0, binding=2, r8) uniform image3D voxelImage; + vec3 worldToVoxelCoordinates(vec3 world, VoxelInfo info){ return (world - info.offset) / info.extent + 0.5f; } @@ -21,10 +26,11 @@ ivec3 voxelCoordinatesToUV(vec3 voxelCoordinates, ivec3 voxelImageResolution){ void main() { vec3 voxelCoordinates = worldToVoxelCoordinates(passPos, voxelInfo); - ivec3 voxeImageSize = imageSize(voxelImage); - ivec3 UV = voxelCoordinatesToUV(voxelCoordinates, voxeImageSize); - if(any(lessThan(UV, ivec3(0))) || any(greaterThanEqual(UV, voxeImageSize))){ + ivec3 voxelImageSize = imageSize(voxelImage); + ivec3 UV = voxelCoordinatesToUV(voxelCoordinates, voxelImageSize); + if(any(lessThan(UV, ivec3(0))) || any(greaterThanEqual(UV, voxelImageSize))){ return; } - imageStore(voxelImage, UV, vec4(1)); + uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); + isFilled[flatIndex] = 1; } \ No newline at end of file diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index 6559fbf2..17a9d82d 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -48,17 +48,28 @@ vkcv::ShaderProgram loadVoxelResetShader() { return shader; } +vkcv::ShaderProgram loadVoxelBufferToImageShader() { + vkcv::shader::GLSLCompiler compiler; + vkcv::ShaderProgram shader; + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelBufferToImage.comp", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + const uint32_t voxelResolution = 32; const size_t voxelCount = voxelResolution * voxelResolution * voxelResolution; const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies) - : + : m_corePtr(corePtr), m_voxelImage(m_corePtr->createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true)), m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true)), m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)), - m_visualisationIndexBuffer(m_corePtr->createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount)) { + m_visualisationIndexBuffer(m_corePtr->createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount)), + m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){ const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader(); @@ -84,8 +95,9 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig); vkcv::DescriptorWrites voxelizationDescriptorWrites; - voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + voxelizationDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; voxelizationDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) }; + voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImage.getHandle()) }; m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites); vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader(); @@ -130,7 +142,7 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies vkcv::DescriptorWrites voxelVisualisationDescriptorWrite; voxelVisualisationDescriptorWrite.storageImageWrites = - { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; voxelVisualisationDescriptorWrite.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) }; m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite); @@ -145,8 +157,21 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies { m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).layout }); vkcv::DescriptorWrites resetVoxelWrites; - resetVoxelWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + resetVoxelWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites); + + + vkcv::ShaderProgram bufferToImageShader = loadVoxelBufferToImageShader(); + + m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(bufferToImageShader.getReflectedDescriptors()[0]); + m_bufferToImagePipe = m_corePtr->createComputePipeline( + bufferToImageShader, + { m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).layout }); + + vkcv::DescriptorWrites bufferToImageDescriptorWrites; + bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; + bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImage.getHandle()) }; + m_corePtr->writeDescriptorSet(m_bufferToImageDescriptorSet, bufferToImageDescriptorWrites); } void Voxelization::voxelizeMeshes( @@ -184,11 +209,11 @@ void Voxelization::voxelizeMeshes( const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4)); // reset voxels - const uint32_t resetVoxelGroupSize[3] = { 4, 4, 4 }; + const uint32_t resetVoxelGroupSize = 64; uint32_t resetVoxelDispatchCount[3]; - for (int i = 0; i < 3; i++) { - resetVoxelDispatchCount[i] = glm::ceil(voxelResolution / float(resetVoxelGroupSize[i])); - } + resetVoxelDispatchCount[0] = glm::ceil(voxelCount / float(resetVoxelGroupSize)); + resetVoxelDispatchCount[1] = 1; + resetVoxelDispatchCount[2] = 1; m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle()); m_corePtr->recordComputeDispatchToCmdStream( @@ -197,8 +222,9 @@ void Voxelization::voxelizeMeshes( resetVoxelDispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) }, vkcv::PushConstantData(nullptr, 0)); - m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); + m_corePtr->recordBufferMemoryBarrier(cmdStream, m_voxelBuffer.getHandle()); + // voxelization std::vector<vkcv::DrawcallInfo> drawcalls; for (const auto& mesh : meshes) { drawcalls.push_back(vkcv::DrawcallInfo( @@ -206,7 +232,6 @@ void Voxelization::voxelizeMeshes( { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle) })); } - // voxelization m_corePtr->recordDrawcallsToCmdStream( cmdStream, m_voxelizationPass, @@ -214,6 +239,21 @@ void Voxelization::voxelizeMeshes( voxelizationPushConstantData, drawcalls, { m_dummyRenderTarget.getHandle() }); + + // buffer to image + const uint32_t bufferToImageGroupSize[3] = { 4, 4, 4 }; + uint32_t bufferToImageDispatchCount[3]; + for (int i = 0; i < 3; i++) { + bufferToImageDispatchCount[i] = glm::ceil(voxelResolution / float(bufferToImageGroupSize[i])); + } + + m_corePtr->recordComputeDispatchToCmdStream( + cmdStream, + m_bufferToImagePipe, + bufferToImageDispatchCount, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).vulkanHandle) }, + vkcv::PushConstantData(nullptr, 0)); + m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); } diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index 7b569db2..db1f1d85 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -25,7 +25,13 @@ public: private: vkcv::Core* m_corePtr; - vkcv::Image m_voxelImage; + struct VoxelBufferContent{ + uint32_t isFilled; + }; + + vkcv::Image m_voxelImage; + vkcv::Buffer<VoxelBufferContent> m_voxelBuffer; + vkcv::Image m_dummyRenderTarget; vkcv::PassHandle m_voxelizationPass; vkcv::PipelineHandle m_voxelizationPipe; @@ -34,6 +40,9 @@ private: vkcv::PipelineHandle m_voxelResetPipe; vkcv::DescriptorSetHandle m_voxelResetDescriptorSet; + vkcv::PipelineHandle m_bufferToImagePipe; + vkcv::DescriptorSetHandle m_bufferToImageDescriptorSet; + vkcv::PassHandle m_visualisationPass; vkcv::PipelineHandle m_visualisationPipe; vkcv::Buffer<uint16_t> m_visualisationIndexBuffer; diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index 6d494c4e..4df411c1 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -5,6 +5,7 @@ #include "vkcv/BufferManager.hpp" #include "vkcv/Core.hpp" +#include <vkcv/Logger.hpp> namespace vkcv { @@ -335,4 +336,33 @@ namespace vkcv { } } + void BufferManager ::recordBufferMemoryBarrier(const BufferHandle& handle, vk::CommandBuffer cmdBuffer) { + + const uint64_t id = handle.getId(); + + if (id >= m_buffers.size()) { + vkcv_log(vkcv::LogLevel::ERROR, "Invalid buffer handle"); + return; + } + + auto& buffer = m_buffers[id]; + + vk::BufferMemoryBarrier memoryBarrier( + vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, + 0, + 0, + buffer.m_handle, + 0, + buffer.m_size); + + cmdBuffer.pipelineBarrier( + vk::PipelineStageFlagBits::eTopOfPipe, + vk::PipelineStageFlagBits::eBottomOfPipe, + {}, + nullptr, + memoryBarrier, + nullptr); + } + } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 1531bc2b..86d8b518 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -501,4 +501,10 @@ namespace vkcv m_ImageManager->recordImageMemoryBarrier(image, cmdBuffer); }, nullptr); } + + void Core::recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer) { + recordCommandsToStream(cmdStream, [buffer, this](const vk::CommandBuffer cmdBuffer) { + m_BufferManager->recordBufferMemoryBarrier(buffer, cmdBuffer); + }, nullptr); + } } -- GitLab