Browse Source

Fix some scaling bugs

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
c48ca43a3b

+ 4 - 1
AnKi/Gr/RenderGraph.inl.h

@@ -38,13 +38,13 @@ inline void RenderPassDescriptionBase::fixSubresource(RenderPassDependency& dep)
 
 
 	TextureSubresourceInfo& subresource = dep.m_texture.m_subresource;
 	TextureSubresourceInfo& subresource = dep.m_texture.m_subresource;
 	const Bool wholeTexture = subresource.m_mipmapCount == MAX_U32;
 	const Bool wholeTexture = subresource.m_mipmapCount == MAX_U32;
+	const RenderGraphDescription::RT& rt = m_descr->m_renderTargets[dep.m_texture.m_handle.m_idx];
 	if(wholeTexture)
 	if(wholeTexture)
 	{
 	{
 		ANKI_ASSERT(subresource.m_firstFace == 0);
 		ANKI_ASSERT(subresource.m_firstFace == 0);
 		ANKI_ASSERT(subresource.m_firstMipmap == 0);
 		ANKI_ASSERT(subresource.m_firstMipmap == 0);
 		ANKI_ASSERT(subresource.m_firstLayer == 0);
 		ANKI_ASSERT(subresource.m_firstLayer == 0);
 
 
-		const RenderGraphDescription::RT& rt = m_descr->m_renderTargets[dep.m_texture.m_handle.m_idx];
 		if(rt.m_importedTex)
 		if(rt.m_importedTex)
 		{
 		{
 			subresource.m_faceCount = textureTypeIsCube(rt.m_importedTex->getTextureType()) ? 6 : 1;
 			subresource.m_faceCount = textureTypeIsCube(rt.m_importedTex->getTextureType()) ? 6 : 1;
@@ -58,6 +58,9 @@ inline void RenderPassDescriptionBase::fixSubresource(RenderPassDependency& dep)
 			subresource.m_layerCount = rt.m_initInfo.m_layerCount;
 			subresource.m_layerCount = rt.m_initInfo.m_layerCount;
 		}
 		}
 	}
 	}
+
+	ANKI_ASSERT(dep.m_texture.m_subresource.m_firstMipmap + dep.m_texture.m_subresource.m_mipmapCount
+				<= ((rt.m_importedTex) ? rt.m_importedTex->getMipmapCount() : rt.m_initInfo.m_mipmapCount));
 }
 }
 
 
 inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& dep)
 inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& dep)

+ 2 - 2
AnKi/Renderer/Bloom.cpp

