Browse Source

Refactor the renderer a bit and the final scaling

Panagiotis Christopoulos Charitos 1 year ago
parent
commit
ce64c5b7e2

+ 5 - 5
AnKi/Core/App.cpp

@@ -24,7 +24,7 @@
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Physics/PhysicsWorld.h>
-#include <AnKi/Renderer/MainRenderer.h>
+#include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Script/ScriptManager.h>
 #include <AnKi/Resource/ResourceFilesystem.h>
 #include <AnKi/Resource/AsyncLoader.h>
@@ -145,7 +145,7 @@ void App::cleanup()
 {
 	SceneGraph::freeSingleton();
 	ScriptManager::freeSingleton();
-	MainRenderer::freeSingleton();
+	Renderer::freeSingleton();
 	UiManager::freeSingleton();
 	GpuSceneMicroPatcher::freeSingleton();
 	ResourceManager::freeSingleton();
@@ -346,11 +346,11 @@ Error App::initInternal()
 	//
 	// Renderer
 	//
-	MainRendererInitInfo renderInit;
+	RendererInitInfo renderInit;
 	renderInit.m_swapchainSize = UVec2(NativeWindow::getSingleton().getWidth(), NativeWindow::getSingleton().getHeight());
 	renderInit.m_allocCallback = allocCb;
 	renderInit.m_allocCallbackUserData = allocCbUserData;
-	ANKI_CHECK(MainRenderer::allocateSingleton().init(renderInit));
+	ANKI_CHECK(Renderer::allocateSingleton().init(renderInit));
 
 	//
 	// Script
@@ -450,7 +450,7 @@ Error App::mainLoop()
 
 			// Render
 			TexturePtr presentableTex = GrManager::getSingleton().acquireNextPresentableTexture();
-			ANKI_CHECK(MainRenderer::getSingleton().render(presentableTex.get()));
+			ANKI_CHECK(Renderer::getSingleton().render(presentableTex.get()));
 
 			// If we get stats exclude the time of GR because it forces some GPU-CPU serialization. We don't want to count that
 			Second grTime = 0.0;

+ 0 - 2
AnKi/Core/App.h

@@ -13,8 +13,6 @@
 namespace anki {
 
 // Forward
-class UiQueueElement;
-class RenderQueue;
 class StatCounter;
 extern NumericCVar<U32> g_windowWidthCVar;
 extern NumericCVar<U32> g_windowHeightCVar;

+ 2 - 2
AnKi/Importer/GltfImporter.cpp

@@ -1196,8 +1196,8 @@ Error GltfImporter::writeCamera(const cgltf_node& node, [[maybe_unused]] const I
 	ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node)\n"));
 	ANKI_CHECK(m_sceneFile.writeText("comp = node:newCameraComponent()\n"));
 
-	ANKI_CHECK(m_sceneFile.writeTextf("comp:setPerspective(%f, %f, getMainRenderer():getAspectRatio() * %f, %f)\n", cam.znear, cam.zfar, cam.yfov,
-									  cam.yfov));
+	ANKI_CHECK(
+		m_sceneFile.writeTextf("comp:setPerspective(%f, %f, getRenderer():getAspectRatio() * %f, %f)\n", cam.znear, cam.zfar, cam.yfov, cam.yfov));
 
 	return Error::kNone;
 }

+ 0 - 1
AnKi/Renderer.h

@@ -13,7 +13,6 @@
 #include <AnKi/Renderer/FinalComposite.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/ShadowMapping.h>
-#include <AnKi/Renderer/MainRenderer.h>
 #include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/LensFlare.h>

+ 1 - 1
AnKi/Renderer/Common.h

@@ -83,7 +83,7 @@ public:
 	F32 m_cameraFar = 0.0f;
 
 	/// The render target that the Renderer will populate.
-	RenderTargetHandle m_outRenderTarget;
+	RenderTargetHandle m_swapchainRenderTarget;
 
 	Array<Mat4, kMaxShadowCascades> m_dirLightTextureMatrices;
 	Array<F32, kMaxShadowCascades> m_dirLightFarPlanes;

+ 75 - 58
AnKi/Renderer/FinalComposite.cpp

@@ -40,6 +40,15 @@ Error FinalComposite::initInternal()
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/VisualizeRenderTarget.ankiprogbin", m_defaultVisualizeRenderTargetProg,
 								 m_defaultVisualizeRenderTargetGrProg));
 
+	if(getRenderer().getSwapchainResolution() != getRenderer().getPostProcessResolution())
+	{
+		m_rtDesc = getRenderer().create2DRenderTargetDescription(
+			getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y(),
+			(GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::kR8G8B8_Unorm : Format::kR8G8B8A8_Unorm,
+			"Final Composite");
+		m_rtDesc.bake();
+	}
+
 	return Error::kNone;
 }
 
@@ -73,12 +82,17 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 	// Create the pass
 	GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("Final Composite");
 
-	pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-		run(rgraphCtx);
-	});
-	pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(ctx.m_outRenderTarget)});
+	const Bool bRendersToSwapchain = getRenderer().getSwapchainResolution() == getRenderer().getPostProcessResolution();
+	const RenderTargetHandle outRt = (!bRendersToSwapchain) ? rgraph.newRenderTarget(m_rtDesc) : ctx.m_swapchainRenderTarget;
 
-	pass.newTextureDependency(ctx.m_outRenderTarget, TextureUsageBit::kRtvDsvWrite);
+	if(!bRendersToSwapchain)
+	{
+		m_runCtx.m_rt = outRt;
+	}
+
+	pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(outRt)});
+
+	pass.newTextureDependency(outRt, TextureUsageBit::kRtvDsvWrite);
 
 	if(g_dbgCVar.get())
 	{
@@ -103,74 +117,77 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 			}
 		}
 	}
-}
 
