Browse Source

Renderer: Remove the mips from IS RT & other fixes

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
01a66f840f

+ 5 - 5
shaders/Bloom.frag.glsl

@@ -26,11 +26,11 @@ void main()
 {
 {
 	const vec2 TEXEL_SIZE = 1.0 / vec2(WIDTH, HEIGHT);
 	const vec2 TEXEL_SIZE = 1.0 / vec2(WIDTH, HEIGHT);
 
 
-	vec3 color = textureLod(u_tex, in_uv, MIPMAP).rgb;
-	color += textureLod(u_tex, in_uv + TEXEL_SIZE, MIPMAP).rgb;
-	color += textureLod(u_tex, in_uv - TEXEL_SIZE, MIPMAP).rgb;
-	color += textureLod(u_tex, in_uv + vec2(TEXEL_SIZE.x, -TEXEL_SIZE.y), MIPMAP).rgb;
-	color += textureLod(u_tex, in_uv + vec2(-TEXEL_SIZE.x, TEXEL_SIZE.y), MIPMAP).rgb;
+	vec3 color = textureLod(u_tex, in_uv, 0.0).rgb;
+	color += textureLod(u_tex, in_uv + TEXEL_SIZE, 0.0).rgb;
+	color += textureLod(u_tex, in_uv - TEXEL_SIZE, 0.0).rgb;
+	color += textureLod(u_tex, in_uv + vec2(TEXEL_SIZE.x, -TEXEL_SIZE.y), 0.0).rgb;
+	color += textureLod(u_tex, in_uv + vec2(-TEXEL_SIZE.x, TEXEL_SIZE.y), 0.0).rgb;
 
 
 	color /= 5.0;
 	color /= 5.0;
 
 

+ 5 - 6
shaders/DownscaleBlur.frag.glsl

@@ -13,13 +13,12 @@ layout(location = 0) out vec3 out_color;
 void main()
 void main()
 {
 {
 	const vec2 TEXEL_SIZE = 1.0 / TEXTURE_SIZE;
 	const vec2 TEXEL_SIZE = 1.0 / TEXTURE_SIZE;
-	const vec2 TEXEL_SIZE2 = 2.0 * TEXEL_SIZE;
 
 
-	out_color = textureLod(u_tex, in_uv, TEXTURE_MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_uv + TEXEL_SIZE, TEXTURE_MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_uv - TEXEL_SIZE, TEXTURE_MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_uv + vec2(TEXEL_SIZE.x, -TEXEL_SIZE.y), TEXTURE_MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_uv + vec2(-TEXEL_SIZE.x, TEXEL_SIZE.y), TEXTURE_MIPMAP).rgb;
+	out_color = textureLod(u_tex, in_uv, 0.0).rgb;
+	out_color += textureLod(u_tex, in_uv + TEXEL_SIZE, 0.0).rgb;
+	out_color += textureLod(u_tex, in_uv - TEXEL_SIZE, 0.0).rgb;
+	out_color += textureLod(u_tex, in_uv + vec2(TEXEL_SIZE.x, -TEXEL_SIZE.y), 0.0).rgb;
+	out_color += textureLod(u_tex, in_uv + vec2(-TEXEL_SIZE.x, TEXEL_SIZE.y), 0.0).rgb;
 
 
 	out_color /= 5.0;
 	out_color /= 5.0;
 }
 }

+ 1 - 1
shaders/Pps.frag.glsl

@@ -159,7 +159,7 @@ void main()
 
 
 #if 0
 #if 0
 	{
 	{
-		out_color = vec3(textureLod(u_isRt, uv, 0.0).r);
+		out_color = vec3(textureLod(u_ppsBloomLfRt, uv, 0.0).rgb);
 	}
 	}
 #endif
 #endif
 
 

+ 6 - 18
shaders/TmAverageLuminance.comp.glsl

@@ -6,25 +6,18 @@
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
 #include "shaders/Tonemapping.glsl"
 #include "shaders/Tonemapping.glsl"
 
 
-#if IS_RT_MIPMAP == 0
-#error Wrong mipmap
-#endif
-
 const uint WORKGROUP_SIZE_X = 16u;
 const uint WORKGROUP_SIZE_X = 16u;
 const uint WORKGROUP_SIZE_Y = 16u;
 const uint WORKGROUP_SIZE_Y = 16u;
 const uint WORKGROUP_SIZE = WORKGROUP_SIZE_X * WORKGROUP_SIZE_Y;
 const uint WORKGROUP_SIZE = WORKGROUP_SIZE_X * WORKGROUP_SIZE_Y;
 
 
 layout(local_size_x = WORKGROUP_SIZE_X, local_size_y = WORKGROUP_SIZE_Y, local_size_z = 1) in;
 layout(local_size_x = WORKGROUP_SIZE_X, local_size_y = WORKGROUP_SIZE_Y, local_size_z = 1) in;
 
 
-const uint MIPMAP_WIDTH = ANKI_RENDERER_WIDTH / (2u << (IS_RT_MIPMAP - 1u));
-const uint MIPMAP_HEIGHT = ANKI_RENDERER_HEIGHT / (2u << (IS_RT_MIPMAP - 1u));
-
-const uint PIXEL_READ_X = MIPMAP_WIDTH / WORKGROUP_SIZE_X;
-const uint PIXEL_READ_Y = MIPMAP_HEIGHT / WORKGROUP_SIZE_Y;
+const uint PIXEL_READ_X = INPUT_TEX_SIZE.x / WORKGROUP_SIZE_X;
+const uint PIXEL_READ_Y = INPUT_TEX_SIZE.y / WORKGROUP_SIZE_Y;
 
 
-layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_isRt;
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex;
 
 
-layout(std140, ANKI_SS_BINDING(0, 0)) buffer _blk
+layout(std140, ANKI_SS_BINDING(0, 0)) buffer ss0_
 {
 {
 	vec4 u_averageLuminancePad3;
 	vec4 u_averageLuminancePad3;
 };
 };
@@ -42,15 +35,10 @@ void main()
 		for(uint x = 0; x < PIXEL_READ_X; ++x)
 		for(uint x = 0; x < PIXEL_READ_X; ++x)
 		{
 		{
 			ivec2 uv = ivec2(xStart, yStart) + ivec2(x, y);
 			ivec2 uv = ivec2(xStart, yStart) + ivec2(x, y);
-// WORKAROUND
-#if defined(ANKI_VK) && defined(ANKI_VENDOR_NVIDIA)
-			vec3 color = textureLod(u_isRt, vec2(uv) / vec2(MIPMAP_WIDTH, MIPMAP_HEIGHT), IS_RT_MIPMAP).rgb;
-#else
-			vec3 color = texelFetch(u_isRt, uv, IS_RT_MIPMAP).rgb;
-#endif
+			vec3 color = texelFetch(u_tex, uv, 0).rgb;
 			float lum = computeLuminance(color);
 			float lum = computeLuminance(color);
 			// avgLum += log(lum);
 			// avgLum += log(lum);
-			avgLum += lum / float(MIPMAP_WIDTH * MIPMAP_HEIGHT);
+			avgLum += lum / float(INPUT_TEX_SIZE.x * INPUT_TEX_SIZE.y);
 		}
 		}
 	}
 	}
 
 