@@ -53,8 +53,8 @@ Error Bloom::initExposure(const ConfigSet& config)
 
 
 Error Bloom::initUpscale(const ConfigSet& config)
 Error Bloom::initUpscale(const ConfigSet& config)
 {
 {
-	m_upscale.m_width = m_r->getWidth() / BLOOM_FRACTION;
-	m_upscale.m_height = m_r->getHeight() / BLOOM_FRACTION;
+	m_upscale.m_width = m_r->getResolution().x() / BLOOM_FRACTION;
+	m_upscale.m_height = m_r->getResolution().y() / BLOOM_FRACTION;
 
 
 	// Create RT descr
 	// Create RT descr
 	m_upscale.m_rtDescr =
 	m_upscale.m_rtDescr =

+ 2 - 2
AnKi/Renderer/ClusterBinning.cpp

@@ -37,7 +37,7 @@ Error ClusterBinning::init(const ConfigSet& config)
 	variantInitInfo.addConstant("TILE_COUNT_X", m_r->getTileCounts().x());
 	variantInitInfo.addConstant("TILE_COUNT_X", m_r->getTileCounts().x());
 	variantInitInfo.addConstant("TILE_COUNT_Y", m_r->getTileCounts().y());
 	variantInitInfo.addConstant("TILE_COUNT_Y", m_r->getTileCounts().y());
 	variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
 	variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
-	variantInitInfo.addConstant("RENDERING_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+	variantInitInfo.addConstant("RENDERING_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 
 
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
@@ -417,7 +417,7 @@ void ClusterBinning::writeClustererBuffersTask()
 	{
 	{
 		ClusteredShadingUniforms& unis = *static_cast<ClusteredShadingUniforms*>(cs.m_clusteredShadingUniformsAddress);
 		ClusteredShadingUniforms& unis = *static_cast<ClusteredShadingUniforms*>(cs.m_clusteredShadingUniformsAddress);
 
 
-		unis.m_renderingSize = Vec2(F32(m_r->getWidth()), F32(m_r->getHeight()));
+		unis.m_renderingSize = Vec2(F32(m_r->getResolution().x()), F32(m_r->getResolution().y()));
 
 
 		unis.m_time = F32(HighRezTimer::getCurrentTime());
 		unis.m_time = F32(HighRezTimer::getCurrentTime());
 		unis.m_frame = m_r->getFrameCount() & MAX_U32;
 		unis.m_frame = m_r->getFrameCount() & MAX_U32;

+ 4 - 1
AnKi/Renderer/ConfigDefs.h

@@ -7,7 +7,10 @@ ANKI_CONFIG_OPTION(r_textureAnisotropy, 8, 1, 16)
 ANKI_CONFIG_OPTION(r_tileSize, 64, 8, 256, "Tile lighting tile size")
 ANKI_CONFIG_OPTION(r_tileSize, 64, 8, 256, "Tile lighting tile size")
 ANKI_CONFIG_OPTION(r_zSplitCount, 64, 8, 1024, "Clusterer number of Z splits")
 ANKI_CONFIG_OPTION(r_zSplitCount, 64, 8, 1024, "Clusterer number of Z splits")
 
 
-ANKI_CONFIG_OPTION(r_renderingQuality, 1.0, 0.5, 1.0, "A factor over the requested renderingresolution")
+ANKI_CONFIG_OPTION(r_internalRenderScaling, 1.0, 0.5, 1.0,
+				   "A factor over the requested swapchain resolution. Applies to all passes up to TAA")
+ANKI_CONFIG_OPTION(r_renderScaling, 1.0, 0.5, 1.0,
+				   "A factor over the requested swapchain resolution. Applies to post-processing and UI")
 
 
 ANKI_CONFIG_OPTION(r_volumetricLightingAccumulationQualityXY, 4.0, 1.0, 16.0)
 ANKI_CONFIG_OPTION(r_volumetricLightingAccumulationQualityXY, 4.0, 1.0, 16.0)
 ANKI_CONFIG_OPTION(r_volumetricLightingAccumulationQualityZ, 4.0, 1.0, 16.0)
 ANKI_CONFIG_OPTION(r_volumetricLightingAccumulationQualityZ, 4.0, 1.0, 16.0)

+ 2 - 2
AnKi/Renderer/Dbg.cpp

@@ -38,7 +38,7 @@ Error Dbg::lazyInit()
 	ANKI_ASSERT(!m_initialized);
 	ANKI_ASSERT(!m_initialized);
 
 
 	// RT descr
 	// RT descr
-	m_rtDescr = m_r->create2DRenderTargetDescription(m_r->getWidth(), m_r->getHeight(),
+	m_rtDescr = m_r->create2DRenderTargetDescription(m_r->getResolution().x(), m_r->getResolution().y(),
 													 DBG_COLOR_ATTACHMENT_PIXEL_FORMAT, "Dbg");
 													 DBG_COLOR_ATTACHMENT_PIXEL_FORMAT, "Dbg");
 	m_rtDescr.bake();
 	m_rtDescr.bake();
 
 
@@ -60,7 +60,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
 	// Set common state
 	// Set common state
-	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	cmdb->setViewport(0, 0, m_r->getResolution().x(), m_r->getResolution().y());
 	cmdb->setDepthWrite(false);
 	cmdb->setDepthWrite(false);
 
 
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);

+ 4 - 4
AnKi/Renderer/DepthDownscale.cpp

@@ -20,8 +20,8 @@ DepthDownscale::~DepthDownscale()
 
 
 Error DepthDownscale::initInternal(const ConfigSet&)
 Error DepthDownscale::initInternal(const ConfigSet&)
 {
 {
-	const U32 width = m_r->getWidth() >> 1;
-	const U32 height = m_r->getHeight() >> 1;
+	const U32 width = m_r->getResolution().x() >> 1;
+	const U32 height = m_r->getResolution().y() >> 1;
 
 
 	m_mipCount = computeMaxMipmapCount2d(width, height, HIERARCHICAL_Z_MIN_HEIGHT);
 	m_mipCount = computeMaxMipmapCount2d(width, height, HIERARCHICAL_Z_MIN_HEIGHT);
 
 
@@ -154,8 +154,8 @@ void DepthDownscale::run(RenderPassWorkContext& rgraphCtx)
 	const U32 mipsToFill = (level + 1 < m_mipCount) ? MIPS_WRITTEN_PER_PASS : 1;
 	const U32 mipsToFill = (level + 1 < m_mipCount) ? MIPS_WRITTEN_PER_PASS : 1;
 	const U32 copyToClientLevel = (level + mipsToFill == m_mipCount) ? mipsToFill - 1 : MAX_U32;
 	const U32 copyToClientLevel = (level + mipsToFill == m_mipCount) ? mipsToFill - 1 : MAX_U32;
 
 
-	const U32 level0Width = m_r->getWidth() >> (level + 1);
-	const U32 level0Height = m_r->getHeight() >> (level + 1);
+	const U32 level0Width = m_r->getResolution().x() >> (level + 1);
+	const U32 level0Height = m_r->getResolution().y() >> (level + 1);
 	const U32 level1Width = level0Width >> 1;
 	const U32 level1Width = level0Width >> 1;
 	const U32 level1Height = level0Height >> 1;
 	const U32 level1Height = level0Height >> 1;
 
 

+ 5 - 3
AnKi/Renderer/DownscaleBlur.cpp

@@ -28,12 +28,14 @@ Error DownscaleBlur::init(const ConfigSet& cfg)
 
 
 Error DownscaleBlur::initInternal(const ConfigSet&)
 Error DownscaleBlur::initInternal(const ConfigSet&)
 {
 {
-	m_passCount = computeMaxMipmapCount2d(m_r->getWidth(), m_r->getHeight(), DOWNSCALE_BLUR_DOWN_TO) - 1;
+	m_passCount =
+		computeMaxMipmapCount2d(m_r->getResolution().x(), m_r->getResolution().y(), DOWNSCALE_BLUR_DOWN_TO) - 1;
 	ANKI_R_LOGI("Initializing dowscale blur (passCount: %u)", m_passCount);
 	ANKI_R_LOGI("Initializing dowscale blur (passCount: %u)", m_passCount);
 
 
 	// Create the miped texture
 	// Create the miped texture
-	TextureInitInfo texinit = m_r->create2DRenderTargetDescription(
-		m_r->getWidth() / 2, m_r->getHeight() / 2, LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT, "DownscaleBlur");
+	TextureInitInfo texinit =
+		m_r->create2DRenderTargetDescription(m_r->getResolution().x() / 2, m_r->getResolution().y() / 2,
+											 LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT, "DownscaleBlur");
 	texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE;
 	texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE;
 	if(m_useCompute)
 	if(m_useCompute)
 	{
 	{

+ 1 - 1
AnKi/Renderer/FinalComposite.cpp

@@ -51,7 +51,7 @@ Error FinalComposite::initInternal(const ConfigSet& config)
 	variantInitInfo.addMutation("BLOOM_ENABLED", 1);
 	variantInitInfo.addMutation("BLOOM_ENABLED", 1);
 	variantInitInfo.addConstant("LUT_SIZE", U32(LUT_SIZE));
 	variantInitInfo.addConstant("LUT_SIZE", U32(LUT_SIZE));
 	variantInitInfo.addConstant("LUT_SIZE", U32(LUT_SIZE));
 	variantInitInfo.addConstant("LUT_SIZE", U32(LUT_SIZE));
-	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 	variantInitInfo.addConstant("MOTION_BLUR_SAMPLES", config.getNumberU32("r_motionBlurSamples"));
 	variantInitInfo.addConstant("MOTION_BLUR_SAMPLES", config.getNumberU32("r_motionBlurSamples"));
 
 
 	for(U32 dbg = 0; dbg < 2; ++dbg)
 	for(U32 dbg = 0; dbg < 2; ++dbg)

+ 3 - 3
AnKi/Renderer/GBuffer.cpp

@@ -38,7 +38,7 @@ Error GBuffer::initInternal(const ConfigSet& initializer)
 	for(U32 i = 0; i < 2; ++i)
 	for(U32 i = 0; i < 2; ++i)
 	{
 	{
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
-			m_r->getWidth(), m_r->getHeight(), GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
+			m_r->getResolution().x(), m_r->getResolution().y(), GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, depthRtNames[i]);
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, depthRtNames[i]);
 
 
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
@@ -51,7 +51,7 @@ Error GBuffer::initInternal(const ConfigSet& initializer)
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 	{
 	{
 		m_colorRtDescrs[i] = m_r->create2DRenderTargetDescription(
 		m_colorRtDescrs[i] = m_r->create2DRenderTargetDescription(
-			m_r->getWidth(), m_r->getHeight(), GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i], rtNames[i]);
+			m_r->getResolution().x(), m_r->getResolution().y(), GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i], rtNames[i]);
 		m_colorRtDescrs[i].bake();
 		m_colorRtDescrs[i].bake();
 	}
 	}
 
 
@@ -95,7 +95,7 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 	ANKI_ASSERT(end != start);
 	ANKI_ASSERT(end != start);
 
 
 	// Set some state, leave the rest to default
 	// Set some state, leave the rest to default
-	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	cmdb->setViewport(0, 0, m_r->getResolution().x(), m_r->getResolution().y());
 
 
 	const I32 earlyZStart = max(I32(start), 0);
 	const I32 earlyZStart = max(I32(start), 0);
 	const I32 earlyZEnd = min(I32(end), I32(earlyZCount));
 	const I32 earlyZEnd = min(I32(end), I32(earlyZCount));

+ 1 - 1
AnKi/Renderer/GBufferPost.cpp

@@ -81,7 +81,7 @@ void GBufferPost::run(RenderPassWorkContext& rgraphCtx)
 	const ClusteredShadingContext& rsrc = ctx.m_clusteredShading;
 	const ClusteredShadingContext& rsrc = ctx.m_clusteredShading;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	cmdb->setViewport(0, 0, m_r->getResolution().x(), m_r->getResolution().y());
 	cmdb->bindShaderProgram(m_grProg);
 	cmdb->bindShaderProgram(m_grProg);
 
 
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::SRC_ALPHA, BlendFactor::ZERO, BlendFactor::ONE);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::SRC_ALPHA, BlendFactor::ZERO, BlendFactor::ONE);

+ 2 - 1
AnKi/Renderer/LensFlare.cpp

@@ -73,7 +73,8 @@ Error LensFlare::initOcclusion(const ConfigSet& config)
 		getResourceManager().loadResource("Shaders/LensFlareUpdateIndirectInfo.ankiprog", m_updateIndirectBuffProg));
 		getResourceManager().loadResource("Shaders/LensFlareUpdateIndirectInfo.ankiprog", m_updateIndirectBuffProg));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_updateIndirectBuffProg);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_updateIndirectBuffProg);
-	variantInitInfo.addConstant("IN_DEPTH_MAP_SIZE", UVec2(m_r->getWidth() / 2 / 2, m_r->getHeight() / 2 / 2));
+	variantInitInfo.addConstant("IN_DEPTH_MAP_SIZE",
+								UVec2(m_r->getResolution().x() / 2 / 2, m_r->getResolution().y() / 2 / 2));
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_updateIndirectBuffProg->getOrCreateVariant(variantInitInfo, variant);
 	m_updateIndirectBuffProg->getOrCreateVariant(variantInitInfo, variant);
 	m_updateIndirectBuffGrProg = variant->getProgram();
 	m_updateIndirectBuffGrProg = variant->getProgram();

+ 4 - 3
AnKi/Renderer/LightShading.cpp

@@ -72,8 +72,9 @@ Error LightShading::initLightShading(const ConfigSet& config)
 	m_lightShading.m_grProg[1] = variant->getProgram();
 	m_lightShading.m_grProg[1] = variant->getProgram();
 
 
 	// Create RT descr
 	// Create RT descr
-	m_lightShading.m_rtDescr = m_r->create2DRenderTargetDescription(
-		m_r->getWidth(), m_r->getHeight(), LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT, "Light Shading");
+	m_lightShading.m_rtDescr =
+		m_r->create2DRenderTargetDescription(m_r->getResolution().x(), m_r->getResolution().y(),
+											 LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT, "Light Shading");
 	m_lightShading.m_rtDescr.bake();
 	m_lightShading.m_rtDescr.bake();
 
 
 	// Create FB descr
 	// Create FB descr
@@ -108,7 +109,7 @@ void LightShading::run(RenderPassWorkContext& rgraphCtx)
 	const RenderingContext& ctx = *m_runCtx.m_ctx;
 	const RenderingContext& ctx = *m_runCtx.m_ctx;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	cmdb->setViewport(0, 0, m_r->getResolution().x(), m_r->getResolution().y());
 
 
 	// Do light shading first
 	// Do light shading first
 	if(rgraphCtx.m_currentSecondLevelCommandBufferIndex == 0)
 	if(rgraphCtx.m_currentSecondLevelCommandBufferIndex == 0)

+ 13 - 15
AnKi/Renderer/MainRenderer.cpp

@@ -39,19 +39,14 @@ Error MainRenderer::init(ThreadHive* hive, ResourceManager* resources, GrManager
 	m_frameAlloc = StackAllocator<U8>(allocCb, allocCbUserData, 1024 * 1024 * 10, 1.0f);
 	m_frameAlloc = StackAllocator<U8>(allocCb, allocCbUserData, 1024 * 1024 * 10, 1.0f);
 
 
 	// Init renderer and manipulate the width/height
 	// Init renderer and manipulate the width/height
-	m_width = config.getNumberU32("width");
-	m_height = config.getNumberU32("height");
-	ConfigSet config2 = config;
-	m_renderingQuality = config.getNumberF32("r_renderingQuality");
-	UVec2 size(U32(m_renderingQuality * F32(m_width)), U32(m_renderingQuality * F32(m_height)));
+	m_swapchainResolution.x() = config.getNumberU32("width");
+	m_swapchainResolution.y() = config.getNumberU32("height");
+	m_renderScaling = config.getNumberF32("r_renderScaling");
 
 
-	config2.set("width", size.x());
-	config2.set("height", size.y());
-
-	m_rDrawToDefaultFb = m_renderingQuality == 1.0;
+	m_rDrawToDefaultFb = m_renderScaling == 1.0f;
 
 
 	m_r.reset(m_alloc.newInstance<Renderer>());
 	m_r.reset(m_alloc.newInstance<Renderer>());
-	ANKI_CHECK(m_r->init(hive, resources, gr, stagingMem, ui, m_alloc, config2, globTimestamp));
+	ANKI_CHECK(m_r->init(hive, resources, gr, stagingMem, ui, m_alloc, config, globTimestamp));
 
 
 	// Init other
 	// Init other
 	if(!m_rDrawToDefaultFb)
 	if(!m_rDrawToDefaultFb)
@@ -62,7 +57,9 @@ Error MainRenderer::init(ThreadHive* hive, ResourceManager* resources, GrManager
 		m_blitGrProg = variant->getProgram();
 		m_blitGrProg = variant->getProgram();
 
 
 		// The RT desc
 		// The RT desc
-		m_tmpRtDesc = m_r->create2DRenderTargetDescription(m_width, m_height, Format::R8G8B8_UNORM, "Final Composite");
+		m_tmpRtDesc = m_r->create2DRenderTargetDescription(U32(F32(m_swapchainResolution.x()) * m_renderScaling),
+														   U32(F32(m_swapchainResolution.y()) * m_renderScaling),
+														   Format::R8G8B8_UNORM, "Final Composite");
 		m_tmpRtDesc.bake();
 		m_tmpRtDesc.bake();
 
 
 		ANKI_R_LOGI("The main renderer will have to blit the offscreen renderer's result");
 		ANKI_R_LOGI("The main renderer will have to blit the offscreen renderer's result");
@@ -70,7 +67,8 @@ Error MainRenderer::init(ThreadHive* hive, ResourceManager* resources, GrManager
 
 
 	m_rgraph = gr->newRenderGraph();
 	m_rgraph = gr->newRenderGraph();
 
 
-	ANKI_R_LOGI("Main renderer initialized. Rendering size %ux%u", m_width, m_height);
+	ANKI_R_LOGI("Main renderer initialized. Rendering size %ux%u", m_swapchainResolution.x(),
+				m_swapchainResolution.x());
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }
@@ -105,8 +103,8 @@ Error MainRenderer::render(RenderQueue& rqueue, TexturePtr presentTex)
 		// m_r will draw to a temp tex
 		// m_r will draw to a temp tex
 
 
 		ctx.m_outRenderTarget = ctx.m_renderGraphDescr.newRenderTarget(m_tmpRtDesc);
 		ctx.m_outRenderTarget = ctx.m_renderGraphDescr.newRenderTarget(m_tmpRtDesc);
-		ctx.m_outRenderTargetWidth = m_width;
-		ctx.m_outRenderTargetHeight = m_height;
+		ctx.m_outRenderTargetWidth = U32(F32(m_swapchainResolution.x()) * m_renderScaling);
+		ctx.m_outRenderTargetHeight = U32(F32(m_swapchainResolution.y()) * m_renderScaling);
 	}
 	}
 
 
 	ctx.m_renderQueue = &rqueue;
 	ctx.m_renderQueue = &rqueue;
@@ -191,7 +189,7 @@ Error MainRenderer::render(RenderQueue& rqueue, TexturePtr presentTex)
 void MainRenderer::runBlit(RenderPassWorkContext& rgraphCtx)
 void MainRenderer::runBlit(RenderPassWorkContext& rgraphCtx)
 {
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
-	cmdb->setViewport(0, 0, m_width, m_height);
+	cmdb->setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());
 
 
 	cmdb->bindShaderProgram(m_blitGrProg);
 	cmdb->bindShaderProgram(m_blitGrProg);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);

+ 2 - 4
AnKi/Renderer/MainRenderer.h

@@ -78,10 +78,8 @@ private:
 	ShaderProgramResourcePtr m_blitProg;
 	ShaderProgramResourcePtr m_blitProg;
 	ShaderProgramPtr m_blitGrProg;
 	ShaderProgramPtr m_blitGrProg;
 
 
-	U32 m_width = 0; ///< Default FB size.
-	U32 m_height = 0; ///< Default FB size.
-
-	F32 m_renderingQuality = 1.0;
+	UVec2 m_swapchainResolution = UVec2(0u);
+	F32 m_renderScaling = 1.0f;
 
 
 	RenderGraphPtr m_rgraph;
 	RenderGraphPtr m_rgraph;
 	RenderTargetDescription m_tmpRtDesc;
 	RenderTargetDescription m_tmpRtDesc;

+ 5 - 5
AnKi/Renderer/MotionVectors.cpp

@@ -22,18 +22,18 @@ Error MotionVectors::init(const ConfigSet& config)
 	// Prog
 	// Prog
 	ANKI_CHECK(getResourceManager().loadResource("Shaders/MotionVectors.ankiprog", m_prog));
 	ANKI_CHECK(getResourceManager().loadResource("Shaders/MotionVectors.ankiprog", m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
-	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_grProg = variant->getProgram();
 	m_grProg = variant->getProgram();
 
 
 	// RTs
 	// RTs
-	m_motionVectorsRtDescr = m_r->create2DRenderTargetDescription(m_r->getWidth(), m_r->getHeight(),
+	m_motionVectorsRtDescr = m_r->create2DRenderTargetDescription(m_r->getResolution().x(), m_r->getResolution().y(),
 																  Format::R16G16_SFLOAT, "Motion vectors");
 																  Format::R16G16_SFLOAT, "Motion vectors");
 	m_motionVectorsRtDescr.bake();
 	m_motionVectorsRtDescr.bake();
 
 
-	m_rejectionFactorRtDescr =
-		m_r->create2DRenderTargetDescription(m_r->getWidth(), m_r->getHeight(), Format::R8_UNORM, "Motion vectors rej");
+	m_rejectionFactorRtDescr = m_r->create2DRenderTargetDescription(m_r->getResolution().x(), m_r->getResolution().y(),
+																	Format::R8_UNORM, "Motion vectors rej");
 	m_rejectionFactorRtDescr.bake();
 	m_rejectionFactorRtDescr.bake();
 
 
 	return Error::NONE;
 	return Error::NONE;
@@ -92,7 +92,7 @@ void MotionVectors::run(RenderPassWorkContext& rgraphCtx)
 	pc.m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_viewProjectionJitter.getInverse();
 	pc.m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_viewProjectionJitter.getInverse();
 	cmdb->setPushConstants(&pc, sizeof(pc));
 	cmdb->setPushConstants(&pc, sizeof(pc));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth(), m_r->getHeight());
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x(), m_r->getResolution().y());
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 8 - 8
AnKi/Renderer/Renderer.cpp

@@ -87,17 +87,17 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_frameCount = 0;
 	m_frameCount = 0;
 
 
 	// Set from the config
 	// Set from the config
-	m_width = config.getNumberU32("width");
-	m_height = config.getNumberU32("height");
-	ANKI_R_LOGI("Initializing offscreen renderer. Size %ux%u", m_width, m_height);
+	m_resolution.x() = U32(F32(config.getNumberU32("width")) * config.getNumberF32("r_renderScaling"));
+	m_resolution.y() = U32(F32(config.getNumberU32("height")) * config.getNumberF32("r_renderScaling"));
+	ANKI_R_LOGI("Initializing offscreen renderer. Size %ux%u", m_resolution.x(), m_resolution.y());
 
 
 	m_tileSize = config.getNumberU32("r_tileSize");
 	m_tileSize = config.getNumberU32("r_tileSize");
-	m_tileCounts.x() = (m_width + m_tileSize - 1) / m_tileSize;
-	m_tileCounts.y() = (m_height + m_tileSize - 1) / m_tileSize;
+	m_tileCounts.x() = (m_resolution.x() + m_tileSize - 1) / m_tileSize;
+	m_tileCounts.y() = (m_resolution.y() + m_tileSize - 1) / m_tileSize;
 	m_zSplitCount = config.getNumberU32("r_zSplitCount");
 	m_zSplitCount = config.getNumberU32("r_zSplitCount");
 
 
 	// A few sanity checks
 	// A few sanity checks
-	if(m_width < 10 || m_height < 10)
+	if(m_resolution.x() < 64 || m_resolution.y() < 64)
 	{
 	{
 		ANKI_R_LOGE("Incorrect sizes");
 		ANKI_R_LOGE("Incorrect sizes");
 		return Error::USER_DATA;
 		return Error::USER_DATA;
@@ -246,7 +246,7 @@ void Renderer::initJitteredMats()
 
 
 	for(U i = 0; i < 16; ++i)
 	for(U i = 0; i < 16; ++i)
 	{
 	{
-		Vec2 texSize(1.0f / Vec2(F32(m_width), F32(m_height))); // Texel size
+		Vec2 texSize(1.0f / Vec2(F32(m_resolution.x()), F32(m_resolution.y()))); // Texel size
 		texSize *= 2.0f; // Move it to NDC
 		texSize *= 2.0f; // Move it to NDC
 
 
 		Vec2 S = SAMPLE_LOCS_16[i] / 8.0f; // In [-1, 1]
 		Vec2 S = SAMPLE_LOCS_16[i] / 8.0f; // In [-1, 1]
@@ -263,7 +263,7 @@ void Renderer::initJitteredMats()
 
 
 	for(U i = 0; i < 8; ++i)
 	for(U i = 0; i < 8; ++i)
 	{
 	{
-		Vec2 texSize(1.0f / Vec2(F32(m_width), F32(m_height))); // Texel size
+		Vec2 texSize(1.0f / Vec2(F32(m_resolution.x()), F32(m_resolution.y()))); // Texel size
 		texSize *= 2.0f; // Move it to NDC
 		texSize *= 2.0f; // Move it to NDC
 
 
 		Vec2 S = SAMPLE_LOCS_8[i] / 8.0f; // In [-1, 1]
 		Vec2 S = SAMPLE_LOCS_8[i] / 8.0f; // In [-1, 1]

+ 4 - 10
AnKi/Renderer/Renderer.h

@@ -56,19 +56,14 @@ public:
 		return m_rtShadows.isCreated();
 		return m_rtShadows.isCreated();
 	}
 	}
 
 
-	U32 getWidth() const
+	const UVec2& getResolution() const
 	{
 	{
-		return m_width;
-	}
-
-	U32 getHeight() const
-	{
-		return m_height;
+		return m_resolution;
 	}
 	}
 
 
 	F32 getAspectRatio() const
 	F32 getAspectRatio() const
 	{
 	{
-		return F32(m_width) / F32(m_height);
+		return F32(m_resolution.x()) / F32(m_resolution.y());
 	}
 	}
 
 
 	/// Init the renderer.
 	/// Init the renderer.
@@ -237,8 +232,7 @@ private:
 	UVec2 m_tileCounts = UVec2(0u);
 	UVec2 m_tileCounts = UVec2(0u);
 	U32 m_zSplitCount = 0;
 	U32 m_zSplitCount = 0;
 
 
-	U32 m_width;
-	U32 m_height;
+	UVec2 m_resolution = UVec2(0u);
 
 
 	RenderableDrawer m_sceneDrawer;
 	RenderableDrawer m_sceneDrawer;
 
 

+ 31 - 30
AnKi/Renderer/RtShadows.cpp

@@ -66,7 +66,8 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsDenoise.ankiprog", m_denoiseProg));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsDenoise.ankiprog", m_denoiseProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_denoiseProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_denoiseProg);
-		variantInitInfo.addConstant("OUT_IMAGE_SIZE", UVec2(m_r->getWidth() / 2, m_r->getHeight() / 2));
+		variantInitInfo.addConstant("OUT_IMAGE_SIZE",
+									UVec2(m_r->getResolution().x() / 2, m_r->getResolution().y() / 2));
 		variantInitInfo.addConstant("MIN_SAMPLE_COUNT", 8u);
 		variantInitInfo.addConstant("MIN_SAMPLE_COUNT", 8u);
 		variantInitInfo.addConstant("MAX_SAMPLE_COUNT", 32u);
 		variantInitInfo.addConstant("MAX_SAMPLE_COUNT", 32u);
 		variantInitInfo.addMutation("BLUR_ORIENTATION", 0);
 		variantInitInfo.addMutation("BLUR_ORIENTATION", 0);
@@ -85,7 +86,7 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfVariance.ankiprog", m_svgfVarianceProg));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfVariance.ankiprog", m_svgfVarianceProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfVarianceProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfVarianceProg);
-		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth() / 2, m_r->getHeight() / 2));
+		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x() / 2, m_r->getResolution().y() / 2));
 
 
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
 		m_svgfVarianceProg->getOrCreateVariant(variantInitInfo, variant);
 		m_svgfVarianceProg->getOrCreateVariant(variantInitInfo, variant);