-void FinalComposite::run(RenderPassWorkContext& rgraphCtx)
-{
-	ANKI_TRACE_SCOPED_EVENT(FinalComposite);
-
-	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool dbgEnabled = g_dbgCVar.get();
+	pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+		ANKI_TRACE_SCOPED_EVENT(FinalComposite);
 
-	Array<RenderTargetHandle, kMaxDebugRenderTargets> dbgRts;
-	ShaderProgramPtr optionalDebugProgram;
-	const Bool hasDebugRt = getRenderer().getCurrentDebugRenderTarget(dbgRts, optionalDebugProgram);
+		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+		const Bool dbgEnabled = g_dbgCVar.get();
 
-	// Bind program
-	if(hasDebugRt && optionalDebugProgram.isCreated())
-	{
-		cmdb.bindShaderProgram(optionalDebugProgram.get());
-	}
-	else if(hasDebugRt)
-	{
-		cmdb.bindShaderProgram(m_defaultVisualizeRenderTargetGrProg.get());
-	}
-	else
-	{
-		cmdb.bindShaderProgram(m_grProgs[dbgEnabled].get());
-	}
+		Array<RenderTargetHandle, kMaxDebugRenderTargets> dbgRts;
+		ShaderProgramPtr optionalDebugProgram;
+		const Bool hasDebugRt = getRenderer().getCurrentDebugRenderTarget(dbgRts, optionalDebugProgram);
 
-	// Bind stuff
-	if(!hasDebugRt)
-	{
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-		cmdb.bindSampler(2, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+		// Bind program
+		if(hasDebugRt && optionalDebugProgram.isCreated())
+		{
+			cmdb.bindShaderProgram(optionalDebugProgram.get());
+		}
+		else if(hasDebugRt)
+		{
+			cmdb.bindShaderProgram(m_defaultVisualizeRenderTargetGrProg.get());
+		}
+		else
+		{
+			cmdb.bindShaderProgram(m_grProgs[dbgEnabled].get());
+		}
 
-		rgraphCtx.bindSrv(0, 0, getRenderer().getScale().getTonemappedRt());
+		// Bind stuff
+		if(!hasDebugRt)
+		{
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+			cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(2, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
 
-		rgraphCtx.bindSrv(1, 0, getRenderer().getBloom().getRt());
-		cmdb.bindSrv(2, 0, TextureView(&m_lut->getTexture(), TextureSubresourceDesc::all()));
-		rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
-		rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getRenderer().getScale().getTonemappedRt());
 
-		if(dbgEnabled)
-		{
-			rgraphCtx.bindSrv(5, 0, getRenderer().getDbg().getRt());
-		}
+			rgraphCtx.bindSrv(1, 0, getRenderer().getBloom().getRt());
+			cmdb.bindSrv(2, 0, TextureView(&m_lut->getTexture(), TextureSubresourceDesc::all()));
+			rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
+			rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());
 
-		const UVec4 pc(g_motionBlurSamplesCVar.get(), floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32, 0);
-		cmdb.setFastConstants(&pc, sizeof(pc));
-	}
-	else
-	{
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+			if(dbgEnabled)
+			{
+				rgraphCtx.bindSrv(5, 0, getRenderer().getDbg().getRt());
+			}
 
-		U32 count = 0;
-		for(const RenderTargetHandle& handle : dbgRts)
+			const UVec4 pc(g_motionBlurSamplesCVar.get(), floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32, 0);
+			cmdb.setFastConstants(&pc, sizeof(pc));
+		}
+		else
 		{
-			if(handle.isValid())
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+
+			U32 count = 0;
+			for(const RenderTargetHandle& handle : dbgRts)
 			{
-				rgraphCtx.bindSrv(count++, 0, handle);
+				if(handle.isValid())
+				{
+					rgraphCtx.bindSrv(count++, 0, handle);
+				}
 			}
 		}
-	}
 
-	cmdb.setViewport(0, 0, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
-	drawQuad(cmdb);
+		cmdb.setViewport(0, 0, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
+		drawQuad(cmdb);
 
-	// Draw UI
-	getRenderer().getUiStage().draw(getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y(), cmdb);
+		// Draw UI
+		const Bool bRendersToSwapchain = getRenderer().getSwapchainResolution() == getRenderer().getPostProcessResolution();
+		if(bRendersToSwapchain)
+		{
+			getRenderer().getUiStage().draw(getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y(), cmdb);
+		}
+	});
 }
 
 } // end namespace anki

+ 13 - 0
AnKi/Renderer/FinalComposite.h

@@ -29,6 +29,11 @@ public:
 	/// Load the color grading texture.
 	Error loadColorGradingTextureImage(CString filename);
 
+	RenderTargetHandle getRenderTarget() const
+	{
+		return m_runCtx.m_rt;
+	}
+
 private:
 	ShaderProgramResourcePtr m_prog;
 	Array<ShaderProgramPtr, 2> m_grProgs; ///< [Debug on or off]
@@ -38,6 +43,14 @@ private:
 
 	ImageResourcePtr m_lut; ///< Color grading lookup texture.
 
+	RenderTargetDesc m_rtDesc;
+
+	class
+	{
+	public:
+		RenderTargetHandle m_rt;
+	} m_runCtx;
+
 	Error initInternal();
 
 	void run(RenderPassWorkContext& rgraphCtx);

+ 0 - 181
AnKi/Renderer/MainRenderer.cpp