+ 1 - 0
src/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -586,6 +586,7 @@ inline void CommandBufferImpl::flushBatches(CommandBufferCommandType type)
 		case CommandBufferCommandType::PUSH_SECOND_LEVEL:
 		case CommandBufferCommandType::PUSH_SECOND_LEVEL:
 			ANKI_ASSERT(m_secondLevelAtomCount > 0);
 			ANKI_ASSERT(m_secondLevelAtomCount > 0);
 			vkCmdExecuteCommands(m_handle, m_secondLevelAtomCount, &m_secondLevelAtoms[0]);
 			vkCmdExecuteCommands(m_handle, m_secondLevelAtomCount, &m_secondLevelAtoms[0]);
+			m_secondLevelAtomCount = 0;
 			break;
 			break;
 		case CommandBufferCommandType::ANY_OTHER_COMMAND:
 		case CommandBufferCommandType::ANY_OTHER_COMMAND:
 			break;
 			break;

+ 1 - 0
src/anki/gr/vulkan/DescriptorSet.cpp

@@ -202,6 +202,7 @@ Error DSThreadAllocator::newSet(
 			out = set;
 			out = set;
 			break;
 			break;
 		}
 		}
+		++it;
 	}
 	}
 
 
 	if(out == nullptr)
 	if(out == nullptr)

+ 37 - 27
src/anki/gr/vulkan/DescriptorSet.h

@@ -111,13 +111,15 @@ public:
 
 
 	void bindTexture(U binding, Texture* tex, DepthStencilAspectBit aspect, VkImageLayout layout)
 	void bindTexture(U binding, Texture* tex, DepthStencilAspectBit aspect, VkImageLayout layout)
 	{
 	{
-		m_bindings[binding].m_type = DescriptorType::TEXTURE;
-		m_bindings[binding].m_uuids[0] = m_bindings[binding].m_uuids[1] = tex->getUuid();
+		AnyBinding& b = m_bindings[binding];
+		b = {};
+		b.m_type = DescriptorType::TEXTURE;
+		b.m_uuids[0] = b.m_uuids[1] = tex->getUuid();
 
 
-		m_bindings[binding].m_tex.m_tex = tex->m_impl.get();
-		m_bindings[binding].m_tex.m_sampler = tex->m_impl->m_sampler->m_impl.get();
-		m_bindings[binding].m_tex.m_aspect = aspect;
-		m_bindings[binding].m_tex.m_layout = layout;
+		b.m_tex.m_tex = tex->m_impl.get();
+		b.m_tex.m_sampler = tex->m_impl->m_sampler->m_impl.get();
+		b.m_tex.m_aspect = aspect;
+		b.m_tex.m_layout = layout;
 
 
 		m_anyBindingDirty = true;
 		m_anyBindingDirty = true;
 	}
 	}
