Browse Source

Fix a bug with HZB generation

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
4b314e8cef

+ 1 - 2
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -660,8 +660,7 @@ void CommandBufferImpl::setPipelineBarrierInternal(ConstWeakArray<TextureBarrier
 
 		if(nextUsage == TextureUsageBit::kGenerateMipmaps) [[unlikely]]
 		{
-			// The transition of the non zero mip levels happens inside CommandBufferImpl::generateMipmapsX so limit the
-			// subresource
+			// The transition of the non zero mip levels happens inside CommandBufferImpl::generateMipmapsX so limit the subresource
 
 			ANKI_ASSERT(subresource.m_firstMipmap == 0 && subresource.m_mipmapCount == 1);
 		}

+ 18 - 6
AnKi/Renderer/Utils/HzbGenerator.cpp

@@ -55,8 +55,9 @@ Error HzbGenerator::init()
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/HzbMaxDepth.ankiprogbin", m_maxDepthProg, m_maxDepthGrProg));
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/HzbMaxDepthProject.ankiprogbin", m_maxBoxProg, m_maxBoxGrProg));
 
+	m_counterBufferElementSize = max<U32>(sizeof(U32), GrManager::getSingleton().getDeviceCapabilities().m_storageBufferBindOffsetAlignment);
 	BufferInitInfo buffInit("HzbCounterBuffer");
-	buffInit.m_size = sizeof(U32);
+	buffInit.m_size = m_counterBufferElementSize * kCounterBufferElementCount;
 	buffInit.m_usage = BufferUsageBit::kStorageComputeWrite | BufferUsageBit::kTransferDestination;
 	m_counterBuffer = GrManager::getSingleton().newBuffer(buffInit);
 
@@ -93,8 +94,19 @@ Error HzbGenerator::init()
 }
 
 void HzbGenerator::populateRenderGraphInternal(RenderTargetHandle srcDepthRt, UVec2 srcDepthRtSize, RenderTargetHandle dstHzbRt, UVec2 dstHzbRtSize,
-											   RenderGraphDescription& rgraph, CString customName) const
+											   U32 counterBufferElement, RenderGraphDescription& rgraph, CString customName) const
 {
+#if ANKI_ASSERTIONS_ENABLED
+	if(m_crntFrame != getRenderer().getFrameCount())
+	{
+		m_crntFrame = getRenderer().getFrameCount();
+		m_counterBufferElementUseMask = 0;
+	}
+
+	ANKI_ASSERT(!(m_counterBufferElementUseMask & (1 << counterBufferElement)));
+	m_counterBufferElementUseMask |= (1 << counterBufferElement);
+#endif
+
 	TextureSubresourceInfo firstMipSubresource;
 
 	const U32 hzbMipCount = min(kMaxSpdMips, computeMaxMipmapCount2d(dstHzbRtSize.x(), dstHzbRtSize.y()));
@@ -104,7 +116,7 @@ void HzbGenerator::populateRenderGraphInternal(RenderTargetHandle srcDepthRt, UV
 	pass.newTextureDependency(srcDepthRt, TextureUsageBit::kSampledCompute, firstMipSubresource);
 	pass.newTextureDependency(dstHzbRt, TextureUsageBit::kImageComputeWrite);
 
-	pass.setWork([this, hzbMipCount, srcDepthRt, srcDepthRtSize, dstHzbRt, dstHzbRtSize](RenderPassWorkContext& rgraphCtx) {
+	pass.setWork([this, hzbMipCount, srcDepthRt, srcDepthRtSize, dstHzbRt, dstHzbRtSize, counterBufferElement](RenderPassWorkContext& rgraphCtx) {
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 		const U32 mipsToCompute = hzbMipCount;
@@ -145,7 +157,7 @@ void HzbGenerator::populateRenderGraphInternal(RenderTargetHandle srcDepthRt, UV
 			rgraphCtx.bindImage(0, 0, dstHzbRt, subresource, mip);
 		}
 
-		cmdb.bindStorageBuffer(0, 1, m_counterBuffer.get(), 0, kMaxPtrSize);
+		cmdb.bindStorageBuffer(0, 1, m_counterBuffer.get(), counterBufferElement * m_counterBufferElementSize, sizeof(U32));
 		rgraphCtx.bindTexture(0, 2, srcDepthRt, TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
 		cmdb.bindSampler(0, 3, m_maxSampler.isCreated() ? m_maxSampler.get() : getRenderer().getSamplers().m_trilinearClamp.get());
 
@@ -156,7 +168,7 @@ void HzbGenerator::populateRenderGraphInternal(RenderTargetHandle srcDepthRt, UV
 void HzbGenerator::populateRenderGraph(RenderTargetHandle srcDepthRt, UVec2 srcDepthRtSize, RenderTargetHandle dstHzbRt, UVec2 dstHzbRtSize,
 									   RenderGraphDescription& rgraph, CString customName) const
 {
-	populateRenderGraphInternal(srcDepthRt, srcDepthRtSize, dstHzbRt, dstHzbRtSize, rgraph, customName);
+	populateRenderGraphInternal(srcDepthRt, srcDepthRtSize, dstHzbRt, dstHzbRtSize, 0, rgraph, customName);
 }
 
 void HzbGenerator::populateRenderGraphDirectionalLight(RenderTargetHandle srcDepthRt, UVec2 srcDepthRtSize,
@@ -251,7 +263,7 @@ void HzbGenerator::populateRenderGraphDirectionalLight(RenderTargetHandle srcDep
 	// Generate the HZBs
 	for(U32 i = 0; i < cascadeCount; ++i)
 	{
-		populateRenderGraphInternal(depthRts[i], dstHzbSizes[i] * 2, dstHzbRts[i], dstHzbSizes[i], rgraph, "HZB generation cascade");
+		populateRenderGraphInternal(depthRts[i], dstHzbSizes[i] * 2, dstHzbRts[i], dstHzbSizes[i], i + 1, rgraph, "HZB generation cascade");
 	}
 }
 

+ 10 - 1
AnKi/Renderer/Utils/HzbGenerator.h

@@ -39,14 +39,23 @@ private:
 
 	SamplerPtr m_maxSampler;
 
+	// This class assumes that the populateRenderGraph and the populateRenderGraphDirectionalLight will be called once per frame
+	static constexpr U32 kCounterBufferElementCount = 1 + kMaxShadowCascades; ///< One for the main pass and a few for shadow cascades
+	U32 m_counterBufferElementSize = 0;
 	BufferPtr m_counterBuffer;
 
 	BufferPtr m_boxIndexBuffer;
 
 	FramebufferDescription m_fbDescr;
 
+#if ANKI_ASSERTIONS_ENABLED
+	// Some helper things to make sure that we don't re-use the counters inside a frame
+	mutable U64 m_crntFrame = 0;
+	mutable U8 m_counterBufferElementUseMask = 0;
+#endif
+
 	void populateRenderGraphInternal(RenderTargetHandle srcDepthRt, UVec2 srcDepthRtSize, RenderTargetHandle dstHzbRt, UVec2 dstHzbRtSize,
-									 RenderGraphDescription& rgraph, CString customName) const;
+									 U32 counterBufferElement, RenderGraphDescription& rgraph, CString customName) const;
 };
 /// @}