@@ -1,181 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Renderer/MainRenderer.h>
-#include <AnKi/Renderer/LightShading.h>
-#include <AnKi/Renderer/FinalComposite.h>
-#include <AnKi/Renderer/Dbg.h>
-#include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Util/Logger.h>
-#include <AnKi/Util/File.h>
-#include <AnKi/Util/Filesystem.h>
-#include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Core/StatsSet.h>
-#include <AnKi/Util/HighRezTimer.h>
-
-namespace anki {
-
-static StatCounter g_rendererCpuTimeStatVar(StatCategory::kTime, "Renderer",
-											StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
-StatCounter g_rendererGpuTimeStatVar(StatCategory::kTime, "GPU frame", StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
-
-MainRenderer::MainRenderer()
-{
-}
-
-MainRenderer::~MainRenderer()
-{
-	ANKI_R_LOGI("Destroying main renderer");
-
-	deleteInstance(RendererMemoryPool::getSingleton(), m_r);
-
-	RendererMemoryPool::freeSingleton();
-}
-
-Error MainRenderer::init(const MainRendererInitInfo& inf)
-{
-	RendererMemoryPool::allocateSingleton(inf.m_allocCallback, inf.m_allocCallbackUserData);
-
-	m_framePool.init(inf.m_allocCallback, inf.m_allocCallbackUserData, 10_MB, 1.0f);
-
-	// Init renderer and manipulate the width/height
-	m_swapchainResolution = inf.m_swapchainSize;
-	m_rDrawToDefaultFb = g_renderScalingCVar.get() == 1.0f;
-
-	ANKI_R_LOGI("Initializing main renderer. Swapchain resolution %ux%u", m_swapchainResolution.x(), m_swapchainResolution.y());
-
-	m_r = newInstance<Renderer>(RendererMemoryPool::getSingleton());
-	ANKI_CHECK(m_r->init(m_swapchainResolution, &m_framePool));
-
-	// Init other
-	if(!m_rDrawToDefaultFb)
-	{
-		ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/Blit.ankiprogbin", m_blitProg));
-		ShaderProgramResourceVariantInitInfo varInit(m_blitProg);
-		const ShaderProgramResourceVariant* variant;
-		m_blitProg->getOrCreateVariant(varInit, variant);
-		m_blitGrProg.reset(&variant->getProgram());
-
-		// The RT desc
-		UVec2 resolution = UVec2(Vec2(m_swapchainResolution) * g_renderScalingCVar.get());
-		alignRoundDown(2, resolution.x());
-		alignRoundDown(2, resolution.y());
-		m_tmpRtDesc = m_r->create2DRenderTargetDescription(
-			resolution.x(), resolution.y(),
-			(GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::kR8G8B8_Unorm : Format::kR8G8B8A8_Unorm,
-			"Final Composite");
-		m_tmpRtDesc.bake();
-
-		ANKI_R_LOGI("There will be a blit pass to the swapchain because render scaling is not 1.0");
-	}
-
-	m_rgraph = GrManager::getSingleton().newRenderGraph();
-
-	return Error::kNone;
-}
-
-Error MainRenderer::render(Texture* presentTex)
-{
-	ANKI_TRACE_SCOPED_EVENT(Render);
-
-	const Second startTime = HighRezTimer::getCurrentTime();
-
-	// First thing, reset the temp mem pool
-	m_framePool.reset();
-
-	// Run renderer
-	RenderingContext ctx(&m_framePool);
-	m_runCtx.m_ctx = &ctx;
-	m_runCtx.m_secondaryTaskId.setNonAtomically(0);
-	ctx.m_renderGraphDescr.setStatisticsEnabled(ANKI_STATS_ENABLED);
-
-	RenderTargetHandle presentRt = ctx.m_renderGraphDescr.importRenderTarget(presentTex, TextureUsageBit::kNone);
-
-	if(m_rDrawToDefaultFb)
-	{
-		// m_r will draw to a presentable texture
-		ctx.m_outRenderTarget = presentRt;
-	}
-	else
-	{
-		// m_r will draw to a temp tex
-		ctx.m_outRenderTarget = ctx.m_renderGraphDescr.newRenderTarget(m_tmpRtDesc);
-	}
-
-	ANKI_CHECK(m_r->populateRenderGraph(ctx));
-
-	// Blit renderer's result to default FB if needed
-	if(!m_rDrawToDefaultFb)
-	{
-		GraphicsRenderPass& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Final Blit");
-
-		pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(presentRt)});
-		pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-			cmdb.setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());
-
-			cmdb.bindShaderProgram(m_blitGrProg.get());
-			cmdb.bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindSrv(0, 0, m_runCtx.m_ctx->m_outRenderTarget);
-
-			cmdb.draw(PrimitiveTopology::kTriangles, 3);
-		});
-
-		pass.newTextureDependency(presentRt, TextureUsageBit::kRtvDsvWrite);
-		pass.newTextureDependency(ctx.m_outRenderTarget, TextureUsageBit::kSrvPixel);
-	}
-
-	// Create a dummy pass to transition the presentable image to present
-	{
-		NonGraphicsRenderPass& pass = ctx.m_renderGraphDescr.newNonGraphicsRenderPass("Present");
-
-		pass.setWork([]([[maybe_unused]] RenderPassWorkContext& rgraphCtx) {
-			// Do nothing. This pass is dummy
-		});
-		pass.newTextureDependency(presentRt, TextureUsageBit::kPresent);
-	}
-
-	// Bake the render graph
-	m_rgraph->compileNewGraph(ctx.m_renderGraphDescr, m_framePool);
-
-	// Flush
-	FencePtr fence;
-	m_rgraph->recordAndSubmitCommandBuffers(&fence);
-
-	// Reset for the next frame
-	m_rgraph->reset();
-	m_r->finalize(ctx, fence.get());
-
-	// Stats
-	if(ANKI_STATS_ENABLED || ANKI_TRACING_ENABLED)
-	{
-		g_rendererCpuTimeStatVar.set((HighRezTimer::getCurrentTime() - startTime) * 1000.0);
-
-		RenderGraphStatistics rgraphStats;
-		m_rgraph->getStatistics(rgraphStats);
-		g_rendererGpuTimeStatVar.set(rgraphStats.m_gpuTime * 1000.0);
-
-		if(rgraphStats.m_gpuTime > 0.0)
-		{
-			// WARNING: The name of the event is somewhat special. Search it to see why
-			ANKI_TRACE_CUSTOM_EVENT(GpuFrameTime, rgraphStats.m_cpuStartTime, rgraphStats.m_gpuTime);
-		}
-	}
-
-	return Error::kNone;
-}
-
-Dbg& MainRenderer::getDbg()
-{
-	return m_r->getDbg();
-}
-
-F32 MainRenderer::getAspectRatio() const
-{
-	return m_r->getAspectRatio();
-}
-
-} // end namespace anki

+ 0 - 78
AnKi/Renderer/MainRenderer.h

@@ -1,78 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Renderer/Common.h>
-#include <AnKi/Resource/Forward.h>
-#include <AnKi/Renderer/Renderer.h>
-
-namespace anki {
-
-/// @addtogroup renderer
-/// @{
-
-class MainRendererInitInfo
-{
-public:
-	UVec2 m_swapchainSize = UVec2(0u);
-
-	AllocAlignedCallback m_allocCallback = nullptr;
-	void* m_allocCallbackUserData = nullptr;
-};
-
-/// Main onscreen renderer
-class MainRenderer : public MakeSingleton<MainRenderer>
-{
-	template<typename>
-	friend class MakeSingleton;
-
-public:
-	Error init(const MainRendererInitInfo& inf);
-
-	Error render(Texture* presentTex);
-
-	Dbg& getDbg();
-
-	F32 getAspectRatio() const;
-
-	const Renderer& getOffscreenRenderer() const
-	{
-		return *m_r;
-	}
-
-	Renderer& getOffscreenRenderer()
-	{
-		return *m_r;
-	}
-
-private:
-	StackMemoryPool m_framePool;
-
-	Renderer* m_r = nullptr;
-	Bool m_rDrawToDefaultFb = false;
-
-	ShaderProgramResourcePtr m_blitProg;
-	ShaderProgramPtr m_blitGrProg;
-
-	UVec2 m_swapchainResolution = UVec2(0u);
-
-	RenderGraphPtr m_rgraph;
-	RenderTargetDesc m_tmpRtDesc;
-
-	class
-	{
-	public:
-		const RenderingContext* m_ctx = nullptr;
-		Atomic<U32> m_secondaryTaskId = {0};
-	} m_runCtx;
-
-	MainRenderer();
-
-	~MainRenderer();
-};
-/// @}
-
-} // end namespace anki

+ 155 - 60
AnKi/Renderer/Renderer.cpp

@@ -83,6 +83,9 @@ NumericCVar<F32> g_lod1MaxDistanceCVar(CVarSubsystem::kRenderer, "Lod1MaxDistanc
 									   "Distance that will be used to calculate the LOD 1");
 
 static StatCounter g_primitivesDrawnStatVar(StatCategory::kRenderer, "Primitives drawn", StatFlag::kMainThreadUpdates | StatFlag::kZeroEveryFrame);