@@ -125,26 +127,30 @@ public:
 	void bindTextureAndSampler(
 	void bindTextureAndSampler(
 		U binding, Texture* tex, Sampler* sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
 		U binding, Texture* tex, Sampler* sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
 	{
 	{
-		m_bindings[binding].m_type = DescriptorType::TEXTURE;
-		m_bindings[binding].m_uuids[0] = tex->getUuid();
-		m_bindings[binding].m_uuids[1] = sampler->getUuid();
+		AnyBinding& b = m_bindings[binding];
+		b = {};
+		b.m_type = DescriptorType::TEXTURE;
+		b.m_uuids[0] = tex->getUuid();
+		b.m_uuids[1] = sampler->getUuid();
 
 
-		m_bindings[binding].m_tex.m_tex = tex->m_impl.get();
-		m_bindings[binding].m_tex.m_sampler = sampler->m_impl.get();
-		m_bindings[binding].m_tex.m_aspect = aspect;
-		m_bindings[binding].m_tex.m_layout = layout;
+		b.m_tex.m_tex = tex->m_impl.get();
+		b.m_tex.m_sampler = sampler->m_impl.get();
+		b.m_tex.m_aspect = aspect;
+		b.m_tex.m_layout = layout;
 
 
 		m_anyBindingDirty = true;
 		m_anyBindingDirty = true;
 	}
 	}
 
 
 	void bindUniformBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	void bindUniformBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	{
 	{
-		m_bindings[binding].m_type = DescriptorType::UNIFORM_BUFFER;
-		m_bindings[binding].m_uuids[0] = m_bindings[binding].m_uuids[1] = buff->getUuid();
+		AnyBinding& b = m_bindings[binding];
+		b = {};
+		b.m_type = DescriptorType::UNIFORM_BUFFER;
+		b.m_uuids[0] = b.m_uuids[1] = buff->getUuid();
 
 
-		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
-		m_bindings[binding].m_buff.m_offset = offset;
-		m_bindings[binding].m_buff.m_range = range;
+		b.m_buff.m_buff = buff->m_impl.get();
+		b.m_buff.m_offset = offset;
+		b.m_buff.m_range = range;
 
 
 		m_anyBindingDirty = true;
 		m_anyBindingDirty = true;
 		m_dynamicOffsetDirty.set(binding);
 		m_dynamicOffsetDirty.set(binding);
@@ -152,12 +158,14 @@ public:
 
 
 	void bindStorageBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	void bindStorageBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	{
 	{
-		m_bindings[binding].m_type = DescriptorType::STORAGE_BUFFER;
-		m_bindings[binding].m_uuids[0] = m_bindings[binding].m_uuids[1] = buff->getUuid();
+		AnyBinding& b = m_bindings[binding];
+		b = {};
+		b.m_type = DescriptorType::STORAGE_BUFFER;
+		b.m_uuids[0] = b.m_uuids[1] = buff->getUuid();
 
 
-		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
-		m_bindings[binding].m_buff.m_offset = offset;
-		m_bindings[binding].m_buff.m_range = range;
+		b.m_buff.m_buff = buff->m_impl.get();
+		b.m_buff.m_offset = offset;
+		b.m_buff.m_range = range;
 
 
 		m_anyBindingDirty = true;
 		m_anyBindingDirty = true;
 		m_dynamicOffsetDirty.set(binding);
 		m_dynamicOffsetDirty.set(binding);
@@ -165,11 +173,13 @@ public:
 
 
 	void bindImage(U binding, Texture* tex, U32 level)
 	void bindImage(U binding, Texture* tex, U32 level)
 	{
 	{
-		m_bindings[binding].m_type = DescriptorType::IMAGE;
-		m_bindings[binding].m_uuids[0] = m_bindings[binding].m_uuids[1] = tex->getUuid();
+		AnyBinding& b = m_bindings[binding];
+		b = {};
+		b.m_type = DescriptorType::IMAGE;
+		b.m_uuids[0] = b.m_uuids[1] = tex->getUuid();
 
 
-		m_bindings[binding].m_image.m_tex = tex->m_impl.get();
-		m_bindings[binding].m_image.m_level = level;
+		b.m_image.m_tex = tex->m_impl.get();
+		b.m_image.m_level = level;
 
 
 		m_anyBindingDirty = true;
 		m_anyBindingDirty = true;
 	}
 	}

+ 9 - 0
src/anki/gr/vulkan/FramebufferImpl.cpp

@@ -150,8 +150,17 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 			{
 			{
 				aspect = DepthStencilAspectBit::STENCIL;
 				aspect = DepthStencilAspectBit::STENCIL;
 			}
 			}
+			else if(tex.m_akAspect == DepthStencilAspectBit::DEPTH)
+			{
+				aspect = DepthStencilAspectBit::DEPTH;
+			}
+			else if(tex.m_akAspect == DepthStencilAspectBit::STENCIL)
+			{
+				aspect = DepthStencilAspectBit::STENCIL;
+			}
 			else
 			else
 			{
 			{
+				ANKI_ASSERT(!!att.m_aspect);
 				aspect = att.m_aspect;
 				aspect = att.m_aspect;
 			}
 			}
 
 

+ 9 - 11
src/anki/renderer/Bloom.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/renderer/Bloom.h>
 #include <anki/renderer/Bloom.h>
-#include <anki/renderer/Is.h>
+#include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Pps.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Tm.h>
 #include <anki/renderer/Tm.h>
@@ -21,8 +21,8 @@ Error BloomExposure::init(const ConfigSet& config)
 {
 {
 	GrManager& gr = getGrManager();
 	GrManager& gr = getGrManager();
 
 
-	m_width = m_r->getWidth() >> (m_r->getIs().getRtMipmapCount() - 2);
-	m_height = m_r->getHeight() >> (m_r->getIs().getRtMipmapCount() - 2);
+	m_width = m_r->getDownscaleBlur().getSmallPassWidth() * 2;
+	m_height = m_r->getDownscaleBlur().getSmallPassHeight() * 2;
 
 
 	m_threshold = config.getNumber("bloom.threshold");
 	m_threshold = config.getNumber("bloom.threshold");
 	m_scale = config.getNumber("bloom.scale");
 	m_scale = config.getNumber("bloom.scale");
@@ -38,18 +38,16 @@ Error BloomExposure::init(const ConfigSet& config)
 	FramebufferInitInfo fbInit;
 	FramebufferInitInfo fbInit;
 	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_rt;
 	fbInit.m_colorAttachments[0].m_texture = m_rt;
-	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::LOAD;
+	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	m_fb = gr.newInstance<Framebuffer>(fbInit);
 	m_fb = gr.newInstance<Framebuffer>(fbInit);
 
 
 	// init shaders
 	// init shaders
 	ANKI_CHECK(m_r->createShaderf("shaders/Bloom.frag.glsl",
 	ANKI_CHECK(m_r->createShaderf("shaders/Bloom.frag.glsl",
 		m_frag,
 		m_frag,
 		"#define WIDTH %u\n"
 		"#define WIDTH %u\n"
-		"#define HEIGHT %u\n"
-		"#define MIPMAP %u.0\n",
-		m_r->getWidth() >> (m_r->getIs().getRtMipmapCount() - 1),
-		m_r->getHeight() >> (m_r->getIs().getRtMipmapCount() - 1),
-		m_r->getIs().getRtMipmapCount() - 1));
+		"#define HEIGHT %u\n",
+		m_r->getDownscaleBlur().getSmallPassWidth(),
+		m_r->getDownscaleBlur().getSmallPassHeight()));
 
 
 	// Init prog
 	// Init prog
 	m_r->createDrawQuadShaderProgram(m_frag->getGrShader(), m_prog);
 	m_r->createDrawQuadShaderProgram(m_frag->getGrShader(), m_prog);
@@ -78,7 +76,7 @@ void BloomExposure::run(RenderingContext& ctx)
 	cmdb->beginRenderPass(m_fb);
 	cmdb->beginRenderPass(m_fb);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->bindShaderProgram(m_prog);
 	cmdb->bindShaderProgram(m_prog);
-	cmdb->bindTexture(0, 0, m_r->getIs().getRt());
+	cmdb->bindTexture(0, 0, m_r->getDownscaleBlur().getSmallPassTexture());
 
 
 	Vec4* uniforms = allocateAndBindUniforms<Vec4*>(sizeof(Vec4), cmdb, 0, 0);
 	Vec4* uniforms = allocateAndBindUniforms<Vec4*>(sizeof(Vec4), cmdb, 0, 0);
 	*uniforms = Vec4(m_threshold, m_scale, 0.0, 0.0);
 	*uniforms = Vec4(m_threshold, m_scale, 0.0, 0.0);
@@ -104,7 +102,7 @@ Error BloomUpscale::init(const ConfigSet& config)
 	m_rt = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(m_width,
 	m_rt = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(m_width,
 		m_height,
 		m_height,
 		BLOOM_RT_PIXEL_FORMAT,
 		BLOOM_RT_PIXEL_FORMAT,
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
+		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 		SamplingFilter::LINEAR));
 		SamplingFilter::LINEAR));
 
 
 	// Create FBs
 	// Create FBs

+ 5 - 2
src/anki/renderer/Common.h

@@ -62,12 +62,15 @@ const U VOLUMETRIC_FRACTION = 4;
 /// Computes the 'a' and 'b' numbers for linearizeDepthOptimal
 /// Computes the 'a' and 'b' numbers for linearizeDepthOptimal
 inline void computeLinearizeDepthOptimal(F32 near, F32 far, F32& a, F32& b)
 inline void computeLinearizeDepthOptimal(F32 near, F32 far, F32& a, F32& b)
 {
 {
-	a = (far + near) / (2.0 * near);
-	b = (near - far) / (2.0 * near);
+	a = (far + near) / (2.0f * near);
+	b = (near - far) / (2.0f * near);
 }
 }
 
 
 const U MS_COLOR_ATTACHMENT_COUNT = 3;
 const U MS_COLOR_ATTACHMENT_COUNT = 3;
 
 
+/// Downsample and blur down to a texture with size DOWNSCALE_BLUR_DOWN_TO
+const U DOWNSCALE_BLUR_DOWN_TO = 32;
+
 extern const Array<PixelFormat, MS_COLOR_ATTACHMENT_COUNT> MS_COLOR_ATTACHMENT_PIXEL_FORMATS;
 extern const Array<PixelFormat, MS_COLOR_ATTACHMENT_COUNT> MS_COLOR_ATTACHMENT_PIXEL_FORMATS;
 
 
 const PixelFormat MS_DEPTH_ATTACHMENT_PIXEL_FORMAT(ComponentFormat::D24S8, TransformFormat::UNORM);
 const PixelFormat MS_DEPTH_ATTACHMENT_PIXEL_FORMAT(ComponentFormat::D24S8, TransformFormat::UNORM);

+ 44 - 19
src/anki/renderer/DownscaleBlur.cpp

@@ -19,24 +19,32 @@ Error DownscaleBlur::initSubpass(U idx, const UVec2& inputTexSize)
 {
 {
 	Subpass& pass = m_passes[idx];
 	Subpass& pass = m_passes[idx];
 
 
+	pass.m_width = inputTexSize.x() / 2;
+	pass.m_height = inputTexSize.y() / 2;
+
 	// frag shader
 	// frag shader
 	ANKI_CHECK(m_r->createShaderf("shaders/DownscaleBlur.frag.glsl",
 	ANKI_CHECK(m_r->createShaderf("shaders/DownscaleBlur.frag.glsl",
 		pass.m_frag,
 		pass.m_frag,
-		"#define TEXTURE_SIZE vec2(%f, %f)\n"
-		"#define TEXTURE_MIPMAP float(%u)\n",
+		"#define TEXTURE_SIZE vec2(%f, %f)\n",
 		F32(inputTexSize.x()),
 		F32(inputTexSize.x()),
-		F32(inputTexSize.y()),
-		idx));
+		F32(inputTexSize.y())));
 
 
 	// prog
 	// prog
 	m_r->createDrawQuadShaderProgram(pass.m_frag->getGrShader(), pass.m_prog);
 	m_r->createDrawQuadShaderProgram(pass.m_frag->getGrShader(), pass.m_prog);
 
 
+	// RT
+	pass.m_rt = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(pass.m_width,
+		pass.m_height,
+		IS_COLOR_ATTACHMENT_PIXEL_FORMAT,
+		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
+			| TextureUsageBit::SAMPLED_COMPUTE,
+		SamplingFilter::LINEAR));
+
 	// FB
 	// FB
 	FramebufferInitInfo fbInit;
 	FramebufferInitInfo fbInit;
 	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachmentCount = 1;
-	fbInit.m_colorAttachments[0].m_texture = m_r->getIs().getRt();
+	fbInit.m_colorAttachments[0].m_texture = pass.m_rt;
 	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
-	fbInit.m_colorAttachments[0].m_surface.m_level = idx + 1;
 	pass.m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
 	pass.m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
 
 
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
@@ -57,7 +65,8 @@ Error DownscaleBlur::init(const ConfigSet& cfg)
 
 
 Error DownscaleBlur::initInternal(const ConfigSet&)
 Error DownscaleBlur::initInternal(const ConfigSet&)
 {
 {
-	m_passes.create(getAllocator(), m_r->getIs().getRtMipmapCount() - 1);
+	const U passCount = computeMaxMipmapCount2d(m_r->getWidth(), m_r->getHeight(), DOWNSCALE_BLUR_DOWN_TO) - 1;
+	m_passes.create(getAllocator(), passCount);
 
 
 	UVec2 size(m_r->getWidth(), m_r->getHeight());
 	UVec2 size(m_r->getWidth(), m_r->getHeight());
 	for(U i = 0; i < m_passes.getSize(); ++i)
 	for(U i = 0; i < m_passes.getSize(); ++i)
@@ -69,38 +78,54 @@ Error DownscaleBlur::initInternal(const ConfigSet&)
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+void DownscaleBlur::setPreRunBarriers(RenderingContext& ctx)
+{
+	ctx.m_commandBuffer->setTextureSurfaceBarrier(m_passes[0].m_rt,
+		TextureUsageBit::NONE,
+		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
+		TextureSurfaceInfo(0, 0, 0, 0));
+}
+
 void DownscaleBlur::run(RenderingContext& ctx)
 void DownscaleBlur::run(RenderingContext& ctx)
 {
 {
 	CommandBufferPtr cmdb = ctx.m_commandBuffer;
 	CommandBufferPtr cmdb = ctx.m_commandBuffer;
 
 
 	cmdb->bindTexture(0, 0, m_r->getIs().getRt());
 	cmdb->bindTexture(0, 0, m_r->getIs().getRt());
 
 
-	UVec2 size(m_r->getWidth(), m_r->getHeight());
 	for(U i = 0; i < m_passes.getSize(); ++i)
 	for(U i = 0; i < m_passes.getSize(); ++i)
 	{
 	{
-		size /= 2;
 		Subpass& pass = m_passes[i];
 		Subpass& pass = m_passes[i];
 
 
-		if(i > 0)
+		if(i > 0u)
 		{
 		{
-			cmdb->setTextureSurfaceBarrier(m_r->getIs().getRt(),
+			cmdb->setTextureSurfaceBarrier(m_passes[i - 1].m_rt,
 				TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 				TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 				TextureUsageBit::SAMPLED_FRAGMENT,
 				TextureUsageBit::SAMPLED_FRAGMENT,
-				TextureSurfaceInfo(i, 0, 0, 0));
-		}
+				TextureSurfaceInfo(0, 0, 0, 0));
 
 
-		cmdb->setTextureSurfaceBarrier(m_r->getIs().getRt(),
-			TextureUsageBit::NONE,
-			TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			TextureSurfaceInfo(i + 1, 0, 0, 0));
+			cmdb->setTextureSurfaceBarrier(pass.m_rt,
+				TextureUsageBit::NONE,
+				TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
+				TextureSurfaceInfo(0, 0, 0, 0));
 
 
-		cmdb->beginRenderPass(pass.m_fb);
-		cmdb->setViewport(0, 0, size.x(), size.y());
+			cmdb->bindTexture(0, 0, m_passes[i - 1].m_rt);
+		}
+
+		cmdb->setViewport(0, 0, pass.m_width, pass.m_height);
 		cmdb->bindShaderProgram(pass.m_prog);
 		cmdb->bindShaderProgram(pass.m_prog);
 
 
+		cmdb->beginRenderPass(pass.m_fb);
 		m_r->drawQuad(cmdb);
 		m_r->drawQuad(cmdb);
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();
 	}
 	}
 }
 }
 
 
+void DownscaleBlur::setPostRunBarriers(RenderingContext& ctx)
+{
+	ctx.m_commandBuffer->setTextureSurfaceBarrier(m_passes.getBack().m_rt,
+		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
+		TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::SAMPLED_FRAGMENT,
+		TextureSurfaceInfo(0, 0, 0, 0));
+}
+
 } // end namespace anki
 } // end namespace anki

+ 19 - 0
src/anki/renderer/DownscaleBlur.h

@@ -26,7 +26,24 @@ anki_internal:
 
 
 	ANKI_USE_RESULT Error init(const ConfigSet& cfg);
 	ANKI_USE_RESULT Error init(const ConfigSet& cfg);
 
 
+	void setPreRunBarriers(RenderingContext& ctx);
 	void run(RenderingContext& ctx);
 	void run(RenderingContext& ctx);
+	void setPostRunBarriers(RenderingContext& ctx);
+
+	U getSmallPassWidth() const
+	{
+		return m_passes.getBack().m_width;
+	}
+
+	U getSmallPassHeight() const
+	{
+		return m_passes.getBack().m_height;
+	}
+
+	TexturePtr getSmallPassTexture() const
+	{
+		return m_passes.getBack().m_rt;
+	}
 
 
 private:
 private:
 	class Subpass
 	class Subpass
@@ -34,7 +51,9 @@ private:
 	public:
 	public:
 		ShaderResourcePtr m_frag;
 		ShaderResourcePtr m_frag;
 		ShaderProgramPtr m_prog;
 		ShaderProgramPtr m_prog;
+		TexturePtr m_rt;
 		FramebufferPtr m_fb;
 		FramebufferPtr m_fb;
+		U32 m_width, m_height;
 	};
 	};
 
 
 	DynamicArray<Subpass> m_passes;
 	DynamicArray<Subpass> m_passes;

+ 2 - 7
src/anki/renderer/Is.cpp

@@ -76,9 +76,6 @@ Error Is::initInternal(const ConfigSet& config)
 		return ErrorCode::USER_DATA;
 		return ErrorCode::USER_DATA;
 	}
 	}
 
 
-	m_rtMipCount = computeMaxMipmapCount2d(m_r->getWidth(), m_r->getHeight(), 32);
-	ANKI_ASSERT(m_rtMipCount);
-
 	m_clusterCounts[0] = config.getNumber("clusterSizeX");
 	m_clusterCounts[0] = config.getNumber("clusterSizeX");
 	m_clusterCounts[1] = config.getNumber("clusterSizeY");
 	m_clusterCounts[1] = config.getNumber("clusterSizeY");
 	m_clusterCounts[2] = config.getNumber("clusterSizeZ");
 	m_clusterCounts[2] = config.getNumber("clusterSizeZ");
@@ -128,10 +125,8 @@ Error Is::initInternal(const ConfigSet& config)
 	m_rt = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(m_r->getWidth(),
 	m_rt = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(m_r->getWidth(),
 		m_r->getHeight(),
 		m_r->getHeight(),
 		IS_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		IS_COLOR_ATTACHMENT_PIXEL_FORMAT,
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE
-			| TextureUsageBit::SAMPLED_COMPUTE,
-		SamplingFilter::LINEAR,
-		m_rtMipCount));
+		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
+		SamplingFilter::LINEAR));
 
 
 	FramebufferInitInfo fbInit;
 	FramebufferInitInfo fbInit;
 	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachmentCount = 1;

+ 0 - 7
src/anki/renderer/Is.h

@@ -41,12 +41,6 @@ anki_internal:
 		return m_rt;
 		return m_rt;
 	}
 	}
 
 
