Skip to content

Commit c2f41d4

Browse files
MarijnS95claude
authored andcommitted
Add first PSO RT test batch: DispatchRays + SBT routing
Four small tests stacked on top of llvm#1275, each isolating one shader-observable PSO raytracing surface. They follow the same shape as the inline-RT batch already in llvm#1271 / llvm#1272 / llvm#1274 / llvm#1276 — one .test file per behavior, single-purpose shader, exact buffer comparison. - `dispatch-rays-index.test` — 4x1x1 dispatch, raygen writes `DispatchRaysIndex().x` into `Output[index]`. Confirms the dispatch grid plumbs through to the per-lane system value with no BLAS / TLAS / hit groups in play (RT-pipeline-only, no AS binding). - `dispatch-rays-dimensions.test` — 2x3x1 dispatch, raygen packs the constant `DispatchRaysDimensions()` into one uint per lane. Confirms every lane sees the host-side `{W, H, D}` even when only one dimension > 1. - `miss-shader-index.test` — two miss shaders writing distinct sentinels (0xAA / 0xBB). 2-lane dispatch picks `MissShaderIndex` 0 and 1 respectively; rays start far enough from the geometry that every ray misses. Verifies the SBT miss region's per-record routing. - `ray-contribution-to-hit-group-index.test` — two hit groups with distinct closest-hit shaders (0xA1 / 0xB2). 2-lane dispatch picks `RayContributionToHitGroupIndex` 0 and 1, every ray hits the same triangle. Verifies the SBT hit-group region's per-record routing. The first two have no AS / Miss / HitGroup in their pipeline at all — just a raygen + a UAV — which exercises the minimum viable RT pipeline shape (one raygen group, zero-sized miss / hit / callable SBT regions). The latter two reuse the single-triangle BLAS/TLAS from `raygen-roundtrip.test`. All four tests are `# REQUIRES: raytracing-pipeline` with `# XFAIL: Clang` — Clang (`clang-dxc`) doesn't yet lower `[shader("…")]` entry points to either DXIL libraries or SPIR-V. With the Metal RT bring-up rebased on top, all four pass natively on Apple Silicon and Metal is dropped from the XFAIL list. Locally verified end-to-end on the user's Linux box: - Vulkan via the native offloader against an NVIDIA RTX 3060: all four tests PASS. - D3D12 via Wine + vkd3d-proton + the cross-compiled offloader.exe on the same GPU: all four tests PASS. And on macOS 15 / metal-irconverter 3.1.1: - Metal via the native offloader: all four tests PASS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f4e85ca commit c2f41d4

4 files changed

Lines changed: 375 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#--- source.hlsl
2+
3+
[[vk::binding(0, 0)]] RWStructuredBuffer<uint> Output : register(u0);
4+
5+
[shader("raygeneration")]
6+
void RayGen() {
7+
// DispatchRaysDimensions() echoes the host-side {W, H, D}. Every lane sees
8+
// the same constant; write the packed value at the lane's linear index so
9+
// the result is independent of which lane orders its store first.
10+
const uint3 D = DispatchRaysDimensions();
11+
const uint Idx = DispatchRaysIndex().y * D.x + DispatchRaysIndex().x;
12+
// Pack {W, H} into one uint for an exact comparison; the dispatch is 2D so
13+
// D.z is always 1 (no need to round-trip it through the buffer).
14+
Output[Idx] = (D.x << 16) | (D.y & 0xFFFF);
15+
}
16+
//--- pipeline.yaml
17+
---
18+
Shaders:
19+
- Stage: RayGeneration
20+
Entry: RayGen
21+
Buffers:
22+
- Name: Output
23+
Format: UInt32
24+
Stride: 4
25+
FillSize: 24
26+
- Name: Expected
27+
Format: UInt32
28+
Stride: 4
29+
# Dispatch is 2x3x1 (W=2, H=3, D=1) so every lane writes (2<<16)|3 = 0x20003.
30+
Data: [ 0x20003, 0x20003, 0x20003, 0x20003, 0x20003, 0x20003 ]
31+
RayTracingPipelineConfig:
32+
MaxTraceRecursionDepth: 1
33+
MaxPayloadSizeInBytes: 0
34+
ShaderBindingTable:
35+
RayGen:
36+
ShaderName: RayGen
37+
DescriptorSets:
38+
- Resources:
39+
- Name: Output
40+
Kind: RWStructuredBuffer
41+
DirectXBinding:
42+
Register: 0
43+
Space: 0
44+
VulkanBinding:
45+
Binding: 0
46+
DispatchParameters:
47+
DispatchGroupCount: [ 2, 3, 1 ]
48+
Results:
49+
- Result: DispatchRaysDimensionsEcho
50+
Rule: BufferExact
51+
Actual: Output
52+
Expected: Expected
53+
...
54+
#--- end
55+
56+
# REQUIRES: raytracing-pipeline
57+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
58+
# XFAIL: Clang
59+
60+
# RUN: split-file %s %t
61+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
62+
# RUN: %offloader %t/pipeline.yaml %t.o
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#--- source.hlsl
2+
3+
[[vk::binding(0, 0)]] RWStructuredBuffer<uint> Output : register(u0);
4+
5+
[shader("raygeneration")]
6+
void RayGen() {
7+
// Each lane writes its own x-coordinate. With a 4x1x1 dispatch the four
8+
// lanes must end up with Output[0..3] = {0, 1, 2, 3}.
9+
Output[DispatchRaysIndex().x] = DispatchRaysIndex().x;
10+
}
11+
//--- pipeline.yaml
12+
---
13+
Shaders:
14+
- Stage: RayGeneration
15+
Entry: RayGen
16+
Buffers:
17+
- Name: Output
18+
Format: UInt32
19+
Stride: 4
20+
FillSize: 16
21+
- Name: Expected
22+
Format: UInt32
23+
Stride: 4
24+
Data: [ 0, 1, 2, 3 ]
25+
RayTracingPipelineConfig:
26+
MaxTraceRecursionDepth: 1
27+
MaxPayloadSizeInBytes: 0
28+
ShaderBindingTable:
29+
RayGen:
30+
ShaderName: RayGen
31+
DescriptorSets:
32+
- Resources:
33+
- Name: Output
34+
Kind: RWStructuredBuffer
35+
DirectXBinding:
36+
Register: 0
37+
Space: 0
38+
VulkanBinding:
39+
Binding: 0
40+
DispatchParameters:
41+
DispatchGroupCount: [ 4, 1, 1 ]
42+
Results:
43+
- Result: DispatchRaysIndexX
44+
Rule: BufferExact
45+
Actual: Output
46+
Expected: Expected
47+
...
48+
#--- end
49+
50+
# REQUIRES: raytracing-pipeline
51+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
52+
# XFAIL: Clang
53+
54+
# RUN: split-file %s %t
55+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
56+
# RUN: %offloader %t/pipeline.yaml %t.o
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#--- source.hlsl
2+
3+
struct Payload {
4+
uint Value;
5+
};
6+
7+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
8+
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> Output : register(u0);
9+
10+
[shader("raygeneration")]
11+
void RayGen() {
12+
Payload P;
13+
P.Value = 0;
14+
RayDesc Ray;
15+
// Origin far enough away from the triangle (which sits at z = 0) that any
16+
// direction guarantees a miss — TMax keeps the ray short, so even a +z
17+
// shoot doesn't accidentally find the BLAS.
18+
Ray.Origin = float3(100, 100, 100);
19+
Ray.Direction = float3(0, 0, 1);
20+
Ray.TMin = 0.0;
21+
Ray.TMax = 1.0;
22+
// Each lane picks a different MissShaderIndex via the second-to-last
23+
// TraceRay argument.
24+
const uint MissIdx = DispatchRaysIndex().x;
25+
TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, MissIdx, Ray, P);
26+
Output[DispatchRaysIndex().x] = P.Value;
27+
}
28+
29+
[shader("miss")]
30+
void Miss0(inout Payload P) {
31+
P.Value = 0xAA;
32+
}
33+
34+
[shader("miss")]
35+
void Miss1(inout Payload P) {
36+
P.Value = 0xBB;
37+
}
38+
39+
[shader("closesthit")]
40+
void ClosestHitMain(inout Payload P, in BuiltInTriangleIntersectionAttributes Attr) {
41+
// Sentinel that should never be observed in this test — every ray misses.
42+
P.Value = 0xDEAD;
43+
}
44+
//--- pipeline.yaml
45+
---
46+
Shaders:
47+
- Stage: RayGeneration
48+
Entry: RayGen
49+
- Stage: Miss
50+
Entry: Miss0
51+
- Stage: Miss
52+
Entry: Miss1
53+
- Stage: ClosestHit
54+
Entry: ClosestHitMain
55+
Buffers:
56+
- Name: Vertices
57+
Format: Float32
58+
Stride: 12
59+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
60+
- Name: Output
61+
Format: UInt32
62+
Stride: 4
63+
FillSize: 8
64+
- Name: Expected
65+
Format: UInt32
66+
Stride: 4
67+
Data: [ 0xAA, 0xBB ]
68+
AccelerationStructures:
69+
BLAS:
70+
- Name: TriangleBLAS
71+
Triangles:
72+
- VertexBuffer: Vertices
73+
VertexFormat: RGB32Float
74+
VertexStride: 12
75+
VertexCount: 3
76+
TLAS:
77+
- Name: Scene
78+
Instances:
79+
- BLAS: TriangleBLAS
80+
RayTracingPipelineConfig:
81+
MaxTraceRecursionDepth: 1
82+
MaxPayloadSizeInBytes: 4
83+
HitGroups:
84+
- Name: TriangleHitGroup
85+
Type: Triangles
86+
ClosestHit: ClosestHitMain
87+
ShaderBindingTable:
88+
RayGen:
89+
ShaderName: RayGen
90+
Miss:
91+
- ShaderName: Miss0
92+
- ShaderName: Miss1
93+
HitGroup:
94+
- ShaderName: TriangleHitGroup
95+
DescriptorSets:
96+
- Resources:
97+
- Name: Scene
98+
Kind: AccelerationStructure
99+
DirectXBinding:
100+
Register: 0
101+
Space: 0
102+
VulkanBinding:
103+
Binding: 0
104+
- Name: Output
105+
Kind: RWStructuredBuffer
106+
DirectXBinding:
107+
Register: 0
108+
Space: 0
109+
VulkanBinding:
110+
Binding: 1
111+
DispatchParameters:
112+
DispatchGroupCount: [ 2, 1, 1 ]
113+
Results:
114+
- Result: MissShaderIndexRouting
115+
Rule: BufferExact
116+
Actual: Output
117+
Expected: Expected
118+
...
119+
#--- end
120+
121+
# REQUIRES: raytracing-pipeline
122+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
123+
# XFAIL: Clang
124+
125+
# RUN: split-file %s %t
126+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
127+
# RUN: %offloader %t/pipeline.yaml %t.o
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#--- source.hlsl
2+
3+
struct Payload {
4+
uint Value;
5+
};
6+
7+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
8+
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> Output : register(u0);
9+
10+
[shader("raygeneration")]
11+
void RayGen() {
12+
Payload P;
13+
P.Value = 0;
14+
RayDesc Ray;
15+
Ray.Origin = float3(0, 0, 1);
16+
Ray.Direction = float3(0, 0, -1);
17+
Ray.TMin = 0.0;
18+
Ray.TMax = 100.0;
19+
// RayContributionToHitGroupIndex (4th TraceRay arg) selects which hit-group
20+
// record the SBT routes to. Lane 0 picks hit-group 0 (writes 0xA1), lane 1
21+
// picks hit-group 1 (writes 0xB2). MultiplierForGeometryContributionToHit-
22+
// GroupIndex (5th arg) stays 1; the BLAS has a single geometry so it
23+
// doesn't add anything to the index.
24+
const uint HGIdx = DispatchRaysIndex().x;
25+
TraceRay(Scene, RAY_FLAG_NONE, 0xFF, HGIdx, 1, 0, Ray, P);
26+
Output[DispatchRaysIndex().x] = P.Value;
27+
}
28+
29+
[shader("miss")]
30+
void MissMain(inout Payload P) {
31+
// Sentinel — never observed in this test since every ray hits the triangle.
32+
P.Value = 0xDEAD;
33+
}
34+
35+
[shader("closesthit")]
36+
void CHA(inout Payload P, in BuiltInTriangleIntersectionAttributes Attr) {
37+
P.Value = 0xA1;
38+
}
39+
40+
[shader("closesthit")]
41+
void CHB(inout Payload P, in BuiltInTriangleIntersectionAttributes Attr) {
42+
P.Value = 0xB2;
43+
}
44+
//--- pipeline.yaml
45+
---
46+
Shaders:
47+
- Stage: RayGeneration
48+
Entry: RayGen
49+
- Stage: Miss
50+
Entry: MissMain
51+
- Stage: ClosestHit
52+
Entry: CHA
53+
- Stage: ClosestHit
54+
Entry: CHB
55+
Buffers:
56+
- Name: Vertices
57+
Format: Float32
58+
Stride: 12
59+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
60+
- Name: Output
61+
Format: UInt32
62+
Stride: 4
63+
FillSize: 8
64+
- Name: Expected
65+
Format: UInt32
66+
Stride: 4
67+
Data: [ 0xA1, 0xB2 ]
68+
AccelerationStructures:
69+
BLAS:
70+
- Name: TriangleBLAS
71+
Triangles:
72+
- VertexBuffer: Vertices
73+
VertexFormat: RGB32Float
74+
VertexStride: 12
75+
VertexCount: 3
76+
TLAS:
77+
- Name: Scene
78+
Instances:
79+
- BLAS: TriangleBLAS
80+
RayTracingPipelineConfig:
81+
MaxTraceRecursionDepth: 1
82+
MaxPayloadSizeInBytes: 4
83+
HitGroups:
84+
- Name: HitGroupA
85+
Type: Triangles
86+
ClosestHit: CHA
87+
- Name: HitGroupB
88+
Type: Triangles
89+
ClosestHit: CHB
90+
ShaderBindingTable:
91+
RayGen:
92+
ShaderName: RayGen
93+
Miss:
94+
- ShaderName: MissMain
95+
HitGroup:
96+
- ShaderName: HitGroupA
97+
- ShaderName: HitGroupB
98+
DescriptorSets:
99+
- Resources:
100+
- Name: Scene
101+
Kind: AccelerationStructure
102+
DirectXBinding:
103+
Register: 0
104+
Space: 0
105+
VulkanBinding:
106+
Binding: 0
107+
- Name: Output
108+
Kind: RWStructuredBuffer
109+
DirectXBinding:
110+
Register: 0
111+
Space: 0
112+
VulkanBinding:
113+
Binding: 1
114+
DispatchParameters:
115+
DispatchGroupCount: [ 2, 1, 1 ]
116+
Results:
117+
- Result: RayContributionRouting
118+
Rule: BufferExact
119+
Actual: Output
120+
Expected: Expected
121+
...
122+
#--- end
123+
124+
# REQUIRES: raytracing-pipeline
125+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
126+
# XFAIL: Clang
127+
128+
# RUN: split-file %s %t
129+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
130+
# RUN: %offloader %t/pipeline.yaml %t.o

0 commit comments

Comments
 (0)