From bf8e45049238172307235089f596b6c210077933 Mon Sep 17 00:00:00 2001 From: apistol78 Date: Thu, 22 Feb 2024 14:54:33 +0100 Subject: [PATCH] Traktor: Generating HiZ in a power-of-two to ensure it's properly aligned with world geometry. Overall cleanup. --- code/Mesh/Instance/InstanceMesh.cpp | 4 + code/Render/Frame/RenderPass.cpp | 10 +- code/Render/Frame/RenderPass.h | 22 ++- code/Render/IRenderView.h | 2 +- code/Render/Vulkan/RenderViewVk.cpp | 60 +++--- code/World/Deferred/WorldRendererDeferred.cpp | 22 +-- code/World/Shared/Passes/GBufferPass.cpp | 4 +- code/World/Shared/Passes/HiZPass.cpp | 41 +++- code/World/Shared/Passes/HiZPass.h | 4 +- .../Mesh/Shaders/Instance/Cull/Cull.xdi | 54 ++++-- data/Source/System/World/HiZ/Shaders/HiZ.xdi | 181 +++++++----------- .../World/Overlay/Shaders/OverlayTargets.xdi | 40 +++- 12 files changed, 241 insertions(+), 203 deletions(-) diff --git a/code/Mesh/Instance/InstanceMesh.cpp b/code/Mesh/Instance/InstanceMesh.cpp index 45b73a0b01..00242a4a01 100644 --- a/code/Mesh/Instance/InstanceMesh.cpp +++ b/code/Mesh/Instance/InstanceMesh.cpp @@ -28,6 +28,7 @@ namespace traktor::mesh render::Handle s_handleInstanceWorld(L"InstanceWorld"); render::Handle s_handleInstanceWorldLast(L"InstanceWorldLast"); +render::Handle s_handleTargetSize(L"InstanceMesh_TargetSize"); render::Handle s_handleBoundingBoxMin(L"InstanceMesh_BoundingBoxMin"); render::Handle s_handleBoundingBoxMax(L"InstanceMesh_BoundingBoxMax"); render::Handle s_handleVisibility(L"InstanceMesh_Visibility"); @@ -132,6 +133,8 @@ void InstanceMesh::build( for (int32_t i = (int32_t)cf.planes.size(); i < sizeof_array(cullFrustum); ++i) cullFrustum[i] = Vector4::zero(); + const Vector2 viewSize = worldRenderView.getViewSize(); + auto renderBlock = renderContext->allocNamed< render::ComputeRenderBlock >( str(L"InstanceMesh cull %d", worldRenderView.getCascade()) ); @@ -155,6 +158,7 @@ void InstanceMesh::build( worldRenderPass.setProgramParameters(renderBlock->programParams); + renderBlock->programParams->setVectorParameter(s_handleTargetSize, Vector4(viewSize.x, viewSize.y, 0.0f, 0.0f)); renderBlock->programParams->setVectorParameter(s_handleBoundingBoxMin, m_renderMesh->getBoundingBox().mn); renderBlock->programParams->setVectorParameter(s_handleBoundingBoxMax, m_renderMesh->getBoundingBox().mx); renderBlock->programParams->setVectorArrayParameter(s_handleCullFrustum, cullFrustum, sizeof_array(cullFrustum)); diff --git a/code/Render/Frame/RenderPass.cpp b/code/Render/Frame/RenderPass.cpp index 860df3d07c..80db168965 100644 --- a/code/Render/Frame/RenderPass.cpp +++ b/code/Render/Frame/RenderPass.cpp @@ -40,14 +40,10 @@ void RenderPass::addInput(handle_t resourceId) input.resourceId = resourceId; } -bool RenderPass::requireInput(handle_t resourceId) const +void RenderPass::addWeakInput(handle_t resourceId) { - for (const auto& input : m_inputs) - { - if (input.resourceId == resourceId) - return true; - } - return false; + // #todo Currently we can get away with not doing anything but + // we need to revisit this to ensure resource life time. } void RenderPass::setOutput(handle_t resourceId) diff --git a/code/Render/Frame/RenderPass.h b/code/Render/Frame/RenderPass.h index bea9425532..0d66272ee3 100644 --- a/code/Render/Frame/RenderPass.h +++ b/code/Render/Frame/RenderPass.h @@ -72,9 +72,21 @@ class T_DLLCLASS RenderPass : public RefCountImpl< ITypedObject > //! \{ + /*! Add input to render pass. + * + * \param resourceId ID of input resource. + */ void addInput(handle_t resourceId); - bool requireInput(handle_t resourceId) const; + /*! Add weak input to render pass. + * + * A weak input doesn't resolve into a dependency between + * passes but only register the pass as it will use the + * resource during build. + * + * \param resourceId ID of input resource. + */ + void addWeakInput(handle_t resourceId); const StaticVector< Input, 16 >& getInputs() const { return m_inputs; } @@ -82,6 +94,14 @@ class T_DLLCLASS RenderPass : public RefCountImpl< ITypedObject > //! \{ + /*! Set output resource of render pass. + * + * Resource ID 0 means the primary framebuffer and + * an ID of ~0 means the render pass doesn't have an + * output resource associated. + * + * \param resourceId ID of output resource. + */ void setOutput(handle_t resourceId); void setOutput(handle_t resourceId, uint32_t load, uint32_t store); diff --git a/code/Render/IRenderView.h b/code/Render/IRenderView.h index 82035d1e02..8d7bfede43 100644 --- a/code/Render/IRenderView.h +++ b/code/Render/IRenderView.h @@ -1,6 +1,6 @@ /* * TRAKTOR - * Copyright (c) 2022 Anders Pistol. + * Copyright (c) 2022-2024 Anders Pistol. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/code/Render/Vulkan/RenderViewVk.cpp b/code/Render/Vulkan/RenderViewVk.cpp index 6fb166d712..2835f60dce 100644 --- a/code/Render/Vulkan/RenderViewVk.cpp +++ b/code/Render/Vulkan/RenderViewVk.cpp @@ -1065,7 +1065,7 @@ void RenderViewVk::barrier(Stage from, Stage to, ITexture* written, uint32_t wri 0, nullptr ); } - else if (from == Stage::Compute && to == Stage::Compute && written == nullptr) + else if (from == Stage::Compute && to == Stage::Compute/* && written == nullptr*/) { VkMemoryBarrier mb = {}; mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; @@ -1083,35 +1083,35 @@ void RenderViewVk::barrier(Stage from, Stage to, ITexture* written, uint32_t wri 0, nullptr ); } - else if (from == Stage::Compute && to == Stage::Compute && written != nullptr) - { - const Image* img = mandatory_non_null_type_cast< TextureVk* >(written)->getImage(); - - VkImageMemoryBarrier imb = {}; - imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imb.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imb.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - imb.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imb.image = img->getVkImage(); - imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imb.subresourceRange.baseMipLevel = writtenMip; - imb.subresourceRange.levelCount = 1; - imb.subresourceRange.baseArrayLayer = 0; - imb.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier( - *frame.graphicsCommandBuffer, - convertStage(from), - convertStage(to), - 0, - 0, nullptr, - 0, nullptr, - 1, &imb - ); - } + //else if (from == Stage::Compute && to == Stage::Compute && written != nullptr) + //{ + // const Image* img = mandatory_non_null_type_cast< TextureVk* >(written)->getImage(); + + // VkImageMemoryBarrier imb = {}; + // imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + // imb.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + // imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + // imb.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + // imb.newLayout = VK_IMAGE_LAYOUT_GENERAL; + // imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + // imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + // imb.image = img->getVkImage(); + // imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + // imb.subresourceRange.baseMipLevel = writtenMip; + // imb.subresourceRange.levelCount = 1; + // imb.subresourceRange.baseArrayLayer = 0; + // imb.subresourceRange.layerCount = 1; + + // vkCmdPipelineBarrier( + // *frame.graphicsCommandBuffer, + // convertStage(from), + // convertStage(to), + // 0, + // 0, nullptr, + // 0, nullptr, + // 1, &imb + // ); + //} else { // No memory access; only add an execution barrier. diff --git a/code/World/Deferred/WorldRendererDeferred.cpp b/code/World/Deferred/WorldRendererDeferred.cpp index 677ad2910e..0cae457c4f 100644 --- a/code/World/Deferred/WorldRendererDeferred.cpp +++ b/code/World/Deferred/WorldRendererDeferred.cpp @@ -59,14 +59,6 @@ const render::Handle s_persistentVisualTargetSet[] = render::Handle(L"World_VisualTargetSet_Odd") }; -const render::Handle s_persistentHiZTexture[] = -{ - render::Handle(L"World_HiZTexture_0"), - render::Handle(L"World_HiZTexture_1"), - render::Handle(L"World_HiZTexture_2"), - render::Handle(L"World_HiZTexture_3") -}; - const resource::Id< render::Shader > c_lightShader(L"{707DE0B0-0E2B-A44A-9441-9B1FCFD428AA}"); } @@ -148,19 +140,7 @@ void WorldRendererDeferred::setup( }; // Add Hi-Z texture. - const Vector2 viewSize = worldRenderView.getViewSize(); - const int32_t viewWidth = (int32_t)viewSize.x; - const int32_t viewHeight = (int32_t)viewSize.y; - const int32_t hiZWidth = viewWidth >> 1; - const int32_t hiZHeight = viewHeight >> 1; - const int32_t hiZMipCount = log2(std::max(hiZWidth, hiZHeight)) + 1; - - render::RenderGraphTextureDesc rgtxd; - rgtxd.width = hiZWidth; - rgtxd.height = hiZHeight; - rgtxd.mipCount = hiZMipCount; - rgtxd.format = render::TfR32F; - const render::handle_t hizTextureId = renderGraph.addPersistentTexture(L"HiZ", s_persistentHiZTexture[worldRenderView.getIndex()], rgtxd); + const render::handle_t hizTextureId = m_hiZPass->addTexture(worldRenderView, renderGraph); // Add passes to render graph. m_lightClusterPass->setup(worldRenderView, m_gatheredView); diff --git a/code/World/Shared/Passes/GBufferPass.cpp b/code/World/Shared/Passes/GBufferPass.cpp index dc6d29b88e..b46921bbcd 100644 --- a/code/World/Shared/Passes/GBufferPass.cpp +++ b/code/World/Shared/Passes/GBufferPass.cpp @@ -61,9 +61,7 @@ render::handle_t GBufferPass::setup( // Add GBuffer render pass. Ref< render::RenderPass > rp = new render::RenderPass(L"GBuffer"); - - // #fixme We cannot add this input since HiZ is created from depth of this pass. - // rp->addInput(hiZTextureId); + rp->addWeakInput(hiZTextureId); render::Clear clear; clear.mask = render::CfColor | render::CfDepth | render::CfStencil; diff --git a/code/World/Shared/Passes/HiZPass.cpp b/code/World/Shared/Passes/HiZPass.cpp index 7cddc31794..9ce6b923d5 100644 --- a/code/World/Shared/Passes/HiZPass.cpp +++ b/code/World/Shared/Passes/HiZPass.cpp @@ -7,6 +7,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "Core/Log/Log.h" +#include "Core/Math/Log2.h" #include "Core/Misc/String.h" #include "Core/Timer/Profiler.h" #include "Render/Buffer.h" @@ -32,6 +33,14 @@ const resource::Id< render::Shader > c_hiZBuildShader(L"{E8879B75-F646-5D46-8873 const render::Handle s_handleHiZInput(L"World_HiZInput"); const render::Handle s_handleHiZOutput(L"World_HiZOutput"); +const render::Handle s_persistentHiZTexture[] = +{ + render::Handle(L"World_HiZTexture_0"), + render::Handle(L"World_HiZTexture_1"), + render::Handle(L"World_HiZTexture_2"), + render::Handle(L"World_HiZTexture_3") +}; + } T_IMPLEMENT_RTTI_CLASS(L"traktor.world.HiZPass", HiZPass, Object) @@ -46,6 +55,23 @@ bool HiZPass::create(resource::IResourceManager* resourceManager) return true; } +render::handle_t HiZPass::addTexture(const WorldRenderView& worldRenderView, render::RenderGraph& renderGraph) const +{ + const Vector2 viewSize = worldRenderView.getViewSize(); + const int32_t viewWidth = (int32_t)viewSize.x; + const int32_t viewHeight = (int32_t)viewSize.y; + const int32_t hiZWidth = nearestLog2(viewWidth >> 1); + const int32_t hiZHeight = nearestLog2(viewHeight >> 1); + const int32_t hiZMipCount = log2(std::max(hiZWidth, hiZHeight)) + 1; + + render::RenderGraphTextureDesc rgtxd; + rgtxd.width = hiZWidth; + rgtxd.height = hiZHeight; + rgtxd.mipCount = hiZMipCount; + rgtxd.format = render::TfR32F; + return renderGraph.addPersistentTexture(L"HiZ", s_persistentHiZTexture[worldRenderView.getIndex()], rgtxd); +} + void HiZPass::setup( const WorldRenderView& worldRenderView, render::RenderGraph& renderGraph, @@ -56,13 +82,10 @@ void HiZPass::setup( T_PROFILER_SCOPE(L"HiZPass::setup"); const Vector2 viewSize = worldRenderView.getViewSize(); - const int32_t viewWidth = (int32_t)viewSize.x; const int32_t viewHeight = (int32_t)viewSize.y; - - const int32_t hiZWidth = viewWidth >> 1; - const int32_t hiZHeight = viewHeight >> 1; - + const int32_t hiZWidth = nearestLog2(viewWidth >> 1); + const int32_t hiZHeight = nearestLog2(viewHeight >> 1); const int32_t hiZMipCount = log2(std::max(hiZWidth, hiZHeight)) + 1; Ref< render::RenderPass > rp = new render::RenderPass(L"HiZ"); @@ -74,6 +97,12 @@ void HiZPass::setup( const int32_t mipWidth = std::max(hiZWidth >> i, 1); const int32_t mipHeight = std::max(hiZHeight >> i, 1); + const int32_t workWidth = std::max(viewWidth >> (i + 1), 1); + const int32_t workHeight = std::max(viewHeight >> (i + 1), 1); + + T_FATAL_ASSERT(workWidth <= mipWidth); + T_FATAL_ASSERT(workHeight <= mipHeight); + rp->addBuild( [=](const render::RenderGraph& renderGraph, render::RenderContext* renderContext) { @@ -87,6 +116,8 @@ void HiZPass::setup( renderBlock->programParams->beginParameters(renderContext); + renderBlock->programParams->setVectorParameter(render::getParameterHandle(L"World_HiZWorkSize"), Vector4(workWidth, workHeight, 0.0f, 0.0f)); + const auto outputTexture = renderGraph.getTexture(outputHiZTextureId); renderBlock->programParams->setImageViewParameter(s_handleHiZOutput, outputTexture, i); diff --git a/code/World/Shared/Passes/HiZPass.h b/code/World/Shared/Passes/HiZPass.h index 774b80ead3..29cfb37572 100644 --- a/code/World/Shared/Passes/HiZPass.h +++ b/code/World/Shared/Passes/HiZPass.h @@ -42,6 +42,8 @@ class HiZPass : public Object public: bool create(resource::IResourceManager* resourceManager); + render::handle_t addTexture(const WorldRenderView& worldRenderView, render::RenderGraph& renderGraph) const; + void setup( const WorldRenderView& worldRenderView, render::RenderGraph& renderGraph, @@ -50,7 +52,7 @@ class HiZPass : public Object ) const; private: -resource::Proxy< render::Shader > m_hiZBuildShader; + resource::Proxy< render::Shader > m_hiZBuildShader; }; } diff --git a/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi b/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi index a03fc1b2e7..9f87b5e513 100644 --- a/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi +++ b/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi @@ -260,8 +260,8 @@ $Buffer[index].visible = $Input; {6FAE432D-36E8-D046-96BA-65165BB9DCCC} - 435 - 918 + 422 + 818 World_HiZTexture Texture2D @@ -313,6 +313,10 @@ $Buffer[index].visible = $Input; {6D0649E3-ED26-0646-A195-028038D29BD8} HiZState + + {652EFABE-595D-9D4D-BC67-5C63D6168B21} + TargetSize + @@ -324,7 +328,7 @@ $Buffer[index].visible = $Input; - {6E68FD9A-ACE2-9E4A-8B5B-AD54A457B107} + {CBB170DD-96E3-CF46-948E-47E5006E153F} - -26 - 268 + -21 + 476 World_HiZInput Image2D Frame - {FACE56FE-0DC8-4C47-A4B5-F75AF6D34A50} + {9E8F9562-547A-AA44-9F23-C243E184C92C} - 154 - 174 + -59 + 556 World_HiZOutput Image2D Frame - - {98BDEF21-F621-1345-8078-0D18AEA33005} - - - -207 - 176 - - Global - - - {75A93A5B-4AFA-E642-B5CB-4DBFDD319264} - - - 40 - 202 - - xy - - - {06182E78-38C4-A74B-8741-0205C03525AF} + + {17342A62-7710-F841-9D31-0EA156A70A34} - 231 - 263 + -61 + 616 - MaxZ - - - 1 - 1 - 1 - - - {0E3643A0-A0DA-B649-9FD8-930F4EB6D42A} - - - - {3C138D5C-5426-334C-99BF-A06F6FA6635B} - Input - - - {109C1796-0BBF-CB47-B322-44901970D7F8} - Index - - - - - {7E64C882-DF9D-C442-9D35-66B1FA5C2F61} - Output - Scalar - - - + World_HiZWorkSize + Vector + Frame - + {1E6639B6-8B58-4694-99E7-C058E3583522} - {60D25829-A948-4883-B26F-F2BE12B49891} - - - - - - {AAE82FD3-522F-43C6-A594-2E13D126E5DB} - - - - {F2E22CA6-DFF3-4B20-A70A-0D7A44EACD8C} + {D69B3EDE-00AB-2540-B217-394E11A1B0E1} - - {ADB4FC1D-3726-4CC5-B4D5-1E2468274325} + + {1E6639B6-8B58-4694-99E7-C058E3583522} - {0907D535-A1B6-409A-A70A-C250D3CDCD58} + {2D2D3531-DD81-1F47-90F9-DDE0C69AEF69} - - {ADB4FC1D-3726-4CC5-B4D5-1E2468274325} - - - - {109C1796-0BBF-CB47-B322-44901970D7F8} - - - - - + {1E6639B6-8B58-4694-99E7-C058E3583522} - - - {3C138D5C-5426-334C-99BF-A06F6FA6635B} - - - - - - {7E64C882-DF9D-C442-9D35-66B1FA5C2F61} - - {4356E929-19D3-45DD-8143-0168015DB701} + {98C61F79-5BF1-9D49-92B7-77AEEA0EDFAF} diff --git a/data/Source/System/World/Overlay/Shaders/OverlayTargets.xdi b/data/Source/System/World/Overlay/Shaders/OverlayTargets.xdi index 7666eb61d6..8f3b299ef2 100644 --- a/data/Source/System/World/Overlay/Shaders/OverlayTargets.xdi +++ b/data/Source/System/World/Overlay/Shaders/OverlayTargets.xdi @@ -2225,8 +2225,8 @@ else {B215A6DE-86D1-2F4B-A606-D8EC68126A45} - -843 - 3988 + -881 + 4009 Scene_DebugTexture Texture2D @@ -2282,10 +2282,10 @@ else {D8AA7F23-349A-6142-9709-083B7811B53A} - -746 - 4151 + -820 + 4072 - 4 + 2 {431F1C47-067D-5042-B5DC-20EBDF01A8C7} @@ -2315,6 +2315,10 @@ else {A5895F7C-509E-0A40-870E-3E262BE78130} TexCoord + + {AFB734B7-EA74-6C4F-B0A9-16FE838CF389} + TargetSize + @@ -2325,15 +2329,23 @@ else + + {A5B004FC-A637-A949-9958-F404AB11CDFC} + + + -882 + 3942 + + @@ -3456,6 +3468,16 @@ $Output = vec4(p, 0.0f, 0.0f); {6D5C5EFE-A35C-4748-B81E-B8EBACE433BC} + + + + {853B6F75-1464-40E7-BEDC-2716C763046E} + + + + {AFB734B7-EA74-6C4F-B0A9-16FE838CF389} + +