-	/// Get the number of mips for IS's render target.
-	U getRtMipmapCount() const
-	{
-		return m_rtMipCount;
-	}
-
 	const LightBin& getLightBin() const
 	const LightBin& getLightBin() const
 	{
 	{
 		return *m_lightBin;
 		return *m_lightBin;
@@ -55,7 +49,6 @@ anki_internal:
 private:
 private:
 	/// The IS render target
 	/// The IS render target
 	TexturePtr m_rt;
 	TexturePtr m_rt;
-	U8 m_rtMipCount = 0;
 
 
 	Array<U32, 3> m_clusterCounts = {{0, 0, 0}};
 	Array<U32, 3> m_clusterCounts = {{0, 0, 0}};
 	U32 m_clusterCount = 0;
 	U32 m_clusterCount = 0;

+ 8 - 11
src/anki/renderer/Renderer.cpp

@@ -109,6 +109,9 @@ Error Renderer::initInternal(const ConfigSet& config)
 		m_dummyTex = getGrManager().newInstance<Texture>(texinit);
 		m_dummyTex = getGrManager().newInstance<Texture>(texinit);
 	}
 	}
 
 
+	m_dummyBuff = getGrManager().newInstance<Buffer>(
+		getDummyBufferSize(), BufferUsageBit::UNIFORM_ALL | BufferUsageBit::STORAGE_ALL, BufferMapAccessBit::NONE);
+
 	// quad setup
 	// quad setup
 	ANKI_CHECK(m_resources->loadResource("shaders/Quad.vert.glsl", m_drawQuadVert));
 	ANKI_CHECK(m_resources->loadResource("shaders/Quad.vert.glsl", m_drawQuadVert));
 
 
