Module: Mesa Branch: main Commit: 62fe4f0b1b8986dbc90f70794bb468496420cb2e URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=62fe4f0b1b8986dbc90f70794bb468496420cb2e
Author: Friedrich Vock <[email protected]> Date: Sun Dec 17 17:27:31 2023 +0100 radv/rt: Move per-geometry build info into a geometry_data struct Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26729> --- src/amd/vulkan/bvh/build_helpers.h | 276 +++++++++++++++++++++++++ src/amd/vulkan/bvh/build_interface.h | 13 +- src/amd/vulkan/bvh/bvh.h | 14 ++ src/amd/vulkan/bvh/leaf.comp | 298 +-------------------------- src/amd/vulkan/radv_acceleration_structure.c | 109 +++++----- 5 files changed, 363 insertions(+), 347 deletions(-) diff --git a/src/amd/vulkan/bvh/build_helpers.h b/src/amd/vulkan/bvh/build_helpers.h index 436faba7038..adbf621a308 100644 --- a/src/amd/vulkan/bvh/build_helpers.h +++ b/src/amd/vulkan/bvh/build_helpers.h @@ -317,6 +317,282 @@ aabb_surface_area(radv_aabb aabb) return 2 * diagonal.x * diagonal.y + 2 * diagonal.y * diagonal.z + 2 * diagonal.x * diagonal.z; } +/* Just a wrapper for 3 uints. */ +struct triangle_indices { + uint32_t index[3]; +}; + +triangle_indices +load_indices(VOID_REF indices, uint32_t index_format, uint32_t global_id) +{ + triangle_indices result; + + uint32_t index_base = global_id * 3; + + switch (index_format) { + case VK_INDEX_TYPE_UINT16: { + result.index[0] = DEREF(INDEX(uint16_t, indices, index_base + 0)); + result.index[1] = DEREF(INDEX(uint16_t, indices, index_base + 1)); + result.index[2] = DEREF(INDEX(uint16_t, indices, index_base + 2)); + break; + } + case VK_INDEX_TYPE_UINT32: { + result.index[0] = DEREF(INDEX(uint32_t, indices, index_base + 0)); + result.index[1] = DEREF(INDEX(uint32_t, indices, index_base + 1)); + result.index[2] = DEREF(INDEX(uint32_t, indices, index_base + 2)); + break; + } + case VK_INDEX_TYPE_NONE_KHR: { + result.index[0] = index_base + 0; + result.index[1] = index_base + 1; + result.index[2] = index_base + 2; + break; + } + case VK_INDEX_TYPE_UINT8_EXT: { + result.index[0] = DEREF(INDEX(uint8_t, indices, index_base + 0)); + result.index[1] = DEREF(INDEX(uint8_t, indices, index_base + 1)); + result.index[2] = DEREF(INDEX(uint8_t, indices, index_base + 2)); + break; + } + } + + return result; +} + +/* Just a wrapper for 3 vec4s. */ +struct triangle_vertices { + vec4 vertex[3]; +}; + +TYPE(float16_t, 2); + +triangle_vertices +load_vertices(VOID_REF vertices, triangle_indices indices, uint32_t vertex_format, uint32_t stride) +{ + triangle_vertices result; + + for (uint32_t i = 0; i < 3; i++) { + VOID_REF vertex_ptr = OFFSET(vertices, indices.index[i] * stride); + vec4 vertex = vec4(0.0, 0.0, 0.0, 1.0); + + switch (vertex_format) { + case VK_FORMAT_R32G32_SFLOAT: + vertex.x = DEREF(INDEX(float, vertex_ptr, 0)); + vertex.y = DEREF(INDEX(float, vertex_ptr, 1)); + break; + case VK_FORMAT_R32G32B32_SFLOAT: + case VK_FORMAT_R32G32B32A32_SFLOAT: + vertex.x = DEREF(INDEX(float, vertex_ptr, 0)); + vertex.y = DEREF(INDEX(float, vertex_ptr, 1)); + vertex.z = DEREF(INDEX(float, vertex_ptr, 2)); + break; + case VK_FORMAT_R16G16_SFLOAT: + vertex.x = DEREF(INDEX(float16_t, vertex_ptr, 0)); + vertex.y = DEREF(INDEX(float16_t, vertex_ptr, 1)); + break; + case VK_FORMAT_R16G16B16_SFLOAT: + case VK_FORMAT_R16G16B16A16_SFLOAT: + vertex.x = DEREF(INDEX(float16_t, vertex_ptr, 0)); + vertex.y = DEREF(INDEX(float16_t, vertex_ptr, 1)); + vertex.z = DEREF(INDEX(float16_t, vertex_ptr, 2)); + break; + case VK_FORMAT_R16G16_SNORM: + vertex.x = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 0)) / float(0x7FFF)); + vertex.y = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 1)) / float(0x7FFF)); + break; + case VK_FORMAT_R16G16B16A16_SNORM: + vertex.x = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 0)) / float(0x7FFF)); + vertex.y = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 1)) / float(0x7FFF)); + vertex.z = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 2)) / float(0x7FFF)); + break; + case VK_FORMAT_R8G8_SNORM: + vertex.x = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 0)) / float(0x7F)); + vertex.y = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 1)) / float(0x7F)); + break; + case VK_FORMAT_R8G8B8A8_SNORM: + vertex.x = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 0)) / float(0x7F)); + vertex.y = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 1)) / float(0x7F)); + vertex.z = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 2)) / float(0x7F)); + break; + case VK_FORMAT_R16G16_UNORM: + vertex.x = DEREF(INDEX(uint16_t, vertex_ptr, 0)) / float(0xFFFF); + vertex.y = DEREF(INDEX(uint16_t, vertex_ptr, 1)) / float(0xFFFF); + break; + case VK_FORMAT_R16G16B16A16_UNORM: + vertex.x = DEREF(INDEX(uint16_t, vertex_ptr, 0)) / float(0xFFFF); + vertex.y = DEREF(INDEX(uint16_t, vertex_ptr, 1)) / float(0xFFFF); + vertex.z = DEREF(INDEX(uint16_t, vertex_ptr, 2)) / float(0xFFFF); + break; + case VK_FORMAT_R8G8_UNORM: + vertex.x = DEREF(INDEX(uint8_t, vertex_ptr, 0)) / float(0xFF); + vertex.y = DEREF(INDEX(uint8_t, vertex_ptr, 1)) / float(0xFF); + break; + case VK_FORMAT_R8G8B8A8_UNORM: + vertex.x = DEREF(INDEX(uint8_t, vertex_ptr, 0)) / float(0xFF); + vertex.y = DEREF(INDEX(uint8_t, vertex_ptr, 1)) / float(0xFF); + vertex.z = DEREF(INDEX(uint8_t, vertex_ptr, 2)) / float(0xFF); + break; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: { + uint32_t data = DEREF(REF(uint32_t)(vertex_ptr)); + vertex.x = float(data & 0x3FF) / 0x3FF; + vertex.y = float((data >> 10) & 0x3FF) / 0x3FF; + vertex.z = float((data >> 20) & 0x3FF) / 0x3FF; + break; + } + } + + result.vertex[i] = vertex; + } + + return result; +} + +/* A GLSL-adapted copy of VkAccelerationStructureInstanceKHR. */ +struct AccelerationStructureInstance { + mat3x4 transform; + uint32_t custom_instance_and_mask; + uint32_t sbt_offset_and_flags; + uint64_t accelerationStructureReference; +}; +TYPE(AccelerationStructureInstance, 8); + +bool +build_triangle(inout radv_aabb bounds, VOID_REF dst_ptr, radv_bvh_geometry_data geom_data, uint32_t global_id) +{ + triangle_indices indices = load_indices(geom_data.indices, geom_data.index_format, global_id); + + triangle_vertices vertices = load_vertices(geom_data.data, indices, geom_data.vertex_format, geom_data.stride); + + /* An inactive triangle is one for which the first (X) component of any vertex is NaN. If any + * other vertex component is NaN, and the first is not, the behavior is undefined. If the vertex + * format does not have a NaN representation, then all triangles are considered active. + */ + if (isnan(vertices.vertex[0].x) || isnan(vertices.vertex[1].x) || isnan(vertices.vertex[2].x)) + return false; + + if (geom_data.transform != NULL) { + mat4 transform = mat4(1.0); + + for (uint32_t col = 0; col < 4; col++) + for (uint32_t row = 0; row < 3; row++) + transform[col][row] = DEREF(INDEX(float, geom_data.transform, col + row * 4)); + + for (uint32_t i = 0; i < 3; i++) + vertices.vertex[i] = transform * vertices.vertex[i]; + } + + REF(radv_bvh_triangle_node) node = REF(radv_bvh_triangle_node)(dst_ptr); + + bounds.min = vec3(INFINITY); + bounds.max = vec3(-INFINITY); + + for (uint32_t coord = 0; coord < 3; coord++) + for (uint32_t comp = 0; comp < 3; comp++) { + DEREF(node).coords[coord][comp] = vertices.vertex[coord][comp]; + bounds.min[comp] = min(bounds.min[comp], vertices.vertex[coord][comp]); + bounds.max[comp] = max(bounds.max[comp], vertices.vertex[coord][comp]); + } + + DEREF(node).triangle_id = global_id; + DEREF(node).geometry_id_and_flags = geom_data.geometry_id; + DEREF(node).id = 9; + + return true; +} + +bool +build_aabb(inout radv_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_t geometry_id, uint32_t global_id) +{ + REF(radv_bvh_aabb_node) node = REF(radv_bvh_aabb_node)(dst_ptr); + + for (uint32_t vec = 0; vec < 2; vec++) + for (uint32_t comp = 0; comp < 3; comp++) { + float coord = DEREF(INDEX(float, src_ptr, comp + vec * 3)); + + if (vec == 0) + bounds.min[comp] = coord; + else + bounds.max[comp] = coord; + } + + /* An inactive AABB is one for which the minimum X coordinate is NaN. If any other component is + * NaN, and the first is not, the behavior is undefined. + */ + if (isnan(bounds.min.x)) + return false; + + DEREF(node).primitive_id = global_id; + DEREF(node).geometry_id_and_flags = geometry_id; + + return true; +} + +radv_aabb +calculate_instance_node_bounds(radv_accel_struct_header header, mat3x4 otw_matrix) +{ + radv_aabb aabb; + for (uint32_t comp = 0; comp < 3; ++comp) { + aabb.min[comp] = otw_matrix[comp][3]; + aabb.max[comp] = otw_matrix[comp][3]; + for (uint32_t col = 0; col < 3; ++col) { + aabb.min[comp] += + min(otw_matrix[comp][col] * header.aabb.min[col], otw_matrix[comp][col] * header.aabb.max[col]); + aabb.max[comp] += + max(otw_matrix[comp][col] * header.aabb.min[col], otw_matrix[comp][col] * header.aabb.max[col]); + } + } + return aabb; +} + +uint32_t +encode_sbt_offset_and_flags(uint32_t src) +{ + uint32_t flags = src >> 24; + uint32_t ret = src & 0xffffffu; + if ((flags & VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR) != 0) + ret |= RADV_INSTANCE_FORCE_OPAQUE; + if ((flags & VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR) == 0) + ret |= RADV_INSTANCE_NO_FORCE_NOT_OPAQUE; + if ((flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR) != 0) + ret |= RADV_INSTANCE_TRIANGLE_FACING_CULL_DISABLE; + if ((flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR) != 0) + ret |= RADV_INSTANCE_TRIANGLE_FLIP_FACING; + return ret; +} + +bool +build_instance(inout radv_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_t global_id) +{ + REF(radv_bvh_instance_node) node = REF(radv_bvh_instance_node)(dst_ptr); + + AccelerationStructureInstance instance = DEREF(REF(AccelerationStructureInstance)(src_ptr)); + + /* An inactive instance is one whose acceleration structure handle is VK_NULL_HANDLE. Since the active terminology is + * only relevant for BVH updates, which we do not implement, we can also skip instances with mask == 0. + */ + if (instance.accelerationStructureReference == 0 || instance.custom_instance_and_mask < (1u << 24u)) + return false; + + radv_accel_struct_header instance_header = + DEREF(REF(radv_accel_struct_header)(instance.accelerationStructureReference)); + + DEREF(node).bvh_ptr = addr_to_node(instance.accelerationStructureReference + instance_header.bvh_offset); + DEREF(node).bvh_offset = instance_header.bvh_offset; + + mat4 transform = mat4(instance.transform); + mat4 inv_transform = transpose(inverse(transpose(transform))); + DEREF(node).wto_matrix = mat3x4(inv_transform); + DEREF(node).otw_matrix = mat3x4(transform); + + bounds = calculate_instance_node_bounds(instance_header, mat3x4(transform)); + + DEREF(node).custom_instance_and_mask = instance.custom_instance_and_mask; + DEREF(node).sbt_offset_and_flags = encode_sbt_offset_and_flags(instance.sbt_offset_and_flags); + DEREF(node).instance_id = global_id; + + return true; +} + /** Compute ceiling of integer quotient of A divided by B. From macros.h */ #define DIV_ROUND_UP(A, B) (((A) + (B)-1) / (B)) diff --git a/src/amd/vulkan/bvh/build_interface.h b/src/amd/vulkan/bvh/build_interface.h index 2ee640d9cc5..09c49230537 100644 --- a/src/amd/vulkan/bvh/build_interface.h +++ b/src/amd/vulkan/bvh/build_interface.h @@ -28,6 +28,7 @@ #include "build_helpers.h" #else #include <stdint.h> +#include "bvh.h" #define REF(type) uint64_t #define VOID_REF uint64_t #endif @@ -38,17 +39,7 @@ struct leaf_args { REF(radv_ir_header) header; REF(key_id_pair) ids; - VOID_REF data; - VOID_REF indices; - VOID_REF transform; - - uint32_t first_id; - uint32_t geometry_type; - uint32_t geometry_id; - - uint32_t stride; - uint32_t vertex_format; - uint32_t index_format; + radv_bvh_geometry_data geom_data; }; struct morton_args { diff --git a/src/amd/vulkan/bvh/bvh.h b/src/amd/vulkan/bvh/bvh.h index b77c6b8d47a..be11c8d1b56 100644 --- a/src/amd/vulkan/bvh/bvh.h +++ b/src/amd/vulkan/bvh/bvh.h @@ -48,6 +48,7 @@ #include <vulkan/vulkan.h> typedef struct radv_ir_node radv_ir_node; typedef struct radv_global_sync_data radv_global_sync_data; +typedef struct radv_bvh_geometry_data radv_bvh_geometry_data; typedef uint16_t float16_t; @@ -197,4 +198,17 @@ struct radv_bvh_box32_node { * more work to do. */ #define TASK_INDEX_INVALID 0xFFFFFFFF +struct radv_bvh_geometry_data { + uint64_t data; + uint64_t indices; + uint64_t transform; + + uint32_t geometry_id; + uint32_t geometry_type; + uint32_t first_id; + uint32_t stride; + uint32_t vertex_format; + uint32_t index_format; +}; + #endif diff --git a/src/amd/vulkan/bvh/leaf.comp b/src/amd/vulkan/bvh/leaf.comp index 6ef35cf156d..ba706fbb91c 100644 --- a/src/amd/vulkan/bvh/leaf.comp +++ b/src/amd/vulkan/bvh/leaf.comp @@ -45,297 +45,21 @@ layout(push_constant) uniform CONSTS { leaf_args args; }; -/* Just a wrapper for 3 uints. */ -struct triangle_indices { - uint32_t index[3]; -}; - -triangle_indices -load_indices(VOID_REF indices, uint32_t index_format, uint32_t global_id) -{ - triangle_indices result; - - uint32_t index_base = global_id * 3; - - switch (index_format) { - case VK_INDEX_TYPE_UINT16: { - result.index[0] = DEREF(INDEX(uint16_t, indices, index_base + 0)); - result.index[1] = DEREF(INDEX(uint16_t, indices, index_base + 1)); - result.index[2] = DEREF(INDEX(uint16_t, indices, index_base + 2)); - break; - } - case VK_INDEX_TYPE_UINT32: { - result.index[0] = DEREF(INDEX(uint32_t, indices, index_base + 0)); - result.index[1] = DEREF(INDEX(uint32_t, indices, index_base + 1)); - result.index[2] = DEREF(INDEX(uint32_t, indices, index_base + 2)); - break; - } - case VK_INDEX_TYPE_NONE_KHR: { - result.index[0] = index_base + 0; - result.index[1] = index_base + 1; - result.index[2] = index_base + 2; - break; - } - case VK_INDEX_TYPE_UINT8_EXT: { - result.index[0] = DEREF(INDEX(uint8_t, indices, index_base + 0)); - result.index[1] = DEREF(INDEX(uint8_t, indices, index_base + 1)); - result.index[2] = DEREF(INDEX(uint8_t, indices, index_base + 2)); - break; - } - } - - return result; -} - -/* Just a wrapper for 3 vec4s. */ -struct triangle_vertices { - vec4 vertex[3]; -}; - -TYPE(float16_t, 2); - -triangle_vertices -load_vertices(VOID_REF vertices, triangle_indices indices, uint32_t vertex_format, uint32_t stride) -{ - triangle_vertices result; - - for (uint32_t i = 0; i < 3; i++) { - VOID_REF vertex_ptr = OFFSET(vertices, indices.index[i] * stride); - vec4 vertex = vec4(0.0, 0.0, 0.0, 1.0); - - switch (vertex_format) { - case VK_FORMAT_R32G32_SFLOAT: - vertex.x = DEREF(INDEX(float, vertex_ptr, 0)); - vertex.y = DEREF(INDEX(float, vertex_ptr, 1)); - break; - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - vertex.x = DEREF(INDEX(float, vertex_ptr, 0)); - vertex.y = DEREF(INDEX(float, vertex_ptr, 1)); - vertex.z = DEREF(INDEX(float, vertex_ptr, 2)); - break; - case VK_FORMAT_R16G16_SFLOAT: - vertex.x = DEREF(INDEX(float16_t, vertex_ptr, 0)); - vertex.y = DEREF(INDEX(float16_t, vertex_ptr, 1)); - break; - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - vertex.x = DEREF(INDEX(float16_t, vertex_ptr, 0)); - vertex.y = DEREF(INDEX(float16_t, vertex_ptr, 1)); - vertex.z = DEREF(INDEX(float16_t, vertex_ptr, 2)); - break; - case VK_FORMAT_R16G16_SNORM: - vertex.x = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 0)) / float(0x7FFF)); - vertex.y = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 1)) / float(0x7FFF)); - break; - case VK_FORMAT_R16G16B16A16_SNORM: - vertex.x = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 0)) / float(0x7FFF)); - vertex.y = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 1)) / float(0x7FFF)); - vertex.z = max(-1.0, DEREF(INDEX(int16_t, vertex_ptr, 2)) / float(0x7FFF)); - break; - case VK_FORMAT_R8G8_SNORM: - vertex.x = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 0)) / float(0x7F)); - vertex.y = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 1)) / float(0x7F)); - break; - case VK_FORMAT_R8G8B8A8_SNORM: - vertex.x = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 0)) / float(0x7F)); - vertex.y = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 1)) / float(0x7F)); - vertex.z = max(-1.0, DEREF(INDEX(int8_t, vertex_ptr, 2)) / float(0x7F)); - break; - case VK_FORMAT_R16G16_UNORM: - vertex.x = DEREF(INDEX(uint16_t, vertex_ptr, 0)) / float(0xFFFF); - vertex.y = DEREF(INDEX(uint16_t, vertex_ptr, 1)) / float(0xFFFF); - break; - case VK_FORMAT_R16G16B16A16_UNORM: - vertex.x = DEREF(INDEX(uint16_t, vertex_ptr, 0)) / float(0xFFFF); - vertex.y = DEREF(INDEX(uint16_t, vertex_ptr, 1)) / float(0xFFFF); - vertex.z = DEREF(INDEX(uint16_t, vertex_ptr, 2)) / float(0xFFFF); - break; - case VK_FORMAT_R8G8_UNORM: - vertex.x = DEREF(INDEX(uint8_t, vertex_ptr, 0)) / float(0xFF); - vertex.y = DEREF(INDEX(uint8_t, vertex_ptr, 1)) / float(0xFF); - break; - case VK_FORMAT_R8G8B8A8_UNORM: - vertex.x = DEREF(INDEX(uint8_t, vertex_ptr, 0)) / float(0xFF); - vertex.y = DEREF(INDEX(uint8_t, vertex_ptr, 1)) / float(0xFF); - vertex.z = DEREF(INDEX(uint8_t, vertex_ptr, 2)) / float(0xFF); - break; - case VK_FORMAT_A2B10G10R10_UNORM_PACK32: { - uint32_t data = DEREF(REF(uint32_t)(vertex_ptr)); - vertex.x = float(data & 0x3FF) / 0x3FF; - vertex.y = float((data >> 10) & 0x3FF) / 0x3FF; - vertex.z = float((data >> 20) & 0x3FF) / 0x3FF; - break; - } - } - - result.vertex[i] = vertex; - } - - return result; -} - -/* A GLSL-adapted copy of VkAccelerationStructureInstanceKHR. */ -struct AccelerationStructureInstance { - mat3x4 transform; - uint32_t custom_instance_and_mask; - uint32_t sbt_offset_and_flags; - uint64_t accelerationStructureReference; -}; -TYPE(AccelerationStructureInstance, 8); - -bool -build_triangle(inout radv_aabb bounds, VOID_REF dst_ptr, uint32_t global_id) -{ - triangle_indices indices = load_indices(args.indices, args.index_format, global_id); - - triangle_vertices vertices = load_vertices(args.data, indices, args.vertex_format, args.stride); - - /* An inactive triangle is one for which the first (X) component of any vertex is NaN. If any - * other vertex component is NaN, and the first is not, the behavior is undefined. If the vertex - * format does not have a NaN representation, then all triangles are considered active. - */ - if (isnan(vertices.vertex[0].x) || isnan(vertices.vertex[1].x) || isnan(vertices.vertex[2].x)) - return false; - - if (args.transform != NULL) { - mat4 transform = mat4(1.0); - - for (uint32_t col = 0; col < 4; col++) - for (uint32_t row = 0; row < 3; row++) - transform[col][row] = DEREF(INDEX(float, args.transform, col + row * 4)); - - for (uint32_t i = 0; i < 3; i++) - vertices.vertex[i] = transform * vertices.vertex[i]; - } - - REF(radv_bvh_triangle_node) node = REF(radv_bvh_triangle_node)(dst_ptr); - - bounds.min = vec3(INFINITY); - bounds.max = vec3(-INFINITY); - - for (uint32_t coord = 0; coord < 3; coord++) - for (uint32_t comp = 0; comp < 3; comp++) { - DEREF(node).coords[coord][comp] = vertices.vertex[coord][comp]; - bounds.min[comp] = min(bounds.min[comp], vertices.vertex[coord][comp]); - bounds.max[comp] = max(bounds.max[comp], vertices.vertex[coord][comp]); - } - - DEREF(node).triangle_id = global_id; - DEREF(node).geometry_id_and_flags = args.geometry_id; - DEREF(node).id = 9; - - return true; -} - -bool -build_aabb(inout radv_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_t global_id) -{ - REF(radv_bvh_aabb_node) node = REF(radv_bvh_aabb_node)(dst_ptr); - - for (uint32_t vec = 0; vec < 2; vec++) - for (uint32_t comp = 0; comp < 3; comp++) { - float coord = DEREF(INDEX(float, src_ptr, comp + vec * 3)); - - if (vec == 0) - bounds.min[comp] = coord; - else - bounds.max[comp] = coord; - } - - /* An inactive AABB is one for which the minimum X coordinate is NaN. If any other component is - * NaN, and the first is not, the behavior is undefined. - */ - if (isnan(bounds.min.x)) - return false; - - DEREF(node).primitive_id = global_id; - DEREF(node).geometry_id_and_flags = args.geometry_id; - - return true; -} - -radv_aabb -calculate_instance_node_bounds(radv_accel_struct_header header, mat3x4 otw_matrix) -{ - radv_aabb aabb; - for (uint32_t comp = 0; comp < 3; ++comp) { - aabb.min[comp] = otw_matrix[comp][3]; - aabb.max[comp] = otw_matrix[comp][3]; - for (uint32_t col = 0; col < 3; ++col) { - aabb.min[comp] += - min(otw_matrix[comp][col] * header.aabb.min[col], otw_matrix[comp][col] * header.aabb.max[col]); - aabb.max[comp] += - max(otw_matrix[comp][col] * header.aabb.min[col], otw_matrix[comp][col] * header.aabb.max[col]); - } - } - return aabb; -} - -uint32_t -encode_sbt_offset_and_flags(uint32_t src) -{ - uint32_t flags = src >> 24; - uint32_t ret = src & 0xffffffu; - if ((flags & VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR) != 0) - ret |= RADV_INSTANCE_FORCE_OPAQUE; - if ((flags & VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR) == 0) - ret |= RADV_INSTANCE_NO_FORCE_NOT_OPAQUE; - if ((flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR) != 0) - ret |= RADV_INSTANCE_TRIANGLE_FACING_CULL_DISABLE; - if ((flags & VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR) != 0) - ret |= RADV_INSTANCE_TRIANGLE_FLIP_FACING; - return ret; -} - -bool -build_instance(inout radv_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_t global_id) -{ - REF(radv_bvh_instance_node) node = REF(radv_bvh_instance_node)(dst_ptr); - - AccelerationStructureInstance instance = DEREF(REF(AccelerationStructureInstance)(src_ptr)); - - /* An inactive instance is one whose acceleration structure handle is VK_NULL_HANDLE. Since the active terminology is - * only relevant for BVH updates, which we do not implement, we can also skip instances with mask == 0. - */ - if (instance.accelerationStructureReference == 0 || instance.custom_instance_and_mask < (1u << 24u)) - return false; - - radv_accel_struct_header instance_header = - DEREF(REF(radv_accel_struct_header)(instance.accelerationStructureReference)); - - DEREF(node).bvh_ptr = addr_to_node(instance.accelerationStructureReference + instance_header.bvh_offset); - DEREF(node).bvh_offset = instance_header.bvh_offset; - - mat4 transform = mat4(instance.transform); - mat4 inv_transform = transpose(inverse(transpose(transform))); - DEREF(node).wto_matrix = mat3x4(inv_transform); - DEREF(node).otw_matrix = mat3x4(transform); - - bounds = calculate_instance_node_bounds(instance_header, mat3x4(transform)); - - DEREF(node).custom_instance_and_mask = instance.custom_instance_and_mask; - DEREF(node).sbt_offset_and_flags = encode_sbt_offset_and_flags(instance.sbt_offset_and_flags); - DEREF(node).instance_id = global_id; - - return true; -} - void main(void) { uint32_t global_id = gl_GlobalInvocationID.x; - uint32_t primitive_id = args.first_id + global_id; + uint32_t primitive_id = args.geom_data.first_id + global_id; REF(key_id_pair) id_ptr = INDEX(key_id_pair, args.ids, primitive_id); - uint32_t src_offset = global_id * args.stride; + uint32_t src_offset = global_id * args.geom_data.stride; uint32_t dst_stride; uint32_t node_type; - if (args.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) { + if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) { dst_stride = SIZEOF(radv_bvh_triangle_node); node_type = radv_ir_node_triangle; - } else if (args.geometry_type == VK_GEOMETRY_TYPE_AABBS_KHR) { + } else if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_AABBS_KHR) { dst_stride = SIZEOF(radv_bvh_aabb_node); node_type = radv_ir_node_aabb; } else { @@ -348,15 +72,15 @@ main(void) radv_aabb bounds; bool is_active; - if (args.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) { - is_active = build_triangle(bounds, dst_ptr, global_id); - } else if (args.geometry_type == VK_GEOMETRY_TYPE_AABBS_KHR) { - VOID_REF src_ptr = OFFSET(args.data, src_offset); - is_active = build_aabb(bounds, src_ptr, dst_ptr, global_id); + if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) { + is_active = build_triangle(bounds, dst_ptr, args.geom_data, global_id); + } else if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_AABBS_KHR) { + VOID_REF src_ptr = OFFSET(args.geom_data.data, src_offset); + is_active = build_aabb(bounds, src_ptr, dst_ptr, args.geom_data.geometry_id, global_id); } else { - VOID_REF src_ptr = OFFSET(args.data, src_offset); + VOID_REF src_ptr = OFFSET(args.geom_data.data, src_offset); /* arrayOfPointers */ - if (args.stride == 8) { + if (args.geom_data.stride == 8) { src_ptr = DEREF(REF(VOID_REF)(src_ptr)); } diff --git a/src/amd/vulkan/radv_acceleration_structure.c b/src/amd/vulkan/radv_acceleration_structure.c index a2981306d58..1b1dfcd5d83 100644 --- a/src/amd/vulkan/radv_acceleration_structure.c +++ b/src/amd/vulkan/radv_acceleration_structure.c @@ -608,6 +608,61 @@ pack_geometry_id_and_flags(uint32_t geometry_id, uint32_t flags) return geometry_id_and_flags; } +static struct radv_bvh_geometry_data +fill_geometry_data(VkAccelerationStructureTypeKHR type, struct bvh_state *bvh_state, uint32_t geom_index, + const VkAccelerationStructureGeometryKHR *geometry, + const VkAccelerationStructureBuildRangeInfoKHR *build_range_info) +{ + struct radv_bvh_geometry_data data = { + .first_id = bvh_state->node_count, + .geometry_id = pack_geometry_id_and_flags(geom_index, geometry->flags), + .geometry_type = geometry->geometryType, + }; + + switch (geometry->geometryType) { + case VK_GEOMETRY_TYPE_TRIANGLES_KHR: + assert(type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + + data.data = geometry->geometry.triangles.vertexData.deviceAddress + + build_range_info->firstVertex * geometry->geometry.triangles.vertexStride; + data.indices = geometry->geometry.triangles.indexData.deviceAddress; + + if (geometry->geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) + data.data += build_range_info->primitiveOffset; + else + data.indices += build_range_info->primitiveOffset; + + data.transform = geometry->geometry.triangles.transformData.deviceAddress; + if (data.transform) + data.transform += build_range_info->transformOffset; + + data.stride = geometry->geometry.triangles.vertexStride; + data.vertex_format = geometry->geometry.triangles.vertexFormat; + data.index_format = geometry->geometry.triangles.indexType; + break; + case VK_GEOMETRY_TYPE_AABBS_KHR: + assert(type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + + data.data = geometry->geometry.aabbs.data.deviceAddress + build_range_info->primitiveOffset; + data.stride = geometry->geometry.aabbs.stride; + break; + case VK_GEOMETRY_TYPE_INSTANCES_KHR: + assert(type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR); + + data.data = geometry->geometry.instances.data.deviceAddress + build_range_info->primitiveOffset; + + if (geometry->geometry.instances.arrayOfPointers) + data.stride = 8; + else + data.stride = sizeof(VkAccelerationStructureInstanceKHR); + break; + default: + unreachable("Unknown geometryType"); + } + + return data; +} + static void build_leaves(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos, @@ -631,60 +686,16 @@ build_leaves(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureGeometryKHR *geom = pInfos[i].pGeometries ? &pInfos[i].pGeometries[j] : pInfos[i].ppGeometries[j]; - const VkAccelerationStructureBuildRangeInfoKHR *buildRangeInfo = &ppBuildRangeInfos[i][j]; - - leaf_consts.first_id = bvh_states[i].node_count; - - leaf_consts.geometry_type = geom->geometryType; - leaf_consts.geometry_id = pack_geometry_id_and_flags(j, geom->flags); - - switch (geom->geometryType) { - case VK_GEOMETRY_TYPE_TRIANGLES_KHR: - assert(pInfos[i].type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); - - leaf_consts.data = geom->geometry.triangles.vertexData.deviceAddress + - buildRangeInfo->firstVertex * geom->geometry.triangles.vertexStride; - leaf_consts.indices = geom->geometry.triangles.indexData.deviceAddress; - - if (geom->geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) - leaf_consts.data += buildRangeInfo->primitiveOffset; - else - leaf_consts.indices += buildRangeInfo->primitiveOffset; - - leaf_consts.transform = geom->geometry.triangles.transformData.deviceAddress; - if (leaf_consts.transform) - leaf_consts.transform += buildRangeInfo->transformOffset; - - leaf_consts.stride = geom->geometry.triangles.vertexStride; - leaf_consts.vertex_format = geom->geometry.triangles.vertexFormat; - leaf_consts.index_format = geom->geometry.triangles.indexType; - break; - case VK_GEOMETRY_TYPE_AABBS_KHR: - assert(pInfos[i].type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); - - leaf_consts.data = geom->geometry.aabbs.data.deviceAddress + buildRangeInfo->primitiveOffset; - leaf_consts.stride = geom->geometry.aabbs.stride; - break; - case VK_GEOMETRY_TYPE_INSTANCES_KHR: - assert(pInfos[i].type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR); - - leaf_consts.data = geom->geometry.instances.data.deviceAddress + buildRangeInfo->primitiveOffset; + const VkAccelerationStructureBuildRangeInfoKHR *build_range_info = &ppBuildRangeInfos[i][j]; - if (geom->geometry.instances.arrayOfPointers) - leaf_consts.stride = 8; - else - leaf_consts.stride = sizeof(VkAccelerationStructureInstanceKHR); - break; - default: - unreachable("Unknown geometryType"); - } + leaf_consts.geom_data = fill_geometry_data(pInfos[i].type, &bvh_states[i], j, geom, build_range_info); vk_common_CmdPushConstants(commandBuffer, cmd_buffer->device->meta_state.accel_struct_build.leaf_p_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(leaf_consts), &leaf_consts); - radv_unaligned_dispatch(cmd_buffer, buildRangeInfo->primitiveCount, 1, 1); + radv_unaligned_dispatch(cmd_buffer, build_range_info->primitiveCount, 1, 1); - bvh_states[i].leaf_node_count += buildRangeInfo->primitiveCount; - bvh_states[i].node_count += buildRangeInfo->primitiveCount; + bvh_states[i].leaf_node_count += build_range_info->primitiveCount; + bvh_states[i].node_count += build_range_info->primitiveCount; } }