@@ -97,7 +98,7 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfAtrous.ankiprog", m_svgfAtrousProg));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfAtrous.ankiprog", m_svgfAtrousProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfAtrousProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfAtrousProg);
-		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth() / 2, m_r->getHeight() / 2));
+		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x() / 2, m_r->getResolution().y() / 2));
 		variantInitInfo.addMutation("LAST_PASS", 0);
 		variantInitInfo.addMutation("LAST_PASS", 0);
 
 
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
@@ -113,7 +114,7 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsUpscale.ankiprog", m_upscaleProg));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsUpscale.ankiprog", m_upscaleProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
-		variantInitInfo.addConstant("OUT_IMAGE_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+		variantInitInfo.addConstant("OUT_IMAGE_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 
 
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
 		m_upscaleProg->getOrCreateVariant(variantInitInfo, variant);
 		m_upscaleProg->getOrCreateVariant(variantInitInfo, variant);
@@ -126,29 +127,29 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 
 
 	// Quarter rez shadow RT
 	// Quarter rez shadow RT
 	{
 	{
-		TextureInitInfo texinit =
-			m_r->create2DRenderTargetInitInfo(m_r->getWidth() / 2, m_r->getHeight() / 2, Format::R32G32_UINT,
-											  TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
-												  | TextureUsageBit::IMAGE_COMPUTE_WRITE,
-											  "RtShadows History");
+		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
+			m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, Format::R32G32_UINT,
+			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
+				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
+			"RtShadows History");
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		m_historyRt = m_r->createAndClearRenderTarget(texinit);
 		m_historyRt = m_r->createAndClearRenderTarget(texinit);
 	}
 	}
 
 
 	// Temp shadow RT
 	// Temp shadow RT
 	{
 	{
-		m_intermediateShadowsRtDescr = m_r->create2DRenderTargetDescription(m_r->getWidth() / 2, m_r->getHeight() / 2,
-																			Format::R32G32_UINT, "RtShadows Tmp");
+		m_intermediateShadowsRtDescr = m_r->create2DRenderTargetDescription(
+			m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, Format::R32G32_UINT, "RtShadows Tmp");
 		m_intermediateShadowsRtDescr.bake();
 		m_intermediateShadowsRtDescr.bake();
 	}
 	}
 
 
 	// Moments RT
 	// Moments RT
 	{
 	{
-		TextureInitInfo texinit =
-			m_r->create2DRenderTargetInitInfo(m_r->getWidth() / 2, m_r->getHeight() / 2, Format::R32G32_SFLOAT,
-											  TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
-												  | TextureUsageBit::IMAGE_COMPUTE_WRITE,
-											  "RtShadows Moments #1");
+		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
+			m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, Format::R32G32_SFLOAT,
+			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
+				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
+			"RtShadows Moments #1");
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		m_momentsRts[0] = m_r->createAndClearRenderTarget(texinit);
 		m_momentsRts[0] = m_r->createAndClearRenderTarget(texinit);
 
 
@@ -158,11 +159,11 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 
 
 	// History len RT
 	// History len RT
 	{
 	{
-		TextureInitInfo texinit =
-			m_r->create2DRenderTargetInitInfo(m_r->getWidth() / 2, m_r->getHeight() / 2, Format::R8_UNORM,
-											  TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
-												  | TextureUsageBit::IMAGE_COMPUTE_WRITE,
-											  "RtShadows History Length #1");
+		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
+			m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, Format::R8_UNORM,
+			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
+				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
+			"RtShadows History Length #1");
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		m_historyLengthRts[0] = m_r->createAndClearRenderTarget(texinit);
 		m_historyLengthRts[0] = m_r->createAndClearRenderTarget(texinit);
 
 
@@ -173,15 +174,15 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	// Variance RT
 	// Variance RT
 	if(m_useSvgf)
 	if(m_useSvgf)
 	{
 	{
-		m_varianceRtDescr = m_r->create2DRenderTargetDescription(m_r->getWidth() / 2, m_r->getHeight() / 2,
-																 Format::R32_SFLOAT, "RtShadows Variance");
+		m_varianceRtDescr = m_r->create2DRenderTargetDescription(
+			m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, Format::R32_SFLOAT, "RtShadows Variance");
 		m_varianceRtDescr.bake();
 		m_varianceRtDescr.bake();
 	}
 	}
 
 
 	// Final RT
 	// Final RT
 	{
 	{
-		m_upscaledRtDescr = m_r->create2DRenderTargetDescription(m_r->getWidth(), m_r->getHeight(), Format::R32G32_UINT,
-																 "RtShadows Upscaled");
+		m_upscaledRtDescr = m_r->create2DRenderTargetDescription(m_r->getResolution().x(), m_r->getResolution().y(),
+																 Format::R32G32_UINT, "RtShadows Upscaled");
 		m_upscaledRtDescr.bake();
 		m_upscaledRtDescr.bake();
 	}
 	}
 
 
@@ -520,7 +521,7 @@ void RtShadows::run(RenderPassWorkContext& rgraphCtx)
 	cmdb->setPushConstants(&unis, sizeof(unis));
 	cmdb->setPushConstants(&unis, sizeof(unis));
 
 
 	cmdb->traceRays(m_runCtx.m_sbtBuffer, m_runCtx.m_sbtOffset, m_sbtRecordSize, m_runCtx.m_hitGroupCount, 1,
 	cmdb->traceRays(m_runCtx.m_sbtBuffer, m_runCtx.m_sbtOffset, m_sbtRecordSize, m_runCtx.m_hitGroupCount, 1,
-					m_r->getWidth() / 2, m_r->getHeight() / 2, 1);
+					m_r->getResolution().x() / 2, m_r->getResolution().y() / 2, 1);
 }
 }
 
 
 void RtShadows::runDenoise(RenderPassWorkContext& rgraphCtx)
 void RtShadows::runDenoise(RenderPassWorkContext& rgraphCtx)