@@ -143,12 +146,12 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_fsUpscale.reset(m_alloc.newInstance<FsUpscale>(this));
 	m_fsUpscale.reset(m_alloc.newInstance<FsUpscale>(this));
 	ANKI_CHECK(m_fsUpscale->init(config));
 	ANKI_CHECK(m_fsUpscale->init(config));
 
 
-	m_tm.reset(getAllocator().newInstance<Tm>(this));
-	ANKI_CHECK(m_tm->init(config));
-
 	m_downscale.reset(getAllocator().newInstance<DownscaleBlur>(this));
 	m_downscale.reset(getAllocator().newInstance<DownscaleBlur>(this));
 	ANKI_CHECK(m_downscale->init(config));
 	ANKI_CHECK(m_downscale->init(config));
 
 
+	m_tm.reset(getAllocator().newInstance<Tm>(this));
+	ANKI_CHECK(m_tm->init(config));
+
 	m_smaa.reset(getAllocator().newInstance<Smaa>(this));
 	m_smaa.reset(getAllocator().newInstance<Smaa>(this));
 	ANKI_CHECK(m_smaa->init(config));
 	ANKI_CHECK(m_smaa->init(config));
 
 
@@ -270,15 +273,13 @@ Error Renderer::render(RenderingContext& ctx)
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT,
 		TextureUsageBit::SAMPLED_FRAGMENT,
 		TextureSurfaceInfo(0, 0, 0, 0));
 		TextureSurfaceInfo(0, 0, 0, 0));
