1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
//TEST:SIMPLE(filecheck=CHECK): -target cuda
//TEST:SIMPLE(filecheck=CHECK_PTX): -target ptx
//TEST_INPUT: set scene = AccelerationStructure
uniform RaytracingAccelerationStructure scene;
// Ray query and geometry intrinsics - order independent
//CHECK-DAG: optixGetHitKind()
//CHECK-DAG: optixGetInstanceIndex()
//CHECK-DAG: optixGetInstanceId()
//CHECK-DAG: optixGetObjectRayDirection()
//CHECK-DAG: optixGetObjectRayOrigin()
//CHECK-DAG: optixGetPrimitiveIndex()
//CHECK-DAG: optixGetRayFlags()
//CHECK-DAG: optixGetRayTmin()
//CHECK-DAG: optixGetWorldRayDirection()
//CHECK-DAG: optixGetWorldRayOrigin()
// HitObject intrinsics - uses generic templated call, not individual _N functions
//CHECK-DAG: optixHitObjectGetAttribute<CustomAttributes_0>
//CHECK-DAG: slangOptixHitObjectIsMiss
// Control flow intrinsics
//CHECK-DAG: optixTerminateRay
//CHECK-DAG: optixTraverse
//CHECK-DAG: optixMakeHitObject
//CHECK-DAG: optixIgnoreIntersection
// Traditional SBT data access
//CHECK-DAG: optixGetSbtDataPointer
// PTX intrinsics validation - using actual PTX names (order independent)
//CHECK_PTX-DAG: _optix_get_hit_kind
//CHECK_PTX-DAG: _optix_read_instance_idx
//CHECK_PTX-DAG: _optix_read_instance_id
//CHECK_PTX-DAG: _optix_get_object_ray_direction_x
//CHECK_PTX-DAG: _optix_get_object_ray_origin_x
//CHECK_PTX-DAG: _optix_read_primitive_idx
//CHECK_PTX-DAG: _optix_get_ray_flags
//CHECK_PTX-DAG: _optix_get_ray_tmin
//CHECK_PTX-DAG: _optix_get_world_ray_direction_x
//CHECK_PTX-DAG: _optix_get_world_ray_origin_x
//CHECK_PTX-DAG: _optix_terminate_ray
//CHECK_PTX-DAG: _optix_ignore_intersection
//CHECK_PTX-DAG: _optix_hitobject_get_traverse_data
//CHECK_PTX-DAG: _optix_hitobject_make_with_traverse_data
//CHECK_PTX-DAG: _optix_get_sbt_data_ptr_64
struct CustomAttributes
{
float attr0;
uint attr1;
float attr2;
uint attr3;
float attr4;
uint attr5;
float attr6;
uint attr7;
};
struct IntrinsicData
{
// Ray geometry data
uint hitKind;
uint instanceIndex;
uint instanceID;
uint primitiveIndex;
float3 objectRayDirection;
float3 objectRayOrigin;
float3 worldRayDirection;
float3 worldRayOrigin;
float rayTmin;
uint rayFlags;
// HitObject attributes
float hitObjAttr0;
uint hitObjAttr1;
float hitObjAttr2;
uint hitObjAttr3;
float hitObjAttr4;
uint hitObjAttr5;
float hitObjAttr6;
uint hitObjAttr7;
// HitObject state
bool isMiss;
};
struct RayPayload
{
IntrinsicData data;
bool shouldTerminate;
};
// Traditional SBT data structure
struct TraditionalSbtData
{
float multiplier;
uint flags;
float3 color;
};
// Add a separate payload for anyhit shader testing
struct AnyHitPayload
{
bool terminateRequested;
uint hitCount;
};
[shader("closesthit")]
void closestHitShader(
uniform TraditionalSbtData sbtData, // This triggers traditional optixGetSbtDataPointer
inout RayPayload payload,
in CustomAttributes attr)
{
// Test basic ray query intrinsics using correct HLSL names
payload.data.hitKind = HitKind();
payload.data.instanceIndex = InstanceIndex();
payload.data.instanceID = InstanceID();
payload.data.primitiveIndex = PrimitiveIndex();
payload.data.objectRayDirection = ObjectRayDirection();
payload.data.objectRayOrigin = ObjectRayOrigin();
payload.data.worldRayDirection = WorldRayDirection();
payload.data.worldRayOrigin = WorldRayOrigin();
payload.data.rayTmin = RayTMin();
payload.data.rayFlags = RayFlags();
// Test HitObject operations (using a NOP HitObject for simplicity)
HitObject hitObj = HitObject::MakeNop();
// Test HitObject attribute access with the correct API
CustomAttributes hitObjAttrs = hitObj.GetAttributes<CustomAttributes>();
payload.data.hitObjAttr0 = hitObjAttrs.attr0;
payload.data.hitObjAttr1 = hitObjAttrs.attr1;
payload.data.hitObjAttr2 = hitObjAttrs.attr2;
payload.data.hitObjAttr3 = hitObjAttrs.attr3;
payload.data.hitObjAttr4 = hitObjAttrs.attr4;
payload.data.hitObjAttr5 = hitObjAttrs.attr5;
payload.data.hitObjAttr6 = hitObjAttrs.attr6;
payload.data.hitObjAttr7 = hitObjAttrs.attr7;
// Test HitObject state queries
payload.data.isMiss = hitObj.IsMiss();
// Test traditional SBT data access - this should generate optixGetSbtDataPointer
payload.data.rayTmin *= sbtData.multiplier;
if (sbtData.flags > 0)
{
payload.data.rayTmin += sbtData.color.x + sbtData.color.y + sbtData.color.z;
}
// Mark test as completed
payload.shouldTerminate = true;
}
[shader("anyhit")]
void anyHitShader(inout AnyHitPayload payload, in CustomAttributes attr)
{
// Test anyhit-specific intrinsics
uint hitKind = HitKind();
uint instanceID = InstanceID();
float rayT = RayTCurrent();
// Count hits for testing
payload.hitCount++;
// Test termination based on some criteria
if (payload.terminateRequested || payload.hitCount > 3)
{
// Test optixTerminateRay - only available in anyhit shaders
AcceptHitAndEndSearch(); // This maps to optixTerminateRay for CUDA
}
else
{
// Test ignoring hit to continue traversal
IgnoreHit();
}
}
[shader("miss")]
void missShader(inout RayPayload payload)
{
// Initialize with miss data
payload.data.hitKind = 0;
payload.data.instanceIndex = ~0u;
}
[shader("raygeneration")]
void rayGenShader()
{
uint2 index = DispatchRaysIndex().xy;
RayPayload payload;
payload.shouldTerminate = (index.x % 2) == 0;
RayDesc ray;
ray.Origin = float3(index.x, index.y, 0);
ray.Direction = float3(0, 0, 1);
ray.TMin = 0.001f;
ray.TMax = 1000.0f;
// Test optixTrace through HitObject TraceRay
HitObject hit = HitObject::TraceRay(
scene,
RAY_FLAG_NONE,
0xFF,
0,
1,
0,
ray,
payload.data
);
// Test optixMakeHitObject and optixHitObjectGetTraverseData
// Create a custom hit object with specific parameters
CustomAttributes testAttrs;
testAttrs.attr0 = 1.0f;
testAttrs.attr1 = 42;
uint hitGroupRecordIndex = 0;
uint instanceIndex = index.x;
uint geometryIndex = 0;
uint primitiveIndex = index.y;
uint hitKind = 0;
// Test optixMakeHitObject through HitObject::MakeHit
HitObject customHit = HitObject::MakeHit(
hitGroupRecordIndex,
scene,
instanceIndex,
geometryIndex,
primitiveIndex,
hitKind,
ray,
testAttrs
);
// Test optixHitObjectGetTraverseData - this should be called internally
// by the HitObject operations and generate the optix call
bool isValidHit = customHit.IsHit();
if (isValidHit)
{
// Access traverse data indirectly through HitObject queries
CustomAttributes retrievedAttrs = customHit.GetAttributes<CustomAttributes>();
payload.data.hitObjAttr0 = retrievedAttrs.attr0;
payload.data.hitObjAttr1 = retrievedAttrs.attr1;
}
}
|