Browse Source

Add a pass to copy the HiZ to a client buffer

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
918e05664d

+ 46 - 0
programs/HiZCopyToClient.ankiprog

@@ -0,0 +1,46 @@
+<!-- 
+Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+All rights reserved.
+Code licensed under the BSD License.
+http://www.anki3d.org/LICENSE
+-->
+<shaderProgram>
+	<shaders>
+		<shader type="comp">
+			<inputs>
+				<input name="HIZ_MIP_SIZE" type="uvec2" const="1"/>
+			</inputs>
+
+			<source><![CDATA[
+#include "shaders/Common.glsl"
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_hizTex;
+
+layout(std430, ANKI_SS_BINDING(0, 0)) writeonly buffer s1_
+{
+	float u_outBuff[];
+};
+
+void main()
+{
+	uint x = gl_GlobalInvocationID.x;
+	uint y = gl_GlobalInvocationID.y;
+
+	if(x > HIZ_MIP_SIZE.x || y > HIZ_MIP_SIZE.y)
+	{
+		// Skup if it's out of bounds
+		return;
+	}
+
+	// Read the tex
+	float depth = texelFetch(u_hizTex, ivec2(x, y), 0).r;
+
+	// Write the depth
+	u_outBuff[y * HIZ_MIP_SIZE.x + x] = depth;
+}
+			]]></source>
+		</shader>
+	</shaders>
+</shaderProgram>

+ 62 - 5
src/anki/renderer/DepthDownscale.cpp

@@ -13,6 +13,11 @@ namespace anki
 DepthDownscale::~DepthDownscale()
 {
 	m_passes.destroy(getAllocator());
+
+	if(m_copyToBuff.m_buffAddr)
+	{
+		m_copyToBuff.m_buff->unmap();
+	}
 }
 
 Error DepthDownscale::initInternal(const ConfigSet&)
@@ -20,12 +25,12 @@ Error DepthDownscale::initInternal(const ConfigSet&)
 	const U width = m_r->getWidth() / 2;
 	const U height = m_r->getHeight() / 2;
 
-	U mipCount = computeMaxMipmapCount2d(width, height, HIERARCHICAL_Z_MIN_HEIGHT);
+	const U mipCount = computeMaxMipmapCount2d(width, height, HIERARCHICAL_Z_MIN_HEIGHT);
+
+	const U lastMipWidth = width >> (mipCount - 1);
+	const U lastMipHeight = height >> (mipCount - 1);
 
-	ANKI_R_LOGI("Initializing HiZ. Mip count %u, last mip size %ux%u",
-		mipCount,
-		width >> (mipCount - 1),
-		height >> (mipCount - 1));
+	ANKI_R_LOGI("Initializing HiZ. Mip count %u, last mip size %ux%u", mipCount, lastMipWidth, lastMipHeight);
 
 	m_passes.create(getAllocator(), mipCount);
 
@@ -71,6 +76,32 @@ Error DepthDownscale::initInternal(const ConfigSet&)
 		m_passes[i].m_grProg = variant->getProgram();
 	}
 
+	// Copy to buffer
+	{
+		m_copyToBuff.m_lastMipWidth = lastMipWidth;
+		m_copyToBuff.m_lastMipHeight = lastMipHeight;
+
+		// Create program
+		ANKI_CHECK(getResourceManager().loadResource("programs/HiZCopyToClient.ankiprog", m_copyToBuff.m_prog));
+
+		ShaderProgramResourceConstantValueInitList<1> consts(m_copyToBuff.m_prog);
+		consts.add("HIZ_MIP_SIZE", UVec2(lastMipWidth, lastMipHeight));
+
+		const ShaderProgramResourceVariant* variant;
+		m_copyToBuff.m_prog->getOrCreateVariant(consts.get(), variant);
+
+		m_copyToBuff.m_grProg = variant->getProgram();
+
+		// Create buffer
+		BufferInitInfo buffInit("HiZ Client");
+		buffInit.m_access = BufferMapAccessBit::READ;
+		buffInit.m_size = lastMipHeight * lastMipWidth * sizeof(F32);
+		buffInit.m_usage = BufferUsageBit::STORAGE_COMPUTE_WRITE;
+		m_copyToBuff.m_buff = getGrManager().newBuffer(buffInit);
+
+		m_copyToBuff.m_buffAddr = m_copyToBuff.m_buff->map(0, buffInit.m_size, BufferMapAccessBit::READ);
+	}
+
 	return Error::NONE;
 }
 
@@ -132,6 +163,18 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 
 		pass.newProducer({m_runCtx.m_hizRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresourceWrite});
 	}
+
+	// Copy to buffer pass
+	{
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("HiZ Copy");
+
+		pass.setWork(runCopyToBufferCallback, this, 0);
+
+		TextureSubresourceInfo subresource;
+		subresource.m_firstMipmap = getMipmapCount() - 1;
+
+		pass.newConsumer({m_runCtx.m_hizRt, TextureUsageBit::SAMPLED_COMPUTE, subresource});
+	}
 }
 
 void DepthDownscale::run(RenderPassWorkContext& rgraphCtx)
@@ -171,4 +214,18 @@ void DepthDownscale::run(RenderPassWorkContext& rgraphCtx)
 	}
 }
 
+void DepthDownscale::runCopyToBuffer(RenderPassWorkContext& rgraphCtx)
+{
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+
+	TextureSubresourceInfo sampleSubresource;
+	sampleSubresource.m_firstMipmap = getMipmapCount() - 1;
+
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_hizRt, sampleSubresource, m_r->getNearestSampler());
+
+	cmdb->bindStorageBuffer(0, 0, m_copyToBuff.m_buff, 0, m_copyToBuff.m_buff->getSize());
+
+	dispatchPPCompute(cmdb, 8, 8, m_copyToBuff.m_lastMipWidth, m_copyToBuff.m_lastMipHeight);
+}
+
 } // end namespace anki

+ 17 - 0
src/anki/renderer/DepthDownscale.h

@@ -73,15 +73,32 @@ private:
 		U m_pass;
 	} m_runCtx; ///< Run context.
 
+	class
+	{
+	public:
+		ShaderProgramResourcePtr m_prog;
+		ShaderProgramPtr m_grProg;
+		BufferPtr m_buff;
+		void* m_buffAddr = nullptr;
+		U32 m_lastMipWidth = MAX_U32, m_lastMipHeight = MAX_U32;
+	} m_copyToBuff; ///< Copy to buffer members.
+
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& cfg);
 
 	void run(RenderPassWorkContext& rgraphCtx);
 
+	void runCopyToBuffer(RenderPassWorkContext& rgraphCtx);
+
 	/// A RenderPassWorkCallback for half depth main pass.
 	static void runCallback(RenderPassWorkContext& rgraphCtx)
 	{
 		static_cast<DepthDownscale*>(rgraphCtx.m_userData)->run(rgraphCtx);
 	}
+
+	static void runCopyToBufferCallback(RenderPassWorkContext& rgraphCtx)
+	{
+		static_cast<DepthDownscale*>(rgraphCtx.m_userData)->runCopyToBuffer(rgraphCtx);
+	}
 };
 /// @}