Browse Source

Move more passes to compute

Panagiotis Christopoulos Charitos 7 năm trước cách đây
mục cha
commit
7fd289b380

+ 22 - 16
shaders/Bloom.glslp

@@ -3,16 +3,15 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki input const Vec2 TEX_SIZE
+#pragma anki input const UVec2 FB_SIZE
+#pragma anki input const UVec2 WORKGROUP_SIZE
 
-#pragma anki start vert
-#include <shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
+#pragma anki start comp
 #include <shaders/Common.glsl>
 #include <shaders/Tonemapping.glsl>
 
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
 // Vars
 layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex; ///< Its the IS RT
 
@@ -26,23 +25,30 @@ layout(ANKI_SS_BINDING(0, 0), std140) readonly buffer ss0_
 	Vec4 u_averageLuminancePad3;
 };
 
-layout(location = 0) in Vec2 in_uv;
-layout(location = 0) out Vec4 out_color;
+layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D out_img;
 
 void main()
 {
-	const Vec2 TEXEL_SIZE = 1.0 / TEX_SIZE;
+	if((FB_SIZE.x % WORKGROUP_SIZE.x) != 0u || (FB_SIZE.y % WORKGROUP_SIZE.y) != 0u) // This check is free
+	{
+		if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
+		{
+			return;
+		}
+	}
+
+	Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
 
-	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;
+	Vec3 color = textureLod(u_tex, uv, 0.0).rgb;
+	color += textureLodOffset(u_tex, uv, 0.0, ivec2(+1, +1)).rgb;
+	color += textureLodOffset(u_tex, uv, 0.0, ivec2(-1, -1)).rgb;
+	color += textureLodOffset(u_tex, uv, 0.0, ivec2(-1, +1)).rgb;
+	color += textureLodOffset(u_tex, uv, 0.0, ivec2(+1, -1)).rgb;
 
-	color /= 5.0;
+	color *= (1.0 / 5.0);
 
 	color = tonemap(color, u_averageLuminancePad3.x, u_thresholdScalePad2.x) * u_thresholdScalePad2.y;
 
-	out_color = Vec4(color, 0.25);
+	imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(color, 0.0));
 }
 #pragma anki end

+ 92 - 17
shaders/BloomUpscale.glslp

@@ -3,31 +3,106 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki input const Vec2 TEX_SIZE
+#pragma anki input const UVec2 INPUT_TEX_SIZE
+#pragma anki input const UVec2 WORKGROUP_SIZE
+#pragma anki input const UVec2 FB_SIZE
 
-#pragma anki start vert
-#include <shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
+#pragma anki start comp
 #include <shaders/Common.glsl>
 
