浏览代码

Move RT shadows to HLSL

Panagiotis Christopoulos Charitos 2 年之前
父节点
当前提交
77a7f5937d

+ 2 - 2
AnKi/Core/GpuMemoryPools.cpp

@@ -64,8 +64,8 @@ Error RebarStagingGpuMemoryPool::init(GrManager* gr, const ConfigSet& cfg)
 	BufferInitInfo buffInit("ReBar");
 	buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
 	buffInit.m_size = cfg.getCoreRebarGpuMemorySize();
-	buffInit.m_usage =
-		BufferUsageBit::kAllUniform | BufferUsageBit::kAllStorage | BufferUsageBit::kVertex | BufferUsageBit::kIndex;
+	buffInit.m_usage = BufferUsageBit::kAllUniform | BufferUsageBit::kAllStorage | BufferUsageBit::kVertex
+					   | BufferUsageBit::kIndex | BufferUsageBit::kShaderBindingTable;
 	m_buffer = gr->newBuffer(buffInit);
 
 	m_bufferSize = buffInit.m_size;

+ 2 - 1
AnKi/Gr/Vulkan/Common.cpp

@@ -320,7 +320,8 @@ VkBufferUsageFlags convertBufferUsageBit(BufferUsageBit usageMask)
 
 	if(!!(usageMask & PrivateBufferUsageBit::kAccelerationStructure))
 	{
-		out |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;
+		out |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR
+			   | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;
 	}
 
 	if(!!(usageMask & BufferUsageBit::kShaderBindingTable))

+ 2 - 0
AnKi/Gr/Vulkan/Common.h

@@ -123,6 +123,8 @@ class PrivateBufferUsageBit
 {
 public:
 	static constexpr BufferUsageBit kAccelerationStructureBuildScratch = BufferUsageBit(1ull << 29ull);
+
+	/// Buffer that holds the memory for the actual AS.
 	static constexpr BufferUsageBit kAccelerationStructure = static_cast<BufferUsageBit>(1ull << 30ull);
 
 	static constexpr BufferUsageBit kAllPrivate = kAccelerationStructureBuildScratch | kAccelerationStructure;

+ 5 - 5
AnKi/Scene/Visibility.cpp

@@ -62,6 +62,7 @@ static FrustumFlags getProbeFrustumFlags()
 	flags.m_gatherModelComponents = true;
 	flags.m_gatherLightComponents = true;
 	flags.m_gatherSkyComponents = true;
+	flags.m_directionalLightsCastShadow = true;
 	return flags;
 }
 
@@ -80,6 +81,7 @@ static FrustumFlags getCameraFrustumFlags()
 	flags.m_coverageBuffer = true;
 	flags.m_earlyZ = true;
 	flags.m_nonDirectionalLightsCastShadow = true;
+	flags.m_directionalLightsCastShadow = true;
 	return flags;
 }
 
@@ -451,16 +453,14 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			}
 			case LightComponentType::kDirectional:
 			{
-				ANKI_ASSERT(lightc.getShadowEnabled() == true && "Only with shadow for now");
-
-				U32 cascadeCount = max(testedFrustum.getShadowCascadeCount(), U32(castsShadow));
-				if(!castsShadow)
+				U32 cascadeCount;
+				if(!castsShadow || !frustumFlags.m_directionalLightsCastShadow)
 				{
 					cascadeCount = 0;
 				}
 				else
 				{
-					cascadeCount = max<U32>(testedFrustum.getShadowCascadeCount(), 1);
+					cascadeCount = testedFrustum.getShadowCascadeCount();
 				}
 				ANKI_ASSERT(cascadeCount <= kMaxShadowCascades);
 

+ 1 - 0
AnKi/Scene/VisibilityInternal.h

@@ -129,6 +129,7 @@ public:
 	Bool m_coverageBuffer : 1 = false;
 	Bool m_earlyZ : 1 = false;
 	Bool m_nonDirectionalLightsCastShadow : 1 = false;
+	Bool m_directionalLightsCastShadow : 1 = false;
 };
 
 class VisibilityFrustum : public FrustumFlags

+ 11 - 1
AnKi/Shaders/RtShadows.hlsl

@@ -10,7 +10,7 @@
 
 constexpr F32 kRtShadowsMaxHistoryLength = 16.0;
 