+static StatCounter g_rendererCpuTimeStatVar(StatCategory::kTime, "Renderer",
+											StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
+StatCounter g_rendererGpuTimeStatVar(StatCategory::kTime, "GPU frame", StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
 
 /// Generate a Halton jitter in [-0.5, 0.5]
 static Vec2 generateJitter(U32 frame)
@@ -123,14 +126,15 @@ Renderer::Renderer()
 
 Renderer::~Renderer()
 {
+#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) deleteInstance(RendererMemoryPool::getSingleton(), m_##name2);
+#include <AnKi/Renderer/RendererObject.def.h>
 }
 
-Error Renderer::init(UVec2 swapchainSize, StackMemoryPool* framePool)
+Error Renderer::init(const RendererInitInfo& inf)
 {
 	ANKI_TRACE_SCOPED_EVENT(RInit);
 
-	m_framePool = framePool;
-	const Error err = initInternal(swapchainSize);
+	const Error err = initInternal(inf);
 	if(err)
 	{
 		ANKI_R_LOGE("Failed to initialize the renderer");
@@ -139,12 +143,17 @@ Error Renderer::init(UVec2 swapchainSize, StackMemoryPool* framePool)
 	return err;
 }
 
-Error Renderer::initInternal(UVec2 swapchainResolution)
+Error Renderer::initInternal(const RendererInitInfo& inf)
 {
+	RendererMemoryPool::allocateSingleton(inf.m_allocCallback, inf.m_allocCallbackUserData);
+
+	m_framePool.init(inf.m_allocCallback, inf.m_allocCallbackUserData, 10_MB, 1.0f);
 	m_frameCount = 0;
+	m_swapchainResolution = inf.m_swapchainSize;
+	m_rgraph = GrManager::getSingleton().newRenderGraph();
 
 	// Set from the config
-	m_postProcessResolution = UVec2(Vec2(swapchainResolution) * g_renderScalingCVar.get());
+	m_postProcessResolution = UVec2(Vec2(m_swapchainResolution) * g_renderScalingCVar.get());
 	alignRoundDown(2, m_postProcessResolution.x());
 	alignRoundDown(2, m_postProcessResolution.y());
 
@@ -201,7 +210,7 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 #define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) \
 	if(initCondition) \
 	{ \
-		m_##name2.reset(newInstance<name>(RendererMemoryPool::getSingleton())); \
+		m_##name2 = newInstance<name>(RendererMemoryPool::getSingleton()); \
 		ANKI_CHECK(m_##name2->init()); \
 	}
 #include <AnKi/Renderer/RendererObject.def.h>
@@ -258,55 +267,23 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 		m_jitterOffsets[i] = generateJitter(i);
 	}
 
+	if(m_swapchainResolution != m_postProcessResolution)
+	{
+		ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/Blit.ankiprogbin", m_blitProg));
+		ShaderProgramResourceVariantInitInfo varInit(m_blitProg);
+		const ShaderProgramResourceVariant* variant;
+		varInit.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel);
+		m_blitProg->getOrCreateVariant(varInit, variant);
+		m_blitGrProg.reset(&variant->getProgram());
+
+		ANKI_R_LOGI("There will be a blit pass to the swapchain because render scaling is not 1.0");
+	}
+
 	return Error::kNone;
 }
 
 Error Renderer::populateRenderGraph(RenderingContext& ctx)
 {
-#if ANKI_STATS_ENABLED
-	updatePipelineStats();
-#endif
-
-	const CameraComponent& cam = SceneGraph::getSingleton().getActiveCameraNode().getFirstComponentOfType<CameraComponent>();
-
-	ctx.m_prevMatrices = m_prevMatrices;
-
-	ctx.m_matrices.m_cameraTransform = Mat3x4(cam.getFrustum().getWorldTransform());
-	ctx.m_matrices.m_view = cam.getFrustum().getViewMatrix();
-	ctx.m_matrices.m_projection = cam.getFrustum().getProjectionMatrix();
-	ctx.m_matrices.m_viewProjection = cam.getFrustum().getViewProjectionMatrix();
-
-	Vec2 jitter = m_jitterOffsets[m_frameCount & (m_jitterOffsets.getSize() - 1)]; // In [-0.5, 0.5]
-	jitter *= 2.0f; // In [-1, 1]
-	const Vec2 ndcPixelSize = 1.0f / Vec2(m_internalResolution);
-	jitter *= ndcPixelSize;
-	ctx.m_matrices.m_jitter = Mat4::getIdentity();
-	ctx.m_matrices.m_jitter.setTranslationPart(Vec3(jitter, 0.0f));
-	ctx.m_matrices.m_jitterOffsetNdc = jitter;
-
-	ctx.m_matrices.m_projectionJitter = ctx.m_matrices.m_jitter * ctx.m_matrices.m_projection;
-	ctx.m_matrices.m_viewProjectionJitter = ctx.m_matrices.m_projectionJitter * Mat4(ctx.m_matrices.m_view, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
-	ctx.m_matrices.m_invertedViewProjectionJitter = ctx.m_matrices.m_viewProjectionJitter.getInverse();
-	ctx.m_matrices.m_invertedViewProjection = ctx.m_matrices.m_viewProjection.getInverse();
-	ctx.m_matrices.m_invertedProjectionJitter = ctx.m_matrices.m_projectionJitter.getInverse();
-
-	ctx.m_matrices.m_reprojection = ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_invertedViewProjection;
-
-	ctx.m_matrices.m_unprojectionParameters = ctx.m_matrices.m_projection.extractPerspectiveUnprojectionParams();
-
-	ctx.m_cameraNear = cam.getNear();
-	ctx.m_cameraFar = cam.getFar();
-
-	// Allocate global constants
-	GlobalRendererConstants* globalConsts;
-	{
-		U32 alignment = (GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
-							? sizeof(*globalConsts)
-							: GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
-		alignment = computeCompoundAlignment(alignment, GrManager::getSingleton().getDeviceCapabilities().m_constantBufferBindOffsetAlignment);
-		ctx.m_globalRenderingConstantsBuffer = RebarTransientMemoryPool::getSingleton().allocate(sizeof(*globalConsts), alignment, globalConsts);
-	}
-
 	// Import RTs first
 	m_downscaleBlur->importRenderTargets(ctx);
 	m_tonemapping->importRenderTargets(ctx);
@@ -354,8 +331,6 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 
 	m_finalComposite->populateRenderGraph(ctx);
 
-	writeGlobalRendererConstants(ctx, *globalConsts);
-
 	return Error::kNone;
 }
 
@@ -415,14 +390,6 @@ void Renderer::writeGlobalRendererConstants(RenderingContext& ctx, GlobalRendere
 	}
 }
 
-void Renderer::finalize(const RenderingContext& ctx, Fence* fence)
-{
-	++m_frameCount;
-
-	m_prevMatrices = ctx.m_matrices;
-	m_readbackManager->endFrame(fence);
-}
-
 TextureInitInfo Renderer::create2DRenderTargetInitInfo(U32 w, U32 h, Format format, TextureUsageBit usage, CString name)
 {
 	ANKI_ASSERT(!!(usage & TextureUsageBit::kRtvDsvWrite) || !!(usage & TextureUsageBit::kUavCompute));
@@ -734,4 +701,132 @@ void Renderer::updatePipelineStats()
 }
 #endif
 
+Error Renderer::render(Texture* presentTex)
+{
+	ANKI_TRACE_SCOPED_EVENT(Render);
+
+	const Second startTime = HighRezTimer::getCurrentTime();
+
+	// First thing, reset the temp mem pool
+	m_framePool.reset();
+
+	RenderingContext ctx(&m_framePool);
+	ctx.m_renderGraphDescr.setStatisticsEnabled(ANKI_STATS_ENABLED);
+	ctx.m_swapchainRenderTarget = ctx.m_renderGraphDescr.importRenderTarget(presentTex, TextureUsageBit::kNone);
+
+#if ANKI_STATS_ENABLED
+	updatePipelineStats();
+#endif
+
+	const CameraComponent& cam = SceneGraph::getSingleton().getActiveCameraNode().getFirstComponentOfType<CameraComponent>();
+
+	ctx.m_prevMatrices = m_prevMatrices;
+
+	ctx.m_matrices.m_cameraTransform = Mat3x4(cam.getFrustum().getWorldTransform());
+	ctx.m_matrices.m_view = cam.getFrustum().getViewMatrix();
+	ctx.m_matrices.m_projection = cam.getFrustum().getProjectionMatrix();
+	ctx.m_matrices.m_viewProjection = cam.getFrustum().getViewProjectionMatrix();
+
+	Vec2 jitter = m_jitterOffsets[m_frameCount & (m_jitterOffsets.getSize() - 1)]; // In [-0.5, 0.5]
+	jitter *= 2.0f; // In [-1, 1]
+	const Vec2 ndcPixelSize = 1.0f / Vec2(m_internalResolution);
+	jitter *= ndcPixelSize;
+	ctx.m_matrices.m_jitter = Mat4::getIdentity();
+	ctx.m_matrices.m_jitter.setTranslationPart(Vec3(jitter, 0.0f));
+	ctx.m_matrices.m_jitterOffsetNdc = jitter;
+
+	ctx.m_matrices.m_projectionJitter = ctx.m_matrices.m_jitter * ctx.m_matrices.m_projection;
+	ctx.m_matrices.m_viewProjectionJitter = ctx.m_matrices.m_projectionJitter * Mat4(ctx.m_matrices.m_view, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+	ctx.m_matrices.m_invertedViewProjectionJitter = ctx.m_matrices.m_viewProjectionJitter.getInverse();
+	ctx.m_matrices.m_invertedViewProjection = ctx.m_matrices.m_viewProjection.getInverse();
+	ctx.m_matrices.m_invertedProjectionJitter = ctx.m_matrices.m_projectionJitter.getInverse();
+
+	ctx.m_matrices.m_reprojection = ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_invertedViewProjection;
+
+	ctx.m_matrices.m_unprojectionParameters = ctx.m_matrices.m_projection.extractPerspectiveUnprojectionParams();
+
+	ctx.m_cameraNear = cam.getNear();
+	ctx.m_cameraFar = cam.getFar();
+
+	// Allocate global constants
+	GlobalRendererConstants* globalConsts;
+	{
+		U32 alignment = (GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
+							? sizeof(*globalConsts)
+							: GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
+		alignment = computeCompoundAlignment(alignment, GrManager::getSingleton().getDeviceCapabilities().m_constantBufferBindOffsetAlignment);
+		ctx.m_globalRenderingConstantsBuffer = RebarTransientMemoryPool::getSingleton().allocate(sizeof(*globalConsts), alignment, globalConsts);
+	}
+
+	ANKI_CHECK(populateRenderGraph(ctx));
+
+	// Blit renderer's result to swapchain
+	const Bool bNeedsBlit = m_postProcessResolution != m_swapchainResolution;
+	if(bNeedsBlit)
+	{
+		GraphicsRenderPass& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Final Blit");
+		pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(ctx.m_swapchainRenderTarget)});
+
+		pass.newTextureDependency(ctx.m_swapchainRenderTarget, TextureUsageBit::kRtvDsvWrite);
+		pass.newTextureDependency(m_finalComposite->getRenderTarget(), TextureUsageBit::kSrvPixel);
+
+		pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+			cmdb.setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());
+
+			cmdb.bindShaderProgram(m_blitGrProg.get());
+			cmdb.bindSampler(0, 0, m_samplers.m_trilinearClamp.get());
+			rgraphCtx.bindSrv(0, 0, m_finalComposite->getRenderTarget());
+
+			cmdb.draw(PrimitiveTopology::kTriangles, 3);
+
+			// Draw the UI
+			m_uiStage->draw(m_swapchainResolution.x(), m_swapchainResolution.y(), cmdb);
+		});
+	}
+
+	// Create a dummy pass to transition the presentable image to present
+	{
+		NonGraphicsRenderPass& pass = ctx.m_renderGraphDescr.newNonGraphicsRenderPass("Present");
+
+		pass.setWork([]([[maybe_unused]] RenderPassWorkContext& rgraphCtx) {
+			// Do nothing. This pass is dummy
+		});
+		pass.newTextureDependency(ctx.m_swapchainRenderTarget, TextureUsageBit::kPresent);
+	}
+
+	writeGlobalRendererConstants(ctx, *globalConsts);
+
+	// Bake the render graph
+	m_rgraph->compileNewGraph(ctx.m_renderGraphDescr, m_framePool);
+
+	// Flush
+	FencePtr fence;
+	m_rgraph->recordAndSubmitCommandBuffers(&fence);
+
+	// Misc
+	m_rgraph->reset();
+	++m_frameCount;
+	m_prevMatrices = ctx.m_matrices;
+	m_readbackManager->endFrame(fence.get());
+
+	// Stats
+	if(ANKI_STATS_ENABLED || ANKI_TRACING_ENABLED)
+	{
+		g_rendererCpuTimeStatVar.set((HighRezTimer::getCurrentTime() - startTime) * 1000.0);
+
+		RenderGraphStatistics rgraphStats;
+		m_rgraph->getStatistics(rgraphStats);
+		g_rendererGpuTimeStatVar.set(rgraphStats.m_gpuTime * 1000.0);
+
+		if(rgraphStats.m_gpuTime > 0.0)
+		{
+			// WARNING: The name of the event is somewhat special. Search it to see why
+			ANKI_TRACE_CUSTOM_EVENT(GpuFrameTime, rgraphStats.m_cpuStartTime, rgraphStats.m_gpuTime);
+		}
+	}
+
+	return Error::kNone;
+}
+
 } // end namespace anki