@@ -545,7 +546,7 @@ void RtShadows::runDenoise(RenderPassWorkContext& rgraphCtx)
 	unis.time = F32(m_r->getGlobalTimestamp());
 	unis.time = F32(m_r->getGlobalTimestamp());
 	cmdb->setPushConstants(&unis, sizeof(unis));
 	cmdb->setPushConstants(&unis, sizeof(unis));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 
 
 	m_runCtx.m_denoiseOrientation = !m_runCtx.m_denoiseOrientation;
 	m_runCtx.m_denoiseOrientation = !m_runCtx.m_denoiseOrientation;
 }
 }
@@ -570,7 +571,7 @@ void RtShadows::runSvgfVariance(RenderPassWorkContext& rgraphCtx)
 	const Mat4& invProjMat = m_runCtx.m_ctx->m_matrices.m_projectionJitter.getInverse();
 	const Mat4& invProjMat = m_runCtx.m_ctx->m_matrices.m_projectionJitter.getInverse();
 	cmdb->setPushConstants(&invProjMat, sizeof(invProjMat));
 	cmdb->setPushConstants(&invProjMat, sizeof(invProjMat));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 }
 }
 
 
 void RtShadows::runSvgfAtrous(RenderPassWorkContext& rgraphCtx)
 void RtShadows::runSvgfAtrous(RenderPassWorkContext& rgraphCtx)
