Browse Source

Convert lens flare shaders to HLSL

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
c21acf20da

+ 1 - 68
AnKi/Gr/Common.h

@@ -9,6 +9,7 @@
 #include <AnKi/Util/Ptr.h>
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/Enum.h>
+#include <AnKi/Shaders/Include/Common.h>
 
 namespace anki {
 
@@ -783,74 +784,6 @@ enum class VrsRate : U8
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VrsRate)
 
-/// The draw indirect structure for index drawing, also the parameters of a regular drawcall
-class DrawElementsIndirectInfo
-{
-public:
-	U32 m_count = kMaxU32;
-	U32 m_instanceCount = 1;
-	U32 m_firstIndex = 0;
-	U32 m_baseVertex = 0;
-	U32 m_baseInstance = 0;
-
-	DrawElementsIndirectInfo() = default;
-
-	DrawElementsIndirectInfo(const DrawElementsIndirectInfo&) = default;
-
-	DrawElementsIndirectInfo(U32 count, U32 instanceCount, U32 firstIndex, U32 baseVertex, U32 baseInstance)
-		: m_count(count)
-		, m_instanceCount(instanceCount)
-		, m_firstIndex(firstIndex)
-		, m_baseVertex(baseVertex)
-		, m_baseInstance(baseInstance)
-	{
-	}
-
-	Bool operator==(const DrawElementsIndirectInfo& b) const
-	{
-		return m_count == b.m_count && m_instanceCount == b.m_instanceCount && m_firstIndex == b.m_firstIndex
-			   && m_baseVertex == b.m_baseVertex && m_baseInstance == b.m_baseInstance;
-	}
-
-	Bool operator!=(const DrawElementsIndirectInfo& b) const
-	{
-		return !(operator==(b));
-	}
-};
-
-/// The draw indirect structure for arrays drawing, also the parameters of a regular drawcall
-class DrawArraysIndirectInfo
-{
-public:
-	U32 m_count = kMaxU32;
-	U32 m_instanceCount = 1;
-	U32 m_first = 0;
-	U32 m_baseInstance = 0;
-
-	DrawArraysIndirectInfo() = default;
-
-	DrawArraysIndirectInfo(const DrawArraysIndirectInfo&) = default;
-
-	DrawArraysIndirectInfo(U32 count, U32 instanceCount, U32 first, U32 baseInstance)
-		: m_count(count)
-		, m_instanceCount(instanceCount)
-		, m_first(first)
-		, m_baseInstance(baseInstance)
-	{
-	}
-
-	Bool operator==(const DrawArraysIndirectInfo& b) const
-	{
-		return m_count == b.m_count && m_instanceCount == b.m_instanceCount && m_first == b.m_first
-			   && m_baseInstance == b.m_baseInstance;
-	}
-
-	Bool operator!=(const DrawArraysIndirectInfo& b) const
-	{
-		return !(operator==(b));
-	}
-};
-
 /// Clear values for textures or attachments.
 class ClearValue
 {

+ 2 - 2
AnKi/Gr/Vulkan/CommandBufferImpl.inl.h

@@ -134,7 +134,7 @@ inline void CommandBufferImpl::drawArraysIndirectInternal(PrimitiveTopology topo
 	ANKI_ASSERT((offset % 4) == 0);
 	ANKI_ASSERT((offset + sizeof(DrawArraysIndirectInfo) * drawCount) <= impl.getSize());
 
-	vkCmdDrawIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawArraysIndirectInfo));
+	vkCmdDrawIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawIndirectInfo));
 }
 
 inline void CommandBufferImpl::drawElementsIndirectInternal(PrimitiveTopology topology, U32 drawCount, PtrSize offset,
@@ -147,7 +147,7 @@ inline void CommandBufferImpl::drawElementsIndirectInternal(PrimitiveTopology to
 	ANKI_ASSERT((offset % 4) == 0);
 	ANKI_ASSERT((offset + sizeof(DrawElementsIndirectInfo) * drawCount) <= impl.getSize());
 
-	vkCmdDrawIndexedIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawElementsIndirectInfo));
+	vkCmdDrawIndexedIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawIndexedIndirectInfo));
 }
 
 inline void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 groupCountY, U32 groupCountZ)

+ 5 - 7
AnKi/Renderer/LensFlare.cpp

