From 27782250486f3d7465444b9a1fe4466650e67ae7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 15 Sep 2024 01:44:34 +0200 Subject: [PATCH] Run the ZMinMax pass before the light tiles compute shader --- .../descriptorsets/vk_descriptorset.cpp | 37 +++++++++ .../vulkan/descriptorsets/vk_descriptorset.h | 12 +++ .../vulkan/pipelines/vk_renderpass.cpp | 36 +++++++++ .../vulkan/pipelines/vk_renderpass.h | 13 +++ .../rendering/vulkan/samplers/vk_samplers.cpp | 9 +++ .../rendering/vulkan/samplers/vk_samplers.h | 2 + .../rendering/vulkan/shaders/vk_shader.cpp | 8 ++ .../rendering/vulkan/shaders/vk_shader.h | 2 +- .../vulkan/textures/vk_imagetransition.cpp | 4 + .../vulkan/textures/vk_imagetransition.h | 2 + .../vulkan/textures/vk_renderbuffers.cpp | 23 +++++- .../vulkan/textures/vk_renderbuffers.h | 1 + .../rendering/vulkan/vk_renderstate.cpp | 79 +++++++++++++++++-- src/common/rendering/vulkan/vk_renderstate.h | 1 + .../static/shaders/scene/frag_zminmax0.glsl | 9 +++ 15 files changed, 231 insertions(+), 7 deletions(-) diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index 4090beed5..d505d5c39 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -44,10 +44,12 @@ VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb) CreateRSBufferLayout(); CreateFixedLayout(); CreateLightTilesLayout(); + CreateZMinMaxLayout(); CreateLevelMeshPool(); CreateRSBufferPool(); CreateFixedPool(); CreateLightTilesPool(); + CreateZMinMaxPool(); CreateBindlessSet(); } @@ -63,6 +65,9 @@ void VkDescriptorSetManager::Init() LevelMesh.Set = LevelMesh.Pool->allocate(LevelMesh.Layout.get()); LightTiles.Set = LightTiles.Pool->allocate(LightTiles.Layout.get()); + for (auto& set : ZMinMax.Set) + set = ZMinMax.Pool->allocate(ZMinMax.Layout.get()); + auto rsbuffers = fb->GetBufferManager()->GetRSBuffers(); WriteDescriptors() .AddBuffer(RSBuffer.Set.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms)) @@ -85,6 +90,7 @@ void VkDescriptorSetManager::BeginFrame() UpdateFixedSet(); UpdateLevelMeshSet(); UpdateLightTilesSet(); + UpdateZMinMaxSet(); } void VkDescriptorSetManager::UpdateLevelMeshSet() @@ -110,6 +116,20 @@ void VkDescriptorSetManager::UpdateLightTilesSet() .Execute(fb->GetDevice()); } +void VkDescriptorSetManager::UpdateZMinMaxSet() +{ + WriteDescriptors() + .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++) + { + 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) + .Execute(fb->GetDevice()); + } +} + void VkDescriptorSetManager::UpdateFixedSet() { fb->GetCommands()->DrawDeleteList->Add(std::move(Fixed.Set)); @@ -273,6 +293,14 @@ void VkDescriptorSetManager::CreateLightTilesLayout() .Create(fb->GetDevice()); } +void VkDescriptorSetManager::CreateZMinMaxLayout() +{ + ZMinMax.Layout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("VkDescriptorSetManager.ZMinMax.Layout") + .Create(fb->GetDevice()); +} + void VkDescriptorSetManager::CreateLightTilesPool() { LightTiles.Pool = DescriptorPoolBuilder() @@ -283,6 +311,15 @@ void VkDescriptorSetManager::CreateLightTilesPool() .Create(fb->GetDevice()); } +void VkDescriptorSetManager::CreateZMinMaxPool() +{ + ZMinMax.Pool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5) + .MaxSets(5) + .DebugName("VkDescriptorSetManager.ZMinMax.Pool") + .Create(fb->GetDevice()); +} + void VkDescriptorSetManager::CreateLevelMeshPool() { LevelMesh.Pool = DescriptorPoolBuilder() diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h index bef21dc79..2dc87b8a9 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h @@ -27,12 +27,14 @@ public: VulkanDescriptorSetLayout* GetFixedLayout() { return Fixed.Layout.get(); } VulkanDescriptorSetLayout* GetBindlessLayout() { return Bindless.Layout.get(); } VulkanDescriptorSetLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); } + VulkanDescriptorSetLayout* GetZMinMaxLayout() { return ZMinMax.Layout.get(); } VulkanDescriptorSet* GetLevelMeshSet() { return LevelMesh.Set.get(); } VulkanDescriptorSet* GetRSBufferSet() { return RSBuffer.Set.get(); } VulkanDescriptorSet* GetFixedSet() { return Fixed.Set.get(); } VulkanDescriptorSet* GetBindlessSet() { return Bindless.Set.get(); } VulkanDescriptorSet* GetLightTilesSet() { return LightTiles.Set.get(); } + VulkanDescriptorSet* GetZMinMaxSet(int index) { return ZMinMax.Set[index].get(); } VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers); @@ -47,14 +49,17 @@ private: void CreateRSBufferLayout(); void CreateFixedLayout(); void CreateLightTilesLayout(); + void CreateZMinMaxLayout(); void CreateLevelMeshPool(); void CreateRSBufferPool(); void CreateFixedPool(); void CreateLightTilesPool(); + void CreateZMinMaxPool(); void CreateBindlessSet(); void UpdateFixedSet(); void UpdateLevelMeshSet(); void UpdateLightTilesSet(); + void UpdateZMinMaxSet(); std::unique_ptr AllocatePPSet(VulkanDescriptorSetLayout* layout); @@ -102,6 +107,13 @@ private: std::unique_ptr Layout; } LightTiles; + struct + { + std::unique_ptr Pool; + std::unique_ptr Set[5]; + std::unique_ptr Layout; + } ZMinMax; + std::list Materials; static const int MaxFixedSets = 100; diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp index f7c1a8797..53ad0b07e 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp @@ -66,6 +66,7 @@ VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb) PipelineCache = builder.Create(fb->GetDevice()); CreateLightTilesPipeline(); + CreateZMinMaxPipeline(); } VkRenderPassManager::~VkRenderPassManager() @@ -172,6 +173,41 @@ void VkRenderPassManager::CreateLightTilesPipeline() .Create(fb->GetDevice()); } +void VkRenderPassManager::CreateZMinMaxPipeline() +{ + ZMinMax.RenderPass = RenderPassBuilder() + .AddAttachment(VK_FORMAT_R32G32_SFLOAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .DebugName("VkRenderPassManager.ZMinMax.RenderPass") + .Create(fb->GetDevice()); + + ZMinMax.Layout = PipelineLayoutBuilder() + .AddSetLayout(fb->GetDescriptorSetManager()->GetZMinMaxLayout()) + //.AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ZMinMaxPushConstants)) + .DebugName("VkRenderPassManager.ZMinMax.Layout") + .Create(fb->GetDevice()); + + for (int i = 0; i < 3; i++) + { + ZMinMax.Pipeline[i] = GraphicsPipelineBuilder() + .Cache(PipelineCache.get()) + .RenderPass(ZMinMax.RenderPass.get()) + .Layout(ZMinMax.Layout.get()) + .AddVertexShader(fb->GetShaderManager()->GetZMinMaxVertexShader()) + .AddFragmentShader(fb->GetShaderManager()->GetZMinMaxFragmentShader(i)) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .AddDynamicState(VK_DYNAMIC_STATE_SCISSOR) + .DebugName("VkRenderPassManager.ZMinMax.Pipeline") + .Create(fb->GetDevice()); + } +} + ///////////////////////////////////////////////////////////////////////////// VkRenderPassSetup::VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb) diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.h b/src/common/rendering/vulkan/pipelines/vk_renderpass.h index 0b559650d..9f9854ae5 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.h +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.h @@ -118,8 +118,14 @@ public: VulkanPipelineLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); } VulkanPipeline* GetLightTilesPipeline() { return LightTiles.Pipeline.get(); } + VulkanRenderPass* GetZMinMaxRenderPass() { return ZMinMax.RenderPass.get(); } + VulkanPipelineLayout* GetZMinMaxLayout() { return ZMinMax.Layout.get(); } + VulkanPipeline* GetZMinMaxPipeline0(VkSampleCountFlagBits samples) { return ZMinMax.Pipeline[samples > 1 ? 1 : 0].get(); } + VulkanPipeline* GetZMinMaxPipeline1() { return ZMinMax.Pipeline[2].get(); } + private: void CreateLightTilesPipeline(); + void CreateZMinMaxPipeline(); VulkanRenderDevice* fb = nullptr; @@ -135,6 +141,13 @@ private: std::unique_ptr Pipeline; } LightTiles; + struct + { + std::unique_ptr RenderPass; + std::unique_ptr Layout; + std::unique_ptr Pipeline[3]; + } ZMinMax; + FString CacheFilename; std::unique_ptr PipelineCache; }; diff --git a/src/common/rendering/vulkan/samplers/vk_samplers.cpp b/src/common/rendering/vulkan/samplers/vk_samplers.cpp index b35c69f75..9d48a42cb 100644 --- a/src/common/rendering/vulkan/samplers/vk_samplers.cpp +++ b/src/common/rendering/vulkan/samplers/vk_samplers.cpp @@ -129,6 +129,7 @@ VkSamplerManager::VkSamplerManager(VulkanRenderDevice* fb) : fb(fb) CreateHWSamplers(); CreateShadowmapSampler(); CreateLightmapSampler(); + CreateZMinMaxSampler(); } VkSamplerManager::~VkSamplerManager() @@ -316,3 +317,11 @@ void VkSamplerManager::CreateLightmapSampler() .DebugName("VkRenderBuffers.LightmapSampler") .Create(fb->GetDevice()); } + +void VkSamplerManager::CreateZMinMaxSampler() +{ + ZMinMaxSampler = SamplerBuilder() + .AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) + .DebugName("VkRenderBuffers.ZMinMaxSampler") + .Create(fb->GetDevice()); +} diff --git a/src/common/rendering/vulkan/samplers/vk_samplers.h b/src/common/rendering/vulkan/samplers/vk_samplers.h index 1b2eba348..1579d02d6 100644 --- a/src/common/rendering/vulkan/samplers/vk_samplers.h +++ b/src/common/rendering/vulkan/samplers/vk_samplers.h @@ -28,12 +28,14 @@ public: std::unique_ptr ShadowmapSampler; std::unique_ptr LightmapSampler; + std::unique_ptr ZMinMaxSampler; private: void CreateHWSamplers(); void DeleteHWSamplers(); void CreateShadowmapSampler(); void CreateLightmapSampler(); + void CreateZMinMaxSampler(); VulkanRenderDevice* fb = nullptr; std::array, NUMSAMPLERS> mSamplers; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index d5f916f95..c80f5670a 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -47,6 +47,14 @@ VkShaderManager::VkShaderManager(VulkanRenderDevice* fb) : fb(fb) .Create("ZMinMax0.frag", fb->GetDevice()); ZMinMax.frag[1] = ShaderBuilder() + .Type(ShaderType::Fragment) + .DebugName("ZMinMax0.frag") + .AddSource("VersionBlock", GetVersionBlock().GetChars()) + .AddSource("DefinesBlock", "#define MULTISAMPLE\n") + .AddSource("shaders/scene/frag_zminmax0.glsl", LoadPrivateShaderLump("shaders/scene/frag_zminmax0.glsl").GetChars()) + .Create("ZMinMax0.frag", fb->GetDevice()); + + ZMinMax.frag[2] = ShaderBuilder() .Type(ShaderType::Fragment) .DebugName("ZMinMax1.frag") .AddSource("VersionBlock", GetVersionBlock().GetChars()) diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index d545f3d7c..1b2c6636f 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -149,7 +149,7 @@ private: struct { std::unique_ptr vert; - std::unique_ptr frag[2]; + std::unique_ptr frag[3]; } ZMinMax; std::unique_ptr LightTiles; diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp index 5701a1871..2f0cfd888 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp @@ -57,6 +57,10 @@ VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLay srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; + case VK_IMAGE_LAYOUT_GENERAL: + srcAccess = 0; + srcStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + break; default: I_FatalError("Unimplemented src image layout transition\n"); } diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.h b/src/common/rendering/vulkan/textures/vk_imagetransition.h index a7c179e01..2cd181878 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.h +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.h @@ -25,6 +25,7 @@ public: for (auto& view : LMViews) deletelist->Add(std::move(view)); LMViews.clear(); + deletelist->Add(std::move(ZMinMaxFramebuffer)); deletelist->Add(std::move(DepthOnlyView)); deletelist->Add(std::move(View)); deletelist->Add(std::move(Image)); @@ -38,6 +39,7 @@ public: VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; std::unique_ptr PPFramebuffer; + std::unique_ptr ZMinMaxFramebuffer; std::map> RSFramebuffers; std::vector> LMViews; std::vector> LMFramebuffers; diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp index 259e67999..fcaf41b66 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -118,6 +118,27 @@ VulkanFramebuffer* VkRenderBuffers::GetFramebuffer(const VkRenderPassKey& key) return framebuffer.get(); } +VulkanFramebuffer* VkRenderBuffers::GetZMinMaxFramebuffer(int index) +{ + auto& framebuffer = SceneZMinMax[index].ZMinMaxFramebuffer; + if (framebuffer) + return framebuffer.get(); + + int width = ((GetWidth() + 63) / 64 * 64) >> 1; + int height = ((GetHeight() + 63) / 64 * 64) >> 1; + + width >>= index; + height >>= index; + + FramebufferBuilder builder; + builder.RenderPass(fb->GetRenderPassManager()->GetZMinMaxRenderPass()); + builder.Size(width, height); + builder.AddAttachment(SceneZMinMax[index].View.get()); + builder.DebugName("VkRenderBuffers.ZMinMaxFramebuffer"); + framebuffer = builder.Create(fb->GetDevice()); + return framebuffer.get(); +} + void VkRenderBuffers::CreatePipelineDepthStencil(int width, int height) { ImageBuilder builder; @@ -284,7 +305,7 @@ void VkRenderBuffers::CreateSceneZMinMax(int width, int height) width = (width + 63) / 64 * 64; height = (height + 63) / 64 * 64; - for (int i = 4; i >= 0; i--) + for (int i = 0; i < 5; 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 e90bb36e7..4f2aa8502 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.h +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.h @@ -29,6 +29,7 @@ public: VkSampleCountFlagBits GetSceneSamples() const { return mSamples; } VulkanFramebuffer* GetFramebuffer(const VkRenderPassKey& key); + VulkanFramebuffer* GetZMinMaxFramebuffer(int index); VkTextureImage SceneColor; VkTextureImage SceneDepthStencil; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index c0d48ad73..c3ef50672 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -867,17 +867,86 @@ void VkRenderState::ApplyLevelMesh() mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetDrawIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); } +void VkRenderState::RunZMinMaxPass() +{ + auto pipelines = fb->GetRenderPassManager(); + auto descriptors = fb->GetDescriptorSetManager(); + auto buffers = fb->GetBuffers(); + auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); + + int width = ((buffers->GetWidth() + 63) / 64 * 64) >> 1; + int height = ((buffers->GetHeight() + 63) / 64 * 64) >> 1; + + 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) + .Execute(cmdbuffer); + + RenderPassBegin() + .RenderPass(pipelines->GetZMinMaxRenderPass()) + .RenderArea(0, 0, width, height) + .Framebuffer(buffers->GetZMinMaxFramebuffer(0)) + .AddClearColor(0.0f, 0.0f, 0.0f, 0.0f) + .Execute(cmdbuffer); + + VkViewport viewport = {}; + viewport.width = (float)width; + viewport.height = (float)height; + cmdbuffer->setViewport(0, 1, &viewport); + + VkRect2D scissor = {}; + scissor.extent.width = width; + scissor.extent.height = height; + cmdbuffer->setScissor(0, 1, &scissor); + + 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->draw(6, 1, 0, 0); + cmdbuffer->endRenderPass(); + + for (int i = 1; i < 5; i++) + { + VkImageTransition() + .AddImage(&fb->GetBuffers()->SceneZMinMax[i - 1], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .AddImage(&fb->GetBuffers()->SceneZMinMax[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) + .Execute(cmdbuffer); + + RenderPassBegin() + .RenderPass(pipelines->GetZMinMaxRenderPass()) + .RenderArea(0, 0, width >> i, height >> i) + .Framebuffer(buffers->GetZMinMaxFramebuffer(i)) + .AddClearColor(0.0f, 0.0f, 0.0f, 0.0f) + .Execute(cmdbuffer); + + viewport = {}; + viewport.width = (float)(width >> i); + viewport.height = (float)(height >> i); + cmdbuffer->setViewport(0, 1, &viewport); + + scissor = {}; + scissor.extent.width = (width >> i); + scissor.extent.height = (height >> i); + cmdbuffer->setScissor(0, 1, &scissor); + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines->GetZMinMaxPipeline1()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines->GetZMinMaxLayout(), 0, descriptors->GetZMinMaxSet(i)); + cmdbuffer->draw(6, 1, 0, 0); + cmdbuffer->endRenderPass(); + } + + VkImageTransition() + .AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false) + .AddImage(&fb->GetBuffers()->SceneZMinMax[4], VK_IMAGE_LAYOUT_GENERAL, false) + .Execute(cmdbuffer); +} + void VkRenderState::DispatchLightTiles() { EndRenderPass(); + RunZMinMaxPass(); auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); - // To do: run the zminmax pass - VkImageTransition() - .AddImage(&fb->GetBuffers()->SceneZMinMax[4], VK_IMAGE_LAYOUT_GENERAL, true /* false */) - .Execute(cmdbuffer); - PipelineBarrier() .AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT) .Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 8b59716ca..80020db86 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -90,6 +90,7 @@ protected: void BeginRenderPass(VulkanCommandBuffer *cmdbuffer); void WaitForStreamBuffers(); + void RunZMinMaxPass(); void ApplyLevelMesh(); void ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, bool noFragmentShader); diff --git a/wadsrc/static/shaders/scene/frag_zminmax0.glsl b/wadsrc/static/shaders/scene/frag_zminmax0.glsl index 4347f539d..7292c9355 100644 --- a/wadsrc/static/shaders/scene/frag_zminmax0.glsl +++ b/wadsrc/static/shaders/scene/frag_zminmax0.glsl @@ -1,10 +1,19 @@ +#if defined(MULTISAMPLE) +layout(binding = 0) uniform sampler2DMS Texture; +#else layout(binding = 0) uniform sampler2D Texture; +#endif + layout(location = 0) out vec4 FragMinMax; void main() { +#if defined(MULTISAMPLE) + ivec2 size = textureSize(Texture) - 1; +#else 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;