@@ -609,7 +610,7 @@ void RtShadows::runSvgfAtrous(RenderPassWorkContext& rgraphCtx)
 	const Mat4& invProjMat = m_runCtx.m_ctx->m_matrices.m_projectionJitter.getInverse();
 	const Mat4& invProjMat = m_runCtx.m_ctx->m_matrices.m_projectionJitter.getInverse();
 	cmdb->setPushConstants(&invProjMat, sizeof(invProjMat));
 	cmdb->setPushConstants(&invProjMat, sizeof(invProjMat));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 
 
 	++m_runCtx.m_atrousPassIdx;
 	++m_runCtx.m_atrousPassIdx;
 }
 }
@@ -628,7 +629,7 @@ void RtShadows::runUpscale(RenderPassWorkContext& rgraphCtx)
 	rgraphCtx.bindTexture(0, 4, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindTexture(0, 4, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindTexture(0, 5, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindTexture(0, 5, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth(), m_r->getHeight());
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x(), m_r->getResolution().y());
 }
 }
 
 
 void RtShadows::buildSbt()
 void RtShadows::buildSbt()

+ 4 - 4
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -29,10 +29,10 @@ Error ShadowmapsResolve::init(const ConfigSet& cfg)
 
 
 Error ShadowmapsResolve::initInternal(const ConfigSet& cfg)
 Error ShadowmapsResolve::initInternal(const ConfigSet& cfg)
 {
 {
-	U32 width = U32(cfg.getNumberF32("r_smResolveFactor") * F32(m_r->getWidth()));
-	width = min(m_r->getWidth(), getAlignedRoundUp(4, width));
-	U32 height = U32(cfg.getNumberF32("r_smResolveFactor") * F32(m_r->getHeight()));
-	height = min(m_r->getHeight(), getAlignedRoundUp(4, height));
+	U32 width = U32(cfg.getNumberF32("r_smResolveFactor") * F32(m_r->getResolution().x()));
+	width = min(m_r->getResolution().x(), getAlignedRoundUp(4, width));
+	U32 height = U32(cfg.getNumberF32("r_smResolveFactor") * F32(m_r->getResolution().y()));
+	height = min(m_r->getResolution().y(), getAlignedRoundUp(4, height));
 	ANKI_R_LOGI("Initializing shadow resolve pass. Size %ux%u", width, height);
 	ANKI_R_LOGI("Initializing shadow resolve pass. Size %ux%u", width, height);
 
 
 	m_rtDescr = m_r->create2DRenderTargetDescription(width, height, Format::R8G8B8A8_UNORM, "SM resolve");
 	m_rtDescr = m_r->create2DRenderTargetDescription(width, height, Format::R8G8B8A8_UNORM, "SM resolve");

+ 2 - 2
AnKi/Renderer/Ssao.cpp

@@ -93,8 +93,8 @@ Error Ssao::initBlur(const ConfigSet& config)
 
 
 Error Ssao::init(const ConfigSet& config)
 Error Ssao::init(const ConfigSet& config)
 {
 {
-	m_width = m_r->getWidth() / SSAO_FRACTION;
-	m_height = m_r->getHeight() / SSAO_FRACTION;
+	m_width = m_r->getResolution().x() / SSAO_FRACTION;
+	m_height = m_r->getResolution().y() / SSAO_FRACTION;
 
 
 	ANKI_R_LOGI("Initializing SSAO. Size %ux%u", m_width, m_height);
 	ANKI_R_LOGI("Initializing SSAO. Size %ux%u", m_width, m_height);
 
 

+ 9 - 9
AnKi/Renderer/Ssgi.cpp

@@ -34,8 +34,8 @@ Error Ssgi::init(const ConfigSet& cfg)
 
 
 Error Ssgi::initInternal(const ConfigSet& cfg)
 Error Ssgi::initInternal(const ConfigSet& cfg)
 {
 {
-	const U32 width = m_r->getWidth();
-	const U32 height = m_r->getHeight();
+	const U32 width = m_r->getResolution().x();
+	const U32 height = m_r->getResolution().y();
 	ANKI_ASSERT((width % 2) == 0 && (height % 2) == 0 && "The algorithms won't work");
 	ANKI_ASSERT((width % 2) == 0 && (height % 2) == 0 && "The algorithms won't work");
 	ANKI_R_LOGI("Initializing SSGI pass");
 	ANKI_R_LOGI("Initializing SSGI pass");
 	m_main.m_maxSteps = cfg.getNumberU32("r_ssgiMaxSteps");
 	m_main.m_maxSteps = cfg.getNumberU32("r_ssgiMaxSteps");
@@ -92,7 +92,7 @@ Error Ssgi::initInternal(const ConfigSet& cfg)
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/SsgiReconstruct.ankiprog", m_recontruction.m_prog));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/SsgiReconstruct.ankiprog", m_recontruction.m_prog));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_recontruction.m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_recontruction.m_prog);
-		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
 
 
 		for(U32 i = 0; i < 4; ++i)
 		for(U32 i = 0; i < 4; ++i)
@@ -205,8 +205,8 @@ void Ssgi::run(RenderPassWorkContext& rgraphCtx)
 
 
 	// Bind uniforms
 	// Bind uniforms
 	SsgiUniforms* unis = allocateAndBindUniforms<SsgiUniforms*>(sizeof(SsgiUniforms), cmdb, 0, 1);
 	SsgiUniforms* unis = allocateAndBindUniforms<SsgiUniforms*>(sizeof(SsgiUniforms), cmdb, 0, 1);
-	unis->m_depthBufferSize = UVec2(m_r->getWidth(), m_r->getHeight()) >> (m_main.m_depthLod + 1);
-	unis->m_framebufferSize = UVec2(m_r->getWidth(), m_r->getHeight());
+	unis->m_depthBufferSize = UVec2(m_r->getResolution().x(), m_r->getResolution().y()) >> (m_main.m_depthLod + 1);
+	unis->m_framebufferSize = UVec2(m_r->getResolution().x(), m_r->getResolution().y());
 	unis->m_invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 	unis->m_invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 	unis->m_projMat = ctx.m_matrices.m_projectionJitter;
 	unis->m_projMat = ctx.m_matrices.m_projectionJitter;
 	unis->m_prevViewProjMatMulInvViewProjMat =
 	unis->m_prevViewProjMatMulInvViewProjMat =
@@ -230,7 +230,7 @@ void Ssgi::run(RenderPassWorkContext& rgraphCtx)
 	rgraphCtx.bindColorTexture(0, 8, m_r->getMotionVectors().getRejectionFactorRt());
 	rgraphCtx.bindColorTexture(0, 8, m_r->getMotionVectors().getRejectionFactorRt());
 
 
 	// Dispatch
 	// Dispatch
-	dispatchPPCompute(cmdb, 16, 16, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 16, 16, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 }
 }
 
 
 void Ssgi::runVBlur(RenderPassWorkContext& rgraphCtx)
 void Ssgi::runVBlur(RenderPassWorkContext& rgraphCtx)
@@ -248,7 +248,7 @@ void Ssgi::runVBlur(RenderPassWorkContext& rgraphCtx)
 	const Mat4 mat = m_runCtx.m_ctx->m_matrices.m_viewProjectionJitter.getInverse();
 	const Mat4 mat = m_runCtx.m_ctx->m_matrices.m_viewProjectionJitter.getInverse();
 	cmdb->setPushConstants(&mat, sizeof(mat));
 	cmdb->setPushConstants(&mat, sizeof(mat));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 }
 }
 
 
 void Ssgi::runHBlur(RenderPassWorkContext& rgraphCtx)
 void Ssgi::runHBlur(RenderPassWorkContext& rgraphCtx)