+ 47 - 19
AnKi/Renderer/Renderer.h

@@ -50,24 +50,38 @@ enum class MeshletRenderingType
 	kSoftware
 };
 
+class RendererInitInfo
+{
+public:
+	UVec2 m_swapchainSize = UVec2(0u);
+
+	AllocAlignedCallback m_allocCallback = nullptr;
+	void* m_allocCallbackUserData = nullptr;
+};
+
 /// Offscreen renderer.
-class Renderer
+class Renderer : public MakeSingleton<Renderer>
 {
 public:
 	Renderer();
 
 	~Renderer();
 
+	Error init(const RendererInitInfo& inf);
+
+	Error render(Texture* presentTex);
+
 #define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) \
 	name& get##name() \
 	{ \
+		ANKI_ASSERT(m_##name2); \
 		return *m_##name2; \
 	}
 #include <AnKi/Renderer/RendererObject.def.h>
 
 	Bool getRtShadowsEnabled() const
 	{
-		return m_rtShadows.isCreated();
+		return m_rtShadows != nullptr;
 	}
 
 	const UVec2& getInternalResolution() const
@@ -80,19 +94,16 @@ public:
 		return m_postProcessResolution;
 	}
 
+	const UVec2& getSwapchainResolution() const
+	{
+		return m_swapchainResolution;
+	}
+
 	F32 getAspectRatio() const
 	{
 		return F32(m_internalResolution.x()) / F32(m_internalResolution.y());
 	}
 
-	/// Init the renderer.
-	Error init(UVec2 swapchainSize, StackMemoryPool* framePool);
-
-	/// This function does all the rendering stages and produces a final result.
-	Error populateRenderGraph(RenderingContext& ctx);
-
-	void finalize(const RenderingContext& ctx, Fence* fence);
-
 	U64 getFrameCount() const
 	{
 		return m_frameCount;
@@ -169,10 +180,9 @@ public:
 	Bool getCurrentDebugRenderTarget(Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles, ShaderProgramPtr& optionalShaderProgram);
 	/// @}
 
-	StackMemoryPool& getFrameMemoryPool() const
+	StackMemoryPool& getFrameMemoryPool()
 	{
-		ANKI_ASSERT(m_framePool);
-		return *m_framePool;
+		return m_framePool;
 	}
 
 #if ANKI_STATS_ENABLED
@@ -185,17 +195,26 @@ public:
 #endif
 
 private:
+	class Cleanup
+	{
+	public:
+		~Cleanup()
+		{
+			RendererMemoryPool::freeSingleton();
+		}
+	} m_cleanup; // First so it will be called last in the renderer's destructor
+
 	/// @name Rendering stages
 	/// @{
-#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) UniquePtr<name, SingletonMemoryPoolDeleter<RendererMemoryPool>> m_##name2;
+#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) name* m_##name2 = nullptr;
 #include <AnKi/Renderer/RendererObject.def.h>
 	/// @}
 
-	UVec2 m_tileCounts = UVec2(0u);
-	U32 m_zSplitCount = 0;
+	StackMemoryPool m_framePool;
 
 	UVec2 m_internalResolution = UVec2(0u); ///< The resolution of all passes up until TAA.
 	UVec2 m_postProcessResolution = UVec2(0u); ///< The resolution of post processing and following passes.
+	UVec2 m_swapchainResolution = UVec2(0u);
 
 	U64 m_frameCount; ///< Frame number
 
@@ -211,8 +230,6 @@ private:
 
 	ShaderProgramResourcePtr m_clearTexComputeProg;
 
-	StackMemoryPool* m_framePool = nullptr;
-
 	class DebugRtInfo
 	{
 	public:
@@ -222,6 +239,14 @@ private:
 	RendererDynamicArray<DebugRtInfo> m_debugRts;
 	RendererString m_currentDebugRtName;
 
+	ShaderProgramResourcePtr m_blitProg;
+	ShaderProgramPtr m_blitGrProg;
+
+	RenderGraphPtr m_rgraph;
+
+	UVec2 m_tileCounts = UVec2(0u);
+	U32 m_zSplitCount = 0;
+
 	class
 	{
 	public:
@@ -235,7 +260,7 @@ private:
 
 	MeshletRenderingType m_meshletRenderingType = MeshletRenderingType::kNone;
 
-	Error initInternal(UVec2 swapchainSize);
+	Error initInternal(const RendererInitInfo& inf);
 
 	void gpuSceneCopy(RenderingContext& ctx);
 
@@ -244,6 +269,9 @@ private:
 #endif
 
 	void writeGlobalRendererConstants(RenderingContext& ctx, GlobalRendererConstants& consts);
+
+	/// This function does all the rendering stages and produces a final result.
+	Error populateRenderGraph(RenderingContext& ctx);
 };
 /// @}
 

+ 1 - 2
AnKi/Renderer/RendererObject.cpp

@@ -5,14 +5,13 @@
 
 #include <AnKi/Renderer/RendererObject.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/MainRenderer.h>
 #include <AnKi/Util/Enum.h>
 
 namespace anki {
 
 Renderer& RendererObject::getRenderer()
 {
-	return MainRenderer::getSingleton().getOffscreenRenderer();
+	return Renderer::getSingleton();
 }
 
 void RendererObject::registerDebugRenderTarget(CString rtName)

+ 0 - 1
AnKi/Scene/SceneGraph.cpp

@@ -7,7 +7,6 @@
 #include <AnKi/Scene/RenderStateBucket.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 #include <AnKi/Resource/ResourceManager.h>
-#include <AnKi/Renderer/MainRenderer.h>
 #include <AnKi/Core/CVarSet.h>
 #include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/Tracer.h>

+ 0 - 2
AnKi/Script/LuaBinder.h

@@ -20,8 +20,6 @@ namespace anki {
 
 // Forward
 class LuaUserData;
-class SceneGraph;
-class MainRenderer;
 
 /// @addtogroup script
 /// @{

+ 37 - 37
AnKi/Script/Renderer.cpp

@@ -11,25 +11,25 @@
 
 namespace anki {
 
-static MainRenderer* getMainRenderer(lua_State* l)
+static Renderer* getRenderer(lua_State* l)
 {
 	LuaBinder* binder = nullptr;
 	lua_getallocf(l, reinterpret_cast<void**>(&binder));
 
-	return &MainRenderer::getSingleton();
+	return &Renderer::getSingleton();
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoMainRenderer = {-6365712250974230727, "MainRenderer",
-													   LuaUserData::computeSizeForGarbageCollected<MainRenderer>(), nullptr, nullptr};
+LuaUserDataTypeInfo luaUserDataTypeInfoRenderer = {4110901869536678112, "Renderer", LuaUserData::computeSizeForGarbageCollected<Renderer>(), nullptr,
+												   nullptr};
 
 template<>
-const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<MainRenderer>()
+const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<Renderer>()
 {
-	return luaUserDataTypeInfoMainRenderer;
+	return luaUserDataTypeInfoRenderer;
 }
 
-/// Pre-wrap method MainRenderer::getAspectRatio.
-static inline int pwrapMainRenderergetAspectRatio(lua_State* l)
+/// Pre-wrap method Renderer::getAspectRatio.
+static inline int pwrapRenderergetAspectRatio(lua_State* l)
 {
 	[[maybe_unused]] LuaUserData* ud;
 	[[maybe_unused]] void* voidp;
@@ -41,12 +41,12 @@ static inline int pwrapMainRenderergetAspectRatio(lua_State* l)
 	}
 
 	// Get "this" as "self"
-	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoMainRenderer, ud))
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoRenderer, ud))
 	{
 		return -1;
 	}
 
-	MainRenderer* self = ud->getData<MainRenderer>();
+	Renderer* self = ud->getData<Renderer>();
 
 	// Call the method
 	F32 ret = self->getAspectRatio();
@@ -57,10 +57,10 @@ static inline int pwrapMainRenderergetAspectRatio(lua_State* l)
 	return 1;
 }
 
-/// Wrap method MainRenderer::getAspectRatio.
-static int wrapMainRenderergetAspectRatio(lua_State* l)
+/// Wrap method Renderer::getAspectRatio.
+static int wrapRenderergetAspectRatio(lua_State* l)
 {
-	int res = pwrapMainRenderergetAspectRatio(l);
+	int res = pwrapRenderergetAspectRatio(l);
 	if(res >= 0)
 	{
 		return res;
@@ -70,8 +70,8 @@ static int wrapMainRenderergetAspectRatio(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method MainRenderer::setCurrentDebugRenderTarget.
-static inline int pwrapMainRenderersetCurrentDebugRenderTarget(lua_State* l)
+/// Pre-wrap method Renderer::setCurrentDebugRenderTarget.
+static inline int pwrapRenderersetCurrentDebugRenderTarget(lua_State* l)
 {
 	[[maybe_unused]] LuaUserData* ud;
 	[[maybe_unused]] void* voidp;
@@ -83,12 +83,12 @@ static inline int pwrapMainRenderersetCurrentDebugRenderTarget(lua_State* l)
 	}
 
 	// Get "this" as "self"
-	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoMainRenderer, ud))
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoRenderer, ud))
 	{
 		return -1;
 	}
 
-	MainRenderer* self = ud->getData<MainRenderer>();
+	Renderer* self = ud->getData<Renderer>();
 
 	// Pop arguments
 	const char* arg0;
@@ -98,15 +98,15 @@ static inline int pwrapMainRenderersetCurrentDebugRenderTarget(lua_State* l)
 	}
 
 	// Call the method
