From ea971356785153ffedfc27642c02ba9756f88be7 Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Wed, 23 Jun 2021 23:15:28 +0200 Subject: [PATCH] [#82] Add MSAA to moment shadow map --- include/vkcv/ImageConfig.hpp | 1 + .../resources/shaders/depthToMoments.comp | 36 +++++++++ .../resources/shaders/shadow.frag | 17 +---- .../resources/shaders/shadow.vert | 5 -- projects/voxelization/src/ShadowMapping.cpp | 73 ++++++++++++++----- projects/voxelization/src/ShadowMapping.hpp | 18 +++-- src/vkcv/ImageConfig.cpp | 10 +++ 7 files changed, 111 insertions(+), 49 deletions(-) create mode 100644 projects/voxelization/resources/shaders/depthToMoments.comp diff --git a/include/vkcv/ImageConfig.hpp b/include/vkcv/ImageConfig.hpp index 8f5b46a5..2e413b97 100644 --- a/include/vkcv/ImageConfig.hpp +++ b/include/vkcv/ImageConfig.hpp @@ -5,4 +5,5 @@ namespace vkcv { enum class Multisampling { None, MSAA2X, MSAA4X, MSAA8X }; vk::SampleCountFlagBits msaaToVkSampleCountFlag(Multisampling msaa); + uint32_t msaaToSampleCount(Multisampling msaa); } diff --git a/projects/voxelization/resources/shaders/depthToMoments.comp b/projects/voxelization/resources/shaders/depthToMoments.comp new file mode 100644 index 00000000..5d327f54 --- /dev/null +++ b/projects/voxelization/resources/shaders/depthToMoments.comp @@ -0,0 +1,36 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#extension GL_ARB_texture_multisample : enable + +#include "shadowMapping.inc" + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(set=0, binding=0) uniform texture2DMS srcTexture; +layout(set=0, binding=1) uniform sampler depthSampler; +layout(set=0, binding=2, r11f_g11f_b10f) uniform image2D outImage; + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout( push_constant ) uniform constants{ + int msaaCount; +}; + +void main(){ + + if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){ + return; + } + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + + float z = 0; + for(int i = 0; i < msaaCount; i++){ + z += texelFetch(sampler2DMS(srcTexture, depthSampler), uv, i).r; + } + z /= msaaCount; + + float z2 = z*z; + vec4 moments = vec4(z, z2, z2*z, z2*z2); + vec4 momentsQuantized = quantizeMoments(moments); + imageStore(outImage, uv, momentsQuantized); +} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadow.frag b/projects/voxelization/resources/shaders/shadow.frag index f98dc436..65592d2c 100644 --- a/projects/voxelization/resources/shaders/shadow.frag +++ b/projects/voxelization/resources/shaders/shadow.frag @@ -2,21 +2,6 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_GOOGLE_include_directive : enable -#include "lightInfo.inc" -#include "shadowMapping.inc" - -layout(set=0, binding=0) uniform LightInfoBuffer { - LightInfo lightInfo; -}; - -layout(location = 0) out vec4 outMoments; - -layout(location = 0) in vec4 passPos; - void main() { - float z = passPos.z / passPos.w; - float z2 = z*z; - outMoments = vec4(z, z2, z2*z, z2*z2); - - outMoments = quantizeMoments(outMoments); + } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadow.vert b/projects/voxelization/resources/shaders/shadow.vert index f6b99c39..d800c547 100644 --- a/projects/voxelization/resources/shaders/shadow.vert +++ b/projects/voxelization/resources/shaders/shadow.vert @@ -3,17 +3,12 @@ #extension GL_GOOGLE_include_directive : enable -#include "lightInfo.inc" - layout(location = 0) in vec3 inPosition; layout( push_constant ) uniform constants{ mat4 mvp; }; -layout(location = 0) out vec4 passPos; - void main() { gl_Position = mvp * vec4(inPosition, 1.0); - passPos = gl_Position; } \ No newline at end of file diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index e6af48c5..72add6d5 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -15,6 +15,16 @@ vkcv::ShaderProgram loadShadowShader() { return shader; } +vkcv::ShaderProgram loadDepthToMomentsShader() { + vkcv::ShaderProgram shader; + vkcv::shader::GLSLCompiler compiler; + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/depthToMoments.comp", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + glm::mat4 computeShadowViewProjectionMatrix( const glm::vec3& lightDirection, const vkcv::camera::Camera& camera, @@ -103,30 +113,24 @@ glm::mat4 computeShadowViewProjectionMatrix( return vulkanCorrectionMatrix * crop * view; } -const vk::Format shadowMapFormat = vk::Format::eR16G16B16A16Unorm; -const vk::Format shadowMapDepthFormat = vk::Format::eD16Unorm; -const uint32_t shadowMapResolution = 2048; +const vk::Format shadowMapFormat = vk::Format::eR16G16B16A16Unorm; +const vk::Format shadowMapDepthFormat = vk::Format::eD32Sfloat; +const uint32_t shadowMapResolution = 2048; +const vkcv::Multisampling msaa = vkcv::Multisampling::MSAA4X; ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vertexLayout) : m_corePtr(corePtr), - m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, false, true)), - m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution)), + m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)), + m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution, 1, false, false, false, msaa)), m_lightInfoBuffer(corePtr->createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3))){ vkcv::ShaderProgram shadowShader = loadShadowShader(); - // descriptor set - m_shadowDescriptorSet = corePtr->createDescriptorSet(shadowShader.getReflectedDescriptors()[0]); - vkcv::DescriptorWrites shadowDescriptorWrites; - shadowDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(0, m_lightInfoBuffer.getHandle()) }; - corePtr->writeDescriptorSet(m_shadowDescriptorSet, shadowDescriptorWrites); - // pass const std::vector<vkcv::AttachmentDescription> shadowAttachments = { - vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat), vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapDepthFormat) }; - const vkcv::PassConfig shadowPassConfig(shadowAttachments); + vkcv::PassConfig shadowPassConfig(shadowAttachments, msaa); m_shadowMapPass = corePtr->createPass(shadowPassConfig); // pipeline @@ -136,9 +140,10 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert shadowMapResolution, m_shadowMapPass, vertexLayout, - { corePtr->getDescriptorSet(m_shadowDescriptorSet).layout }, + {}, false }; + shadowPipeConfig.m_multisampling = msaa; shadowPipeConfig.m_EnableDepthClamping = true; m_shadowMapPipe = corePtr->createGraphicsPipeline(shadowPipeConfig); @@ -148,10 +153,21 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::SamplerMipmapMode::NEAREST, vkcv::SamplerAddressMode::CLAMP_TO_EDGE ); + + // depth to moments + vkcv::ShaderProgram depthToMomentsShader = loadDepthToMomentsShader(); + m_depthToMomentsDescriptorSet = corePtr->createDescriptorSet(depthToMomentsShader.getReflectedDescriptors()[0]); + m_depthToMomentsPipe = corePtr->createComputePipeline(depthToMomentsShader, { corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).layout }); + + vkcv::DescriptorWrites depthToMomentDescriptorWrites; + depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) }; + depthToMomentDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; + depthToMomentDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; + corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites); } void ShadowMapping::recordShadowMapRendering( - const vkcv::CommandStreamHandle& cmdStream, + const vkcv::CommandStreamHandle& cmdStream, const glm::vec2& lightAngleRadian, const glm::vec3& lightColor, float lightStrength, @@ -165,9 +181,9 @@ void ShadowMapping::recordShadowMapRendering( float voxelVolumeExtent) { LightInfo lightInfo; - lightInfo.sunColor = lightColor; - lightInfo.sunStrength = lightStrength; - lightInfo.direction = glm::normalize(glm::vec3( + lightInfo.sunColor = lightColor; + lightInfo.sunStrength = lightStrength; + lightInfo.direction = glm::normalize(glm::vec3( std::cos(lightAngleRadian.x) * std::cos(lightAngleRadian.y), std::sin(lightAngleRadian.x), std::cos(lightAngleRadian.x) * std::sin(lightAngleRadian.y))); @@ -190,7 +206,7 @@ void ShadowMapping::recordShadowMapRendering( std::vector<vkcv::DrawcallInfo> drawcalls; for (const auto& mesh : meshes) { - drawcalls.push_back(vkcv::DrawcallInfo(mesh, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowDescriptorSet).vulkanHandle) })); + drawcalls.push_back(vkcv::DrawcallInfo(mesh, {})); } m_corePtr->recordDrawcallsToCmdStream( @@ -199,7 +215,24 @@ void ShadowMapping::recordShadowMapRendering( m_shadowMapPipe, shadowPushConstantData, drawcalls, - { m_shadowMap.getHandle(), m_shadowMapDepth.getHandle() }); + { m_shadowMapDepth.getHandle() }); + m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapDepth.getHandle()); + + // depth to moments + uint32_t dispatchCount[3]; + dispatchCount[0] = (uint32_t)std::ceilf(shadowMapResolution / 8.f); + dispatchCount[1] = (uint32_t)std::ceilf(shadowMapResolution / 8.f); + dispatchCount[2] = 1; + + const uint32_t msaaSampleCount = msaaToSampleCount(msaa); + + m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle()); + m_corePtr->recordComputeDispatchToCmdStream( + cmdStream, + m_depthToMomentsPipe, + dispatchCount, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) }, + vkcv::PushConstantData((void*)&msaaSampleCount, sizeof(msaaSampleCount))); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); } diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 1478755d..e9ad792c 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -42,12 +42,14 @@ public: private: vkcv::Core* m_corePtr; - vkcv::Image m_shadowMap; - vkcv::Image m_shadowMapDepth; - vkcv::SamplerHandle m_shadowSampler; - vkcv::Buffer<LightInfo> m_lightInfoBuffer; - vkcv::DescriptorSetHandle m_shadowDescriptorSet; - - vkcv::PassHandle m_shadowMapPass; - vkcv::PipelineHandle m_shadowMapPipe; + vkcv::Image m_shadowMap; + vkcv::Image m_shadowMapDepth; + vkcv::SamplerHandle m_shadowSampler; + vkcv::Buffer<LightInfo> m_lightInfoBuffer; + + vkcv::PassHandle m_shadowMapPass; + vkcv::PipelineHandle m_shadowMapPipe; + + vkcv::PipelineHandle m_depthToMomentsPipe; + vkcv::DescriptorSetHandle m_depthToMomentsDescriptorSet; }; \ No newline at end of file diff --git a/src/vkcv/ImageConfig.cpp b/src/vkcv/ImageConfig.cpp index a9d6a36f..80aeac3d 100644 --- a/src/vkcv/ImageConfig.cpp +++ b/src/vkcv/ImageConfig.cpp @@ -11,4 +11,14 @@ namespace vkcv { default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); return vk::SampleCountFlagBits::e1; } } + + uint32_t msaaToSampleCount(Multisampling msaa) { + switch (msaa) { + case Multisampling::None: return 1; + case Multisampling::MSAA2X: return 2; + case Multisampling::MSAA4X: return 4; + case Multisampling::MSAA8X: return 8; + default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); return 1; + } + } } \ No newline at end of file -- GitLab