radv/rt: Move per-geometry build info into a geometry_data struct

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26729>
This commit is contained in:
Friedrich Vock 2023-12-17 17:27:31 +01:00 committed by Marge Bot
parent 3da2773316
commit 62fe4f0b1b
5 changed files with 363 additions and 347 deletions

View file

@ -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))

View file

@ -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 {

View file

@ -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

View file

@ -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));
}

View file

@ -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];
const VkAccelerationStructureBuildRangeInfoKHR *build_range_info = &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;
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;
}
}