-	self->getOffscreenRenderer().setCurrentDebugRenderTarget(arg0);
+	self->setCurrentDebugRenderTarget(arg0);
 
 	return 0;
 }
 
-/// Wrap method MainRenderer::setCurrentDebugRenderTarget.
-static int wrapMainRenderersetCurrentDebugRenderTarget(lua_State* l)
+/// Wrap method Renderer::setCurrentDebugRenderTarget.
+static int wrapRenderersetCurrentDebugRenderTarget(lua_State* l)
 {
-	int res = pwrapMainRenderersetCurrentDebugRenderTarget(l);
+	int res = pwrapRenderersetCurrentDebugRenderTarget(l);
 	if(res >= 0)
 	{
 		return res;
@@ -116,17 +116,17 @@ static int wrapMainRenderersetCurrentDebugRenderTarget(lua_State* l)
 	return 0;
 }
 
-/// Wrap class MainRenderer.
-static inline void wrapMainRenderer(lua_State* l)
+/// Wrap class Renderer.
+static inline void wrapRenderer(lua_State* l)
 {
-	LuaBinder::createClass(l, &luaUserDataTypeInfoMainRenderer);
-	LuaBinder::pushLuaCFuncMethod(l, "getAspectRatio", wrapMainRenderergetAspectRatio);
-	LuaBinder::pushLuaCFuncMethod(l, "setCurrentDebugRenderTarget", wrapMainRenderersetCurrentDebugRenderTarget);
+	LuaBinder::createClass(l, &luaUserDataTypeInfoRenderer);
+	LuaBinder::pushLuaCFuncMethod(l, "getAspectRatio", wrapRenderergetAspectRatio);
+	LuaBinder::pushLuaCFuncMethod(l, "setCurrentDebugRenderTarget", wrapRenderersetCurrentDebugRenderTarget);
 	lua_settop(l, 0);
 }
 
-/// Pre-wrap function getMainRenderer.
-static inline int pwrapgetMainRenderer(lua_State* l)
+/// Pre-wrap function getRenderer.
+static inline int pwrapgetRenderer(lua_State* l)
 {
 	[[maybe_unused]] LuaUserData* ud;
 	[[maybe_unused]] void* voidp;
@@ -138,7 +138,7 @@ static inline int pwrapgetMainRenderer(lua_State* l)
 	}
 
 	// Call the function
-	MainRenderer* ret = getMainRenderer(l);
+	Renderer* ret = getRenderer(l);
 
 	// Push return value
 	if(ret == nullptr) [[unlikely]]
@@ -149,17 +149,17 @@ static inline int pwrapgetMainRenderer(lua_State* l)
 
 	voidp = lua_newuserdata(l, sizeof(LuaUserData));
 	ud = static_cast<LuaUserData*>(voidp);
-	luaL_setmetatable(l, "MainRenderer");
-	extern LuaUserDataTypeInfo luaUserDataTypeInfoMainRenderer;
-	ud->initPointed(&luaUserDataTypeInfoMainRenderer, ret);
+	luaL_setmetatable(l, "Renderer");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoRenderer;
+	ud->initPointed(&luaUserDataTypeInfoRenderer, ret);
 
 	return 1;
 }
 
