xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/lavapipe/lvp_acceleration_structure.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2023 Valve Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "lvp_acceleration_structure.h"
7 #include "lvp_entrypoints.h"
8 
9 #include "util/format/format_utils.h"
10 #include "util/half_float.h"
11 
12 static_assert(sizeof(struct lvp_bvh_triangle_node) % 8 == 0, "lvp_bvh_triangle_node is not padded");
13 static_assert(sizeof(struct lvp_bvh_aabb_node) % 8 == 0, "lvp_bvh_aabb_node is not padded");
14 static_assert(sizeof(struct lvp_bvh_instance_node) % 8 == 0, "lvp_bvh_instance_node is not padded");
15 static_assert(sizeof(struct lvp_bvh_box_node) % 8 == 0, "lvp_bvh_box_node is not padded");
16 
17 VKAPI_ATTR void VKAPI_CALL
lvp_GetAccelerationStructureBuildSizesKHR(VkDevice _device,VkAccelerationStructureBuildTypeKHR buildType,const VkAccelerationStructureBuildGeometryInfoKHR * pBuildInfo,const uint32_t * pMaxPrimitiveCounts,VkAccelerationStructureBuildSizesInfoKHR * pSizeInfo)18 lvp_GetAccelerationStructureBuildSizesKHR(
19    VkDevice _device, VkAccelerationStructureBuildTypeKHR buildType,
20    const VkAccelerationStructureBuildGeometryInfoKHR *pBuildInfo,
21    const uint32_t *pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR *pSizeInfo)
22 {
23    pSizeInfo->buildScratchSize = 64;
24    pSizeInfo->updateScratchSize = 64;
25 
26    uint32_t leaf_count = 0;
27    for (uint32_t i = 0; i < pBuildInfo->geometryCount; i++)
28       leaf_count += pMaxPrimitiveCounts[i];
29 
30    uint32_t internal_count = MAX2(leaf_count, 2) - 1;
31 
32    VkGeometryTypeKHR geometry_type = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
33    if (pBuildInfo->geometryCount) {
34       if (pBuildInfo->pGeometries)
35          geometry_type = pBuildInfo->pGeometries[0].geometryType;
36       else
37          geometry_type = pBuildInfo->ppGeometries[0]->geometryType;
38    }
39 
40    uint32_t leaf_size;
41    switch (geometry_type) {
42    case VK_GEOMETRY_TYPE_TRIANGLES_KHR:
43       leaf_size = sizeof(struct lvp_bvh_triangle_node);
44       break;
45    case VK_GEOMETRY_TYPE_AABBS_KHR:
46       leaf_size = sizeof(struct lvp_bvh_aabb_node);
47       break;
48    case VK_GEOMETRY_TYPE_INSTANCES_KHR:
49       leaf_size = sizeof(struct lvp_bvh_instance_node);
50       break;
51    default:
52       unreachable("Unknown VkGeometryTypeKHR");
53    }
54 
55    uint32_t bvh_size = sizeof(struct lvp_bvh_header);
56    bvh_size += leaf_count * leaf_size;
57    bvh_size += internal_count * sizeof(struct lvp_bvh_box_node);
58 
59    pSizeInfo->accelerationStructureSize = bvh_size;
60 }
61 
62 VKAPI_ATTR VkResult VKAPI_CALL
lvp_WriteAccelerationStructuresPropertiesKHR(VkDevice _device,uint32_t accelerationStructureCount,const VkAccelerationStructureKHR * pAccelerationStructures,VkQueryType queryType,size_t dataSize,void * pData,size_t stride)63 lvp_WriteAccelerationStructuresPropertiesKHR(
64    VkDevice _device, uint32_t accelerationStructureCount,
65    const VkAccelerationStructureKHR *pAccelerationStructures, VkQueryType queryType,
66    size_t dataSize, void *pData, size_t stride)
67 {
68    unreachable("Unimplemented");
69    return VK_ERROR_FEATURE_NOT_PRESENT;
70 }
71 
72 VKAPI_ATTR VkResult VKAPI_CALL
lvp_BuildAccelerationStructuresKHR(VkDevice _device,VkDeferredOperationKHR deferredOperation,uint32_t infoCount,const VkAccelerationStructureBuildGeometryInfoKHR * pInfos,const VkAccelerationStructureBuildRangeInfoKHR * const * ppBuildRangeInfos)73 lvp_BuildAccelerationStructuresKHR(
74    VkDevice _device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount,
75    const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
76    const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos)
77 {
78    unreachable("Unimplemented");
79    return VK_ERROR_FEATURE_NOT_PRESENT;
80 }
81 
82 VKAPI_ATTR void VKAPI_CALL
lvp_GetDeviceAccelerationStructureCompatibilityKHR(VkDevice _device,const VkAccelerationStructureVersionInfoKHR * pVersionInfo,VkAccelerationStructureCompatibilityKHR * pCompatibility)83 lvp_GetDeviceAccelerationStructureCompatibilityKHR(
84    VkDevice _device, const VkAccelerationStructureVersionInfoKHR *pVersionInfo,
85    VkAccelerationStructureCompatibilityKHR *pCompatibility)
86 {
87    uint8_t uuid[VK_UUID_SIZE];
88    lvp_device_get_cache_uuid(uuid);
89    bool compat = memcmp(pVersionInfo->pVersionData, uuid, VK_UUID_SIZE) == 0;
90    *pCompatibility = compat ? VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR
91                             : VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR;
92 }
93 
94 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CopyAccelerationStructureKHR(VkDevice _device,VkDeferredOperationKHR deferredOperation,const VkCopyAccelerationStructureInfoKHR * pInfo)95 lvp_CopyAccelerationStructureKHR(VkDevice _device, VkDeferredOperationKHR deferredOperation,
96                                  const VkCopyAccelerationStructureInfoKHR *pInfo)
97 {
98    unreachable("Unimplemented");
99    return VK_ERROR_FEATURE_NOT_PRESENT;
100 }
101 
102 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CopyMemoryToAccelerationStructureKHR(VkDevice _device,VkDeferredOperationKHR deferredOperation,const VkCopyMemoryToAccelerationStructureInfoKHR * pInfo)103 lvp_CopyMemoryToAccelerationStructureKHR(VkDevice _device, VkDeferredOperationKHR deferredOperation,
104                                          const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo)
105 {
106    unreachable("Unimplemented");
107    return VK_ERROR_FEATURE_NOT_PRESENT;
108 }
109 
110 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CopyAccelerationStructureToMemoryKHR(VkDevice _device,VkDeferredOperationKHR deferredOperation,const VkCopyAccelerationStructureToMemoryInfoKHR * pInfo)111 lvp_CopyAccelerationStructureToMemoryKHR(VkDevice _device, VkDeferredOperationKHR deferredOperation,
112                                          const VkCopyAccelerationStructureToMemoryInfoKHR *pInfo)
113 {
114    unreachable("Unimplemented");
115    return VK_ERROR_FEATURE_NOT_PRESENT;
116 }
117 
118 static uint32_t
lvp_pack_geometry_id_and_flags(uint32_t geometry_id,uint32_t flags)119 lvp_pack_geometry_id_and_flags(uint32_t geometry_id, uint32_t flags)
120 {
121    uint32_t geometry_id_and_flags = geometry_id;
122    if (flags & VK_GEOMETRY_OPAQUE_BIT_KHR)
123       geometry_id_and_flags |= LVP_GEOMETRY_OPAQUE;
124 
125    return geometry_id_and_flags;
126 }
127 
128 static uint32_t
lvp_pack_sbt_offset_and_flags(uint32_t sbt_offset,VkGeometryInstanceFlagsKHR flags)129 lvp_pack_sbt_offset_and_flags(uint32_t sbt_offset, VkGeometryInstanceFlagsKHR flags)
130 {
131    uint32_t ret = sbt_offset;
132    if (flags & VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR)
133       ret |= LVP_INSTANCE_FORCE_OPAQUE;
134    if (!(flags & VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR))
135       ret |= LVP_INSTANCE_NO_FORCE_NOT_OPAQUE;
136    if (flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR)
137       ret |= LVP_INSTANCE_TRIANGLE_FACING_CULL_DISABLE;
138    if (flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR)
139       ret |= LVP_INSTANCE_TRIANGLE_FLIP_FACING;
140    return ret;
141 }
142 
143 struct lvp_build_internal_ctx {
144    uint8_t *dst;
145    uint32_t dst_offset;
146 
147    void *leaf_nodes;
148    uint32_t leaf_nodes_offset;
149    uint32_t leaf_node_type;
150    uint32_t leaf_node_size;
151 };
152 
153 static uint32_t
lvp_build_internal_node(struct lvp_build_internal_ctx * ctx,uint32_t first_leaf,uint32_t last_leaf)154 lvp_build_internal_node(struct lvp_build_internal_ctx *ctx, uint32_t first_leaf, uint32_t last_leaf)
155 {
156    uint32_t dst_offset = ctx->dst_offset;
157    ctx->dst_offset += sizeof(struct lvp_bvh_box_node);
158 
159    uint32_t node_id = dst_offset | lvp_bvh_node_internal;
160 
161    struct lvp_bvh_box_node *node = (void *)(ctx->dst + dst_offset);
162 
163    uint32_t split = (first_leaf + last_leaf) / 2;
164 
165    if (first_leaf < split)
166       node->children[0] = lvp_build_internal_node(ctx, first_leaf, split);
167    else
168       node->children[0] =
169          (ctx->leaf_nodes_offset + (first_leaf * ctx->leaf_node_size)) | ctx->leaf_node_type;
170 
171    if (first_leaf < last_leaf) {
172       if (split + 1 < last_leaf)
173          node->children[1] = lvp_build_internal_node(ctx, split + 1, last_leaf);
174       else
175          node->children[1] =
176             (ctx->leaf_nodes_offset + (last_leaf * ctx->leaf_node_size)) | ctx->leaf_node_type;
177    } else {
178       node->children[1] = LVP_BVH_INVALID_NODE;
179    }
180 
181    for (uint32_t i = 0; i < 2; i++) {
182       struct lvp_aabb *aabb = &node->bounds[i];
183 
184       if (node->children[i] == LVP_BVH_INVALID_NODE) {
185          aabb->min.x = INFINITY;
186          aabb->min.y = INFINITY;
187          aabb->min.z = INFINITY;
188          aabb->max.x = -INFINITY;
189          aabb->max.y = -INFINITY;
190          aabb->max.z = -INFINITY;
191          continue;
192       }
193 
194       uint32_t child_offset = node->children[i] & (~3u);
195       uint32_t child_type = node->children[i] & 3u;
196       void *child_node = (void *)(ctx->dst + child_offset);
197 
198       switch (child_type) {
199       case lvp_bvh_node_triangle: {
200          struct lvp_bvh_triangle_node *triangle = child_node;
201 
202          aabb->min.x = MIN3(triangle->coords[0][0], triangle->coords[1][0], triangle->coords[2][0]);
203          aabb->min.y = MIN3(triangle->coords[0][1], triangle->coords[1][1], triangle->coords[2][1]);
204          aabb->min.z = MIN3(triangle->coords[0][2], triangle->coords[1][2], triangle->coords[2][2]);
205 
206          aabb->max.x = MAX3(triangle->coords[0][0], triangle->coords[1][0], triangle->coords[2][0]);
207          aabb->max.y = MAX3(triangle->coords[0][1], triangle->coords[1][1], triangle->coords[2][1]);
208          aabb->max.z = MAX3(triangle->coords[0][2], triangle->coords[1][2], triangle->coords[2][2]);
209 
210          break;
211       }
212       case lvp_bvh_node_internal: {
213          struct lvp_bvh_box_node *box = child_node;
214 
215          aabb->min.x = MIN2(box->bounds[0].min.x, box->bounds[1].min.x);
216          aabb->min.y = MIN2(box->bounds[0].min.y, box->bounds[1].min.y);
217          aabb->min.z = MIN2(box->bounds[0].min.z, box->bounds[1].min.z);
218 
219          aabb->max.x = MAX2(box->bounds[0].max.x, box->bounds[1].max.x);
220          aabb->max.y = MAX2(box->bounds[0].max.y, box->bounds[1].max.y);
221          aabb->max.z = MAX2(box->bounds[0].max.z, box->bounds[1].max.z);
222 
223          break;
224       }
225       case lvp_bvh_node_instance: {
226          struct lvp_bvh_instance_node *instance = child_node;
227          struct lvp_bvh_header *instance_header = (void *)(uintptr_t)instance->bvh_ptr;
228 
229          float bounds[2][3];
230 
231          float header_bounds[2][3];
232          memcpy(header_bounds, &instance_header->bounds, sizeof(struct lvp_aabb));
233 
234          for (unsigned j = 0; j < 3; ++j) {
235             bounds[0][j] = instance->otw_matrix.values[j][3];
236             bounds[1][j] = instance->otw_matrix.values[j][3];
237             for (unsigned k = 0; k < 3; ++k) {
238                bounds[0][j] += MIN2(instance->otw_matrix.values[j][k] * header_bounds[0][k],
239                                     instance->otw_matrix.values[j][k] * header_bounds[1][k]);
240                bounds[1][j] += MAX2(instance->otw_matrix.values[j][k] * header_bounds[0][k],
241                                     instance->otw_matrix.values[j][k] * header_bounds[1][k]);
242             }
243          }
244 
245          memcpy(aabb, bounds, sizeof(struct lvp_aabb));
246 
247          break;
248       }
249       case lvp_bvh_node_aabb: {
250          struct lvp_bvh_aabb_node *aabb_node = child_node;
251 
252          memcpy(aabb, &aabb_node->bounds, sizeof(struct lvp_aabb));
253 
254          break;
255       }
256       default:
257          unreachable("Invalid node type");
258       }
259    }
260 
261    return node_id;
262 }
263 
264 void
lvp_build_acceleration_structure(VkAccelerationStructureBuildGeometryInfoKHR * info,const VkAccelerationStructureBuildRangeInfoKHR * ranges)265 lvp_build_acceleration_structure(VkAccelerationStructureBuildGeometryInfoKHR *info,
266                                  const VkAccelerationStructureBuildRangeInfoKHR *ranges)
267 {
268    VK_FROM_HANDLE(vk_acceleration_structure, accel_struct, info->dstAccelerationStructure);
269    void *dst = (void *)(uintptr_t)vk_acceleration_structure_get_va(accel_struct);
270 
271    memset(dst, 0, accel_struct->size);
272 
273    struct lvp_bvh_header *header = dst;
274    header->instance_count = 0;
275 
276    struct lvp_bvh_box_node *root = (void *)((uint8_t *)dst + sizeof(struct lvp_bvh_header));
277 
278    uint32_t leaf_count = 0;
279    for (unsigned i = 0; i < info->geometryCount; i++)
280       leaf_count += ranges[i].primitiveCount;
281 
282    if (!leaf_count) {
283       for (uint32_t i = 0; i < 2; i++) {
284          root->bounds[i].min.x = INFINITY;
285          root->bounds[i].min.y = INFINITY;
286          root->bounds[i].min.z = INFINITY;
287          root->bounds[i].max.x = -INFINITY;
288          root->bounds[i].max.y = -INFINITY;
289          root->bounds[i].max.z = -INFINITY;
290       }
291       return;
292    }
293 
294    uint32_t internal_count = MAX2(leaf_count, 2) - 1;
295 
296    uint32_t primitive_index = 0;
297 
298    header->leaf_nodes_offset =
299       sizeof(struct lvp_bvh_header) + sizeof(struct lvp_bvh_box_node) * internal_count;
300    void *leaf_nodes = (void *)((uint8_t *)dst + header->leaf_nodes_offset);
301 
302    for (unsigned i = 0; i < info->geometryCount; i++) {
303       const VkAccelerationStructureGeometryKHR *geom =
304          info->pGeometries ? &info->pGeometries[i] : info->ppGeometries[i];
305 
306       const VkAccelerationStructureBuildRangeInfoKHR *range = &ranges[i];
307 
308       uint32_t geometry_id_and_flags = lvp_pack_geometry_id_and_flags(i, geom->flags);
309 
310       switch (geom->geometryType) {
311       case VK_GEOMETRY_TYPE_TRIANGLES_KHR: {
312          assert(info->type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);
313 
314          const uint8_t *vertex_data_base = geom->geometry.triangles.vertexData.hostAddress;
315          vertex_data_base += range->firstVertex * geom->geometry.triangles.vertexStride;
316 
317          const uint8_t *index_data = geom->geometry.triangles.indexData.hostAddress;
318 
319          if (geom->geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR)
320             vertex_data_base += range->primitiveOffset;
321          else
322             index_data += range->primitiveOffset;
323 
324          VkTransformMatrixKHR transform_matrix = {
325             .matrix =
326                {
327                   {1.0, 0.0, 0.0, 0.0},
328                   {0.0, 1.0, 0.0, 0.0},
329                   {0.0, 0.0, 1.0, 0.0},
330                },
331          };
332 
333          const uint8_t *transform = geom->geometry.triangles.transformData.hostAddress;
334          if (transform) {
335             transform += range->transformOffset;
336             transform_matrix = *(VkTransformMatrixKHR *)transform;
337          }
338 
339          VkDeviceSize stride = geom->geometry.triangles.vertexStride;
340          VkFormat vertex_format = geom->geometry.triangles.vertexFormat;
341          VkIndexType index_type = geom->geometry.triangles.indexType;
342 
343          for (uint32_t j = 0; j < range->primitiveCount; j++) {
344             struct lvp_bvh_triangle_node *node = leaf_nodes;
345             node += primitive_index;
346 
347             node->primitive_id = j;
348             node->geometry_id_and_flags = geometry_id_and_flags;
349 
350             for (uint32_t v = 0; v < 3; v++) {
351                uint32_t index = range->firstVertex;
352                switch (index_type) {
353                case VK_INDEX_TYPE_NONE_KHR:
354                   index += j * 3 + v;
355                   break;
356                case VK_INDEX_TYPE_UINT8_EXT:
357                   index += *(const uint8_t *)index_data;
358                   index_data += 1;
359                   break;
360                case VK_INDEX_TYPE_UINT16:
361                   index += *(const uint16_t *)index_data;
362                   index_data += 2;
363                   break;
364                case VK_INDEX_TYPE_UINT32:
365                   index += *(const uint32_t *)index_data;
366                   index_data += 4;
367                   break;
368                case VK_INDEX_TYPE_MAX_ENUM:
369                   unreachable("Unhandled VK_INDEX_TYPE_MAX_ENUM");
370                   break;
371                }
372 
373                const uint8_t *vertex_data = vertex_data_base + index * stride;
374                float coords[4];
375                switch (vertex_format) {
376                case VK_FORMAT_R32G32_SFLOAT:
377                   coords[0] = *(const float *)(vertex_data + 0);
378                   coords[1] = *(const float *)(vertex_data + 4);
379                   coords[2] = 0.0f;
380                   coords[3] = 1.0f;
381                   break;
382                case VK_FORMAT_R32G32B32_SFLOAT:
383                   coords[0] = *(const float *)(vertex_data + 0);
384                   coords[1] = *(const float *)(vertex_data + 4);
385                   coords[2] = *(const float *)(vertex_data + 8);
386                   coords[3] = 1.0f;
387                   break;
388                case VK_FORMAT_R32G32B32A32_SFLOAT:
389                   coords[0] = *(const float *)(vertex_data + 0);
390                   coords[1] = *(const float *)(vertex_data + 4);
391                   coords[2] = *(const float *)(vertex_data + 8);
392                   coords[3] = *(const float *)(vertex_data + 12);
393                   break;
394                case VK_FORMAT_R16G16_SFLOAT:
395                   coords[0] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 0));
396                   coords[1] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 2));
397                   coords[2] = 0.0f;
398                   coords[3] = 1.0f;
399                   break;
400                case VK_FORMAT_R16G16B16_SFLOAT:
401                   coords[0] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 0));
402                   coords[1] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 2));
403                   coords[2] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 4));
404                   coords[3] = 1.0f;
405                   break;
406                case VK_FORMAT_R16G16B16A16_SFLOAT:
407                   coords[0] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 0));
408                   coords[1] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 2));
409                   coords[2] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 4));
410                   coords[3] = _mesa_half_to_float(*(const uint16_t *)(vertex_data + 6));
411                   break;
412                case VK_FORMAT_R16G16_SNORM:
413                   coords[0] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 0), 16);
414                   coords[1] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 2), 16);
415                   coords[2] = 0.0f;
416                   coords[3] = 1.0f;
417                   break;
418                case VK_FORMAT_R16G16_UNORM:
419                   coords[0] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 0), 16);
420                   coords[1] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 2), 16);
421                   coords[2] = 0.0f;
422                   coords[3] = 1.0f;
423                   break;
424                case VK_FORMAT_R16G16B16A16_SNORM:
425                   coords[0] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 0), 16);
426                   coords[1] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 2), 16);
427                   coords[2] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 4), 16);
428                   coords[3] = _mesa_snorm_to_float(*(const int16_t *)(vertex_data + 6), 16);
429                   break;
430                case VK_FORMAT_R16G16B16A16_UNORM:
431                   coords[0] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 0), 16);
432                   coords[1] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 2), 16);
433                   coords[2] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 4), 16);
434                   coords[3] = _mesa_unorm_to_float(*(const uint16_t *)(vertex_data + 6), 16);
435                   break;
436                case VK_FORMAT_R8G8_SNORM:
437                   coords[0] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 0), 8);
438                   coords[1] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 1), 8);
439                   coords[2] = 0.0f;
440                   coords[3] = 1.0f;
441                   break;
442                case VK_FORMAT_R8G8_UNORM:
443                   coords[0] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 0), 8);
444                   coords[1] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 1), 8);
445                   coords[2] = 0.0f;
446                   coords[3] = 1.0f;
447                   break;
448                case VK_FORMAT_R8G8B8A8_SNORM:
449                   coords[0] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 0), 8);
450                   coords[1] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 1), 8);
451                   coords[2] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 2), 8);
452                   coords[3] = _mesa_snorm_to_float(*(const int8_t *)(vertex_data + 3), 8);
453                   break;
454                case VK_FORMAT_R8G8B8A8_UNORM:
455                   coords[0] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 0), 8);
456                   coords[1] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 1), 8);
457                   coords[2] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 2), 8);
458                   coords[3] = _mesa_unorm_to_float(*(const uint8_t *)(vertex_data + 3), 8);
459                   break;
460                case VK_FORMAT_A2B10G10R10_UNORM_PACK32: {
461                   uint32_t val = *(const uint32_t *)vertex_data;
462                   coords[0] = _mesa_unorm_to_float((val >> 0) & 0x3FF, 10);
463                   coords[1] = _mesa_unorm_to_float((val >> 10) & 0x3FF, 10);
464                   coords[2] = _mesa_unorm_to_float((val >> 20) & 0x3FF, 10);
465                   coords[3] = _mesa_unorm_to_float((val >> 30) & 0x3, 2);
466                } break;
467                default:
468                   unreachable("Unhandled vertex format in BVH build");
469                }
470 
471                for (unsigned comp = 0; comp < 3; comp++) {
472                   float r = 0;
473                   for (unsigned col = 0; col < 4; col++)
474                      r += transform_matrix.matrix[comp][col] * coords[col];
475 
476                   node->coords[v][comp] = r;
477                }
478             }
479 
480             primitive_index++;
481          }
482 
483          break;
484       }
485       case VK_GEOMETRY_TYPE_AABBS_KHR: {
486          assert(info->type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);
487 
488          const uint8_t *data = geom->geometry.aabbs.data.hostAddress;
489          data += range->primitiveOffset;
490 
491          VkDeviceSize stride = geom->geometry.aabbs.stride;
492 
493          for (uint32_t j = 0; j < range->primitiveCount; j++) {
494             struct lvp_bvh_aabb_node *node = leaf_nodes;
495             node += primitive_index;
496 
497             node->primitive_id = j;
498             node->geometry_id_and_flags = geometry_id_and_flags;
499 
500             const VkAabbPositionsKHR *aabb = (const VkAabbPositionsKHR *)(data + j * stride);
501             node->bounds.min.x = aabb->minX;
502             node->bounds.min.y = aabb->minY;
503             node->bounds.min.z = aabb->minZ;
504             node->bounds.max.x = aabb->maxX;
505             node->bounds.max.y = aabb->maxY;
506             node->bounds.max.z = aabb->maxZ;
507 
508             primitive_index++;
509          }
510 
511          break;
512       }
513       case VK_GEOMETRY_TYPE_INSTANCES_KHR: {
514          assert(info->type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR);
515 
516          const uint8_t *data = geom->geometry.instances.data.hostAddress;
517          data += range->primitiveOffset;
518 
519          for (uint32_t j = 0; j < range->primitiveCount; j++) {
520             struct lvp_bvh_instance_node *node = leaf_nodes;
521             node += primitive_index;
522 
523             const VkAccelerationStructureInstanceKHR *instance =
524                geom->geometry.instances.arrayOfPointers
525                   ? (((const VkAccelerationStructureInstanceKHR *const *)data)[j])
526                   : &((const VkAccelerationStructureInstanceKHR *)data)[j];
527             if (!instance->accelerationStructureReference)
528                continue;
529 
530             node->bvh_ptr = instance->accelerationStructureReference;
531 
532             float transform[16], inv_transform[16];
533             memcpy(transform, &instance->transform.matrix, sizeof(instance->transform.matrix));
534             transform[12] = transform[13] = transform[14] = 0.0f;
535             transform[15] = 1.0f;
536 
537             util_invert_mat4x4(inv_transform, transform);
538             memcpy(node->wto_matrix.values, inv_transform, sizeof(node->wto_matrix.values));
539 
540             node->custom_instance_and_mask = instance->instanceCustomIndex | (instance->mask << 24);
541             node->sbt_offset_and_flags = lvp_pack_sbt_offset_and_flags(
542                instance->instanceShaderBindingTableRecordOffset, instance->flags);
543             node->instance_id = j;
544 
545             memcpy(node->otw_matrix.values, instance->transform.matrix,
546                    sizeof(node->otw_matrix.values));
547 
548             primitive_index++;
549             header->instance_count++;
550          }
551 
552          break;
553       }
554       default:
555          unreachable("Unknown geometryType");
556       }
557    }
558 
559    leaf_count = primitive_index;
560 
561    struct lvp_build_internal_ctx internal_ctx = {
562       .dst = dst,
563       .dst_offset = sizeof(struct lvp_bvh_header),
564 
565       .leaf_nodes = leaf_nodes,
566       .leaf_nodes_offset = header->leaf_nodes_offset,
567    };
568 
569    VkGeometryTypeKHR geometry_type = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
570    if (info->geometryCount) {
571       if (info->pGeometries)
572          geometry_type = info->pGeometries[0].geometryType;
573       else
574          geometry_type = info->ppGeometries[0]->geometryType;
575    }
576 
577    switch (geometry_type) {
578    case VK_GEOMETRY_TYPE_TRIANGLES_KHR:
579       internal_ctx.leaf_node_type = lvp_bvh_node_triangle;
580       internal_ctx.leaf_node_size = sizeof(struct lvp_bvh_triangle_node);
581       break;
582    case VK_GEOMETRY_TYPE_AABBS_KHR:
583       internal_ctx.leaf_node_type = lvp_bvh_node_aabb;
584       internal_ctx.leaf_node_size = sizeof(struct lvp_bvh_aabb_node);
585       break;
586    case VK_GEOMETRY_TYPE_INSTANCES_KHR:
587       internal_ctx.leaf_node_type = lvp_bvh_node_instance;
588       internal_ctx.leaf_node_size = sizeof(struct lvp_bvh_instance_node);
589       break;
590    default:
591       unreachable("Unknown VkGeometryTypeKHR");
592    }
593 
594    if (leaf_count) {
595       lvp_build_internal_node(&internal_ctx, 0, leaf_count - 1);
596    } else {
597       root->children[0] = LVP_BVH_INVALID_NODE;
598       root->children[1] = LVP_BVH_INVALID_NODE;
599    }
600 
601    header->bounds.min.x = MIN2(root->bounds[0].min.x, root->bounds[1].min.x);
602    header->bounds.min.y = MIN2(root->bounds[0].min.y, root->bounds[1].min.y);
603    header->bounds.min.z = MIN2(root->bounds[0].min.z, root->bounds[1].min.z);
604 
605    header->bounds.max.x = MAX2(root->bounds[0].max.x, root->bounds[1].max.x);
606    header->bounds.max.y = MAX2(root->bounds[0].max.y, root->bounds[1].max.y);
607    header->bounds.max.z = MAX2(root->bounds[0].max.z, root->bounds[1].max.z);
608 
609    header->serialization_size = sizeof(struct lvp_accel_struct_serialization_header) +
610                                 sizeof(uint64_t) * header->instance_count + accel_struct->size;
611 }
612