+	m_downscale->setPreRunBarriers(ctx);
 
 
 	// Passes
 	// Passes
 	m_downscale->run(ctx);
 	m_downscale->run(ctx);
 
 
 	// Barriers
 	// Barriers
-	cmdb->setTextureSurfaceBarrier(m_is->getRt(),
-		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-		TextureUsageBit::SAMPLED_COMPUTE,
-		TextureSurfaceInfo(m_is->getRtMipmapCount() - 1, 0, 0, 0));
+	m_downscale->setPostRunBarriers(ctx);
 	m_smaa->m_edge.setPreRunBarriers(ctx);
 	m_smaa->m_edge.setPreRunBarriers(ctx);
 
 
 	// Passes
 	// Passes
@@ -286,10 +287,6 @@ Error Renderer::render(RenderingContext& ctx)
 	m_smaa->m_edge.run(ctx);
 	m_smaa->m_edge.run(ctx);
 
 
 	// Barriers
 	// Barriers
-	cmdb->setTextureSurfaceBarrier(m_is->getRt(),
-		TextureUsageBit::SAMPLED_COMPUTE,
-		TextureUsageBit::SAMPLED_FRAGMENT,
-		TextureSurfaceInfo(m_is->getRtMipmapCount() - 1, 0, 0, 0));
 	m_smaa->m_edge.setPostRunBarriers(ctx);
 	m_smaa->m_edge.setPostRunBarriers(ctx);
 	m_bloom->m_extractExposure.setPreRunBarriers(ctx);
 	m_bloom->m_extractExposure.setPreRunBarriers(ctx);
 	m_smaa->m_weights.setPreRunBarriers(ctx);
 	m_smaa->m_weights.setPreRunBarriers(ctx);

