Browse Source

Preparing renderer for full MT

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
69e0d454b6

+ 1 - 0
include/anki/gr/CommandBuffer.h

@@ -72,6 +72,7 @@ class CommandBufferInitInfo
 {
 public:
 	Bool m_secondLevel = false;
+	FramebufferPtr m_framebuffer; ///< For second level command buffers.
 };
 
 /// Command buffer initialization hints. They are used to optimize the

+ 1 - 1
include/anki/renderer/Bloom.h

@@ -44,7 +44,7 @@ anki_internal:
 	~Bloom();
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
-	void run(CommandBufferPtr& jobs);
+	void run(RenderingContext& ctx);
 
 	TexturePtr& getRt()
 	{

+ 2 - 0
include/anki/renderer/Common.h

@@ -28,6 +28,8 @@ class Ir;
 class Upsample;
 class DownscaleBlur;
 
+class RenderingContext;
+
 /// Computes the 'a' and 'b' numbers for linearizeDepthOptimal
 inline void computeLinearizeDepthOptimal(F32 near, F32 far, F32& a, F32& b)
 {

+ 1 - 1
include/anki/renderer/Dbg.h

@@ -62,7 +62,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 
-	ANKI_USE_RESULT Error run(CommandBufferPtr& jobs);
+	ANKI_USE_RESULT Error run(RenderingContext& ctx);
 
 private:
 	Bool m_enabled = false;

+ 1 - 1
include/anki/renderer/DownscaleBlur.h

@@ -24,7 +24,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 
-	void run(CommandBufferPtr& cmdb);
+	void run(RenderingContext& ctx);
 
 private:
 	class Subpass

+ 1 - 1
include/anki/renderer/Fs.h

@@ -25,7 +25,7 @@ anki_internal:
 	~Fs();
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
-	ANKI_USE_RESULT Error run(CommandBufferPtr& cmdb);
+	ANKI_USE_RESULT Error run(RenderingContext& ctx);
 
 	TexturePtr getRt() const
 	{

+ 5 - 5
include/anki/renderer/Ir.h

@@ -34,7 +34,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 
-	ANKI_USE_RESULT Error run(CommandBufferPtr cmdb);
+	ANKI_USE_RESULT Error run(RenderingContext& ctx);
 
 	DynamicBufferToken getProbesToken() const
 	{
@@ -102,14 +102,14 @@ private:
 	void binProbes(U32 threadId, PtrSize threadsCount, IrRunContext& ctx);
 
 	ANKI_USE_RESULT Error writeProbeAndRender(
-		SceneNode& node, IrShaderReflectionProbe& probe, CommandBufferPtr cmdb);
+		RenderingContext& ctx, SceneNode& node, IrShaderReflectionProbe& probe);
 
 	void binProbe(U probeIdx, IrRunContext& ctx, IrTaskContext& task) const;
 
-	ANKI_USE_RESULT Error renderReflection(SceneNode& node,
+	ANKI_USE_RESULT Error renderReflection(RenderingContext& ctx,
+		SceneNode& node,
 		ReflectionProbeComponent& reflc,
-		U cubemapIdx,
-		CommandBufferPtr cmdb);
+		U cubemapIdx);
 
 	static void writeIndicesAndCluster(
 		U clusterIdx, Bool hasPrevCluster, IrRunContext& ctx);

+ 5 - 2
include/anki/renderer/Is.h

@@ -51,7 +51,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 
-	ANKI_USE_RESULT Error run(CommandBufferPtr& cmdBuff);
+	ANKI_USE_RESULT Error run(RenderingContext& ctx);
 
 	TexturePtr getRt() const
 	{
@@ -146,7 +146,7 @@ private:
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 
 	/// Do the actual pass
-	ANKI_USE_RESULT Error lightPass(CommandBufferPtr& cmdBuff);
+	ANKI_USE_RESULT Error lightPass(RenderingContext& ctx);
 
 	/// Prepare GL for rendering
 	void setState(CommandBufferPtr& cmdBuff);
@@ -156,16 +156,19 @@ private:
 
 	// Binning
 	void binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& data);
+
 	I writePointLight(const LightComponent& light,
 		const MoveComponent& move,
 		const FrustumComponent& camfrc,
 		TaskCommonData& task);
+
 	I writeSpotLight(const LightComponent& lightc,
 		const MoveComponent& lightMove,
 		const FrustumComponent* lightFrc,
 		const MoveComponent& camMove,
 		const FrustumComponent& camFrc,
 		TaskCommonData& task);
+
 	void binLight(SpatialComponent& sp,
 		U pos,
 		U lightType,

+ 2 - 2
include/anki/renderer/Lf.h

@@ -29,9 +29,9 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& config);
 
-	void runOcclusionTests(CommandBufferPtr& cmdb);
+	void runOcclusionTests(RenderingContext& ctx);
 
-	void run(CommandBufferPtr& cmdb);
+	void run(RenderingContext& ctx);
 
 private:
 	// Occlusion query

+ 1 - 1
include/anki/renderer/Ms.h

@@ -31,7 +31,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 
-	ANKI_USE_RESULT Error run(CommandBufferPtr& jobs);
+	ANKI_USE_RESULT Error run(RenderingContext& ctx);
 
 	TexturePtr& getRt0()
 	{

+ 1 - 1
include/anki/renderer/Pps.h

@@ -35,7 +35,7 @@ anki_internal:
 	~Pps();
 
 	ANKI_USE_RESULT Error init(const ConfigSet& config);
-	void run(CommandBufferPtr& jobs);
+	void run(RenderingContext& ctx);
 
 	const TexturePtr& getRt() const
 	{

+ 13 - 15
include/anki/renderer/Renderer.h

@@ -25,6 +25,18 @@ class ResourceManager;
 /// @addtogroup renderer
 /// @{
 
+/// Rendering context.
+class RenderingContext
+{
+public:
+	/// Active frustum.
+	FrustumComponent* m_frustumComponent ANKI_DBG_NULLIFY_PTR;
+
+	CommandBufferPtr m_commandBuffer; ///< Primary command buffer.
+
+	DArray<CommandBufferPtr> m_fsCommandBuffers;
+};
+
 /// Offscreen renderer. It is a class and not a namespace because we may need
 /// external renderers for security cameras for example
 class Renderer
@@ -141,8 +153,7 @@ public:
 	}
 
 	/// This function does all the rendering stages and produces a final result.
-	ANKI_USE_RESULT Error render(
-		SceneNode& frustumableNode, U frustumIdx, CommandBufferPtr cmdb);
+	ANKI_USE_RESULT Error render(RenderingContext& ctx);
 
 anki_internal:
 	/// WARNING: If you change the tile size you need to change some shaders
@@ -163,18 +174,6 @@ anki_internal:
 		return m_frameCount;
 	}
 
-	const FrustumComponent& getActiveFrustumComponent() const
-	{
-		ANKI_ASSERT(m_frc);
-		return *m_frc;
-	}
-
-	FrustumComponent& getActiveFrustumComponent()
-	{
-		ANKI_ASSERT(m_frc);
-		return *m_frc;
-	}
-
 	const RenderableDrawer& getSceneDrawer() const
 	{
 		return m_sceneDrawer;
@@ -353,7 +352,6 @@ private:
 
 	ShaderResourcePtr m_drawQuadVert;
 
-	FrustumComponent* m_frc = nullptr; ///< Cache current frustum component.
 	RenderableDrawer m_sceneDrawer;
 
 	U64 m_frameCount; ///< Frame number

+ 1 - 1
include/anki/renderer/Sm.h

@@ -42,7 +42,7 @@ anki_internal:
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
 	ANKI_USE_RESULT Error run(SArray<SceneNode*> spotShadowCasters,
 		SArray<SceneNode*> omniShadowCasters,
-		CommandBufferPtr& cmdBuff);
+		RenderingContext& ctx);
 
 	Bool getEnabled() const
 	{

+ 1 - 1
include/anki/renderer/Ssao.h

@@ -29,7 +29,7 @@ anki_internal:
 	}
 
 	ANKI_USE_RESULT Error init(const ConfigSet& initializer);
-	void run(CommandBufferPtr& cmdBuff);
+	void run(RenderingContext& ctx);
 
 	TexturePtr& getRt()
 	{

+ 1 - 1
include/anki/renderer/Sslf.h

@@ -23,7 +23,7 @@ anki_internal:
 	}
 
 	ANKI_USE_RESULT Error init(const ConfigSet& config);
-	void run(CommandBufferPtr& cmdb);
+	void run(RenderingContext& ctx);
 
 	TexturePtr& getRt()
 	{

+ 1 - 1
include/anki/renderer/Tm.h

@@ -29,7 +29,7 @@ anki_internal:
 
 	ANKI_USE_RESULT Error create(const ConfigSet& initializer);
 
-	void run(CommandBufferPtr& cmdb);
+	void run(RenderingContext& ctx);
 
 private:
 	ShaderResourcePtr m_luminanceShader;

+ 1 - 1
include/anki/renderer/Upsample.h

@@ -24,7 +24,7 @@ public:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& config);
 
-	void run(CommandBufferPtr cmdb);
+	void run(RenderingContext& ctx);
 
 private:
 	ResourceGroupPtr m_rcGroup;

+ 2 - 3
src/renderer/Bloom.cpp

@@ -150,10 +150,9 @@ Error Bloom::init(const ConfigSet& config)
 }
 
 //==============================================================================
-void Bloom::run(CommandBufferPtr& cmdb)
+void Bloom::run(RenderingContext& ctx)
 {
-	// For the passes it should be NEAREST_BASE
-	// vblurFai.setFiltering(Texture::TFrustumType::NEAREST_BASE);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
 	// pass 0
 	cmdb->bindFramebuffer(m_vblurFb);

+ 3 - 2
src/renderer/Dbg.cpp

@@ -78,15 +78,16 @@ Error Dbg::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-Error Dbg::run(CommandBufferPtr& cmdb)
+Error Dbg::run(RenderingContext& ctx)
 {
 	Error err = ErrorCode::NONE;
 
 	ANKI_ASSERT(m_enabled);
 
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	cmdb->bindFramebuffer(m_fb);
 
-	FrustumComponent& camFr = m_r->getActiveFrustumComponent();
+	FrustumComponent& camFr = *ctx.m_frustumComponent;
 	SceneNode& cam = camFr.getSceneNode();
 	m_drawer->prepareDraw(cmdb);
 	m_drawer->setViewProjectionMatrix(camFr.getViewProjectionMatrix());

+ 2 - 1
src/renderer/DownscaleBlur.cpp

@@ -80,8 +80,9 @@ Error DownscaleBlur::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void DownscaleBlur::run(CommandBufferPtr& cmdb)
+void DownscaleBlur::run(RenderingContext& ctx)
 {
+	CommandBufferPtr cmdb = ctx.m_commandBuffer;
 	UVec2 size(m_r->getWidth(), m_r->getHeight());
 	for(U i = 0; i < m_passes.getSize(); ++i)
 	{

+ 3 - 2
src/renderer/Fs.cpp

@@ -64,12 +64,13 @@ Error Fs::init(const ConfigSet&)
 }
 
 //==============================================================================
-Error Fs::run(CommandBufferPtr& cmdb)
+Error Fs::run(RenderingContext& ctx)
 {
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	cmdb->bindFramebuffer(m_fb);
 	cmdb->setViewport(0, 0, m_r->getWidth() / 2, m_r->getHeight() / 2);
 
-	FrustumComponent& camFr = m_r->getActiveFrustumComponent();
+	FrustumComponent& camFr = *ctx.m_frustumComponent;
 
 	DynamicBufferInfo dyn;
 	dyn.m_storageBuffers[0] = m_r->getIs().getCommonVarsToken();

+ 27 - 10
src/renderer/Ir.cpp

@@ -290,10 +290,11 @@ Error Ir::initIrradiance()
 }
 
 //==============================================================================
-Error Ir::run(CommandBufferPtr cmdb)
+Error Ir::run(RenderingContext& rctx)
 {
 	ANKI_TRACE_START_EVENT(RENDER_IR);
-	FrustumComponent& frc = m_r->getActiveFrustumComponent();
+	CommandBufferPtr& cmdb = rctx.m_commandBuffer;
+	FrustumComponent& frc = *rctx.m_frustumComponent;
 	VisibilityTestResults& visRez = frc.getVisibilityTestResults();
 
 	if(visRez.getCount(VisibilityGroupType::REFLECTION_PROBES)
@@ -352,7 +353,7 @@ Error Ir::run(CommandBufferPtr cmdb)
 	while(it != end)
 	{
 		// Write and render probe
-		ANKI_CHECK(writeProbeAndRender(*it->m_node, probes[probeIdx], cmdb));
+		ANKI_CHECK(writeProbeAndRender(rctx, *it->m_node, probes[probeIdx]));
 
 		++it;
 		++probeIdx;
@@ -477,9 +478,9 @@ void Ir::binProbes(U32 threadId, PtrSize threadsCount, IrRunContext& ctx)
 
 //==============================================================================
 Error Ir::writeProbeAndRender(
-	SceneNode& node, IrShaderReflectionProbe& probe, CommandBufferPtr cmdb)
+	RenderingContext& ctx, SceneNode& node, IrShaderReflectionProbe& probe)
 {
-	const FrustumComponent& frc = m_r->getActiveFrustumComponent();
+	const FrustumComponent& frc = *ctx.m_frustumComponent;
 	ReflectionProbeComponent& reflc =
 		node.getComponent<ReflectionProbeComponent>();
 
@@ -495,7 +496,7 @@ Error Ir::writeProbeAndRender(
 	if(reflc.getMarkedForRendering())
 	{
 		reflc.setMarkedForRendering(false);
-		ANKI_CHECK(renderReflection(node, reflc, entry, cmdb));
+		ANKI_CHECK(renderReflection(ctx, node, reflc, entry));
 	}
 
 	// If you need to render it mark it for the next frame
@@ -583,18 +584,34 @@ void Ir::writeIndicesAndCluster(
 }
 
 //==============================================================================
-Error Ir::renderReflection(SceneNode& node,
+Error Ir::renderReflection(RenderingContext& ctx,
+	SceneNode& node,
 	ReflectionProbeComponent& reflc,
-	U cubemapIdx,
-	CommandBufferPtr cmdb)
+	U cubemapIdx)
 {
 	ANKI_TRACE_INC_COUNTER(RENDERER_REFLECTIONS, 1);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
+	// Get the frustum components
+	Array<FrustumComponent*, 6> frustumComponents;
+	U count = 0;
+	Error err = node.iterateComponentsOfType<FrustumComponent>(
+		[&](FrustumComponent& frc) -> Error {
+			frustumComponents[count++] = &frc;
+			return ErrorCode::NONE;
+		});
+	(void)err;
+	ANKI_ASSERT(count == 6);
 
 	// Render cubemap
 	for(U i = 0; i < 6; ++i)
 	{
 		// Render
-		ANKI_CHECK(m_nestedR.render(node, i, cmdb));
+		RenderingContext nestedCtx;
+		nestedCtx.m_frustumComponent = frustumComponents[i];
+		nestedCtx.m_commandBuffer = cmdb;
+
+		ANKI_CHECK(m_nestedR.render(nestedCtx));
 
 		// Copy env texture
 		cmdb->copyTextureToTexture(m_nestedR.getIs().getRt(),

+ 6 - 5
src/renderer/Is.cpp

@@ -338,11 +338,12 @@ Error Is::initInternal(const ConfigSet& config)
 }
 
 //==============================================================================
-Error Is::lightPass(CommandBufferPtr& cmdb)
+Error Is::lightPass(RenderingContext& ctx)
 {
 	ANKI_TRACE_START_EVENT(RENDER_IS);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	ThreadPool& threadPool = m_r->getThreadPool();
-	m_frc = &m_r->getActiveFrustumComponent();
+	m_frc = ctx.m_frustumComponent;
 	VisibilityTestResults& vi = m_frc->getVisibilityTestResults();
 
 	U clusterCount = m_r->getClusterCount();
@@ -401,7 +402,7 @@ Error Is::lightPass(CommandBufferPtr& cmdb)
 	{
 		ANKI_CHECK(m_sm.run({&spotCasters[0], spotCastersCount},
 			{&omniCasters[0], omniCastersCount},
-			cmdb));
+			ctx));
 	}
 
 	//
@@ -792,10 +793,10 @@ void Is::setState(CommandBufferPtr& cmdb)
 }
 
 //==============================================================================
-Error Is::run(CommandBufferPtr& cmdb)
+Error Is::run(RenderingContext& ctx)
 {
 	// Do the light pass including the shadow passes
-	return lightPass(cmdb);
+	return lightPass(ctx);
 }
 
 //==============================================================================

+ 6 - 4
src/renderer/Lf.cpp

@@ -154,10 +154,11 @@ Error Lf::initInternal(const ConfigSet& config)
 }
 
 //==============================================================================
-void Lf::runOcclusionTests(CommandBufferPtr& cmdb)
+void Lf::runOcclusionTests(RenderingContext& ctx)
 {
 	// Retrieve some things
-	FrustumComponent& camFr = m_r->getActiveFrustumComponent();
+	FrustumComponent& camFr = *ctx.m_frustumComponent;
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	VisibilityTestResults& vi = camFr.getVisibilityTestResults();
 
 	if(vi.getCount(VisibilityGroupType::FLARES) > m_maxFlares)
@@ -216,10 +217,11 @@ void Lf::runOcclusionTests(CommandBufferPtr& cmdb)
 }
 
 //==============================================================================
-void Lf::run(CommandBufferPtr& cmdb)
+void Lf::run(RenderingContext& ctx)
 {
 	// Retrieve some things
-	FrustumComponent& camFr = m_r->getActiveFrustumComponent();
+	FrustumComponent& camFr = *ctx.m_frustumComponent;
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	VisibilityTestResults& vi = camFr.getVisibilityTestResults();
 
 	U totalCount =

+ 6 - 1
src/renderer/MainRenderer.cpp

@@ -151,7 +151,12 @@ Error MainRenderer::render(SceneGraph& scene)
 
 	// Run renderer
 	m_r->getIs().setAmbientColor(scene.getAmbientColor());
-	ANKI_CHECK(m_r->render(scene.getActiveCamera(), 0, cmdb));
+
+	RenderingContext ctx;
+	ctx.m_commandBuffer = cmdb;
+	ctx.m_frustumComponent = 
+		&scene.getActiveCamera().getComponent<FrustumComponent>();
+	ANKI_CHECK(m_r->render(ctx));
 
 	if(!rDrawToDefault)
 	{

+ 3 - 2
src/renderer/Ms.cpp

@@ -116,9 +116,10 @@ Error Ms::initInternal(const ConfigSet& initializer)
 }
 
 //==============================================================================
-Error Ms::run(CommandBufferPtr& cmdb)
+Error Ms::run(RenderingContext& ctx)
 {
 	ANKI_TRACE_START_EVENT(RENDER_MS);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
 	// Create 2nd level cmdbs
 	U threadCount = m_r->getThreadPool().getThreadsCount();
@@ -134,7 +135,7 @@ Error Ms::run(CommandBufferPtr& cmdb)
 	cmdb->bindFramebuffer(m_fb);
 
 	// render all
-	FrustumComponent& frc = m_r->getActiveFrustumComponent();
+	FrustumComponent& frc = *ctx.m_frustumComponent;
 	SArray<CommandBufferPtr> cmdbs(
 		&m_secondLevelCmdbs[0], m_secondLevelCmdbs.getSize());
 	ANKI_CHECK(m_r->getSceneDrawer().render(frc,

+ 3 - 2
src/renderer/Pps.cpp

@@ -155,8 +155,9 @@ Error Pps::loadColorGradingTexture(CString filename)
 }
 
 //==============================================================================
-void Pps::run(CommandBufferPtr& cmdb)
+void Pps::run(RenderingContext& ctx)
 {
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	FramebufferPtr fb = m_fb;
 	U32 width = m_r->getWidth();
 	U32 height = m_r->getHeight();
@@ -182,7 +183,7 @@ void Pps::run(CommandBufferPtr& cmdb)
 		cmdb->writeBuffer(m_uniformsBuff, 0, token);
 		unis->m_fogColorFogFactor = Vec4(m_fogColor, m_fogFactor);
 
-		const FrustumComponent& frc = m_r->getActiveFrustumComponent();
+		const FrustumComponent& frc = *ctx.m_frustumComponent;
 		unis->m_nearFarPad2 = Vec4(
 			frc.getFrustum().getNear(), frc.getFrustum().getFar(), 0.0, 0.0);
 	}

+ 25 - 37
src/renderer/Renderer.cpp

@@ -203,26 +203,14 @@ Error Renderer::initInternal(const ConfigSet& config)
 }
 
 //==============================================================================
-Error Renderer::render(
-	SceneNode& frustumableNode, U frustumIdx, CommandBufferPtr cmdb)
+Error Renderer::render(RenderingContext& ctx)
 {
-	m_frc = nullptr;
-	Error err = frustumableNode.iterateComponentsOfType<FrustumComponent>(
-		[&](FrustumComponent& frc) -> Error {
-			if(frustumIdx == 0)
-			{
-				m_frc = &frc;
-			}
-
-			--frustumIdx;
-			return ErrorCode::NONE;
-		});
-	(void)err;
-	ANKI_ASSERT(m_frc && "Not enough frustum components");
+	FrustumComponent& frc = *ctx.m_frustumComponent;
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
 	// Misc
-	ANKI_ASSERT(m_frc->getFrustum().getType() == Frustum::Type::PERSPECTIVE);
-	m_clusterer.prepare(getThreadPool(), *m_frc);
+	ANKI_ASSERT(frc.getFrustum().getType() == Frustum::Type::PERSPECTIVE);
+	m_clusterer.prepare(getThreadPool(), frc);
 
 	// Write the common uniforms
 	RendererCommonUniforms* commonUniforms =
@@ -232,73 +220,73 @@ Error Renderer::render(
 				BufferUsage::UNIFORM,
 				m_commonUniformsToken));
 
-	commonUniforms->m_projectionParams = m_frc->getProjectionParameters();
-	commonUniforms->m_nearFarLinearizeDepth.x() = m_frc->getFrustum().getNear();
-	commonUniforms->m_nearFarLinearizeDepth.y() = m_frc->getFrustum().getFar();
-	computeLinearizeDepthOptimal(m_frc->getFrustum().getNear(),
-		m_frc->getFrustum().getFar(),
+	commonUniforms->m_projectionParams = frc.getProjectionParameters();
+	commonUniforms->m_nearFarLinearizeDepth.x() = frc.getFrustum().getNear();
+	commonUniforms->m_nearFarLinearizeDepth.y() = frc.getFrustum().getFar();
+	computeLinearizeDepthOptimal(frc.getFrustum().getNear(),
+		frc.getFrustum().getFar(),
 		commonUniforms->m_nearFarLinearizeDepth.z(),
 		commonUniforms->m_nearFarLinearizeDepth.w());
 
-	commonUniforms->m_projectionMatrix = m_frc->getProjectionMatrix();
+	commonUniforms->m_projectionMatrix = frc.getProjectionMatrix();
 
 	// Run stages
 	if(m_ir)
 	{
-		ANKI_CHECK(m_ir->run(cmdb));
+		ANKI_CHECK(m_ir->run(ctx));
 	}
 
-	ANKI_CHECK(m_ms->run(cmdb));
+	ANKI_CHECK(m_ms->run(ctx));
 
-	m_lf->runOcclusionTests(cmdb);
+	m_lf->runOcclusionTests(ctx);
 
 	// m_tiler->run(cmdb);
 
-	ANKI_CHECK(m_is->run(cmdb));
+	ANKI_CHECK(m_is->run(ctx));
 
 	cmdb->generateMipmaps(m_ms->getDepthRt());
 	cmdb->generateMipmaps(m_ms->getRt2());
 
-	ANKI_CHECK(m_fs->run(cmdb));
-	m_lf->run(cmdb);
+	ANKI_CHECK(m_fs->run(ctx));
+	m_lf->run(ctx);
 
-	m_upsample->run(cmdb);
+	m_upsample->run(ctx);
 
 	cmdb->generateMipmaps(m_is->getRt());
 
 	if(m_downscale)
 	{
-		m_downscale->run(cmdb);
+		m_downscale->run(ctx);
 	}
 
 	if(m_tm)
 	{
-		m_tm->run(cmdb);
+		m_tm->run(ctx);
 	}
 
 	if(m_bloom)
 	{
-		m_bloom->run(cmdb);
+		m_bloom->run(ctx);
 	}
 
 	if(m_sslf)
 	{
-		m_sslf->run(cmdb);
+		m_sslf->run(ctx);
 	}
 
 	if(m_ssao)
 	{
-		m_ssao->run(cmdb);
+		m_ssao->run(ctx);
 	}
 
 	if(m_pps)
 	{
-		m_pps->run(cmdb);
+		m_pps->run(ctx);
 	}
 
 	if(m_dbg->getEnabled())
 	{
-		ANKI_CHECK(m_dbg->run(cmdb));
+		ANKI_CHECK(m_dbg->run(ctx));
 	}
 
 	++m_frameCount;

+ 4 - 3
src/renderer/Sm.cpp

@@ -106,10 +106,11 @@ Error Sm::init(const ConfigSet& config)
 //==============================================================================
 Error Sm::run(SArray<SceneNode*> spotShadowCasters,
 	SArray<SceneNode*> omniShadowCasters,
-	CommandBufferPtr& cmdBuff)
+	RenderingContext& ctx)
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_TRACE_START_EVENT(RENDER_SM);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
 	if(omniShadowCasters.getSize() > m_omnis.getSize()
 		|| spotShadowCasters.getSize() > m_spots.getSize())
@@ -120,12 +121,12 @@ Error Sm::run(SArray<SceneNode*> spotShadowCasters,
 	// render all
 	for(SceneNode* node : spotShadowCasters)
 	{
-		ANKI_CHECK(doSpotLight(*node, cmdBuff));
+		ANKI_CHECK(doSpotLight(*node, cmdb));
 	}
 
 	for(SceneNode* node : omniShadowCasters)
 	{
-		ANKI_CHECK(doOmniLight(*node, cmdBuff));
+		ANKI_CHECK(doOmniLight(*node, cmdb));
 	}
 
 	ANKI_TRACE_STOP_EVENT(RENDER_SM);

+ 3 - 1
src/renderer/Ssao.cpp

@@ -276,8 +276,10 @@ Error Ssao::init(const ConfigSet& config)
 }
 
 //==============================================================================
-void Ssao::run(CommandBufferPtr& cmdb)
+void Ssao::run(RenderingContext& ctx)
 {
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
 	// 1st pass
 	//
 	cmdb->bindFramebuffer(m_vblurFb);

+ 3 - 1
src/renderer/Sslf.cpp

@@ -78,8 +78,10 @@ Error Sslf::initInternal(const ConfigSet& config)
 }
 
 //==============================================================================
-void Sslf::run(CommandBufferPtr& cmdb)
+void Sslf::run(RenderingContext& ctx)
 {
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
 	// Draw to the SSLF FB
 	cmdb->bindFramebuffer(m_fb);
 	cmdb->setViewport(

+ 2 - 1
src/renderer/Tm.cpp

@@ -59,8 +59,9 @@ Error Tm::create(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void Tm::run(CommandBufferPtr& cmdb)
+void Tm::run(RenderingContext& ctx)
 {
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	cmdb->bindPipeline(m_luminancePpline);
 	cmdb->bindResourceGroup(m_rcGroup, 0, nullptr);
 

+ 3 - 2
src/renderer/Upsample.cpp

@@ -86,14 +86,15 @@ Error Upsample::init(const ConfigSet& config)
 }
 
 //==============================================================================
-void Upsample::run(CommandBufferPtr cmdb)
+void Upsample::run(RenderingContext& ctx)
 {
+	CommandBufferPtr cmdb = ctx.m_commandBuffer;
 	DynamicBufferInfo dyn;
 
 	Vec4* linearDepth =
 		static_cast<Vec4*>(getGrManager().allocateFrameHostVisibleMemory(
 			sizeof(Vec4), BufferUsage::UNIFORM, dyn.m_uniformBuffers[0]));
-	const Frustum& fr = m_r->getActiveFrustumComponent().getFrustum();
+	const Frustum& fr = ctx.m_frustumComponent->getFrustum();
 	computeLinearizeDepthOptimal(
 		fr.getNear(), fr.getFar(), linearDepth->x(), linearDepth->y());