@@ -266,7 +266,7 @@ void Ssgi::runHBlur(RenderPassWorkContext& rgraphCtx)
 	const Mat4 mat = m_runCtx.m_ctx->m_matrices.m_viewProjectionJitter.getInverse();
 	const Mat4 mat = m_runCtx.m_ctx->m_matrices.m_viewProjectionJitter.getInverse();
 	cmdb->setPushConstants(&mat, sizeof(mat));
 	cmdb->setPushConstants(&mat, sizeof(mat));
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth() / 2, m_r->getHeight() / 2);
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x() / 2, m_r->getResolution().y() / 2);
 }
 }
 
 
 void Ssgi::runRecontruct(RenderPassWorkContext& rgraphCtx)
 void Ssgi::runRecontruct(RenderPassWorkContext& rgraphCtx)
@@ -280,7 +280,7 @@ void Ssgi::runRecontruct(RenderPassWorkContext& rgraphCtx)
 
 
 	rgraphCtx.bindImage(0, 3, m_runCtx.m_finalRt, TextureSubresourceInfo());
 	rgraphCtx.bindImage(0, 3, m_runCtx.m_finalRt, TextureSubresourceInfo());
 
 
-	dispatchPPCompute(cmdb, 16, 16, m_r->getWidth(), m_r->getHeight());
+	dispatchPPCompute(cmdb, 16, 16, m_r->getResolution().x(), m_r->getResolution().y());
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 9 - 7
AnKi/Renderer/Ssr.cpp