-UVec4 packRtShadows(F32 shadowFactors[kMaxRtShadowLayers])
+UVec4 packRtShadows(RF32 shadowFactors[kMaxRtShadowLayers])
 {
 	const U32 a = newPackUnorm4x8(Vec4(shadowFactors[0], shadowFactors[1], shadowFactors[2], shadowFactors[3]));
 	const U32 b = newPackUnorm4x8(Vec4(shadowFactors[4], shadowFactors[5], shadowFactors[6], shadowFactors[7]));
@@ -38,3 +38,13 @@ void zeroRtShadowLayers(out RF32 shadowFactors[kMaxRtShadowLayers])
 		shadowFactors[i] = 0.0;
 	}
 }
+
+struct [raypayload] RayPayload
+{
+	F32 m_shadowFactor : write(caller, anyhit, miss): read(caller);
+};
+
+struct Barycentrics
+{
+	Vec2 m_value;
+};

+ 9 - 53
AnKi/Shaders/RtShadowsHit.ankiprog

@@ -3,74 +3,30 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
 #pragma anki library RtShadows
 #pragma anki ray_type 0
 
 #pragma anki mutator ANKI_TECHNIQUE 4
 #pragma anki mutator ALPHA_TEXTURE 0 1
 
-#include <AnKi/Shaders/Common.glsl>
-#include <AnKi/Shaders/Include/ModelTypes.h>
-
-layout(shaderRecordEXT, scalar) buffer b_model
-{
-	ModelGpuDescriptor u_modelDescriptor;
-};
-
-layout(set = 0, binding = 5) uniform sampler u_sampler;
-
-ANKI_BINDLESS_SET(1);
-
-layout(location = 0) rayPayloadInEXT F32 g_payload;
+#include <AnKi/Shaders/RtShadows.hlsl>
 
 #pragma anki start ahit
 
-hitAttributeEXT vec2 g_attribs;
-
-#if ALPHA_TEXTURE == 1 && ANKI_SUPPORTS_64BIT_TYPES
-ANKI_DEFINE_LOAD_STORE(U16Vec3, 2)
-ANKI_DEFINE_LOAD_STORE(MainVertex, alignof(MainVertex))
-#endif
-
-void main()
+[shader("anyhit")] void main(inout RayPayload payload, in Barycentrics barycentrics)
 {
-#if ALPHA_TEXTURE == 1 && ANKI_SUPPORTS_64BIT_TYPES
-	const ModelGpuDescriptor model = u_modelDescriptor;
-	const MeshGpuDescriptor mesh = model.m_mesh;
-
-	const U32 offset = U32(gl_PrimitiveID) * sizeof(U16Vec3);
-	U16Vec3 indices16;
-	load(mesh.m_indexBufferPtr + U64(offset), indices16);
-	const UVec3 indices = UVec3(indices16);
-
-	const U64 vertBufferPtr = mesh.m_vertexBufferPtrs[kVertexAttributeBufferIdNormalTangentUv0];
-
-	MainVertex vert0, vert1, vert2;
-	load(vertBufferPtr + U64(indices[0] * sizeof(MainVertex)), vert0);
-	load(vertBufferPtr + U64(indices[1] * sizeof(MainVertex)), vert1);
-	load(vertBufferPtr + U64(indices[2] * sizeof(MainVertex)), vert2);
-
-	const Vec3 barycentrics = Vec3(1.0f - g_attribs.x - g_attribs.y, g_attribs.x, g_attribs.y);
-
-	const Vec2 uv = vert0.m_uv0 * barycentrics.x + vert1.m_uv0 * barycentrics.y + vert2.m_uv0 * barycentrics.z;
-
-	const U32 texIdx = U32(model.m_material.m_bindlessTextureIndices[TEXTURE_CHANNEL_ID_DIFFUSE]);
-	const F32 alpha = textureLod(u_bindlessTextures2dF32[nonuniformEXT(texIdx)], u_sampler, uv, 3.0).a;
-
-	g_payload += alpha;
+	ANKI_MAYBE_UNUSED(payload);
+	ANKI_MAYBE_UNUSED(barycentrics);
 
-	if(g_payload >= 1.0)
-	{
-		terminateRayEXT;
-	}
-#else
-	terminateRayEXT;
-#endif
+	AcceptHitAndEndSearch();
 }
 #pragma anki end
 
 #pragma anki start chit