-layout(ANKI_TEX_BINDING(0, 0)) uniform mediump sampler2D u_tex;
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex;
+layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_lensDirtTex;
+
+layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D out_img;
+
+// Constants
+const U32 MAX_GHOSTS = 4u;
+const F32 GHOST_DISPERSAL = 0.7;
+const F32 HALO_WIDTH = 0.4;
+const F32 CHROMATIC_DISTORTION = 3.0;
+#define ENABLE_CHROMATIC_DISTORTION 1
+#define ENABLE_HALO 1
+const F32 HALO_OPACITY = 0.5;
+
+Vec3 textureDistorted(sampler2D tex,
+	Vec2 uv,
+	Vec2 direction, // direction of DISTORTION
+	Vec3 DISTORTION) // per-channel DISTORTION factor
+{
+#if ENABLE_CHROMATIC_DISTORTION
+	return Vec3(textureLod(tex, uv + direction * DISTORTION.r, 0.0).r,
+		textureLod(tex, uv + direction * DISTORTION.g, 0.0).g,
+		textureLod(tex, uv + direction * DISTORTION.b, 0.0).b);
+#else
+	return textureLod(tex, uv, 0.0).rgb;
+#endif
+}
+
+Vec3 ssLensFlare(Vec2 uv)
+{
+	const Vec2 TEXEL_SIZE = 1.0 / Vec2(INPUT_TEX_SIZE);
+	const Vec3 DISTORTION = Vec3(-TEXEL_SIZE.x * CHROMATIC_DISTORTION, 0.0, TEXEL_SIZE.x * CHROMATIC_DISTORTION);
+	const F32 LEN_OF_HALF = length(Vec2(0.5));
+
+	Vec2 flipUv = Vec2(1.0) - uv;
+
+	Vec2 ghostVec = (Vec2(0.5) - flipUv) * GHOST_DISPERSAL;
 
-layout(location = 0) in Vec2 in_texCoord;
-layout(location = 0) out Vec3 out_color;
+	Vec2 direction = normalize(ghostVec);
+	Vec3 result = Vec3(0.0);
+
+	// sample ghosts:
+	ANKI_UNROLL for(U32 i = 0u; i < MAX_GHOSTS; ++i)
+	{
+		Vec2 offset = fract(flipUv + ghostVec * F32(i));
+
+		F32 weight = length(Vec2(0.5) - offset) / LEN_OF_HALF;
+		weight = pow(1.0 - weight, 10.0);
+
+		result += textureDistorted(u_tex, offset, direction, DISTORTION) * weight;
+	}
+
+	// Sample halo
+#if ENABLE_HALO
+	Vec2 haloVec = normalize(ghostVec) * HALO_WIDTH;
+	F32 weight = length(Vec2(0.5) - fract(flipUv + haloVec)) / LEN_OF_HALF;
+	weight = pow(1.0 - weight, 20.0);
+	result += textureDistorted(u_tex, flipUv + haloVec, direction, DISTORTION) * (weight * HALO_OPACITY);
+#endif
+
+	// Lens dirt
+	result *= textureLod(u_lensDirtTex, uv, 0.0).rgb;
+
+	return result;
+}
+
+Vec3 upscale(Vec2 uv)
+{
+	Vec3 result = textureLod(u_tex, uv, 0.0).rgb;
+	result += textureLodOffset(u_tex, uv, 0.0, ivec2(+1, +1)).rgb;
+	result += textureLodOffset(u_tex, uv, 0.0, ivec2(+1, -1)).rgb;
+	result += textureLodOffset(u_tex, uv, 0.0, ivec2(-1, -1)).rgb;
+	result += textureLodOffset(u_tex, uv, 0.0, ivec2(-1, +1)).rgb;
+
+	result *= (1.0 / 5.0);
+	return result;
+}
 
 void main()
 {
-	const Vec2 TEXEL_SIZE = 1.0 / TEX_SIZE;
-	const F32 MIPMAP = 0.0;
+	if((FB_SIZE.x % WORKGROUP_SIZE.x) != 0u || (FB_SIZE.y % WORKGROUP_SIZE.y) != 0u) // This check is free
+	{
+		if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
+		{
+			return;
+		}
+	}
 
-	out_color = textureLod(u_tex, in_texCoord, MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_texCoord + TEXEL_SIZE, MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_texCoord - TEXEL_SIZE, MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_texCoord + Vec2(TEXEL_SIZE.x, -TEXEL_SIZE.y), MIPMAP).rgb;
-	out_color += textureLod(u_tex, in_texCoord + Vec2(-TEXEL_SIZE.x, TEXEL_SIZE.y), MIPMAP).rgb;
+	Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
 
-	out_color /= 5.0;
+	Vec3 outColor = ssLensFlare(uv) + upscale(uv);
+	imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
 }
 #pragma anki end

+ 30 - 22
shaders/TemporalAAResolve.glslp

@@ -10,19 +10,15 @@
 
 #pragma anki input const F32 VARIANCE_CLIPPING_GAMMA
 #pragma anki input const F32 BLEND_FACTOR
+#pragma anki input const UVec2 FB_SIZE
+#pragma anki input const UVec2 WORKGROUP_SIZE
 