+ 16 - 0
src/anki/renderer/Renderer.h

@@ -212,6 +212,11 @@ public:
 		return *m_smaa;
 		return *m_smaa;
 	}
 	}
 
 
+	DownscaleBlur& getDownscaleBlur()
+	{
+		return *m_downscale;
+	}
+
 	U32 getWidth() const
 	U32 getWidth() const
 	{
 	{
 		return m_width;
 		return m_width;
@@ -361,6 +366,16 @@ anki_internal:
 		return m_dummyTex;
 		return m_dummyTex;
 	}
 	}
 
 
+	BufferPtr getDummyBuffer() const
+	{
+		return m_dummyBuff;
+	}
+
+	static constexpr PtrSize getDummyBufferSize()
+	{
+		return 1024;
+	}
+
 private:
 private:
 	ThreadPool* m_threadpool = nullptr;
 	ThreadPool* m_threadpool = nullptr;
 	ResourceManager* m_resources = nullptr;
 	ResourceManager* m_resources = nullptr;
@@ -412,6 +427,7 @@ private:
 	Mat4 m_prevCamTransform = Mat4::getIdentity();
 	Mat4 m_prevCamTransform = Mat4::getIdentity();
 
 
 	TexturePtr m_dummyTex;
 	TexturePtr m_dummyTex;