@@ -64,7 +64,7 @@ Error LensFlare::initOcclusion()
 {
 	GrManager& gr = *getExternalSubsystems().m_grManager;
 
-	m_indirectBuff = gr.newBuffer(BufferInitInfo(m_maxFlares * sizeof(DrawArraysIndirectInfo),
+	m_indirectBuff = gr.newBuffer(BufferInitInfo(m_maxFlares * sizeof(DrawIndirectInfo),
 												 BufferUsageBit::kIndirectDraw | BufferUsageBit::kStorageComputeWrite,
 												 BufferMapAccessBit::kNone, "LensFlares"));
 
@@ -89,11 +89,10 @@ void LensFlare::updateIndirectInfo(const RenderingContext& ctx, RenderPassWorkCo
 
 	cmdb->bindShaderProgram(m_updateIndirectBuffGrProg);
 
-	// Write flare info
-	Vec4* flarePositions = allocateAndBindStorage<Vec4*>(sizeof(Mat4) + count * sizeof(Vec4), cmdb, 0, 0);
-	*reinterpret_cast<Mat4*>(flarePositions) = ctx.m_matrices.m_viewProjectionJitter;
-	flarePositions += 4;
+	cmdb->setPushConstants(&ctx.m_matrices.m_viewProjectionJitter, sizeof(ctx.m_matrices.m_viewProjectionJitter));
 
+	// Write flare info
+	Vec4* flarePositions = allocateAndBindStorage<Vec4*>(count * sizeof(Vec4), cmdb, 0, 0);
 	for(U32 i = 0; i < count; ++i)
 	{
 		*flarePositions = Vec4(ctx.m_renderQueue->m_lensFlares[i].m_worldPosition, 1.0f);
@@ -185,8 +184,7 @@ void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBufferPtr& cmd
 		cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearRepeat);
 		cmdb->bindTexture(0, 2, TextureViewPtr(const_cast<TextureView*>(flareEl.m_textureView)));
 
-		cmdb->drawArraysIndirect(PrimitiveTopology::kTriangleStrip, 1, i * sizeof(DrawArraysIndirectInfo),
-								 m_indirectBuff);
+		cmdb->drawArraysIndirect(PrimitiveTopology::kTriangleStrip, 1, i * sizeof(DrawIndirectInfo), m_indirectBuff);
 	}
 
 	// Restore state

+ 82 - 1
AnKi/Shaders/Include/Common.h

@@ -682,7 +682,7 @@ constexpr F16 kMinF16 = 0.00006104hf;
 constexpr F32 kPi = 3.14159265358979323846f;
 #endif
 
-//! == Consts ==========================================================================================================
+//! == Common ==========================================================================================================
 ANKI_BEGIN_NAMESPACE
 
 /// The renderer will group drawcalls into instances up to this number.
@@ -694,4 +694,85 @@ constexpr U32 kMaxShadowCascades = 4u;
 constexpr F32 kShadowsPolygonOffsetFactor = 1.25f;
 constexpr F32 kShadowsPolygonOffsetUnits = 2.75f;
 
+struct DrawIndirectInfo
+{
+	U32 m_vertexCount;
+	U32 m_instanceCount;
+	U32 m_firstVertex;
+	U32 m_firstInstance;
+
+#if defined(__cplusplus)
+	DrawIndirectInfo()
+		: m_vertexCount(kMaxU32)
+		, m_instanceCount(1)
+		, m_firstVertex(0)
+		, m_firstInstance(0)
+	{
+	}
+
+	DrawIndirectInfo(const DrawIndirectInfo&) = default;
+
+	DrawIndirectInfo(U32 count, U32 instanceCount, U32 first, U32 baseInstance)
+		: m_vertexCount(count)
+		, m_instanceCount(instanceCount)
+		, m_firstVertex(first)
+		, m_firstInstance(baseInstance)
+	{
+	}
+
+	Bool operator==(const DrawIndirectInfo& b) const
+	{
+		return m_vertexCount == b.m_vertexCount && m_instanceCount == b.m_instanceCount
+			   && m_firstVertex == b.m_firstVertex && m_firstInstance == b.m_firstInstance;
+	}
+
+	Bool operator!=(const DrawIndirectInfo& b) const
+	{
+		return !(operator==(b));
+	}
+#endif
+};
+
+struct DrawIndexedIndirectInfo
+{
+	U32 m_indexCount;
+	U32 m_instanceCount;
+	U32 m_firstIndex;
+	I32 m_vertexOffset;
+	U32 m_firstInstance;
+
+#if defined(__cplusplus)
+	DrawIndexedIndirectInfo()
+		: m_indexCount(kMaxU32)
+		, m_instanceCount(1)
+		, m_firstIndex(0)
+		, m_vertexOffset(0)
+		, m_firstInstance(0)
+	{
+	}
+
+	DrawIndexedIndirectInfo(const DrawIndexedIndirectInfo&) = default;
+
+	DrawIndexedIndirectInfo(U32 count, U32 instanceCount, U32 firstIndex, U32 baseVertex, U32 baseInstance)
+		: m_indexCount(count)
+		, m_instanceCount(instanceCount)
+		, m_firstIndex(firstIndex)
+		, m_vertexOffset(baseVertex)
+		, m_firstInstance(baseInstance)
+	{
+	}
+
+	Bool operator==(const DrawIndexedIndirectInfo& b) const
+	{
+		return m_indexCount == b.m_indexCount && m_instanceCount == b.m_instanceCount && m_firstIndex == b.m_firstIndex
+			   && m_vertexOffset == b.m_vertexOffset && m_firstInstance == b.m_firstInstance;
+	}
+
+	Bool operator!=(const DrawIndexedIndirectInfo& b) const
+	{
+		return !(operator==(b));
+	}
+#endif
+};
+
 ANKI_END_NAMESPACE

+ 25 - 24
AnKi/Shaders/LensFlareSprite.ankiprog

@@ -3,49 +3,50 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki start vert
-#include <AnKi/Shaders/Common.glsl>
+#pragma anki hlsl
+
+#include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 
-// The block contains data for all flares
-layout(std140, set = 0, binding = 0) readonly buffer b_ssbo
+struct VertOut
 {
-	LensFlareSprite u_sprites[];
+	Vec3 m_uv : TEXCOORD;
+	RVec4 m_color : COLOR;
+	Vec4 m_svPosition : SV_POSITION;
 };
 
-layout(location = 0) out Vec3 out_uv;
-layout(location = 1) flat out ANKI_RP Vec4 out_color;
+#pragma anki start vert
 
-void main()
+// The block contains data for all flares
+[[vk::binding(0)]] StructuredBuffer<LensFlareSprite> g_sprites;
+
+VertOut main(U32 svVertexId : SV_VERTEXID, U32 svInstanceId : SV_INSTANCEID)
 {
-	const Vec2 position = UV_TO_NDC(Vec2(gl_VertexIndex & 1, gl_VertexIndex >> 1));
+	const Vec2 position = uvToNdc(Vec2(svVertexId & 1, svVertexId >> 1));
 
-	const LensFlareSprite sprite = u_sprites[gl_InstanceIndex];
+	const LensFlareSprite sprite = g_sprites[svInstanceId];
 
 	// Write tex coords of the 2D array texture
-	out_uv = Vec3((position * 0.5) + 0.5, sprite.m_depthPad3.x);
+	VertOut output;
+	output.m_uv = Vec3((position * 0.5) + 0.5, sprite.m_depthPad3.x);
 
 	const Vec4 posScale = sprite.m_posScale;
-	gl_Position = Vec4(position * posScale.zw + posScale.xy, 0.0, 1.0);
+	output.m_svPosition = Vec4(position * posScale.zw + posScale.xy, 0.0, 1.0);
+
+	output.m_color = sprite.m_color;
 
-	out_color = sprite.m_color;
+	return output;
 }
 #pragma anki end
 
 #pragma anki start frag
-#include <AnKi/Shaders/Common.glsl>
-
-layout(set = 0, binding = 1) uniform sampler u_trilinearRepeatSampler;
-layout(set = 0, binding = 2) uniform ANKI_RP texture2DArray u_tex;
-
-layout(location = 0) in Vec3 in_uv;
-layout(location = 1) flat in ANKI_RP Vec4 in_color;
 
-layout(location = 0) out ANKI_RP Vec4 out_color;
+[[vk::binding(1)]] SamplerState g_trilinearRepeatSampler;
+[[vk::binding(2)]] Texture2DArray<RVec4> g_tex;
 
-void main()
+RVec4 main(VertOut input) : SV_TARGET0
 {
-	const ANKI_RP Vec4 col = texture(u_tex, u_trilinearRepeatSampler, in_uv);
-	out_color = col * in_color;
+	const RVec4 col = g_tex.Sample(g_trilinearRepeatSampler, input.m_uv);
+	return col * input.m_color;
 }
 #pragma anki end

+ 28 - 44
AnKi/Shaders/LensFlareUpdateIndirectInfo.ankiprog

@@ -3,76 +3,60 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
+
 #pragma anki start comp
-#include <AnKi/Shaders/Common.glsl>
+#include <AnKi/Shaders/Common.hlsl>
 
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(kInDepthMapSize, 0u);
+#define THREAD_COUNT_SQRT 8
 
-const U32 kWorkgroupSize = 8u;
-layout(local_size_x = kWorkgroupSize, local_size_y = kWorkgroupSize, local_size_z = 1) in;
+[[vk::push_constant]] ConstantBuffer<Mat4> g_mvp;
+[[vk::binding(0)]] StructuredBuffer<Vec4> g_flarePositions;
+[[vk::binding(1)]] RWStructuredBuffer<DrawIndirectInfo> g_indirectInfo;
+[[vk::binding(2)]] SamplerState g_nearestAnyClampSampler;
+[[vk::binding(3)]] Texture2D g_depthMap;
 
-struct DrawArraysIndirectInfo
-{
-	U32 count;
-	U32 instanceCount;
-	U32 first;
-	U32 baseInstance;
-};
+groupshared U32 s_maxDepth;
 
-layout(set = 0, binding = 0, std430, row_major) readonly buffer b_lf
-{
-	Mat4 u_mvp;
-	Vec4 u_flarePositions[];
-};
-
-layout(set = 0, binding = 1, std430) writeonly buffer b_indirectInfo
-{
-	DrawArraysIndirectInfo u_indirectInfo[];
-};
-
-layout(set = 0, binding = 2) uniform sampler u_nearestAnyClampSampler;
-layout(set = 0, binding = 3) uniform texture2D u_depthMap;
-
-shared U32 s_maxDepth;
-
-void main()
+[numthreads(THREAD_COUNT_SQRT, THREAD_COUNT_SQRT, 1)] void
+main(U32 svGroupIndex : SV_GROUPINDEX, UVec3 svGroupThreadId : SV_GROUPTHREADID, UVec3 svGroupId : SV_GROUPID)
 {
 	// Init the s_maxDepth
-	if(gl_LocalInvocationIndex == 0u)
+	if(svGroupIndex == 0u)
 	{
 		s_maxDepth = 0u;
 	}
-	memoryBarrierShared();
-	barrier();
+
+	GroupMemoryBarrierWithGroupSync();
 
 	// Project the flare
-	const U32 flareIdx = gl_WorkGroupID.x;
-	const Vec4 posClip = u_mvp * u_flarePositions[flareIdx];
+	const U32 flareIdx = svGroupId.x;
+	const Vec4 posClip = mul(g_mvp, g_flarePositions[flareIdx]);
 	const Vec3 posNdc = posClip.xyz / posClip.w;
 	const F32 depth = posNdc.z;
 
 	// Compute the UVs to sample the depth map
-	// Belongs to [-kWorkgroupSize, kWorkgroupSize]
-	const Vec2 displacement = Vec2(gl_LocalInvocationID.xy) - Vec2(kWorkgroupSize / 2u);
+	// Belongs to [-THREAD_COUNT_SQRT, THREAD_COUNT_SQRT]
+	const Vec2 displacement = Vec2(svGroupThreadId.xy) - (THREAD_COUNT_SQRT / 2u);
 	const Vec2 texelSize = 1.0 / Vec2(kInDepthMapSize);
-	const Vec2 uv = NDC_TO_UV(posNdc.xy) + displacement * texelSize;
+	const Vec2 uv = ndcToUv(posNdc.xy) + displacement * texelSize;
 
 	// Sample and store depth
-	const F32 refDepth = textureLod(u_depthMap, u_nearestAnyClampSampler, uv, 0.0).r;
-	atomicMax(s_maxDepth, U32(refDepth * F32(kMaxU32)));
+	const F32 refDepth = g_depthMap.SampleLevel(g_nearestAnyClampSampler, uv, 0.0).r;
+	InterlockedMax(s_maxDepth, U32(refDepth * F32(kMaxU32)));
 
 	// Sync
-	memoryBarrierShared();
-	barrier();
+	GroupMemoryBarrierWithGroupSync();
 
-	if(gl_LocalInvocationIndex == 0u)
+	if(svGroupIndex == 0u)
 	{
 		const F32 refDepth2 = F32(s_maxDepth) / F32(kMaxU32);
-		u_indirectInfo[flareIdx].count = (depth > refDepth2) ? 0u : 4u;
+		g_indirectInfo[flareIdx].m_vertexCount = (depth > refDepth2) ? 0u : 4u;
 
-		u_indirectInfo[flareIdx].instanceCount = 1u;
-		u_indirectInfo[flareIdx].first = 0u;
-		u_indirectInfo[flareIdx].baseInstance = 0u;
+		g_indirectInfo[flareIdx].m_instanceCount = 1u;
+		g_indirectInfo[flareIdx].m_firstVertex = 0u;
+		g_indirectInfo[flareIdx].m_firstInstance = 0u;
 	}
 }
 #pragma anki end

+ 0 - 81
AnKi/Shaders/LumaAwareBlur.ankiprog

@@ -1,81 +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
-
-#pragma anki mutator HORIZONTAL 0 1
-#pragma anki mutator KERNEL_SIZE 3 5 7 9 11 13 15
-#pragma anki mutator COLOR_COMPONENTS 4 3 1
-
-#pragma anki start vert
-#include <AnKi/Shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
-#include <AnKi/Shaders/GaussianBlurCommon.glsl>
-#include <AnKi/Shaders/TonemappingFunctions.glsl>
-
-ANKI_SPECIALIZATION_CONSTANT_UVEC2(kTextureSize, 0u);
-
-layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
-layout(set = 0, binding = 1) uniform texture2D u_tex;
-
-layout(location = 0) in Vec2 in_uv;
-
-// Determine color type
-#if COLOR_COMPONENTS == 4
-#	define COL_TYPE Vec4
-#	define TEX_FETCH rgba
-#elif COLOR_COMPONENTS == 3
-#	define COL_TYPE Vec3
-#	define TEX_FETCH rgb
-#elif COLOR_COMPONENTS == 1
-#	define COL_TYPE F32
-#	define TEX_FETCH r
-#else
-#	error See file
-#endif
-
-F32 computeLumaWeight(F32 refLuma, COL_TYPE col)
-{
-	const F32 l = computeLuminance(Vec3(col));
-	const F32 diff = abs(refLuma - l);
-	const F32 weight = 1.0 / (kEpsilonf + diff);
-	return weight;
-}
-
-// Output
-layout(location = 0) out COL_TYPE out_color;
-
-void main()
-{
-#if HORIZONTAL
-	const Vec2 texelSize = Vec2(1.0 / F32(kTextureSize.x), 0.0);
-#else
-	const Vec2 texelSize = Vec2(0.0, 1.0 / F32(kTextureSize.y));
-#endif
-
-	COL_TYPE col = textureLod(u_tex, u_linearAnyClampSampler, in_uv, 0.0).TEX_FETCH;
-	out_color = col;
-	const F32 refLuma = computeLuminance(Vec3(col));
-	F32 weight = 1.0;
-	Vec2 texCoordOffset = 1.5 * texelSize;
-
-	for(U32 i = 0u; i < U32(KERNEL_SIZE); ++i)
-	{
-		COL_TYPE col = textureLod(u_tex, u_linearAnyClampSampler, in_uv + texCoordOffset, 0.0).TEX_FETCH;
-		F32 w = computeLumaWeight(refLuma, col);
-		out_color += col * w;
-		weight += w;
-
-		col = textureLod(u_tex, u_linearAnyClampSampler, in_uv - texCoordOffset, 0.0).TEX_FETCH;
-		w = computeLumaWeight(refLuma, col);
-		out_color += col * w;
-		weight += w;
-
-		texCoordOffset += 2.0 * texelSize;
-	}
-
-	out_color = out_color / weight;
-}
-#pragma anki end