-#pragma anki start vert
-#include <shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
+#pragma anki start comp
 #include <shaders/Functions.glsl>
 #include <shaders/Pack.glsl>
 #include <shaders/Tonemapping.glsl>
 
-layout(location = 0) in Vec2 in_uv;
-
-layout(location = 0) out Vec3 out_color;
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
 
 layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_depthRt;
 layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_inputRt;
@@ -33,6 +29,8 @@ layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_
 	Mat4 u_prevViewProjMatMulInvViewProjMat;
 };
 
+layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D out_img;
+
 #if TONEMAP_FIX
 #	define TONEMAPPING_SET 0
 #	define TONEMAPPING_BINDING 1
@@ -47,13 +45,13 @@ layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_
 #	define sampleOffset(s, uv, x, y) textureLodOffset(s, uv, 0.0, IVec2(x, y)).rgb
 #endif
 
-Vec3 sharpen()
+Vec3 sharpen(Vec2 uv)
 {
-	Vec3 center = sample(u_inputRt, in_uv);
+	Vec3 center = sample(u_inputRt, uv);
 #if SHARPEN == 1
-	Vec3 near = sampleOffset(u_inputRt, in_uv, 1, 0) + sampleOffset(u_inputRt, in_uv, -1, 0);
+	Vec3 near = sampleOffset(u_inputRt, uv, 1, 0) + sampleOffset(u_inputRt, uv, -1, 0);
 #else
-	Vec3 near = sampleOffset(u_inputRt, in_uv, 0, 1) + sampleOffset(u_inputRt, in_uv, 0, -1);
+	Vec3 near = sampleOffset(u_inputRt, uv, 0, 1) + sampleOffset(u_inputRt, uv, 0, -1);
 #endif
 	near *= 0.5;
 	F32 sharpness = 1.0;
@@ -62,25 +60,34 @@ Vec3 sharpen()
 
 void main()
 {
-	F32 depth = textureLod(u_depthRt, in_uv, 0.0).r;
+	if((FB_SIZE.x % WORKGROUP_SIZE.x) != 0u || (FB_SIZE.y % WORKGROUP_SIZE.y) != 0u) // This check is free
+	{
+		if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
+		{
+			return;
+		}
+	}
+
+	Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
+	F32 depth = textureLod(u_depthRt, uv, 0.0).r;
 
 	// Get prev uv coords
-	Vec4 v4 = u_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(in_uv), depth, 1.0);
+	Vec4 v4 = u_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
 	Vec2 oldUv = NDC_TO_UV(v4.xy / v4.w);
 
 	// Read textures
 	Vec3 historyCol = sample(u_historyRt, oldUv);
 #if SHARPEN > 0
-	Vec3 crntCol = sharpen();
+	Vec3 crntCol = sharpen(uv);
 #else
-	Vec3 crntCol = sample(u_inputRt, in_uv);
+	Vec3 crntCol = sample(u_inputRt, uv);
 #endif
 
 	// Remove ghosting by clamping the history color to neighbour's AABB
-	Vec3 near0 = sampleOffset(u_inputRt, in_uv, 1, 0);
-	Vec3 near1 = sampleOffset(u_inputRt, in_uv, 0, 1);
-	Vec3 near2 = sampleOffset(u_inputRt, in_uv, -1, 0);
-	Vec3 near3 = sampleOffset(u_inputRt, in_uv, 0, -1);
+	Vec3 near0 = sampleOffset(u_inputRt, uv, 1, 0);
+	Vec3 near1 = sampleOffset(u_inputRt, uv, 0, 1);
+	Vec3 near2 = sampleOffset(u_inputRt, uv, -1, 0);
+	Vec3 near3 = sampleOffset(u_inputRt, uv, 0, -1);
 
 #if VARIANCE_CLIPPING
 	Vec3 m1 = crntCol + near0 + near1 + near2 + near3;
@@ -121,10 +128,11 @@ void main()
 
 	// Write result
 #if YCBCR
-	out_color = yCbCrToRgb(mix(historyCol, crntCol, feedback));
+	Vec3 outColor = yCbCrToRgb(mix(historyCol, crntCol, feedback));
 #else
-	out_color = mix(historyCol, crntCol, feedback);
+	Vec3 outColor = mix(historyCol, crntCol, feedback);
 #endif
+	imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
 }
 
 #pragma anki end