@@ -31,8 +31,8 @@ Error Ssr::init(const ConfigSet& cfg)
 
 
 Error Ssr::initInternal(const ConfigSet& cfg)
 Error Ssr::initInternal(const ConfigSet& cfg)
 {
 {
-	const U32 width = m_r->getWidth();
-	const U32 height = m_r->getHeight();
+	const U32 width = m_r->getResolution().x();
+	const U32 height = m_r->getResolution().y();
 	ANKI_R_LOGI("Initializing SSR pass (%ux%u)", width, height);
 	ANKI_R_LOGI("Initializing SSR pass (%ux%u)", width, height);
 	m_maxSteps = cfg.getNumberU32("r_ssrMaxSteps");
 	m_maxSteps = cfg.getNumberU32("r_ssrMaxSteps");
 	m_depthLod = cfg.getNumberU32("r_ssrDepthLod");
 	m_depthLod = cfg.getNumberU32("r_ssrDepthLod");
@@ -85,7 +85,7 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 	rpass.newDependency({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE});
 	rpass.newDependency({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE});
 
 
 	TextureSubresourceInfo hizSubresource;
 	TextureSubresourceInfo hizSubresource;
-	hizSubresource.m_firstMipmap = m_depthLod;
+	hizSubresource.m_firstMipmap = min(m_depthLod, m_r->getDepthDownscale().getMipmapCount() - 1);
 	rpass.newDependency({m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_COMPUTE, hizSubresource});
 	rpass.newDependency({m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_COMPUTE, hizSubresource});
 
 
 	rpass.newDependency({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
 	rpass.newDependency({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
@@ -98,11 +98,12 @@ void Ssr::run(RenderPassWorkContext& rgraphCtx)
 	cmdb->bindShaderProgram(m_grProg[m_r->getFrameCount() & 1u]);
 	cmdb->bindShaderProgram(m_grProg[m_r->getFrameCount() & 1u]);
 
 
 	rgraphCtx.bindImage(0, 0, m_runCtx.m_rt, TextureSubresourceInfo());
 	rgraphCtx.bindImage(0, 0, m_runCtx.m_rt, TextureSubresourceInfo());
+	const U32 depthLod = min(m_depthLod, m_r->getDepthDownscale().getMipmapCount() - 1);
 
 
 	// Bind uniforms
 	// Bind uniforms
 	SsrUniforms* unis = allocateAndBindUniforms<SsrUniforms*>(sizeof(SsrUniforms), cmdb, 0, 1);
 	SsrUniforms* unis = allocateAndBindUniforms<SsrUniforms*>(sizeof(SsrUniforms), cmdb, 0, 1);
-	unis->m_depthBufferSize = UVec2(m_r->getWidth(), m_r->getHeight()) >> (m_depthLod + 1);
-	unis->m_framebufferSize = UVec2(m_r->getWidth(), m_r->getHeight());
+	unis->m_depthBufferSize = UVec2(m_r->getResolution().x(), m_r->getResolution().y()) >> (depthLod + 1);
+	unis->m_framebufferSize = UVec2(m_r->getResolution().x(), m_r->getResolution().y());
 	unis->m_frameCount = m_r->getFrameCount() & MAX_U32;
 	unis->m_frameCount = m_r->getFrameCount() & MAX_U32;
 	unis->m_depthMipCount = m_r->getDepthDownscale().getMipmapCount();
 	unis->m_depthMipCount = m_r->getDepthDownscale().getMipmapCount();
 	unis->m_maxSteps = m_maxSteps;
 	unis->m_maxSteps = m_maxSteps;
@@ -121,7 +122,7 @@ void Ssr::run(RenderPassWorkContext& rgraphCtx)
 	rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
 
 
 	TextureSubresourceInfo hizSubresource;
 	TextureSubresourceInfo hizSubresource;
-	hizSubresource.m_firstMipmap = m_depthLod;
+	hizSubresource.m_firstMipmap = depthLod;
 	rgraphCtx.bindTexture(0, 5, m_r->getDepthDownscale().getHiZRt(), hizSubresource);
 	rgraphCtx.bindTexture(0, 5, m_r->getDepthDownscale().getHiZRt(), hizSubresource);
 
 
 	rgraphCtx.bindColorTexture(0, 6, m_r->getDownscaleBlur().getRt());
 	rgraphCtx.bindColorTexture(0, 6, m_r->getDownscaleBlur().getRt());
@@ -130,7 +131,8 @@ void Ssr::run(RenderPassWorkContext& rgraphCtx)
 	cmdb->bindTexture(0, 8, m_noiseImage->getTextureView());
 	cmdb->bindTexture(0, 8, m_noiseImage->getTextureView());
 
 
 	// Dispatch
 	// Dispatch
-	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_r->getWidth() / 2, m_r->getHeight());
+	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_r->getResolution().x() / 2,
+					  m_r->getResolution().y());
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 3 - 3
AnKi/Renderer/TemporalAA.cpp

@@ -44,7 +44,7 @@ Error TemporalAA::initInternal(const ConfigSet& config)
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		variantInitInfo.addConstant("VARIANCE_CLIPPING_GAMMA", 2.7f);
 		variantInitInfo.addConstant("VARIANCE_CLIPPING_GAMMA", 2.7f);
 		variantInitInfo.addConstant("BLEND_FACTOR", 1.0f / 16.0f);
 		variantInitInfo.addConstant("BLEND_FACTOR", 1.0f / 16.0f);
-		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+		variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getResolution().x(), m_r->getResolution().y()));
 		variantInitInfo.addMutation("SHARPEN", i + 1);
 		variantInitInfo.addMutation("SHARPEN", i + 1);
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("TONEMAP_FIX", 1);
 		variantInitInfo.addMutation("TONEMAP_FIX", 1);
@@ -58,7 +58,7 @@ Error TemporalAA::initInternal(const ConfigSet& config)
 	for(U i = 0; i < 2; ++i)
 	for(U i = 0; i < 2; ++i)
 	{
 	{
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
-			m_r->getWidth(), m_r->getHeight(), LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
+			m_r->getResolution().x(), m_r->getResolution().y(), LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE,
 			"TemporalAA");
 			"TemporalAA");
 
 
@@ -84,7 +84,7 @@ void TemporalAA::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphC
 	rgraphCtx.bindImage(0, 5, m_runCtx.m_renderRt, TextureSubresourceInfo());
 	rgraphCtx.bindImage(0, 5, m_runCtx.m_renderRt, TextureSubresourceInfo());
 	rgraphCtx.bindUniformBuffer(0, 6, m_r->getTonemapping().getAverageLuminanceBuffer());
 	rgraphCtx.bindUniformBuffer(0, 6, m_r->getTonemapping().getAverageLuminanceBuffer());
 
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth(), m_r->getHeight());
+	dispatchPPCompute(cmdb, 8, 8, m_r->getResolution().x(), m_r->getResolution().y());
 }
 }
 
 
 void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 void TemporalAA::populateRenderGraph(RenderingContext& ctx)

+ 2 - 1
AnKi/Renderer/UiStage.cpp

@@ -25,7 +25,8 @@ UiStage::~UiStage()
 Error UiStage::init(const ConfigSet&)
 Error UiStage::init(const ConfigSet&)
 {
 {
 	ANKI_CHECK(m_r->getUiManager().newInstance(m_font, "EngineAssets/UbuntuRegular.ttf", Array<U32, 3>{12, 16, 20}));
 	ANKI_CHECK(m_r->getUiManager().newInstance(m_font, "EngineAssets/UbuntuRegular.ttf", Array<U32, 3>{12, 16, 20}));
-	ANKI_CHECK(m_r->getUiManager().newInstance(m_canvas, m_font, 12, m_r->getWidth(), m_r->getHeight()));
+	ANKI_CHECK(
+		m_r->getUiManager().newInstance(m_canvas, m_font, 12, m_r->getResolution().x(), m_r->getResolution().y()));
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }