Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions test/Feature/RT/callable-shader.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#--- 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<uint> 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
# DXC's `-spirv` backend lists *every* callable's IncomingCallableDataKHR
# variable in *every* callable entry point's interface, which violates
# VUID-StandaloneSpirv-IncomingCallableDataKHR-04706 and gets rejected by
# vkCreateShaderModule. The Vulkan backend implementation is correct
# (`spirv-opt --remove-unused-interface-variables` cleans the SPIR-V and
# the test then passes natively) — track the DXC fix upstream.
# XFAIL: Clang, Vulkan

# 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
127 changes: 127 additions & 0 deletions test/Feature/RT/ray-flag-skip-closest-hit.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#--- source.hlsl

struct Payload {
uint Value;
};

[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> 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
134 changes: 134 additions & 0 deletions test/Feature/RT/trace-ray-recursion.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#--- source.hlsl

struct Payload {
uint Value;
};

[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> 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
Loading