-void main()
+[shader("closesthit")] void main(inout RayPayload payload, in Barycentrics barycentrics)
 {
+	ANKI_MAYBE_UNUSED(payload);
+	ANKI_MAYBE_UNUSED(barycentrics);
 }
 #pragma anki end

+ 4 - 5
AnKi/Shaders/RtShadowsMiss.ankiprog

@@ -3,17 +3,16 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
 #pragma anki library RtShadows
 #pragma anki ray_type 0
 
 #pragma anki start miss
 
-#include <AnKi/Shaders/Common.glsl>
+#include <AnKi/Shaders/RtShadows.hlsl>
 
-layout(location = 0) rayPayloadInEXT F32 g_payload;
-
-void main()
+[shader("miss")] void main(inout RayPayload payload)
 {
-	g_payload = 1.0;
+	payload.m_shadowFactor = 1.0;
 }
 #pragma anki end

+ 68 - 65
AnKi/Shaders/RtShadowsRayGen.ankiprog

@@ -3,106 +3,109 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki hlsl
+
 #pragma anki mutator RAYS_PER_PIXEL 1 2 4 8
 #pragma anki library RtShadows
 #pragma anki ray_type 0
 
 #pragma anki start rgen
 
-#include <AnKi/Shaders/ImportanceSampling.glsl>
-#include <AnKi/Shaders/PackFunctions.glsl>
-#include <AnKi/Shaders/RtShadows.glsl>
+#include <AnKi/Shaders/ImportanceSampling.hlsl>
+#include <AnKi/Shaders/PackFunctions.hlsl>
+#include <AnKi/Shaders/RtShadows.hlsl>
 
 #define CLUSTERED_SHADING_SET 0u
 #define CLUSTERED_SHADING_UNIFORMS_BINDING 0u
 #define CLUSTERED_SHADING_LIGHTS_BINDING 1u
 #define CLUSTERED_SHADING_CLUSTERS_BINDING 4u
-#include <AnKi/Shaders/ClusteredShadingCommon.glsl>
+#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
 
 // Used by the hit shaders. When changing the binding you need to update other shaders
-layout(set = 0, binding = 5) uniform sampler u_trilinearRepeatSampler;
-
-layout(set = 0, binding = 6) uniform uimage2D u_shadowsImage;
-layout(set = 0, binding = 7) uniform utexture2D u_historyShadowsTex;
-layout(set = 0, binding = 8) uniform sampler u_linearAnyClampSampler;
-layout(set = 0, binding = 9) uniform sampler u_nearestAnyClampSampler;
-layout(set = 0, binding = 10) uniform texture2D u_depthRt;
-layout(set = 0, binding = 11) uniform texture2D u_motionVectorsRt;
-layout(set = 0, binding = 12) uniform texture2D u_historyLengthTex;
-layout(set = 0, binding = 13) uniform texture2D u_normalRt;
-layout(set = 0, binding = 14) uniform accelerationStructureEXT u_tlas;
-layout(set = 0, binding = 15) uniform texture2D u_prevMomentsTex;
-layout(set = 0, binding = 16) uniform image2D u_momentsImage;
-layout(set = 0, binding = 17) uniform texture2D u_blueNoiseTex;
+[[vk::binding(5)]] SamplerState g_trilinearRepeatSampler;
+
+[[vk::binding(6)]] RWTexture2D<UVec4> g_shadowsImage;
+[[vk::binding(7)]] Texture2D<UVec4> g_historyShadowsTex;
+[[vk::binding(8)]] SamplerState g_linearAnyClampSampler;
+[[vk::binding(9)]] SamplerState g_nearestAnyClampSampler;
+[[vk::binding(10)]] Texture2D g_depthRt;
+[[vk::binding(11)]] Texture2D g_motionVectorsRt;
+[[vk::binding(12)]] Texture2D g_historyLengthTex;
+[[vk::binding(13)]] Texture2D g_normalRt;
+[[vk::binding(14)]] RaytracingAccelerationStructure g_tlas;
+[[vk::binding(15)]] Texture2D g_prevMomentsTex;
+[[vk::binding(16)]] RWTexture2D<Vec4> g_momentsImage;
+[[vk::binding(17)]] Texture2D g_blueNoiseTex;
 
 ANKI_BINDLESS_SET(1); // Used by the hit shaders
 
