Browse Source

Moving Bloom shader to HLSL

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
42914c7405

+ 1 - 1
AnKi/Renderer/Bloom.cpp

@@ -205,7 +205,7 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 			{
 				rgraphCtx.bindImage(0, 3, m_runCtx.m_upscaleRt, TextureSubresourceInfo());
 
-				dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_upscale.m_width, m_upscale.m_height);
+				dispatchPPCompute(cmdb, 8, 8, m_upscale.m_width, m_upscale.m_height);
 			}
 			else
 			{

+ 0 - 2
AnKi/Renderer/Bloom.h

@@ -43,8 +43,6 @@ public:
 private:
 	static constexpr Format kRtPixelFormat = Format::kA2B10G10R10_Unorm_Pack32;
 
-	const Array<U32, 2> m_workgroupSize = {16, 16};
-
 	FramebufferDescription m_fbDescr;
 
 	class

+ 0 - 118
AnKi/Shaders/BloomUpscale.glsl

@@ -1,118 +0,0 @@
-// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Shaders/Functions.glsl>
-
-ANKI_SPECIALIZATION_CONSTANT_UVEC2(kViewport, 0u);
-ANKI_SPECIALIZATION_CONSTANT_UVEC2(kInputTextureSize, 2u);
-
-layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
-layout(set = 0, binding = 1) uniform ANKI_RP texture2D u_tex;
-layout(set = 0, binding = 2) uniform ANKI_RP texture2D u_lensDirtTex;
-
-#if defined(ANKI_COMPUTE_SHADER)
-const UVec2 kWorkgroupSize = UVec2(16u, 16u);
-layout(local_size_x = kWorkgroupSize.x, local_size_y = kWorkgroupSize.y, local_size_z = 1) in;
-
-layout(set = 0, binding = 3) writeonly uniform ANKI_RP image2D u_outImg;
-#else
-layout(location = 0) in Vec2 in_uv;
-layout(location = 0) out ANKI_RP Vec3 out_color;
-#endif
-
-// Constants
-const U32 kMaxGhosts = 4u;
-const F32 kGhostDispersal = 0.7;
-const F32 kHaloWidth = 0.4;
-const F32 kChromaticDistortion = 3.0;
-#define ENABLE_CHROMATIC_DISTORTION 1
-#define ENABLE_HALO 1
-const F32 kHaloOpacity = 0.5;
-
-ANKI_RP Vec3 textureDistorted(ANKI_RP texture2D tex, sampler sampl, Vec2 uv,
-							  Vec2 direction, // direction of distortion
-							  Vec3 distortion) // per-channel distortion factor
-{
-#if ENABLE_CHROMATIC_DISTORTION
-	return Vec3(textureLod(tex, sampl, uv + direction * distortion.r, 0.0).r,
-				textureLod(tex, sampl, uv + direction * distortion.g, 0.0).g,
-				textureLod(tex, sampl, uv + direction * distortion.b, 0.0).b);
-#else
-	return textureLod(tex, uv, 0.0).rgb;
-#endif
-}
-
-ANKI_RP Vec3 ssLensFlare(Vec2 uv)
-{
-	const Vec2 kTexelSize = 1.0 / Vec2(kInputTextureSize);
-	const Vec3 kDistortion = Vec3(-kTexelSize.x * kChromaticDistortion, 0.0, kTexelSize.x * kChromaticDistortion);
-	const F32 kLensOfHalf = length(Vec2(0.5));
-
-	const Vec2 flipUv = Vec2(1.0) - uv;
-
-	const Vec2 ghostVec = (Vec2(0.5) - flipUv) * kGhostDispersal;
-
-	const Vec2 direction = normalize(ghostVec);
-	ANKI_RP Vec3 result = Vec3(0.0);
-
-	// Sample ghosts
-	[[unroll]] for(U32 i = 0u; i < kMaxGhosts; ++i)
-	{
-		const Vec2 offset = fract(flipUv + ghostVec * F32(i));
-
-		ANKI_RP F32 weight = length(Vec2(0.5) - offset) / kLensOfHalf;
-		weight = pow(1.0 - weight, 10.0);
-
-		result += textureDistorted(u_tex, u_linearAnyClampSampler, offset, direction, kDistortion) * weight;
-	}
-
-	// Sample halo
-#if ENABLE_HALO
-	const Vec2 haloVec = normalize(ghostVec) * kHaloWidth;
-	ANKI_RP F32 weight = length(Vec2(0.5) - fract(flipUv + haloVec)) / kLensOfHalf;
-	weight = pow(1.0 - weight, 20.0);
-	result += textureDistorted(u_tex, u_linearAnyClampSampler, flipUv + haloVec, direction, kDistortion)
-			  * (weight * kHaloOpacity);
-#endif
-
-	// Lens dirt
-	result *= textureLod(u_lensDirtTex, u_linearAnyClampSampler, uv, 0.0).rgb;
-
-	return result;
-}
-
-ANKI_RP Vec3 upscale(Vec2 uv)
-{
-	const ANKI_RP F32 weight = 1.0 / 5.0;
-	ANKI_RP Vec3 result = textureLod(u_tex, u_linearAnyClampSampler, uv, 0.0).rgb * weight;
-	result += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, ivec2(+1, +1)).rgb * weight;
-	result += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, ivec2(+1, -1)).rgb * weight;
-	result += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, ivec2(-1, -1)).rgb * weight;
-	result += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, ivec2(-1, +1)).rgb * weight;
-
-	return result;
-}
-
-void main()
-{
-#if defined(ANKI_COMPUTE_SHADER)
-	if(skipOutOfBoundsInvocations(kWorkgroupSize, kViewport))
-	{
-		return;
-	}
-
-	const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(kViewport);
-#else
-	const Vec2 uv = in_uv;
-#endif
-
-	const ANKI_RP Vec3 outColor = ssLensFlare(uv) + upscale(uv);
-
-#if defined(ANKI_COMPUTE_SHADER)
-	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
-#else
-	out_color = outColor;
-#endif
-}