+	BufferPtr m_dummyBuff;
 
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 
 

+ 24 - 0
src/anki/renderer/RenderingPass.cpp

@@ -40,4 +40,28 @@ void* RenderingPass::allocateFrameStagingMemory(PtrSize size, StagingGpuMemoryTy
 	return m_r->getStagingGpuMemoryManager().allocateFrame(size, usage, token);
 	return m_r->getStagingGpuMemoryManager().allocateFrame(size, usage, token);
 }
 }
 
 
+void RenderingPass::bindUniforms(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token) const
+{
+	if(token && !token.isUnused())
+	{
+		cmdb->bindUniformBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
+	}
+	else
+	{
+		cmdb->bindUniformBuffer(set, binding, m_r->getDummyBuffer(), 0, m_r->getDummyBufferSize());
+	}
+}
+
+void RenderingPass::bindStorage(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token) const
+{
+	if(token && !token.isUnused())
+	{
+		cmdb->bindStorageBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
+	}
+	else
+	{
+		cmdb->bindStorageBuffer(set, binding, m_r->getDummyBuffer(), 0, m_r->getDummyBufferSize());
+	}
+}
+
 } // end namespace anki
 } // end namespace anki

+ 2 - 14
src/anki/renderer/RenderingPass.h

@@ -46,13 +46,7 @@ anki_internal:
 		return static_cast<TPtr>(allocateFrameStagingMemory(size, StagingGpuMemoryType::UNIFORM, token));
 		return static_cast<TPtr>(allocateFrameStagingMemory(size, StagingGpuMemoryType::UNIFORM, token));
 	}
 	}
 
 
-	static void bindUniforms(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token)
-	{
-		if(token && !token.isUnused())
-		{
-			cmdb->bindUniformBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
-		}
-	}
+	void bindUniforms(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token) const;
 
 
 	template<typename TPtr>
 	template<typename TPtr>
 	TPtr allocateAndBindUniforms(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
 	TPtr allocateAndBindUniforms(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
@@ -69,13 +63,7 @@ anki_internal:
 		return static_cast<TPtr>(allocateFrameStagingMemory(size, StagingGpuMemoryType::STORAGE, token));
 		return static_cast<TPtr>(allocateFrameStagingMemory(size, StagingGpuMemoryType::STORAGE, token));
 	}
 	}
 
 
-	static void bindStorage(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token)
-	{
-		if(token && !token.isUnused())
-		{
-			cmdb->bindStorageBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
-		}
-	}
+	void bindStorage(CommandBufferPtr& cmdb, U set, U binding, const StagingGpuMemoryToken& token) const;
 
 
 protected:
 protected:
 	Renderer* m_r; ///< Know your father
 	Renderer* m_r; ///< Know your father

+ 5 - 10
src/anki/renderer/Tm.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/renderer/Tm.h>
 #include <anki/renderer/Tm.h>
-#include <anki/renderer/Is.h>
+#include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 
 
 namespace anki
 namespace anki
@@ -25,16 +25,11 @@ Error Tm::init(const ConfigSet& cfg)
 Error Tm::initInternal(const ConfigSet& initializer)
 Error Tm::initInternal(const ConfigSet& initializer)
 {
 {
 	// Create shader
 	// Create shader
-	ANKI_ASSERT(m_r->getIs().getRtMipmapCount() > 1);
-
 	ANKI_CHECK(m_r->createShaderf("shaders/TmAverageLuminance.comp.glsl",
 	ANKI_CHECK(m_r->createShaderf("shaders/TmAverageLuminance.comp.glsl",
 		m_luminanceShader,
 		m_luminanceShader,
-		"#define IS_RT_MIPMAP %u\n"
-		"#define ANKI_RENDERER_WIDTH %u\n"
-		"#define ANKI_RENDERER_HEIGHT %u\n",
-		m_r->getIs().getRtMipmapCount() - 1,
-		m_r->getWidth(),
-		m_r->getHeight()));
+		"#define INPUT_TEX_SIZE uvec2(%uu, %uu)\n",
+		m_r->getDownscaleBlur().getSmallPassWidth(),
+		m_r->getDownscaleBlur().getSmallPassHeight()));
 
 
 	// Create prog
 	// Create prog
 	m_prog = getGrManager().newInstance<ShaderProgram>(m_luminanceShader->getGrShader());
 	m_prog = getGrManager().newInstance<ShaderProgram>(m_luminanceShader->getGrShader());
@@ -62,7 +57,7 @@ void Tm::run(RenderingContext& ctx)
 	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 	cmdb->bindShaderProgram(m_prog);
 	cmdb->bindShaderProgram(m_prog);
 	cmdb->bindStorageBuffer(0, 0, m_luminanceBuff, 0, MAX_PTR_SIZE);
 	cmdb->bindStorageBuffer(0, 0, m_luminanceBuff, 0, MAX_PTR_SIZE);
-	cmdb->bindTexture(0, 0, m_r->getIs().getRt());
+	cmdb->bindTexture(0, 0, m_r->getDownscaleBlur().getSmallPassTexture());
 
 
 	cmdb->dispatchCompute(1, 1, 1);
 	cmdb->dispatchCompute(1, 1, 1);
 }
 }