-/// Wrap function getMainRenderer.
-static int wrapgetMainRenderer(lua_State* l)
+/// Wrap function getRenderer.
+static int wrapgetRenderer(lua_State* l)
 {
-	int res = pwrapgetMainRenderer(l);
+	int res = pwrapgetRenderer(l);
 	if(res >= 0)
 	{
 		return res;
@@ -172,8 +172,8 @@ static int wrapgetMainRenderer(lua_State* l)
 /// Wrap the module.
 void wrapModuleRenderer(lua_State* l)
 {
-	wrapMainRenderer(l);
-	LuaBinder::pushLuaCFunc(l, "getMainRenderer", wrapgetMainRenderer);
+	wrapRenderer(l);
+	LuaBinder::pushLuaCFunc(l, "getRenderer", wrapgetRenderer);
 }
 
 } // end namespace anki

+ 6 - 9
AnKi/Script/Renderer.xml

@@ -12,25 +12,22 @@
 
 namespace anki {
 
-static MainRenderer* getMainRenderer(lua_State* l)
+static Renderer* getRenderer(lua_State* l)
 {
 	LuaBinder* binder = nullptr;
 	lua_getallocf(l, reinterpret_cast<void**>(&binder));
 
-	MainRenderer* r = binder->getOtherSystems().m_renderer;
-	ANKI_ASSERT(r);
-	return r;
+	return &Renderer::getSingleton();
 }
 ]]></head>
 
 	<classes>