+ 136 - 0
AnKi/Shaders/BloomUpscale.hlsl

@@ -0,0 +1,136 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Shaders/Functions.hlsl>
+
+ANKI_SPECIALIZATION_CONSTANT_UVEC2(kViewport, 0u);
+ANKI_SPECIALIZATION_CONSTANT_UVEC2(kInputTextureSize, 2u);
+
+// Constants
+#define ENABLE_CHROMATIC_DISTORTION 1
+#define ENABLE_HALO 1
+constexpr U32 kMaxGhosts = 4u;
+constexpr F32 kGhostDispersal = 0.7;
+constexpr F32 kHaloWidth = 0.4;
+constexpr F32 kChromaticDistortion = 3.0;
+constexpr F32 kHaloOpacity = 0.5;
+
+[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
+[[vk::binding(1)]] Texture2D<RVec4> g_inputTex;
+[[vk::binding(2)]] Texture2D<RVec3> g_lensDirtTex;
+
+struct CompIn
+{
+	UVec3 m_svDispatchThreadId : SV_DISPATCHTHREADID;
+};
+
+struct VertOut
+{
+	Vec4 m_position : SV_POSITION;
+	[[vk::location(0)]] Vec2 m_uv : TEXCOORD;
+};
+
+struct FragOut
+{
+	RVec3 m_svTarget : SV_TARGET0;
+};
+
+#if defined(ANKI_COMPUTE_SHADER)
+#	define THREADGROUP_SIZE_XY 8
+[[vk::binding(3)]] RWTexture2D<RVec4> g_outUav;
+#endif
+
+RVec3 textureDistorted(Texture2D<RVec4> tex, SamplerState sampl, Vec2 uv,
+					   Vec2 direction, // direction of distortion
+					   Vec3 distortion) // per-channel distortion factor
+{
+#if ENABLE_CHROMATIC_DISTORTION
+	return RVec3(tex.SampleLevel(sampl, uv + direction * distortion.r, 0.0).r,
+				 tex.SampleLevel(sampl, uv + direction * distortion.g, 0.0).g,
+				 tex.SampleLevel(sampl, uv + direction * distortion.b, 0.0).b);
+#else
+	return tex.SampleLevel(uv, 0.0).rgb;
+#endif
+}
+
+RVec3 ssLensFlare(Vec2 uv)
+{
+	constexpr Vec2 kTexelSize = 1.0 / Vec2(kInputTextureSize);
+	constexpr Vec3 kDistortion = Vec3(-kTexelSize.x * kChromaticDistortion, 0.0, kTexelSize.x * kChromaticDistortion);
+	constexpr F32 kLensOfHalf = length(Vec2(0.5, 0.5));
+
+	const Vec2 flipUv = Vec2(1.0, 1.0) - uv;
+
+	const Vec2 ghostVec = (Vec2(0.5, 0.5) - flipUv) * kGhostDispersal;
+
+	const Vec2 direction = normalize(ghostVec);
+	RVec3 result = Vec3(0.0, 0.0, 0.0);
+
+	// Sample ghosts
+	[[unroll]] for(U32 i = 0u; i < kMaxGhosts; ++i)
+	{
+		const Vec2 offset = frac(flipUv + ghostVec * F32(i));
+
+		RF32 weight = length(Vec2(0.5, 0.5) - offset) / kLensOfHalf;
+		weight = pow(1.0 - weight, 10.0);
+
+		result += textureDistorted(g_inputTex, g_linearAnyClampSampler, offset, direction, kDistortion) * weight;
+	}
+
+	// Sample halo
+#if ENABLE_HALO
+	const Vec2 haloVec = normalize(ghostVec) * kHaloWidth;
+	RF32 weight = length(Vec2(0.5, 0.5) - frac(flipUv + haloVec)) / kLensOfHalf;
+	weight = pow(1.0 - weight, 20.0);
+	result += textureDistorted(g_inputTex, g_linearAnyClampSampler, flipUv + haloVec, direction, kDistortion)
+			  * (weight * kHaloOpacity);
+#endif
+
+	// Lens dirt
+	result *= g_lensDirtTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb;
+
+	return result;
+}
+
+RVec3 upscale(Vec2 uv)
+{
+	const RF32 weight = 1.0 / 5.0;
+	RVec3 result = g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
+
+	return result;
+}
+
+#if defined(ANKI_COMPUTE_SHADER)
+ANKI_NUMTHREADS(THREADGROUP_SIZE_XY, THREADGROUP_SIZE_XY, 1) void main(CompIn input)
+#else
+FragOut main(VertOut input)
+#endif
+{
+#if defined(ANKI_COMPUTE_SHADER)
+	if(skipOutOfBoundsInvocations(UVec2(THREADGROUP_SIZE_XY, THREADGROUP_SIZE_XY), kViewport,
+								  input.m_svDispatchThreadId))
+	{
+		return;
+	}
+
+	const Vec2 uv = (Vec2(input.m_svDispatchThreadId.xy) + 0.5) / Vec2(kViewport);
+#else
+	const Vec2 uv = input.m_uv;
+#endif
+
+	const RVec3 outColor = ssLensFlare(uv) + upscale(uv);
+
+#if defined(ANKI_COMPUTE_SHADER)
+	g_outUav[input.m_svDispatchThreadId.xy] = RVec4(outColor, 0.0);
+#else
+	FragOut output;
+	output.m_svTarget = outColor;
+	return output;
+#endif
+}

+ 3 - 1
AnKi/Shaders/BloomUpscaleCompute.ankiprog

@@ -3,6 +3,8 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
+
 #pragma anki start comp
-#include <AnKi/Shaders/BloomUpscale.glsl>
+#include <AnKi/Shaders/BloomUpscale.hlsl>
 #pragma anki end

+ 4 - 2
AnKi/Shaders/BloomUpscaleRaster.ankiprog

@@ -3,10 +3,12 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
+
 #pragma anki start vert
-#include <AnKi/Shaders/QuadVert.glsl>
+#include <AnKi/Shaders/QuadVert.hlsl>
 #pragma anki end
 
 #pragma anki start frag
-#include <AnKi/Shaders/BloomUpscale.glsl>
+#include <AnKi/Shaders/BloomUpscale.hlsl>
 #pragma anki end