diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index d505d5c39..711fea0a0 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -110,7 +110,7 @@ void VkDescriptorSetManager::UpdateLevelMeshSet() void VkDescriptorSetManager::UpdateLightTilesSet() { WriteDescriptors() - .AddStorageImage(LightTiles.Set.get(), 0, fb->GetBuffers()->SceneZMinMax[4].View.get(), VK_IMAGE_LAYOUT_GENERAL) + .AddStorageImage(LightTiles.Set.get(), 0, fb->GetBuffers()->SceneZMinMax[5].View.get(), VK_IMAGE_LAYOUT_GENERAL) .AddBuffer(LightTiles.Set.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer()) .AddBuffer(LightTiles.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBuffers()->SceneLightTiles.get()) .Execute(fb->GetDevice()); @@ -122,7 +122,7 @@ void VkDescriptorSetManager::UpdateZMinMaxSet() .AddCombinedImageSampler(ZMinMax.Set[0].get(), 0, fb->GetBuffers()->SceneDepthStencil.DepthOnlyView.get(), fb->GetSamplerManager()->ZMinMaxSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) .Execute(fb->GetDevice()); - for (int i = 1; i < 5; i++) + for (int i = 1; i < 6; i++) { WriteDescriptors() .AddCombinedImageSampler(ZMinMax.Set[i].get(), 0, fb->GetBuffers()->SceneZMinMax[i - 1].View.get(), fb->GetSamplerManager()->ZMinMaxSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) @@ -314,8 +314,8 @@ void VkDescriptorSetManager::CreateLightTilesPool() void VkDescriptorSetManager::CreateZMinMaxPool() { ZMinMax.Pool = DescriptorPoolBuilder() - .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5) - .MaxSets(5) + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) + .MaxSets(6) .DebugName("VkDescriptorSetManager.ZMinMax.Pool") .Create(fb->GetDevice()); } diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h index 2dc87b8a9..d85ca280f 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h @@ -110,7 +110,7 @@ private: struct { std::unique_ptr Pool; - std::unique_ptr Set[5]; + std::unique_ptr Set[6]; std::unique_ptr Layout; } ZMinMax; diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp index 53ad0b07e..8c63b586d 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp @@ -189,7 +189,7 @@ void VkRenderPassManager::CreateZMinMaxPipeline() ZMinMax.Layout = PipelineLayoutBuilder() .AddSetLayout(fb->GetDescriptorSetManager()->GetZMinMaxLayout()) - //.AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ZMinMaxPushConstants)) + .AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ZMinMaxPushConstants)) .DebugName("VkRenderPassManager.ZMinMax.Layout") .Create(fb->GetDevice()); diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 7428f1f46..ba46c50e6 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -53,6 +53,14 @@ struct PushConstants int uFogballIndex; // fog balls }; +struct ZMinMaxPushConstants +{ + float LinearizeDepthA; + float LinearizeDepthB; + float InverseDepthRangeA; + float InverseDepthRangeB; +}; + struct LightTilesPushConstants { int additiveCount; diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp index fcaf41b66..57dab614a 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -305,7 +305,7 @@ void VkRenderBuffers::CreateSceneZMinMax(int width, int height) width = (width + 63) / 64 * 64; height = (height + 63) / 64 * 64; - for (int i = 0; i < 5; i++) + for (int i = 0; i < 6; i++) { width >>= 1; height >>= 1; diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.h b/src/common/rendering/vulkan/textures/vk_renderbuffers.h index 4f2aa8502..16ce615b2 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.h +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.h @@ -37,7 +37,7 @@ public: VkTextureImage SceneFog; VkTextureImage SceneLinearDepth; - VkTextureImage SceneZMinMax[5]; + VkTextureImage SceneZMinMax[6]; std::unique_ptr SceneLightTiles; VkFormat PipelineDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 457cd990a..ee26209e8 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -877,6 +877,12 @@ void VkRenderState::RunZMinMaxPass() int width = ((buffers->GetWidth() + 63) / 64 * 64) >> 1; int height = ((buffers->GetHeight() + 63) / 64 * 64) >> 1; + ZMinMaxPushConstants pushConstants = {}; + pushConstants.LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear(); + pushConstants.LinearizeDepthB = max(1.0f / screen->GetZNear(), 1.e-8f); + pushConstants.InverseDepthRangeA = 1.0f; + pushConstants.InverseDepthRangeB = 0.0f; + VkImageTransition() .AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) .AddImage(&fb->GetBuffers()->SceneZMinMax[0], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) @@ -901,10 +907,11 @@ void VkRenderState::RunZMinMaxPass() cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines->GetZMinMaxPipeline0(mRenderTarget.Samples)); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines->GetZMinMaxLayout(), 0, descriptors->GetZMinMaxSet(0)); + cmdbuffer->pushConstants(pipelines->GetZMinMaxLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(ZMinMaxPushConstants), &pushConstants); cmdbuffer->draw(6, 1, 0, 0); cmdbuffer->endRenderPass(); - for (int i = 1; i < 5; i++) + for (int i = 1; i < 6; i++) { VkImageTransition() .AddImage(&fb->GetBuffers()->SceneZMinMax[i - 1], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) @@ -936,7 +943,7 @@ void VkRenderState::RunZMinMaxPass() VkImageTransition() .AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false) - .AddImage(&fb->GetBuffers()->SceneZMinMax[4], VK_IMAGE_LAYOUT_GENERAL, false) + .AddImage(&fb->GetBuffers()->SceneZMinMax[5], VK_IMAGE_LAYOUT_GENERAL, false) .Execute(cmdbuffer); } diff --git a/wadsrc/static/shaders/scene/frag_zminmax0.glsl b/wadsrc/static/shaders/scene/frag_zminmax0.glsl index 7292c9355..bb13ca4d4 100644 --- a/wadsrc/static/shaders/scene/frag_zminmax0.glsl +++ b/wadsrc/static/shaders/scene/frag_zminmax0.glsl @@ -7,6 +7,16 @@ layout(binding = 0) uniform sampler2D Texture; layout(location = 0) out vec4 FragMinMax; +layout(push_constant) uniform ZMinMaxPushConstants +{ + float LinearizeDepthA; + float LinearizeDepthB; + float InverseDepthRangeA; + float InverseDepthRangeB; +}; + +float normalizeDepth(float depth); + void main() { #if defined(MULTISAMPLE) @@ -15,12 +25,18 @@ void main() ivec2 size = textureSize(Texture, 0) - 1; #endif ivec2 pos = ivec2(gl_FragCoord.xy) * 2; - float z0 = texelFetch(Texture, min(pos, size), 0).w; - float z1 = texelFetch(Texture, min(pos + ivec2(1,0), size), 0).w; - float z2 = texelFetch(Texture, min(pos + ivec2(0,1), size), 0).w; - float z3 = texelFetch(Texture, min(pos + ivec2(1,1), size), 0).w; + float z0 = texelFetch(Texture, min(pos, size), 0).x; + float z1 = texelFetch(Texture, min(pos + ivec2(1,0), size), 0).x; + float z2 = texelFetch(Texture, min(pos + ivec2(0,1), size), 0).x; + float z3 = texelFetch(Texture, min(pos + ivec2(1,1), size), 0).x; vec2 zminmax = vec2( min(min(min(z0, z1), z2), z3), max(max(max(z0, z1), z2), z3)); - FragMinMax = vec4(zminmax, 0, 0); + FragMinMax = vec4(normalizeDepth(zminmax.x), normalizeDepth(zminmax.y), 0, 0); +} + +float normalizeDepth(float depth) +{ + float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0); + return 1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB); } diff --git a/wadsrc/static/shaders/scene/frag_zminmax1.glsl b/wadsrc/static/shaders/scene/frag_zminmax1.glsl index 1b3387025..bdcd56329 100644 --- a/wadsrc/static/shaders/scene/frag_zminmax1.glsl +++ b/wadsrc/static/shaders/scene/frag_zminmax1.glsl @@ -2,6 +2,14 @@ layout(binding = 0) uniform sampler2D Texture; layout(location = 0) out vec4 FragMinMax; +layout(push_constant) uniform ZMinMaxPushConstants +{ + float LinearizeDepthA; + float LinearizeDepthB; + float InverseDepthRangeA; + float InverseDepthRangeB; +}; + void main() { ivec2 pos = ivec2(gl_FragCoord.xy) * 2;