Skip to content

Commit be000eb

Browse files
MarijnS95claude
andcommitted
Cover ClosestHit ray system values: barycentrics, PrimitiveIndex, WorldRay
Three small PSO RT tests stacked on llvm#1275, each isolating one shader- observable closest-hit system value from llvm#1268's 👍 list. Same shape as the prior batch in llvm#1277 — one .test file per behavior, single-purpose shader, exact buffer comparison. - `closest-hit-barycentrics.test` — 3-lane dispatch, each lane fires at a clearly-interior point of the single triangle so the closest- hit shader reports a known `BuiltInTriangleIntersectionAttributes ::barycentrics` (u, v). Points are picked from the inside of the triangle to avoid the watertight-traversal edge-rule lottery you hit at edge midpoints / vertices (the first cut of this test used midpoint(v0, v1) and one lane silently missed on both backends). - `closest-hit-primitive-index.test` — three triangles tiled at x = -3, 0, +3 in a single BLAS. 3-lane dispatch fires straight down at each triangle's centroid; the closest-hit reports `PrimitiveIndex()` and must match the lane index 0..2. - `closest-hit-world-ray.test` — 2-lane dispatch with rays from different z heights (1.0 and 2.0). Closest-hit packs `WorldRayOrigin().z`, `WorldRayDirection().z`, and `RayTCurrent()` through the payload; raygen flattens the float3 into a 6-element Float32 buffer. Verifies the system values match the raygen-side `RayDesc` and that t is correctly computed by the traversal. All three are `# REQUIRES: raytracing-pipeline` with `# XFAIL: Clang` — `clang-dxc` doesn't yet lower `[shader(…)]` entry points. With the Metal RT bring-up rebased on top, all three pass natively on Apple Silicon and Metal is dropped from the XFAIL list. Locally verified end-to-end on the user's Linux box: all three pass on Vulkan via the native offloader, and on D3D12 via Wine + vkd3d-proton + the cross-compiled `offloader.exe`, against an NVIDIA RTX 3060. And on macOS 15 / metal-irconverter 3.1.1 via the native offloader: all three PASS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 31c01cf commit be000eb

3 files changed