+ 9 - 1
src/anki/gr/Enums.h

@@ -419,7 +419,15 @@ enum class TextureUsageBit : U16
 	/// @name Misc
 	/// @{
 	GENERATE_MIPMAPS = 1 << 11,
-	CLEAR = 1 << 12 ///< Will be used in CommandBuffer::clearImage.
+	CLEAR = 1 << 12, ///< Will be used in CommandBuffer::clearImage.
+	/// @}
+
+	/// @name Other
+	/// @{
+	ANY_COMPUTE = SAMPLED_COMPUTE | IMAGE_COMPUTE_READ_WRITE,
+	ANY_GRAPHICS = SAMPLED_ALL_GRAPHICS | FRAMEBUFFER_ATTACHMENT_READ_WRITE,
+	ANY_READ = SAMPLED_ALL | IMAGE_COMPUTE_READ | FRAMEBUFFER_ATTACHMENT_READ,
+	ANY_WRITE = IMAGE_COMPUTE_WRITE | FRAMEBUFFER_ATTACHMENT_WRITE | TRANSFER_DESTINATION | GENERATE_MIPMAPS | CLEAR,
 	/// @}
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureUsageBit, inline)

+ 2 - 0
src/anki/gr/RenderGraph.h

@@ -334,6 +334,8 @@ protected:
 	}
 
 	void fixSubresource(RenderPassDependency& dep) const;
+
+	void validateDep(const RenderPassDependency& dep);
 };
 
 /// Framebuffer attachment info.

+ 22 - 0
src/anki/gr/RenderGraph.inl.h

@@ -53,8 +53,28 @@ inline void RenderPassDescriptionBase::fixSubresource(RenderPassDependency& dep)
 	}
 }
 
+inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& dep)
+{
+	// Validate dep
+	if(dep.m_isTexture)
+	{
+		TextureUsageBit usage = dep.m_texture.m_usage;
+		(void)usage;
+		if(m_type == Type::GRAPHICS)
+		{
+			ANKI_ASSERT(!(usage & TextureUsageBit::ANY_COMPUTE));
+		}
+		else
+		{
+			ANKI_ASSERT(!(usage & TextureUsageBit::ANY_GRAPHICS));
+		}
+	}
+}
+
 inline void RenderPassDescriptionBase::newConsumer(const RenderPassDependency& dep)
 {
+	validateDep(dep);
+
 	DynamicArray<RenderPassDependency>& consumers = (dep.m_isTexture) ? m_rtConsumers : m_buffConsumers;
 
 	consumers.emplaceBack(m_alloc, dep);
@@ -76,6 +96,8 @@ inline void RenderPassDescriptionBase::newConsumer(const RenderPassDependency& d
 
 inline void RenderPassDescriptionBase::newProducer(const RenderPassDependency& dep)
 {
+	validateDep(dep);
+
 	DynamicArray<RenderPassDependency>& producers = (dep.m_isTexture) ? m_rtProducers : m_buffProducers;
 
 	producers.emplaceBack(m_alloc, dep);

+ 26 - 55
src/anki/renderer/Bloom.cpp

@@ -35,17 +35,12 @@ Error Bloom::initExposure(const ConfigSet& config)
 		m_r->create2DRenderTargetDescription(m_exposure.m_width, m_exposure.m_height, RT_PIXEL_FORMAT, "Bloom Exp");
 	m_exposure.m_rtDescr.bake();
 
-	// Create FB info
-	m_exposure.m_fbDescr.m_colorAttachmentCount = 1;
-	m_exposure.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
-	m_exposure.m_fbDescr.bake();
-
 	// init shaders
 	ANKI_CHECK(getResourceManager().loadResource("shaders/Bloom.glslp", m_exposure.m_prog));
 
-	ShaderProgramResourceConstantValueInitList<1> consts(m_exposure.m_prog);
-	consts.add(
-		"TEX_SIZE", Vec2(m_r->getDownscaleBlur().getPassWidth(MAX_U), m_r->getDownscaleBlur().getPassHeight(MAX_U)));
+	ShaderProgramResourceConstantValueInitList<2> consts(m_exposure.m_prog);
+	consts.add("FB_SIZE", UVec2(m_exposure.m_width, m_exposure.m_height))
+		.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
 
 	const ShaderProgramResourceVariant* variant;
 	m_exposure.m_prog->getOrCreateVariant(consts.get(), variant);
@@ -64,35 +59,20 @@ Error Bloom::initUpscale(const ConfigSet& config)
 		m_r->create2DRenderTargetDescription(m_upscale.m_width, m_upscale.m_height, RT_PIXEL_FORMAT, "Bloom Upscale");
 	m_upscale.m_rtDescr.bake();
 
-	// Create FB descr
-	m_upscale.m_fbDescr.m_colorAttachmentCount = 1;
-	m_upscale.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
-	m_upscale.m_fbDescr.bake();
-
 	// init shaders
 	ANKI_CHECK(getResourceManager().loadResource("shaders/BloomUpscale.glslp", m_upscale.m_prog));
 
-	ShaderProgramResourceConstantValueInitList<1> consts(m_upscale.m_prog);
-	consts.add("TEX_SIZE", Vec2(m_upscale.m_width, m_upscale.m_height));
+	ShaderProgramResourceConstantValueInitList<3> consts(m_upscale.m_prog);
+	consts.add("FB_SIZE", UVec2(m_upscale.m_width, m_upscale.m_height))
+		.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]))
+		.add("INPUT_TEX_SIZE", UVec2(m_exposure.m_width, m_exposure.m_height));
 
 	const ShaderProgramResourceVariant* variant;
 	m_upscale.m_prog->getOrCreateVariant(consts.get(), variant);
 	m_upscale.m_grProg = variant->getProgram();
 
-	return Error::NONE;
-}
-
-Error Bloom::initSslf(const ConfigSet& cfg)
-{
-	ANKI_CHECK(getResourceManager().loadResource("engine_data/LensDirt.ankitex", m_sslf.m_lensDirtTex));
-	ANKI_CHECK(getResourceManager().loadResource("shaders/ScreenSpaceLensFlare.glslp", m_sslf.m_prog));
-
-	ShaderProgramResourceConstantValueInitList<1> consts(m_sslf.m_prog);
-	consts.add("INPUT_TEX_SIZE", UVec2(m_exposure.m_width, m_exposure.m_height));
-
-	const ShaderProgramResourceVariant* variant;
-	m_sslf.m_prog->getOrCreateVariant(consts.get(), variant);
-	m_sslf.m_grProg = variant->getProgram();
+	// Textures
+	ANKI_CHECK(getResourceManager().loadResource("engine_data/LensDirt.ankitex", m_upscale.m_lensDirtTex));
 
 	return Error::NONE;
 }
@@ -107,16 +87,14 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 		m_runCtx.m_exposureRt = rgraph.newRenderTarget(m_exposure.m_rtDescr);
 
 		// Set the render pass
-		GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("Bloom Main");
+		ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("Bloom Main");
 		rpass.setWork(runExposureCallback, this, 0);
-		rpass.setFramebufferInfo(m_exposure.m_fbDescr, {{m_runCtx.m_exposureRt}}, {});
 
 		TextureSubresourceInfo inputTexSubresource;
 		inputTexSubresource.m_firstMipmap = m_r->getDownscaleBlur().getMipmapCount() - 1;
