xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan/grl/gpu/bvh_build_primref.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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(&centroidBounds);
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(&centroidBounds);
234     }
235 
236 
237     struct AABB subgroup_bbox = AABB_sub_group_reduce(&new_primref);
238     struct AABB subgroup_CentroidBounds = AABB_sub_group_reduce(&centroidBounds);
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