Lines changed: 385 additions & 0 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#--- source.hlsl
2+
3+
struct Payload {
4+
float2 Bary;
5+
};
6+
7+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
8+
[[vk::binding(1, 0)]] RWStructuredBuffer<float> Output : register(u0);
9+
10+
[shader("raygeneration")]
11+
void RayGen() {
12+
// Each lane fires straight down at a clearly-interior point of the single
13+
// triangle (vertices v0=(0,1,0), v1=(-1,-1,0), v2=(1,-1,0)). HLSL's
14+
// closest-hit `barycentrics` attribute holds (u, v) with u + v + w == 1
15+
// and w being vertex-0's weight, so a hit point at
16+
// P = w * v0 + u * v1 + v * v2
17+
// reports bary = (u, v).
18+
// Lane 0 -> bary (0.25, 0.25), hit at 0.5*v0 + 0.25*v1 + 0.25*v2 = (0, 0, 0)
19+
// Lane 1 -> bary (0.5, 0.25), hit at 0.25*v0 + 0.5*v1 + 0.25*v2 = (-0.25,-0.5, 0)
20+
// Lane 2 -> bary (0.25, 0.5), hit at 0.25*v0 + 0.25*v1 + 0.5*v2 = (0.25, -0.5, 0)
21+
// All three points sit well inside the triangle so the watertight-
22+
// traversal edge rules are not in play and the hits are deterministic
23+
// across rasterizers. Each lane writes 2 floats (u, v) at output offsets
24+
// [2*Index .. 2*Index+1].
25+
const uint Idx = DispatchRaysIndex().x;
26+
const float2 Targets[3] = {float2(0, 0), float2(-0.25, -0.5),
27+
float2(0.25, -0.5)};
28+
29+
Payload P;
30+
P.Bary = float2(0, 0);
31+
RayDesc Ray;
32+
Ray.Origin = float3(Targets[Idx], 1);
33+
Ray.Direction = float3(0, 0, -1);
34+
Ray.TMin = 0.0;
35+
Ray.TMax = 100.0;
36+
TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, Ray, P);
37+
38+
Output[2 * Idx + 0] = P.Bary.x;
39+
Output[2 * Idx + 1] = P.Bary.y;
40+
}
41+
42+
[shader("miss")]
43+
void MissMain(inout Payload P) {
44+
// Sentinel — every ray hits the triangle in this test.
45+
P.Bary = float2(-1, -1);
46+
}
47+
48+
[shader("closesthit")]
49+
void ClosestHitMain(inout Payload P,
50+
in BuiltInTriangleIntersectionAttributes Attr) {
51+
P.Bary = Attr.barycentrics;
52+
}
53+
//--- pipeline.yaml
54+
---
55+
Shaders:
56+
- Stage: RayGeneration
57+
Entry: RayGen
58+
- Stage: Miss
59+
Entry: MissMain
60+
- Stage: ClosestHit
61+
Entry: ClosestHitMain
62+
Buffers:
63+
- Name: Vertices
64+
Format: Float32
65+
Stride: 12
66+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
67+
- Name: Output
68+
Format: Float32
69+
Stride: 4
70+
FillSize: 24
71+
- Name: Expected
72+
Format: Float32
73+
Stride: 4
74+
Data: [ 0.25, 0.25, 0.5, 0.25, 0.25, 0.5 ]
75+
AccelerationStructures:
76+
BLAS:
77+
- Name: TriangleBLAS
78+
Triangles:
79+
- VertexBuffer: Vertices
80+
VertexFormat: RGB32Float
81+
VertexStride: 12
82+
VertexCount: 3
83+
TLAS:
84+
- Name: Scene
85+
Instances:
86+
- BLAS: TriangleBLAS
87+
RayTracingPipelineConfig:
88+
MaxTraceRecursionDepth: 1
89+
MaxPayloadSizeInBytes: 8
90+
HitGroups:
91+
- Name: TriangleHitGroup
92+
Type: Triangles
93+
ClosestHit: ClosestHitMain
94+
ShaderBindingTable:
95+
RayGen:
96+
ShaderName: RayGen
97+
Miss:
98+
- ShaderName: MissMain
99+
HitGroup:
100+
- ShaderName: TriangleHitGroup
101+
DescriptorSets:
102+
- Resources:
103+
- Name: Scene
104+
Kind: AccelerationStructure
105+
DirectXBinding:
106+
Register: 0
107+
Space: 0
108+
VulkanBinding:
109+
Binding: 0
110+
- Name: Output
111+
Kind: RWStructuredBuffer
112+
DirectXBinding:
113+
Register: 0
114+
Space: 0
115+
VulkanBinding:
116+
Binding: 1
117+
DispatchParameters:
118+
DispatchGroupCount: [ 3, 1, 1 ]
119+
Results:
120+
- Result: ClosestHitBarycentrics
121+
Rule: BufferExact
122+
Actual: Output
123+
Expected: Expected
124+
...
125+
#--- end
126+
127+
# REQUIRES: raytracing-pipeline
128+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
129+
# XFAIL: Clang
130+
131+
# RUN: split-file %s %t
132+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
133+
# RUN: %offloader %t/pipeline.yaml %t.o
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#--- source.hlsl
2+
3+
struct Payload {
4+
uint Prim;
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+
// Three triangles tiled along x at x = -3, 0, +3 in a single BLAS. Each
13+
// lane shoots straight down at its own triangle's centroid; the closest-
14+
// hit shader reports its `PrimitiveIndex()` and must match the lane index.
15+
const float Centers[3] = {-3.0, 0.0, 3.0};
16+
const uint Idx = DispatchRaysIndex().x;
17+
18+
Payload P;
19+
P.Prim = 0xFFFFFFFF;
20+
RayDesc Ray;
21+
Ray.Origin = float3(Centers[Idx], 0, 1);
22+
Ray.Direction = float3(0, 0, -1);
23+
Ray.TMin = 0.0;
24+
Ray.TMax = 100.0;
25+
TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, Ray, P);
26+
Output[Idx] = P.Prim;
27+
}
28+
29+
[shader("miss")]
30+
void MissMain(inout Payload P) {
31+
P.Prim = 0xDEAD;
32+
}
33+
34+
[shader("closesthit")]
35+
void ClosestHitMain(inout Payload P,
36+
in BuiltInTriangleIntersectionAttributes Attr) {
37+
P.Prim = PrimitiveIndex();
38+
}
39+
//--- pipeline.yaml
40+
---
41+
Shaders:
42+
- Stage: RayGeneration
43+
Entry: RayGen
44+
- Stage: Miss
45+
Entry: MissMain
46+
- Stage: ClosestHit
47+
Entry: ClosestHitMain
48+
Buffers:
49+
- Name: Vertices
50+
Format: Float32
51+
Stride: 12
52+
# Three triangles in one BLAS, each ~1 unit wide, centroid x at -3 / 0 / +3.
53+
Data: [
54+
-3.0, 1.0, 0.0, -4.0, -1.0, 0.0, -2.0, -1.0, 0.0,
55+
0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0,
56+
3.0, 1.0, 0.0, 2.0, -1.0, 0.0, 4.0, -1.0, 0.0,
57+
]
58+
- Name: Output
59+
Format: UInt32
60+
Stride: 4
61+
FillSize: 12
62+
- Name: Expected
63+
Format: UInt32
64+
Stride: 4
65+
Data: [ 0, 1, 2 ]
66+
AccelerationStructures:
67+
BLAS:
68+
- Name: ThreeTrianglesBLAS
69+
Triangles:
70+
- VertexBuffer: Vertices
71+
VertexFormat: RGB32Float
72+
VertexStride: 12
73+
VertexCount: 9
74+
TLAS:
75+
- Name: Scene
76+
Instances:
77+
- BLAS: ThreeTrianglesBLAS
78+
RayTracingPipelineConfig:
79+
MaxTraceRecursionDepth: 1
80+
MaxPayloadSizeInBytes: 4
81+
HitGroups:
82+
- Name: TriangleHitGroup
83+
Type: Triangles
84+
ClosestHit: ClosestHitMain
85+
ShaderBindingTable:
86+
RayGen:
87+
ShaderName: RayGen
88+
Miss:
89+
- ShaderName: MissMain
90+
HitGroup:
91+
- ShaderName: TriangleHitGroup
92+
DescriptorSets:
93+
- Resources:
94+
- Name: Scene
95+
Kind: AccelerationStructure
96+
DirectXBinding:
97+
Register: 0
98+
Space: 0
99+
VulkanBinding:
100+
Binding: 0
101+
- Name: Output
102+
Kind: RWStructuredBuffer
103+
DirectXBinding:
104+
Register: 0
105+
Space: 0
106+
VulkanBinding:
107+
Binding: 1
108+
DispatchParameters:
109+
DispatchGroupCount: [ 3, 1, 1 ]
110+
Results:
111+
- Result: ClosestHitPrimitiveIndex
112+
Rule: BufferExact
113+
Actual: Output
114+
Expected: Expected
115+
...
116+
#--- end
117+
118+
# REQUIRES: raytracing-pipeline
119+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
120+
# XFAIL: Clang
121+
122+
# RUN: split-file %s %t
123+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
124+
# RUN: %offloader %t/pipeline.yaml %t.o
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#--- source.hlsl
2+
3+
struct Payload {
4+
// Packed: (OriginZ, DirectionZ, RayTCurrent) per lane.
5+
float3 Reading;
6+
};
7+
8+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
9+
[[vk::binding(1, 0)]] RWStructuredBuffer<float> Output : register(u0);
10+
11+
[shader("raygeneration")]
12+
void RayGen() {
13+
// Two lanes fire from different z heights at the single triangle (z=0).
14+
// Lane 0: Origin.z = 1 -> ClosestHit sees Origin.z=1, Dir.z=-1, T=1.
15+
// Lane 1: Origin.z = 2 -> ClosestHit sees Origin.z=2, Dir.z=-1, T=2.
16+
// The ClosestHit reports WorldRayOrigin().z, WorldRayDirection().z, and
17+
// RayTCurrent() through the payload.
18+
const uint Idx = DispatchRaysIndex().x;
19+
const float Origins[2] = {1.0, 2.0};
20+
21+
Payload P;
22+
P.Reading = float3(0, 0, 0);
23+
RayDesc Ray;
24+
Ray.Origin = float3(0, 0, Origins[Idx]);
25+
Ray.Direction = float3(0, 0, -1);
26+
Ray.TMin = 0.0;
27+
Ray.TMax = 100.0;
28+
TraceRay(Scene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, Ray, P);
29+
30+
Output[3 * Idx + 0] = P.Reading.x;
31+
Output[3 * Idx + 1] = P.Reading.y;
32+
Output[3 * Idx + 2] = P.Reading.z;
33+
}
34+
35+
[shader("miss")]
36+
void MissMain(inout Payload P) {
37+
// Sentinel — every ray hits the triangle.
38+
P.Reading = float3(-1, -1, -1);
39+
}
40+
41+
[shader("closesthit")]
42+
void ClosestHitMain(inout Payload P,
43+
in BuiltInTriangleIntersectionAttributes Attr) {
44+
P.Reading.x = WorldRayOrigin().z;
45+
P.Reading.y = WorldRayDirection().z;
46+
P.Reading.z = RayTCurrent();
47+
}
48+
//--- pipeline.yaml
49+
---
50+
Shaders:
51+
- Stage: RayGeneration
52+
Entry: RayGen
53+
- Stage: Miss
54+
Entry: MissMain
55+
- Stage: ClosestHit
56+
Entry: ClosestHitMain
57+
Buffers:
58+
- Name: Vertices
59+
Format: Float32
60+
Stride: 12
61+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
62+
- Name: Output
63+
Format: Float32
64+
Stride: 4
65+
FillSize: 24
66+
- Name: Expected
67+
Format: Float32
68+
Stride: 4
69+
Data: [ 1.0, -1.0, 1.0, 2.0, -1.0, 2.0 ]
70+
AccelerationStructures:
71+
BLAS:
72+
- Name: TriangleBLAS
73+
Triangles:
74+
- VertexBuffer: Vertices
75+
VertexFormat: RGB32Float
76+
VertexStride: 12
77+
VertexCount: 3
78+
TLAS:
79+
- Name: Scene
80+
Instances:
81+
- BLAS: TriangleBLAS
82+
RayTracingPipelineConfig:
83+
MaxTraceRecursionDepth: 1
84+
MaxPayloadSizeInBytes: 12
85+
HitGroups:
86+
- Name: TriangleHitGroup
87+
Type: Triangles
88+
ClosestHit: ClosestHitMain
89+
ShaderBindingTable:
90+
RayGen:
91+
ShaderName: RayGen
92+
Miss:
93+
- ShaderName: MissMain
94+
HitGroup:
95+
- ShaderName: TriangleHitGroup
96+
DescriptorSets:
97+
- Resources:
98+
- Name: Scene
99+
Kind: AccelerationStructure
100+
DirectXBinding:
101+
Register: 0
102+
Space: 0
103+
VulkanBinding:
104+
Binding: 0
105+
- Name: Output
106+
Kind: RWStructuredBuffer
107+
DirectXBinding:
108+
Register: 0
109+
Space: 0
110+
VulkanBinding:
111+
Binding: 1
112+
DispatchParameters:
113+
DispatchGroupCount: [ 2, 1, 1 ]
114+
Results:
115+
- Result: ClosestHitWorldRay
116+
Rule: BufferExact
117+
Actual: Output
118+
Expected: Expected
119+
...
120+
#--- end
121+
122+
# REQUIRES: raytracing-pipeline
123+
# Unimplemented https://github.com/llvm/offload-test-suite/issues/1268
124+
# XFAIL: Clang
125+
126+
# RUN: split-file %s %t
127+
# RUN: %dxc_target_lib -T lib_6_5 -Fo %t.o %t/source.hlsl
128+
# RUN: %offloader %t/pipeline.yaml %t.o

0 commit comments

Comments
 (0)