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