radv/rra/gfx12: Add validation

Reviewed-by: Natalie Vock <natalie.vock@gmx.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35166>
This commit is contained in:
Konstantin Seurer 2025-05-26 16:30:24 +02:00 committed by Marge Bot
parent a61f78b8f4
commit e5af8152eb

View file

@ -19,6 +19,25 @@ struct rra_instance_sideband_data {
mat3x4 otw_matrix;
};
static const char *node_type_names[16] = {
[radv_bvh_node_triangle + 0] = "triangle0",
[radv_bvh_node_triangle + 1] = "triangle1",
[radv_bvh_node_triangle + 2] = "triangle2",
[radv_bvh_node_triangle + 3] = "triangle3",
[radv_bvh_node_box16] = "invalid4",
[radv_bvh_node_box32] = "box32",
[radv_bvh_node_instance] = "instance",
[radv_bvh_node_aabb] = "invalid7",
[8] = "invalid8",
[9] = "invalid9",
[10] = "invalid10",
[11] = "invalid11",
[12] = "invalid12",
[13] = "invalid13",
[14] = "invalid14",
[15] = "invalid15",
};
bool
rra_validate_node_gfx12(struct hash_table_u64 *accel_struct_vas, uint8_t *data, void *node, uint32_t geometry_count,
uint32_t size, bool is_bottom_level, uint32_t depth)
@ -33,6 +52,66 @@ rra_validate_node_gfx12(struct hash_table_u64 *accel_struct_vas, uint8_t *data,
uint32_t cur_offset = (uint8_t *)node - data;
snprintf(ctx.location, sizeof(ctx.location), "internal node (offset=%u)", cur_offset);
struct radv_gfx12_box_node *box = node;
uint32_t valid_child_count_minus_one = box->child_count_exponents >> 28;
if (valid_child_count_minus_one == 0xf)
return ctx.failed;
uint32_t internal_id = box->internal_base_id;
uint32_t primitive_id = box->primitive_base_id;
for (uint32_t i = 0; i <= valid_child_count_minus_one; i++) {
uint32_t child_type = (box->children[i].dword2 >> 24) & 0xf;
uint32_t child_size = box->children[i].dword2 >> 28;
uint32_t child_id;
if (child_type == radv_bvh_node_box32) {
child_id = internal_id;
internal_id += (child_size * RADV_GFX12_BVH_NODE_SIZE) >> 3;
} else {
child_id = primitive_id;
primitive_id += (child_size * RADV_GFX12_BVH_NODE_SIZE) >> 3;
}
uint32_t child_offset = (child_id & (~7u)) << 3;
if (child_offset >= size) {
rra_validation_fail(&ctx, "Invalid child offset (child index %u)", i);
continue;
}
struct rra_validation_context child_ctx = {0};
snprintf(child_ctx.location, sizeof(child_ctx.location), "%s node (offset=%u)", node_type_names[child_type],
child_offset);
void *child_node = data + child_offset;
if (child_type == radv_bvh_node_box32) {
ctx.failed |= rra_validate_node_gfx12(accel_struct_vas, data, child_node, geometry_count, size,
is_bottom_level, depth + 1);
} else if (child_type == radv_bvh_node_instance) {
struct radv_gfx12_instance_node *child = (struct radv_gfx12_instance_node *)(child_node);
const struct radv_gfx12_instance_node_user_data *user_data =
(const void *)((const uint8_t *)child + sizeof(struct radv_gfx12_instance_node));
uint64_t blas_va = radv_node_to_addr(child->pointer_flags_bvh_addr) - user_data->bvh_offset;
if (!_mesa_hash_table_u64_search(accel_struct_vas, blas_va))
rra_validation_fail(&child_ctx, "Invalid blas_addr(0x%llx)", (unsigned long long)blas_va);
} else {
uint32_t indices_midpoint = BITSET_EXTRACT(child_node, 42, 10);
if (indices_midpoint < 54 + 28) {
rra_validation_fail(&child_ctx, "Invalid indices_midpoint(%u)", indices_midpoint);
} else {
uint32_t geometry_id = BITSET_EXTRACT(child_node, indices_midpoint - 28, 28);
if (geometry_id >= geometry_count) {
rra_validation_fail(&child_ctx, "Invalid geometry_id(%u) >= geometry_count(%u)", geometry_id,
geometry_count);
}
}
if (!BITSET_TEST((BITSET_WORD *)child_node, 1024 - 29))
rra_validation_fail(&child_ctx, "prim_range_stop is not set");
}
}
return ctx.failed;
}