@@ -71,12 +71,12 @@ layout(std140, binding = 1) buffer restrict readonly RaysBlock
71
71
72
72
layout(std140, binding = 2) buffer restrict readonly NumraysBlock
73
73
{
74
- int Numrays;
74
+ uint Numrays;
75
75
};
76
76
77
77
layout(std430, binding = 3) buffer StackBlock
78
78
{
79
- int Stack[];
79
+ uint Stack[];
80
80
};
81
81
82
82
layout(std430, binding = 4) buffer restrict writeonly HitsBlock
@@ -86,15 +86,239 @@ layout(std430, binding = 4) buffer restrict writeonly HitsBlock
86
86
87
87
layout(std430, binding = 4) buffer restrict writeonly HitsResults
88
88
{
89
- int Hitresults[];
89
+ uint Hitresults[];
90
90
};
91
91
92
92
layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
93
93
94
94
shared uint lds_stack[GROUP_SIZE * LDS_STACK_SIZE];
95
95
96
+ float copysign(float a, float b)
97
+ {
98
+ return sign(b) >= 0.f ? a : -a;
99
+ }
100
+
101
+ float mymin3(float a, float b, float c)
102
+ {
103
+ return min(c, min(a, b));
104
+ }
105
+
106
+ float mymax3(float a, float b, float c)
107
+ {
108
+ return max(c, max(a, b));
109
+ }
110
+
111
+ vec2 calculate_barycentrics(vec3 p, vec3 v1, vec3 v2, vec3 v3)
112
+ {
113
+ vec3 e1 = v2 - v1;
114
+ vec3 e2 = v3 - v1;
115
+ vec3 e = p - v1;
116
+ float d00 = dot(e1, e1);
117
+ float d01 = dot(e1, e2);
118
+ float d11 = dot(e2, e2);
119
+ float d20 = dot(e, e1);
120
+ float d21 = dot(e, e2);
121
+ float invdenom = 1.0 / (d00 * d11 - d01 * d01);
122
+ float b1 = (d11 * d20 - d01 * d21) * invdenom;
123
+ float b2 = (d00 * d21 - d01 * d20) * invdenom;
124
+ return vec2(b1, b2);
125
+ }
126
+
127
+ vec2 fast_intersect_aabb(
128
+ vec3 pmin, vec3 pmax,
129
+ vec3 invdir, vec3 oxinvdir,
130
+ float t_max)
131
+ {
132
+ vec3 f = fma(pmax, invdir, oxinvdir);
133
+ vec3 n = fma(pmin, invdir, oxinvdir);
134
+ vec3 tmax = max(f, n);
135
+ vec3 tmin = min(f, n);
136
+ float t1 = min(mymin3(tmax.x, tmax.y, tmax.z), t_max);
137
+ float t0 = max(mymax3(tmin.x, tmin.y, tmin.z), 0.0);
138
+ return vec2(t0, t1);
139
+ }
140
+
141
+ float fast_intersect_triangle(ray r, vec3 v1, vec3 v2, vec3 v3, float t_max)
142
+ {
143
+ vec3 e1 = v2 - v1;
144
+ vec3 e2 = v3 - v1;
145
+ vec3 s1 = cross(r.d.xyz, e2);
146
+ float invd = 1.0 / dot(s1, e1);
147
+ vec3 d = r.o.xyz - v1;
148
+ float b1 = dot(d, s1) * invd;
149
+ vec3 s2 = cross(d, e1);
150
+ float b2 = dot(r.d.xyz, s2) * invd;
151
+ float temp = dot(e2, s2) * invd;
152
+
153
+ if (b1 < 0.0 || b1 > 1.0 ||
154
+ b2 < 0.0 || b1 + b2 > 1.0 ||
155
+ temp < 0.0 || temp > t_max)
156
+ {
157
+ return t_max;
158
+ }
159
+ else
160
+ {
161
+ return temp;
162
+ }
163
+ }
164
+
165
+ vec3 safe_invdir(vec3 d)
166
+ {
167
+ float dirx = d.x;
168
+ float diry = d.y;
169
+ float dirz = d.z;
170
+ float ooeps = 1e-5;
171
+ vec3 invdir;
172
+ invdir.x = 1.0 / (abs(dirx) > ooeps ? dirx : copysign(ooeps, dirx));
173
+ invdir.y = 1.0 / (abs(diry) > ooeps ? diry : copysign(ooeps, diry));
174
+ invdir.z = 1.0 / (abs(dirz) > ooeps ? dirz : copysign(ooeps, dirz));
175
+ return invdir;
176
+ }
177
+
96
178
void intersect_main()
97
179
{
180
+ uint index = gl_GlobalInvocationID.x;
181
+ uint local_index = gl_LocalInvocationID.x;
182
+
183
+ // Handle only working subset
184
+ if (index >= Numrays) return;
185
+
186
+ ray myRay = Rays[index]; // TODO: VK:- SC SPIR-V module not valid: OpStore Pointer <id> '136's type does not match Object <id> '137's type. (gboisse)
187
+ vec3 invDir = safe_invdir(myRay.d.xyz);
188
+ vec3 oxInvDir = -myRay.o.xyz * invDir;
189
+
190
+ // Intersection parametric distance
191
+ float closest_t = myRay.o.w;
192
+
193
+ // Current node address
194
+ uint addr = 0;
195
+ // Current closest address
196
+ uint closest_addr = INVALID_ADDR;
197
+
198
+ uint stack_bottom = STACK_SIZE * index;
199
+ uint sptr = stack_bottom;
200
+ uint lds_stack_bottom = local_index * LDS_STACK_SIZE;
201
+ uint lds_sptr = lds_stack_bottom;
202
+
203
+ lds_stack[lds_sptr++] = INVALID_ADDR;
204
+
205
+ #if 0
206
+
207
+ while (addr != INVALID_ADDR)
208
+ {
209
+ BvhNode node = bvh[addr];
210
+
211
+ if (INTERNAL_NODE(node))
212
+ {
213
+ vec2 s0 = fast_intersect_aabb(
214
+ node.aabb_left_min_or_v0,
215
+ node.aabb_left_max_or_v1,
216
+ invDir, oxInvDir, closest_t);
217
+ vec2 s1 = fast_intersect_aabb(
218
+ node.aabb_right_min_or_v2,
219
+ node.aabb_right_max,
220
+ invDir, oxInvDir, closest_t);
221
+
222
+ bool traverse_c0 = (s0.x <= s0.y);
223
+ bool traverse_c1 = (s1.x <= s1.y);
224
+ bool c1first = traverse_c1 && (s0.x > s1.x);
225
+
226
+ if (traverse_c0 || traverse_c1) {
227
+ uint deferred = INVALID_ADDR;
228
+
229
+ if (c1first || !traverse_c0) {
230
+ addr = node.addr_right;
231
+ deferred = node.addr_left;
232
+ }
233
+ else {
234
+ addr = node.addr_left;
235
+ deferred = node.addr_right;
236
+ }
237
+
238
+ if (traverse_c0 && traverse_c1) {
239
+ if (lds_sptr - lds_stack_bottom >= LDS_STACK_SIZE) {
240
+ for (int i = 1; i < LDS_STACK_SIZE; ++i) {
241
+ stack[sptr + i] = lds_stack[lds_stack_bottom + i];
242
+ }
243
+
244
+ sptr += LDS_STACK_SIZE;
245
+ lds_sptr = lds_stack_bottom + 1;
246
+ }
247
+
248
+ lds_stack[lds_sptr++] = deferred;
249
+ }
250
+
251
+ continue;
252
+ }
253
+ }
254
+ else {
255
+ float t = fast_intersect_triangle(
256
+ myRay,
257
+ node.aabb_left_min_or_v0,
258
+ node.aabb_left_max_or_v1,
259
+ node.aabb_right_min_or_v2,
260
+ closest_t);
261
+
262
+ if (t < closest_t) {
263
+ closest_t = t;
264
+ closest_addr = addr;
265
+ }
266
+ }
267
+
268
+ addr = lds_stack[--lds_sptr];
269
+
270
+ if (addr == INVALID_ADDR && sptr > stack_bottom) {
271
+ sptr -= LDS_STACK_SIZE;
272
+ for (int i = 1; i < LDS_STACK_SIZE; ++i) {
273
+ lds_stack[lds_stack_bottom + i] = stack[sptr + i];
274
+ }
275
+
276
+ lds_sptr = lds_stack_bottom + LDS_STACK_SIZE - 1;
277
+ addr = lds_stack[lds_sptr];
278
+ }
279
+ }
280
+
281
+ #endif
282
+
283
+ #if 0
284
+ // TODO: what, why?!? (gboisse)
285
+ Intersection isect;
286
+ isect.padding.x = 667;
287
+ isect.padding.y = r.padding.x;
288
+ isect.uvwt = vec4(0.0f, 0.0f, 0.0f, closest_t);
289
+
290
+ #if 0
291
+
292
+ // Check if we have found an intersection
293
+ if (closest_addr != INVALID_ADDR)
294
+ {
295
+ // Calculate hit position
296
+ BvhNode node = Nodes[closest_addr];
297
+ vec3 p = myRay.o.xyz + closest_t * myRay.d.xyz;
298
+
299
+ // Calculate barycentric coordinates
300
+ isect.uvwt.xy = calculate_barycentrics(
301
+ p,
302
+ node.aabb_left_min_or_v0,
303
+ node.aabb_left_max_or_v1,
304
+ node.aabb_right_min_or_v2
305
+ );
306
+
307
+ // Update hit information
308
+ hit.prim_id = node.prim_id;
309
+ hit.shape_id = node.mesh_id;
310
+ }
311
+ else
312
+ #endif
313
+ {
314
+ // Miss here
315
+ isect.prim_id = -1;
316
+ isect.shape_id = -1;
317
+ }
318
+
319
+ // Write result to memory
320
+ Hits[index] = isect;
321
+ #endif
98
322
}
99
323
100
324
void occluded_main()
0 commit comments