1 //
2 // Copyright (C) 2009-2021 Intel Corporation
3 //
4 // SPDX-License-Identifier: MIT
5 //
6 //
7
8 #if 0
9 /*
10
11 Create primrefs from array of instance descriptors.
12
13 */
14
15 void store_instance_primref(
16 global struct BVHBase* top_bvh,
17 global struct Globals* globals,
18 global PrimRef* primrefs,
19 bool alloc_primref,
20 PrimRef new_primref )
21 {
22 uint allocatePrimref = alloc_primref ? 1 : 0;
23 uint index = 0;
24 uint numAllocations = sub_group_reduce_add(allocatePrimref);
25
26 if (get_sub_group_local_id() == 0)
27 {
28 index = atomic_add_global(&globals->numPrimitives, numAllocations);
29 }
30
31 index = sub_group_broadcast(index, 0);
32 index = index + sub_group_scan_exclusive_add(allocatePrimref);
33
34 if (allocatePrimref)
35 {
36 primrefs[index] = new_primref;
37 }
38
39 struct AABB centroidBounds;
40 centroidBounds.lower = centroidBounds.upper = AABB_centroid2(&new_primref);
41 struct AABB subgroup_bbox = AABB_sub_group_reduce(&new_primref);
42 struct AABB subgroup_CentroidBounds = AABB_sub_group_reduce(¢roidBounds);
43
44 if (get_sub_group_local_id() == 0)
45 {
46 AABB3f_atomic_merge_global_lu(&top_bvh->Meta.bounds, subgroup_bbox.lower.xyz, subgroup_bbox.upper.xyz);
47 AABB_global_atomic_merge(&globals->centroidBounds, &subgroup_CentroidBounds);
48 }
49 }
50
51
52
53 // Compute transformed blas AABB. Returns false if instance is degenerate
54 bool create_instance_primref(
55 PrimRef* ref_out,
56 global __const struct GRL_RAYTRACING_INSTANCE_DESC* instance,
57 global struct BVHBase* bvh,
58 uint instanceMask,
59 uint instanceIndex
60 )
61 {
62 struct AABB3f bbox;
63 bool alloc_primref = false;
64 uint rootNodeOffset = NO_NODE_OFFSET;
65 if (bvh != 0)
66 {
67 alloc_primref = true;
68 AABB3f AS_bounds = BVHBase_GetRootAABB(bvh);
69
70 const bool valid_min = isfinite(AS_bounds.lower[0]) && isfinite(AS_bounds.lower[1]) && isfinite(AS_bounds.lower[2]);
71 const bool valid_max = isfinite(AS_bounds.upper[0]) && isfinite(AS_bounds.upper[1]) && isfinite(AS_bounds.upper[2]);
72
73 if (!valid_min || !valid_max || instanceMask == 0)
74 {
75 // degenerated instance case
76
77 // TODO this should be under if ( allocate backpointers )
78 {
79 // we have to allocate the primref because this instance can be updated to non-degenerated
80 // take the origin of the instance as a bounding box.
81
82 bbox.lower[0] = instance->Transform[3];
83 bbox.lower[1] = instance->Transform[7];
84 bbox.lower[2] = instance->Transform[11];
85 bbox.upper[0] = instance->Transform[3];
86 bbox.upper[1] = instance->Transform[7];
87 bbox.upper[2] = instance->Transform[11];
88 instanceMask = 0;
89 }
90 }
91 else
92 {
93 rootNodeOffset = BVH_ROOT_NODE_OFFSET;
94 float transformOverhead = 0.0f;
95 bbox = compute_xfm_bbox(instance->Transform, BVHBase_GetRootNode(bvh), XFM_BOX_NOT_REFINED_TAKE_CLIPBOX, &AS_bounds, transformOverhead);
96 }
97 }
98
99 *ref_out = PRIMREF_set_instance(AABB3f_load_lower(&bbox), AABB3f_load_upper(&bbox), instanceIndex, instanceMask, rootNodeOffset, 0);
100 return alloc_primref;
101 }
102
103 GRL_INLINE void primrefs_from_instances(
104 global struct Globals* globals,
105 global struct BVHBase* top_bvh,
106 global __const struct GRL_RAYTRACING_INSTANCE_DESC* instance,
107 uint instanceIndex,
108 global struct AABB* primrefs)
109 {
110 bool alloc_primref = false;
111 PrimRef new_primref;
112 AABB_init(&new_primref);
113
114 if (instance)
115 {
116 uint mask = GRL_get_InstanceMask(instance);
117 global struct BVHBase* bvh = (global struct BVHBase*)instance->AccelerationStructure;
118 alloc_primref = create_instance_primref(&new_primref, instance, bvh, mask, instanceIndex);
119 }
120
121 store_instance_primref(top_bvh, globals, primrefs, alloc_primref, new_primref);
122 }
123 #endif
124
125 #if 1
primrefs_from_instances(global struct Globals * globals,global struct BVHBase * top_bvh,global __const struct GRL_RAYTRACING_INSTANCE_DESC * instance,uint instanceIndex,global struct AABB * primrefs,global GRL_RAYTRACING_AABB * procedural_aabb,uint allowUpdate)126 GRL_INLINE void primrefs_from_instances(
127 global struct Globals* globals,
128 global struct BVHBase* top_bvh,
129 global __const struct GRL_RAYTRACING_INSTANCE_DESC* instance,
130 uint instanceIndex,
131 global struct AABB* primrefs,
132 global GRL_RAYTRACING_AABB* procedural_aabb,
133 uint allowUpdate
134 )
135 {
136 struct AABB3f bbox;
137 uint allocatePrimref = 0;
138
139 uint rootNodeOffset = NO_NODE_OFFSET;
140 uint instanceMask = 0;
141
142 bool is_procedural = (procedural_aabb != 0);
143
144 if( instance )
145 {
146 instanceMask = GRL_get_InstanceMask(instance) ;
147 if ( is_procedural )
148 {
149 // procedural instance primref
150 allocatePrimref = 1;
151
152 float3 lower = (float3)(procedural_aabb->MinX, procedural_aabb->MinY, procedural_aabb->MinZ);
153 float3 upper = (float3)(procedural_aabb->MaxX, procedural_aabb->MaxY, procedural_aabb->MaxZ);
154
155 if (instanceMask == 0 || any(lower > upper))
156 {
157 bbox.lower[0] = instance->Transform[3];
158 bbox.lower[1] = instance->Transform[7];
159 bbox.lower[2] = instance->Transform[11];
160 bbox.upper[0] = instance->Transform[3];
161 bbox.upper[1] = instance->Transform[7];
162 bbox.upper[2] = instance->Transform[11];
163 instanceMask = 0;
164 }
165 else
166 {
167 bbox = transform_aabb(lower, upper, instance->Transform);
168 }
169 }
170 else
171 {
172 // HW-instance primref
173
174 global struct BVHBase* bvh = instance ?
175 (global struct BVHBase*)instance->AccelerationStructure :
176 0;
177
178 if (bvh != 0)
179 {
180 AABB3f AS_bounds = BVHBase_GetRootAABB(bvh);
181
182 const bool valid_min = isfinite(AS_bounds.lower[0]) && isfinite(AS_bounds.lower[1]) && isfinite(AS_bounds.lower[2]);
183 const bool valid_max = isfinite(AS_bounds.upper[0]) && isfinite(AS_bounds.upper[1]) && isfinite(AS_bounds.upper[2]);
184
185
186 if (valid_min && valid_max && instanceMask != 0)
187 {
188 allocatePrimref = 1;
189 rootNodeOffset = BVH_ROOT_NODE_OFFSET;
190 float transformOverhead = 0.0f;
191 bbox = compute_xfm_bbox(instance->Transform, BVHBase_GetRootNode(bvh), XFM_BOX_NOT_REFINED_TAKE_CLIPBOX, &AS_bounds, transformOverhead);
192 }
193 else if (allowUpdate)
194 {
195 // degenerated instance case
196 // we have to allocate the primref because this instance can be updated to non-degenerated
197 // take the origin of the instance as a bounding box.
198 allocatePrimref = 1;
199 bbox.lower[0] = instance->Transform[3];
200 bbox.lower[1] = instance->Transform[7];
201 bbox.lower[2] = instance->Transform[11];
202 bbox.upper[0] = instance->Transform[3];
203 bbox.upper[1] = instance->Transform[7];
204 bbox.upper[2] = instance->Transform[11];
205 instanceMask = 0;
206 }
207 }
208 }
209 }
210
211 uint index = 0;
212 uint numAllocations = sub_group_reduce_add(allocatePrimref);
213
214 if (get_sub_group_local_id() == 0)
215 {
216 index = atomic_add_global(&globals->numPrimitives, numAllocations);
217 }
218
219 index = sub_group_broadcast(index, 0);
220 index = index + sub_group_scan_exclusive_add(allocatePrimref);
221
222 struct AABB new_primref;
223 struct AABB centroidBounds;
224 if (allocatePrimref)
225 {
226 new_primref = PRIMREF_set_instance(AABB3f_load_lower(&bbox), AABB3f_load_upper(&bbox), instanceIndex, instanceMask, rootNodeOffset, is_procedural);
227 primrefs[index] = new_primref;
228 centroidBounds.lower = centroidBounds.upper = AABB_centroid2(&new_primref);
229 }
230 else
231 {
232 AABB_init(&new_primref);
233 AABB_init(¢roidBounds);
234 }
235
236
237 struct AABB subgroup_bbox = AABB_sub_group_reduce(&new_primref);
238 struct AABB subgroup_CentroidBounds = AABB_sub_group_reduce(¢roidBounds);
239
240 if (get_sub_group_local_id() == 0)
241 {
242 AABB3f_atomic_merge_global_lu(&top_bvh->Meta.bounds, subgroup_bbox.lower.xyz, subgroup_bbox.upper.xyz);
243 AABB_global_atomic_merge(&globals->centroidBounds, &subgroup_CentroidBounds);
244 }
245 }
246 #endif
247