-		<class name="MainRenderer">
+		<class name="Renderer">
 			<methods>
 				<method name="getAspectRatio">
 					<return>F32</return>
 				</method>
 				<method name="setCurrentDebugRenderTarget">
-					<overrideCall>self->getOffscreenRenderer().setCurrentDebugRenderTarget(arg0);</overrideCall>
 					<args>
 						<arg>CString</arg>
 					</args>
@@ -39,9 +36,9 @@ static MainRenderer* getMainRenderer(lua_State* l)
 		</class>
 	</classes>
 	<functions>
-		<function name="getMainRenderer">
-			<overrideCall>MainRenderer* ret = getMainRenderer(l);</overrideCall>
-			<return>MainRenderer*</return>
+		<function name="getRenderer">
+			<overrideCall>Renderer* ret = getRenderer(l);</overrideCall>
+			<return>Renderer*</return>
 		</function>
 	</functions>
 	<tail><![CDATA[} // end namespace anki]]></tail>

+ 1 - 1
Samples/Common/SampleApp.cpp

@@ -42,7 +42,7 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 	quit = false;
 
 	SceneGraph& scene = SceneGraph::getSingleton();
-	Renderer& renderer = MainRenderer::getSingleton().getOffscreenRenderer();
+	Renderer& renderer = Renderer::getSingleton();
 	Input& in = Input::getSingleton();
 
 	if(in.getKey(KeyCode::kEscape))

+ 1 - 1
Samples/PhysicsPlayground/Assets/Scene.lua

@@ -304,7 +304,7 @@ node:setLocalTransform(trf)
 node = scene:newSceneNode("Camera_Orientation")
 scene:setActiveCameraNode(node)
 comp = node:newCameraComponent()
-comp:setPerspective(0.100000, 500.000000, getMainRenderer():getAspectRatio() * 0.750416, 0.750416)
+comp:setPerspective(0.100000, 500.000000, getRenderer():getAspectRatio() * 0.750416, 0.750416)
 trf = Transform.new()
 trf:setOrigin(Vec4.new(7.481132, 7.870111, 6.507640, 0))
 rot = Mat3x4.new()

+ 5 - 5
Samples/PhysicsPlayground/Main.cpp

@@ -200,7 +200,7 @@ Error MyApp::sampleExtraInit()
 Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 {
 	// ANKI_CHECK(SampleApp::userMainLoop(quit));
-	Renderer& renderer = MainRenderer::getSingleton().getOffscreenRenderer();
+	Renderer& renderer = Renderer::getSingleton();
 
 	if(Input::getSingleton().getKey(KeyCode::kEscape))
 	{
@@ -256,14 +256,14 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 		else if(mode == 1)
 		{
 			g_dbgCVar.set(true);
-			MainRenderer::getSingleton().getDbg().setDepthTestEnabled(true);
-			MainRenderer::getSingleton().getDbg().setDitheredDepthTestEnabled(false);
+			renderer.getDbg().setDepthTestEnabled(true);
+			renderer.getDbg().setDitheredDepthTestEnabled(false);
 		}
 		else
 		{
 			g_dbgCVar.set(true);
-			MainRenderer::getSingleton().getDbg().setDepthTestEnabled(false);
-			MainRenderer::getSingleton().getDbg().setDitheredDepthTestEnabled(true);
+			renderer.getDbg().setDepthTestEnabled(false);
+			renderer.getDbg().setDitheredDepthTestEnabled(true);
 		}
 	}
 

+ 1 - 1
Samples/SimpleScene/Assets/Scene.lua

@@ -85,7 +85,7 @@ node:setLocalTransform(trf)
 node = scene:newSceneNode("Camera")
 scene:setActiveCameraNode(node)
 comp = node:newCameraComponent()
-comp:setPerspective(0.100000, 500.000000, getMainRenderer():getAspectRatio() * 1.024779, 1.024779)
+comp:setPerspective(0.100000, 500.000000, getRenderer():getAspectRatio() * 1.024779, 1.024779)
 trf = Transform.new()
 trf:setOrigin(Vec4.new(0.217066, 6.668793, 17.325689, 0))
 rot = Mat3x4.new()

+ 1 - 1
Samples/SkeletalAnimation/Assets/Scene.lua

@@ -62,7 +62,7 @@ node:setLocalTransform(trf)
 node = scene:newSceneNode("Camera")
 scene:setActiveCameraNode(node)
 comp = node:newCameraComponent()
-comp:setPerspective(0.100000, 200.000000, getMainRenderer():getAspectRatio() * 0.750416, 0.750416)
+comp:setPerspective(0.100000, 200.000000, getRenderer():getAspectRatio() * 0.750416, 0.750416)
 trf = Transform.new()
 trf:setOrigin(Vec4.new(5.526846, 8.527484, -6.015655, 0))
 rot = Mat3x4.new()

+ 1 - 1
Samples/Sponza/Assets/Scene.lua

@@ -107,7 +107,7 @@ node:setLocalTransform(trf)
 node = scene:newSceneNode("Camera.001")
 scene:setActiveCameraNode(node)
 comp = node:newCameraComponent()
-comp:setPerspective(0.100000, 200.000000, getMainRenderer():getAspectRatio() * 1.024779, 1.024779)
+comp:setPerspective(0.100000, 200.000000, getRenderer():getAspectRatio() * 1.024779, 1.024779)
 trf = Transform.new()
 trf:setOrigin(Vec4.new(17.666607, 11.278920, 1.745400, 0))
 rot = Mat3x4.new()

+ 1 - 1
Sandbox/Main.cpp

@@ -88,7 +88,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	SceneGraph& scene = SceneGraph::getSingleton();
 	Input& in = Input::getSingleton();
-	Renderer& renderer = MainRenderer::getSingleton().getOffscreenRenderer();
+	Renderer& renderer = Renderer::getSingleton();
 
 	if(in.getKey(KeyCode::kEscape))
 	{