diff --git a/test/Feature/RT/callable-shader.test b/test/Feature/RT/callable-shader.test new file mode 100644 index 000000000..91b289576 --- /dev/null +++ b/test/Feature/RT/callable-shader.test @@ -0,0 +1,87 @@ +#--- source.hlsl + +// Callable shaders receive an inout user-defined parameter — Vulkan / DXR +// don't have a Built-in convention beyond "size matches what the caller +// declared". One uint of payload is enough to confirm routing. +struct CallableParams { + uint Value; +}; + +[[vk::binding(0, 0)]] RWStructuredBuffer Output : register(u0); + +[shader("raygeneration")] +void RayGen() { + // Each lane calls a different callable shader index. CallShader picks + // the callable record at the given index in the SBT's Callable region + // — inline RT has no equivalent of this stage. + const uint Idx = DispatchRaysIndex().x; + CallableParams P; + P.Value = 0; + CallShader(Idx, P); + Output[Idx] = P.Value; +} + +[shader("callable")] +void CallableA(inout CallableParams P) { + P.Value = 0xAAAA; +} + +[shader("callable")] +void CallableB(inout CallableParams P) { + P.Value = 0xBBBB; +} +//--- pipeline.yaml +--- +Shaders: + - Stage: RayGeneration + Entry: RayGen + - Stage: Callable + Entry: CallableA + - Stage: Callable + Entry: CallableB +Buffers: + - Name: Output + Format: UInt32 + Stride: 4 + FillSize: 8 + - Name: Expected + Format: UInt32 + Stride: 4 + Data: [ 0xAAAA, 0xBBBB ] +RayTracingPipelineConfig: + # No TraceRay calls — depth 1 is sufficient (CallShader doesn't count + # against ray recursion). + MaxTraceRecursionDepth: 1 + MaxPayloadSizeInBytes: 4 +ShaderBindingTable: + RayGen: + ShaderName: RayGen + Callable: + - ShaderName: CallableA + - ShaderName: CallableB +DescriptorSets: + - Resources: + - Name: Output + Kind: RWStructuredBuffer + DirectXBinding: + Register: 0 + Space: 0 + VulkanBinding: + Binding: 0 +DispatchParameters: + DispatchGroupCount: [ 2, 1, 1 ] +Results: + - Result: CallableRouting + Rule: BufferExact + Actual: Output + Expected: Expected +... +#--- end + +# REQUIRES: raytracing-pipeline +# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268 +# XFAIL: Clang + +# RUN: split-file %s %t +# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl +# RUN: %offloader %t/pipeline.yaml %t.o diff --git a/test/Feature/RT/ray-flag-skip-closest-hit.test b/test/Feature/RT/ray-flag-skip-closest-hit.test new file mode 100644 index 000000000..db7ec4683 --- /dev/null +++ b/test/Feature/RT/ray-flag-skip-closest-hit.test @@ -0,0 +1,127 @@ +#--- source.hlsl + +struct Payload { + uint Value; +}; + +[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0); +[[vk::binding(1, 0)]] RWStructuredBuffer Output : register(u0); + +[shader("raygeneration")] +void RayGen() { + // Both lanes fire identical rays that hit the same triangle. Lane 0 + // uses RAY_FLAG_NONE so the closest-hit shader runs and writes + // 0xBEEF into the payload. Lane 1 sets + // RAY_FLAG_SKIP_CLOSEST_HIT_SHADER (a PSO-only flag — inline RT can't + // express this) so the traversal records a hit but the closest-hit + // shader is never invoked. With initial payload = 0xAAAA the output + // is the sentinel for lane 1 and 0xBEEF for lane 0. + const uint Idx = DispatchRaysIndex().x; + const uint Flags = + Idx == 0 ? RAY_FLAG_NONE : RAY_FLAG_SKIP_CLOSEST_HIT_SHADER; + + Payload P; + P.Value = 0xAAAA; + RayDesc Ray; + Ray.Origin = float3(0, 0, 1); + Ray.Direction = float3(0, 0, -1); + Ray.TMin = 0.0; + Ray.TMax = 100.0; + TraceRay(Scene, Flags, 0xFF, 0, 1, 0, Ray, P); + Output[Idx] = P.Value; +} + +[shader("miss")] +void MissMain(inout Payload P) { + // Sentinel — every ray hits the triangle, so this never runs. + P.Value = 0xDEAD; +} + +[shader("closesthit")] +void ClosestHitMain(inout Payload P, + in BuiltInTriangleIntersectionAttributes Attr) { + P.Value = 0xBEEF; +} +//--- pipeline.yaml +--- +Shaders: + - Stage: RayGeneration + Entry: RayGen + - Stage: Miss + Entry: MissMain + - Stage: ClosestHit + Entry: ClosestHitMain +Buffers: + - Name: Vertices + Format: Float32 + Stride: 12 + Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ] + - Name: Output + Format: UInt32 + Stride: 4 + FillSize: 8 + - Name: Expected + Format: UInt32 + Stride: 4 + # Lane 0: closest-hit runs, writes 0xBEEF. + # Lane 1: closest-hit skipped, payload stays at the initial 0xAAAA. + Data: [ 0xBEEF, 0xAAAA ] +AccelerationStructures: + BLAS: + - Name: TriangleBLAS + Triangles: + - VertexBuffer: Vertices + VertexFormat: RGB32Float + VertexStride: 12 + VertexCount: 3 + TLAS: + - Name: Scene + Instances: + - BLAS: TriangleBLAS +RayTracingPipelineConfig: + MaxTraceRecursionDepth: 1 + MaxPayloadSizeInBytes: 4 +HitGroups: + - Name: TriangleHitGroup + Type: Triangles + ClosestHit: ClosestHitMain +ShaderBindingTable: + RayGen: + ShaderName: RayGen + Miss: + - ShaderName: MissMain + HitGroup: + - ShaderName: TriangleHitGroup +DescriptorSets: + - Resources: + - Name: Scene + Kind: AccelerationStructure + DirectXBinding: + Register: 0 + Space: 0 + VulkanBinding: + Binding: 0 + - Name: Output + Kind: RWStructuredBuffer + DirectXBinding: + Register: 0 + Space: 0 + VulkanBinding: + Binding: 1 +DispatchParameters: + DispatchGroupCount: [ 2, 1, 1 ] +Results: + - Result: RayFlagSkipClosestHit + Rule: BufferExact + Actual: Output + Expected: Expected +... +#--- end + +# REQUIRES: raytracing-pipeline +# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268 +# XFAIL: Clang + +# RUN: split-file %s %t +# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl +# RUN: %offloader %t/pipeline.yaml %t.o diff --git a/test/Feature/RT/trace-ray-recursion.test b/test/Feature/RT/trace-ray-recursion.test new file mode 100644 index 000000000..98d509ba3 --- /dev/null +++ b/test/Feature/RT/trace-ray-recursion.test @@ -0,0 +1,134 @@ +#--- source.hlsl + +struct Payload { + uint Value; +}; + +[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0); +[[vk::binding(1, 0)]] RWStructuredBuffer Output : register(u0); + +[shader("raygeneration")] +void RayGen() { + Payload P; + P.Value = 0; + RayDesc Ray; + Ray.Origin = float3(0, 0, 1); + Ray.Direction = float3(0, 0, -1); + Ray.TMin = 0.0; + Ray.TMax = 100.0; + TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, Ray, P); + Output[0] = P.Value; +} + +[shader("miss")] +void MissMain(inout Payload P) { + // Sentinel — never observed (every ray hits the triangle). + P.Value = 0xDEAD; +} + +[shader("closesthit")] +void RecursiveCH(inout Payload P, in BuiltInTriangleIntersectionAttributes Attr) { + // First entry into the hit shader: payload still carries raygen's 0. + // Bump it to a marker, fire a secondary ray from a fresh origin above the + // triangle so we hit the same triangle again, then OR in the high marker + // when the secondary chain unwinds. The secondary invocation sees a + // non-zero payload and goes down the second-level branch. + if (P.Value == 0) { + P.Value = 0x1; + RayDesc Ray; + Ray.Origin = float3(0, 0, 2); + Ray.Direction = float3(0, 0, -1); + Ray.TMin = 0.0; + Ray.TMax = 100.0; + TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, Ray, P); + P.Value |= 0x100; + } else { + // Second-level hit: write the low marker and don't recurse further. + P.Value = 0x10; + } +} +//--- pipeline.yaml +--- +Shaders: + - Stage: RayGeneration + Entry: RayGen + - Stage: Miss + Entry: MissMain + - Stage: ClosestHit + Entry: RecursiveCH +Buffers: + - Name: Vertices + Format: Float32 + Stride: 12 + Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ] + - Name: Output + Format: UInt32 + Stride: 4 + FillSize: 4 + - Name: Expected + Format: UInt32 + Stride: 4 + # First-level CH sets Value=0x1 (overwritten by secondary CH to 0x10), then + # OR's in 0x100 after the secondary chain unwinds — final = 0x110. + Data: [ 0x110 ] +AccelerationStructures: + BLAS: + - Name: TriangleBLAS + Triangles: + - VertexBuffer: Vertices + VertexFormat: RGB32Float + VertexStride: 12 + VertexCount: 3 + TLAS: + - Name: Scene + Instances: + - BLAS: TriangleBLAS +RayTracingPipelineConfig: + # Raygen invokes TraceRay (depth 1) and the first-level CH invokes + # TraceRay again (depth 2). Both need to be allowed. + MaxTraceRecursionDepth: 2 + MaxPayloadSizeInBytes: 4 +HitGroups: + - Name: TriangleHitGroup + Type: Triangles + ClosestHit: RecursiveCH +ShaderBindingTable: + RayGen: + ShaderName: RayGen + Miss: + - ShaderName: MissMain + HitGroup: + - ShaderName: TriangleHitGroup +DescriptorSets: + - Resources: + - Name: Scene + Kind: AccelerationStructure + DirectXBinding: + Register: 0 + Space: 0 + VulkanBinding: + Binding: 0 + - Name: Output + Kind: RWStructuredBuffer + DirectXBinding: + Register: 0 + Space: 0 + VulkanBinding: + Binding: 1 +DispatchParameters: + DispatchGroupCount: [ 1, 1, 1 ] +Results: + - Result: TraceRayRecursion + Rule: BufferExact + Actual: Output + Expected: Expected +... +#--- end + +# REQUIRES: raytracing-pipeline +# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268 +# XFAIL: Clang + +# RUN: split-file %s %t +# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl +# RUN: %offloader %t/pipeline.yaml %t.o