-layout(push_constant, std430) uniform b_pc
-{
-	RtShadowsUniforms u_unis;
-};
-
-layout(location = 0) rayPayloadEXT F32 g_payload;
+[[vk::push_constant]] ConstantBuffer<RtShadowsUniforms> g_unis;
 
 F32 trace(const Vec3 rayOrigin, const Vec3 rayDir, F32 tMax)
 {
-	const U32 flags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
+	const U32 flags =
+		RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
 	const U32 cullMask = 0xFFu;
 	const U32 sbtRecordOffset = 0u;
 	const U32 sbtRecordStride = 0u;
 	const U32 missIndex = 0u;
-	const F32 tMin = 0.1;
-	const I32 payloadLocation = 0;
-	g_payload = 0.0;
-	traceRayEXT(u_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, rayOrigin, tMin, rayDir, tMax,
-				payloadLocation);
+	RayDesc ray;
+	ray.Origin = rayOrigin;
+	ray.TMin = 0.1;
+	ray.Direction = rayDir;
+	ray.TMax = tMax;
+
+	RayPayload payload = (RayPayload)0;
+	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
 
-	return g_payload;
+	return payload.m_shadowFactor;
 }
 
-void main()
+[shader("raygeneration")] void main()
 {
 	// World position
-	const Vec2 uv = (Vec2(gl_LaunchIDEXT.xy) + 0.5) / Vec2(gl_LaunchSizeEXT.xy);
-	const Vec2 ndc = UV_TO_NDC(uv);
-	const F32 depth = textureLod(u_depthRt, u_linearAnyClampSampler, uv, 0.0).r;
-	const Vec4 worldPos4 = u_clusteredShading.m_matrices.m_invertedViewProjectionJitter * Vec4(ndc, depth, 1.0);
+	const Vec2 uv = (Vec2(DispatchRaysIndex().xy) + 0.5) / Vec2(DispatchRaysDimensions().xy);
+	const Vec2 ndc = uvToNdc(uv);
+	const F32 depth = g_depthRt.SampleLevel(g_linearAnyClampSampler, uv, 0.0).r;
+	const Vec4 worldPos4 = mul(g_clusteredShading.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
 	const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
 	if(depth == 1.0)
 	{
-		imageStore(u_shadowsImage, IVec2(gl_LaunchIDEXT.xy), UVec4(0));
-		imageStore(u_momentsImage, IVec2(gl_LaunchIDEXT.xy), Vec4(0.0));
+		g_shadowsImage[DispatchRaysIndex().xy] = UVec4(0, 0, 0, 0);
+		g_momentsImage[DispatchRaysIndex().xy] = Vec4(0.0, 0.0, 0.0, 0.0);
 		return;
 	}
 
 	// World normal
-	const Vec3 normal = unpackNormalFromGBuffer(textureLod(u_normalRt, u_linearAnyClampSampler, uv, 0.0));
+	const Vec3 normal = unpackNormalFromGBuffer(g_normalRt.SampleLevel(g_linearAnyClampSampler, uv, 0.0));
 
 	// Cluster
-	Cluster cluster = getClusterFragCoord(Vec3(uv * u_clusteredShading.m_renderingSize, depth));
+	Cluster cluster = getClusterFragCoord(Vec3(uv * g_clusteredShading.m_renderingSize, depth));
 
-	F32 shadowFactors[kMaxRtShadowLayers];
+	RF32 shadowFactors[kMaxRtShadowLayers];
 	zeroRtShadowLayers(shadowFactors);
 
 	// Get a random factor
 	Vec3 random[RAYS_PER_PIXEL];
 	for(I32 i = 0; i < RAYS_PER_PIXEL; ++i)
 	{
-		const U32 frameIdx = u_clusteredShading.m_frame * U32(RAYS_PER_PIXEL + i);
+		const U32 frameIdx = g_clusteredShading.m_frame * U32(RAYS_PER_PIXEL + i);
 #if 0
-		const UVec3 irandom = rand3DPCG16(UVec3(gl_LaunchIDEXT.xy, frameIdx));
+		const UVec3 irandom = rand3DPCG16(UVec3(DispatchRaysIndex().xy, frameIdx));
 		random[i] = Vec3(irandom) / F32(0xFFFF) * 2.0 - 1.0; // In [-1.0, 1.0]
 #else
 		random[i] =
-			textureLod(u_blueNoiseTex, u_trilinearRepeatSampler, Vec2(gl_LaunchSizeEXT.xy) / Vec2(64.0) * uv, 0.0).rgb;
+			g_blueNoiseTex
+				.SampleLevel(g_trilinearRepeatSampler, Vec2(DispatchRaysDimensions().xy) / Vec2(64.0, 64.0) * uv, 0.0)
+				.rgb;
 		random[i] = animateBlueNoise(random[i], frameIdx);
 		random[i] = random[i] * 2.0 - 1.0; // In [-1.0, 1.0]
 #endif
 	}
 
 	// Dir light
-	const DirectionalLight dirLight = u_clusteredShading.m_directionalLight;
+	const DirectionalLight dirLight = g_clusteredShading.m_directionalLight;
 	[branch] if(dirLight.m_active != 0u && dirLight.m_shadowCascadeCount > 0u)
 	{
 		for(I32 i = 0; i < RAYS_PER_PIXEL; ++i)
@@ -119,11 +122,11 @@ void main()
 	}
 
 	// Point lights
-	[[dont_unroll]] while(cluster.m_pointLightsMask != ExtendedClusterObjectMask(0))
+	[loop] while(cluster.m_pointLightsMask != ExtendedClusterObjectMask(0))
 	{
-		const I32 idx = findLSB2(cluster.m_pointLightsMask);
+		const I32 idx = firstbitlow2(cluster.m_pointLightsMask);
 		cluster.m_pointLightsMask &= ~(ExtendedClusterObjectMask(1) << ExtendedClusterObjectMask(idx));
-		const PointLight light = u_pointLights2[idx];
+		const PointLight light = g_pointLights[idx];
 
 		[branch] if(light.m_shadowAtlasTileScale >= 0.0)
 		{
@@ -146,11 +149,11 @@ void main()
 	}
 
 	// Spot lights
-	[[dont_unroll]] while(cluster.m_spotLightsMask != ExtendedClusterObjectMask(0))
+	[loop] while(cluster.m_spotLightsMask != ExtendedClusterObjectMask(0))
 	{
-		const I32 idx = findLSB2(cluster.m_spotLightsMask);
+		const I32 idx = firstbitlow2(cluster.m_spotLightsMask);
 		cluster.m_spotLightsMask &= ~(ExtendedClusterObjectMask(1) << ExtendedClusterObjectMask(idx));
-		const SpotLight light = u_spotLights[idx];
+		const SpotLight light = g_spotLights[idx];
 
 		[branch] if(light.m_shadowLayer != kMaxU32)
 		{
@@ -172,31 +175,31 @@ void main()
 	}
 
 	// Get history length
-	const Vec2 historyUv = uv + textureLod(u_motionVectorsRt, u_linearAnyClampSampler, uv, 0.0).xy;
-	const F32 historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).x;
+	const Vec2 historyUv = uv + g_motionVectorsRt.SampleLevel(g_linearAnyClampSampler, uv, 0.0).xy;
+	const F32 historyLength = g_historyLengthTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).x;
 
 	// Compute blend fractor. Use nearest sampler because it's an integer texture
 	const F32 lowestBlendFactor = 0.1;
 	const F32 stableFrames = 4.0;
-	const F32 lerp = min(1.0, (historyLength * kRtShadowsMaxHistoryLength - 1.0) / stableFrames);
-	const F32 blendFactor = mix(1.0, lowestBlendFactor, lerp);
+	const F32 lerpv = min(1.0, (historyLength * kRtShadowsMaxHistoryLength - 1.0) / stableFrames);
+	const F32 blendFactor = lerp(1.0, lowestBlendFactor, lerpv);
 
 	// Blend with history
-	const UVec4 packedhistory = textureLod(u_historyShadowsTex, u_nearestAnyClampSampler, historyUv, 0.0);
-	F32 history[kMaxRtShadowLayers];
+	const UVec4 packedhistory = g_historyShadowsTex.SampleLevel(g_nearestAnyClampSampler, historyUv, 0.0);
+	RF32 history[kMaxRtShadowLayers];
 	unpackRtShadows(packedhistory, history);
 	for(U32 i = 0u; i < kMaxRtShadowLayers; ++i)
 	{
-		const F32 lerp = min(1.0, u_unis.historyRejectFactor[i] + blendFactor);
-		shadowFactors[i] = mix(history[i], shadowFactors[i], lerp);
+		const F32 lerpv = min(1.0, g_unis.historyRejectFactor[i] + blendFactor);
+		shadowFactors[i] = lerp(history[i], shadowFactors[i], lerpv);
 	}
 
 	// Store the shadows image
 	const UVec4 packed = packRtShadows(shadowFactors);
-	imageStore(u_shadowsImage, IVec2(gl_LaunchIDEXT.xy), packed);
+	g_shadowsImage[DispatchRaysIndex().xy] = packed;
 
 	// Compute the moments that will give temporal variance
-	Vec2 moments = Vec2(0.0);
+	Vec2 moments = 0.0;
 	[unroll] for(U32 i = 0u; i < kMaxRtShadowLayers; ++i)
 	{
 		moments.x += shadowFactors[i];
@@ -204,12 +207,12 @@ void main()
 	moments.y = moments.x * moments.x;
 
 	// Blend the moments
-	const Vec2 prevMoments = textureLod(u_prevMomentsTex, u_linearAnyClampSampler, historyUv, 0.0).xy;
+	const Vec2 prevMoments = g_prevMomentsTex.SampleLevel(g_linearAnyClampSampler, historyUv, 0.0).xy;
 	const F32 lowestMomentsBlendFactor = 0.2;
-	const F32 momentsBlendFactor = mix(1.0, lowestMomentsBlendFactor, lerp);
-	moments = mix(prevMoments, moments, momentsBlendFactor);
+	const F32 momentsBlendFactor = lerp(1.0, lowestMomentsBlendFactor, lerpv);
+	moments = lerp(prevMoments, moments, momentsBlendFactor);
 
 	// Store the moments
-	imageStore(u_momentsImage, IVec2(gl_LaunchIDEXT.xy), Vec4(moments, 0.0, 0.0));
+	g_momentsImage[DispatchRaysIndex().xy] = Vec4(moments, 0.0, 0.0);
 }
 #pragma anki end

+ 11 - 3
Tools/FormatSource.py

@@ -16,9 +16,11 @@ import platform
 
 file_extensions = ["h", "hpp", "c", "cpp", "glsl", "hlsl", "ankiprog"]
 directories = ["AnKi", "Tests", "Sandbox", "Tools", "Samples"]
-hlsl_semantics = ["TEXCOORD", "SV_POSITION", "SV_TARGET0",
-                  "SV_TARGET", "SV_DISPATCHTHREADID", "SV_GROUPINDEX", "SV_GROUPID"]
-
+hlsl_semantics = ["TEXCOORD", "SV_POSITION", "SV_TARGET0", "SV_TARGET", "SV_DISPATCHTHREADID", "SV_GROUPINDEX",
+                  "SV_GROUPID"]
+hlsl_attribs = ["[shader(\"closesthit\")]", "[shader(\"anyhit\")]", "[shader(\"raygeneration\")]", "[shader(\"miss\")]",
+                "[raypayload]"]
+hlsl_attribs_fake = ["__ak_chit__", "__ak_ahit__", "__ak_rgen__", "__ak_miss__", "[[raypayload]]"]
 
 def thread_callback(tid):
     """ Call clang-format """
@@ -51,6 +53,9 @@ def thread_callback(tid):
             for semantic in hlsl_semantics:
                 file_txt = file_txt.replace(": " + semantic, "__" + semantic)
 
+            for i in range(0, len(hlsl_attribs)):
+                file_txt = file_txt.replace(hlsl_attribs[i], hlsl_attribs_fake[i])
+
             # Write the new file
             tmp_filefd, tmp_filename = tempfile.mkstemp()
             with open(tmp_filename, "w", newline="\n") as f:
@@ -81,6 +86,9 @@ def thread_callback(tid):
             for semantic in hlsl_semantics:
                 file_txt = file_txt.replace("__" + semantic, ": " + semantic)
 
+            for i in range(0, len(hlsl_attribs)):
+                file_txt = file_txt.replace(hlsl_attribs_fake[i], hlsl_attribs[i])
+
             new_file_hash = hash(file_txt)
 
             # Write formatted file