-		rpass.newConsumer({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_FRAGMENT, inputTexSubresource});
-		rpass.newConsumer({m_runCtx.m_exposureRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
-		rpass.newConsumer({m_r->getTonemapping().getAverageLuminanceBuffer(), BufferUsageBit::STORAGE_FRAGMENT_READ});
-		rpass.newProducer({m_runCtx.m_exposureRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		rpass.newConsumer({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_COMPUTE, inputTexSubresource});
+		rpass.newConsumer({m_r->getTonemapping().getAverageLuminanceBuffer(), BufferUsageBit::STORAGE_COMPUTE_READ});
+		rpass.newConsumerAndProducer({m_runCtx.m_exposureRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
 	}
 
 	// Upscale & SSLF pass
@@ -125,13 +103,11 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 		m_runCtx.m_upscaleRt = rgraph.newRenderTarget(m_upscale.m_rtDescr);
 
 		// Set the render pass
-		GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("Bloom Upscale");
+		ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("Bloom Upscale");
 		rpass.setWork(runUpscaleAndSslfCallback, this, 0);
-		rpass.setFramebufferInfo(m_upscale.m_fbDescr, {{m_runCtx.m_upscaleRt}}, {});
 
-		rpass.newConsumer({m_runCtx.m_upscaleRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
-		rpass.newConsumer({m_runCtx.m_exposureRt, TextureUsageBit::SAMPLED_FRAGMENT});
-		rpass.newProducer({m_runCtx.m_upscaleRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		rpass.newConsumerAndProducer({m_runCtx.m_upscaleRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+		rpass.newConsumer({m_runCtx.m_exposureRt, TextureUsageBit::SAMPLED_COMPUTE});
 	}
 }
 
@@ -139,7 +115,6 @@ void Bloom::runExposure(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	cmdb->setViewport(0, 0, m_exposure.m_width, m_exposure.m_height);
 	cmdb->bindShaderProgram(m_exposure.m_grProg);
 
 	TextureSubresourceInfo inputTexSubresource;
@@ -152,31 +127,27 @@ void Bloom::runExposure(RenderPassWorkContext& rgraphCtx)
 
 	rgraphCtx.bindStorageBuffer(0, 0, m_r->getTonemapping().getAverageLuminanceBuffer());
 
-	drawQuad(cmdb);
+	rgraphCtx.bindImage(0, 0, m_runCtx.m_exposureRt, TextureSubresourceInfo());
+
+	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_exposure.m_width, m_exposure.m_height);
 }
 
 void Bloom::runUpscaleAndSslf(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	// Upscale
-	cmdb->setViewport(0, 0, m_upscale.m_width, m_upscale.m_height);
 	cmdb->bindShaderProgram(m_upscale.m_grProg);
-	rgraphCtx.bindColorTextureAndSampler(0, 0, m_runCtx.m_exposureRt, m_r->getLinearSampler());
-	drawQuad(cmdb);
 
-	// SSLF
-	cmdb->bindShaderProgram(m_sslf.m_grProg);
-	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
+	rgraphCtx.bindColorTextureAndSampler(0, 0, m_runCtx.m_exposureRt, m_r->getLinearSampler());
 	cmdb->bindTextureAndSampler(0,
 		1,
-		m_sslf.m_lensDirtTex->getGrTextureView(),
-		m_sslf.m_lensDirtTex->getSampler(),
-		TextureUsageBit::SAMPLED_FRAGMENT);
-	drawQuad(cmdb);
+		m_upscale.m_lensDirtTex->getGrTextureView(),
+		m_upscale.m_lensDirtTex->getSampler(),
+		TextureUsageBit::SAMPLED_COMPUTE);
+
+	rgraphCtx.bindImage(0, 0, m_runCtx.m_upscaleRt, TextureSubresourceInfo());
 
-	// Retore state
-	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ZERO);
+	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_upscale.m_width, m_upscale.m_height);
 }
 
 } // end namespace anki

+ 3 - 12
src/anki/renderer/Bloom.h

@@ -45,6 +45,8 @@ anki_internal:
 private:
 	static const Format RT_PIXEL_FORMAT = Format::A2B10G10R10_UNORM_PACK32;
 
+	Array<U32, 2> m_workgroupSize = {{8, 8}};
+
 	class
 	{
 	public:
@@ -56,13 +58,13 @@ private:
 		U32 m_width = 0;
 		U32 m_height = 0;
 
-		FramebufferDescription m_fbDescr;
 		RenderTargetDescription m_rtDescr;
 	} m_exposure;
 
 	class
 	{
 	public:
+		TextureResourcePtr m_lensDirtTex;
 		ShaderProgramResourcePtr m_prog;
 		ShaderProgramPtr m_grProg;
 
@@ -70,17 +72,8 @@ private:
 		U32 m_height = 0;
 
 		RenderTargetDescription m_rtDescr;
-		FramebufferDescription m_fbDescr;
 	} m_upscale;
 
-	class
-	{
-	public:
-		ShaderProgramResourcePtr m_prog;
-		ShaderProgramPtr m_grProg;
-		TextureResourcePtr m_lensDirtTex;
-	} m_sslf;
-
 	class
 	{
 	public:
@@ -90,13 +83,11 @@ private:
 
 	ANKI_USE_RESULT Error initExposure(const ConfigSet& cfg);
 	ANKI_USE_RESULT Error initUpscale(const ConfigSet& cfg);
-	ANKI_USE_RESULT Error initSslf(const ConfigSet& cfg);
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& cfg)
 	{
 		ANKI_CHECK(initExposure(cfg));
 		ANKI_CHECK(initUpscale(cfg));
-		ANKI_CHECK(initSslf(cfg));
 		return Error::NONE;
 	}
 

+ 6 - 4
src/anki/renderer/Renderer.cpp

@@ -104,6 +104,8 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_dummyBuff = getGrManager().newBuffer(BufferInitInfo(
 		1024, BufferUsageBit::UNIFORM_ALL | BufferUsageBit::STORAGE_ALL, BufferMapAccessBit::NONE, "Dummy"));
 
+	ANKI_CHECK(m_resources->loadResource("shaders/ClearTextureCompute.glslp", m_clearTexComputeProg));
+
 	// Init the stages. Careful with the order!!!!!!!!!!
 	m_indirect.reset(m_alloc.newInstance<Indirect>(this));
 	ANKI_CHECK(m_indirect->init(config));
@@ -178,8 +180,6 @@ Error Renderer::initInternal(const ConfigSet& config)
 
 	initJitteredMats();
 
-	ANKI_CHECK(m_resources->loadResource("shaders/ClearTextureCompute.glslp", m_clearTexComputeProg));
-
 	return Error::NONE;
 }
 
@@ -335,7 +335,8 @@ Vec3 Renderer::unproject(
 
 TextureInitInfo Renderer::create2DRenderTargetInitInfo(U32 w, U32 h, Format format, TextureUsageBit usage, CString name)
 {
-	ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+	ANKI_ASSERT(
+		!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE) || !!(usage & TextureUsageBit::IMAGE_COMPUTE_WRITE));
 	TextureInitInfo init(name);
 
 	init.m_width = w;
@@ -370,7 +371,8 @@ RenderTargetDescription Renderer::create2DRenderTargetDescription(U32 w, U32 h,
 
 TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, const ClearValue& clearVal)
 {
-	ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+	ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE)
+				|| !!(inf.m_usage & TextureUsageBit::IMAGE_COMPUTE_WRITE));
 
 	const U faceCount = (inf.m_type == TextureType::CUBE || inf.m_type == TextureType::CUBE_ARRAY) ? 6 : 1;
 

+ 14 - 19
src/anki/renderer/TemporalAA.cpp

@@ -40,8 +40,11 @@ Error TemporalAA::initInternal(const ConfigSet& config)
 
 	for(U i = 0; i < 2; ++i)
 	{
-		ShaderProgramResourceConstantValueInitList<2> consts(m_prog);
-		consts.add("VARIANCE_CLIPPING_GAMMA", 1.7f).add("BLEND_FACTOR", 1.0f / 16.0f);
+		ShaderProgramResourceConstantValueInitList<4> consts(m_prog);
+		consts.add("VARIANCE_CLIPPING_GAMMA", 1.7f)
+			.add("BLEND_FACTOR", 1.0f / 16.0f)
+			.add("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()))
+			.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
 
 		ShaderProgramResourceMutationInitList<4> mutations(m_prog);
 		mutations.add("SHARPEN", i + 1).add("VARIANCE_CLIPPING", 1).add("TONEMAP_FIX", 1).add("YCBCR", 0);
@@ -56,15 +59,10 @@ Error TemporalAA::initInternal(const ConfigSet& config)
 		m_rtTextures[i] = m_r->createAndClearRenderTarget(m_r->create2DRenderTargetInitInfo(m_r->getWidth(),
 			m_r->getHeight(),
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
-			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
-				| TextureUsageBit::SAMPLED_COMPUTE,
+			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE,
 			"TemporalAA"));
 	}
 
-	m_fbDescr.m_colorAttachmentCount = 1;
-	m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
-	m_fbDescr.bake();
-
 	return Error::NONE;
 }
 
@@ -72,8 +70,6 @@ void TemporalAA::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphC
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
-
 	cmdb->bindShaderProgram(m_grProgs[m_r->getFrameCount() & 1]);
 	rgraphCtx.bindTextureAndSampler(0,
 		0,
@@ -88,7 +84,9 @@ void TemporalAA::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphC
 
 	rgraphCtx.bindUniformBuffer(0, 1, m_r->getTonemapping().getAverageLuminanceBuffer());
 
-	drawQuad(cmdb);
+	rgraphCtx.bindImage(0, 0, m_runCtx.m_renderRt, TextureSubresourceInfo());
+
+	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_r->getWidth(), m_r->getHeight());
 }
 
 void TemporalAA::populateRenderGraph(RenderingContext& ctx)
@@ -102,19 +100,16 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 	m_runCtx.m_renderRt = rgraph.importRenderTarget(m_rtTextures[m_r->getFrameCount() & 1], TextureUsageBit::NONE);
 
 	// Create pass
-	GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("TemporalAA");
+	ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("TemporalAA");
 
 	pass.setWork(runCallback, this, 0);
-	pass.setFramebufferInfo(m_fbDescr, {{m_runCtx.m_renderRt}}, {});
 
-	pass.newConsumer({m_runCtx.m_renderRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+	pass.newConsumerAndProducer({m_runCtx.m_renderRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
 	pass.newConsumer({m_r->getGBuffer().getDepthRt(),
-		TextureUsageBit::SAMPLED_FRAGMENT,
+		TextureUsageBit::SAMPLED_COMPUTE,
 		TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
-	pass.newConsumer({m_r->getLightShading().getRt(), TextureUsageBit::SAMPLED_FRAGMENT});
-	pass.newConsumer({m_runCtx.m_historyRt, TextureUsageBit::SAMPLED_FRAGMENT});
-
-	pass.newProducer({m_runCtx.m_renderRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+	pass.newConsumer({m_r->getLightShading().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
+	pass.newConsumer({m_runCtx.m_historyRt, TextureUsageBit::SAMPLED_COMPUTE});
 }
 
 } // end namespace anki

+ 2 - 1
src/anki/renderer/TemporalAA.h

@@ -32,11 +32,12 @@ public:
 
 private:
 	Array<TexturePtr, 2> m_rtTextures;
-	FramebufferDescription m_fbDescr;
 
 	ShaderProgramResourcePtr m_prog;
 	Array<ShaderProgramPtr, 2> m_grProgs;
 
+	Array<U32, 2> m_workgroupSize = {{8, 8}};
+
 	class
 	{
 	public:

+ 3 - 0
tools/scene/Exporter.h

@@ -12,9 +12,12 @@
 #include <fstream>
 #include <vector>
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
 #include <assimp/Importer.hpp>
 #include <assimp/scene.h>
 #include <assimp/postprocess.h>
+#pragma GCC diagnostic pop
 
 #include "Common.h"