1/* 2 * Copyright © 2023 Valve Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#version 460 25 26#extension GL_GOOGLE_include_directive : require 27 28#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require 29#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require 30#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require 31#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require 32#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require 33#extension GL_EXT_scalar_block_layout : require 34#extension GL_EXT_buffer_reference : require 35#extension GL_EXT_buffer_reference2 : require 36#extension GL_KHR_memory_scope_semantics : require 37 38layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 39 40#include "build_interface.h" 41 42layout(push_constant) uniform CONSTS { 43 update_args args; 44}; 45 46uint32_t fetch_parent_node(VOID_REF bvh, uint32_t node) 47{ 48 uint64_t addr = bvh - node / 8 * 4 - 4; 49 return DEREF(REF(uint32_t)(addr)); 50} 51 52void main() { 53 uint32_t bvh_offset = DEREF(args.src).bvh_offset; 54 55 VOID_REF src_bvh = OFFSET(args.src, bvh_offset); 56 VOID_REF dst_bvh = OFFSET(args.dst, bvh_offset); 57 58 uint32_t leaf_node_size; 59 if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) 60 leaf_node_size = SIZEOF(radv_bvh_triangle_node); 61 else if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_AABBS_KHR) 62 leaf_node_size = SIZEOF(radv_bvh_aabb_node); 63 else 64 leaf_node_size = SIZEOF(radv_bvh_instance_node); 65 66 uint32_t leaf_node_id = args.geom_data.first_id + gl_GlobalInvocationID.x; 67 uint32_t first_leaf_offset = id_to_offset(RADV_BVH_ROOT_NODE) + SIZEOF(radv_bvh_box32_node); 68 69 uint32_t dst_offset = leaf_node_id * leaf_node_size + first_leaf_offset; 70 VOID_REF dst_ptr = OFFSET(dst_bvh, dst_offset); 71 uint32_t src_offset = gl_GlobalInvocationID.x * args.geom_data.stride; 72 73 radv_aabb bounds; 74 bool is_active; 75 if (args.geom_data.geometry_type == VK_GEOMETRY_TYPE_TRIANGLES_KHR) { 76 is_active = build_triangle(bounds, dst_ptr, args.geom_data, gl_GlobalInvocationID.x); 77 } else { 78 VOID_REF src_ptr = OFFSET(args.geom_data.data, src_offset); 79 is_active = build_aabb(bounds, src_ptr, dst_ptr, args.geom_data.geometry_id, gl_GlobalInvocationID.x); 80 } 81 82 if (!is_active) 83 return; 84 85 DEREF(INDEX(radv_aabb, args.leaf_bounds, leaf_node_id)) = bounds; 86 memoryBarrier(gl_ScopeDevice, 87 gl_StorageSemanticsBuffer, 88 gl_SemanticsAcquireRelease | gl_SemanticsMakeAvailable | gl_SemanticsMakeVisible); 89 90 uint32_t node_id = pack_node_id(dst_offset, 0); 91 uint32_t parent_id = fetch_parent_node(src_bvh, node_id); 92 uint32_t internal_nodes_offset = first_leaf_offset + args.leaf_node_count * leaf_node_size; 93 while (parent_id != RADV_BVH_INVALID_NODE) { 94 uint32_t offset = id_to_offset(parent_id); 95 96 uint32_t parent_index = (offset - internal_nodes_offset) / SIZEOF(radv_bvh_box32_node) + 1; 97 if (parent_id == RADV_BVH_ROOT_NODE) 98 parent_index = 0; 99 100 /* Make accesses to internal nodes in dst_bvh available and visible */ 101 memoryBarrier(gl_ScopeDevice, 102 gl_StorageSemanticsBuffer, 103 gl_SemanticsAcquireRelease | gl_SemanticsMakeAvailable | gl_SemanticsMakeVisible); 104 105 REF(radv_bvh_box32_node) src_node = REF(radv_bvh_box32_node)OFFSET(src_bvh, offset); 106 REF(radv_bvh_box32_node) dst_node = REF(radv_bvh_box32_node)OFFSET(dst_bvh, offset); 107 uint32_t children[4]; 108 for (uint32_t i = 0; i < 4; ++i) 109 children[i] = DEREF(src_node).children[i]; 110 111 uint32_t valid_child_count = 0; 112 for (uint32_t i = 0; i < 4; ++valid_child_count, ++i) 113 if (children[i] == RADV_BVH_INVALID_NODE) 114 break; 115 116 /* Check if all children have been processed. As this is an atomic the last path coming from 117 * a child will pass here, while earlier paths break. 118 */ 119 uint32_t ready_child_count = atomicAdd( 120 DEREF(INDEX(uint32_t, args.internal_ready_count, parent_index)), 1, gl_ScopeDevice, 121 gl_StorageSemanticsBuffer, 122 gl_SemanticsAcquireRelease | gl_SemanticsMakeAvailable | gl_SemanticsMakeVisible); 123 124 if (ready_child_count != valid_child_count - 1) 125 break; 126 127 for (uint32_t i = 0; i < 4; ++i) 128 DEREF(dst_node).children[i] = children[i]; 129 130 for (uint32_t i = 0; i < valid_child_count; ++i) { 131 uint32_t child_offset = id_to_offset(children[i]); 132 radv_aabb child_bounds; 133 if (child_offset == dst_offset) 134 child_bounds = bounds; 135 else if (child_offset >= internal_nodes_offset) { 136 child_bounds = radv_aabb(vec3(INFINITY), vec3(-INFINITY)); 137 REF(radv_bvh_box32_node) child_node = REF(radv_bvh_box32_node)OFFSET(dst_bvh, child_offset); 138 for (uint32_t j = 0; j < 4; ++j) { 139 if (DEREF(child_node).children[j] == RADV_BVH_INVALID_NODE) 140 break; 141 child_bounds.min = min(child_bounds.min, DEREF(child_node).coords[j].min); 142 child_bounds.max = max(child_bounds.max, DEREF(child_node).coords[j].max); 143 } 144 } else { 145 uint32_t child_index = (child_offset - first_leaf_offset) / leaf_node_size; 146 child_bounds = DEREF(INDEX(radv_aabb, args.leaf_bounds, child_index)); 147 } 148 149 DEREF(dst_node).coords[i] = child_bounds; 150 } 151 152 if (parent_id == RADV_BVH_ROOT_NODE) { 153 radv_aabb root_bounds = radv_aabb(vec3(INFINITY), vec3(-INFINITY)); 154 for (uint32_t i = 0; i < valid_child_count; ++i) { 155 radv_aabb bounds = DEREF(dst_node).coords[i]; 156 root_bounds.min = min(root_bounds.min, bounds.min); 157 root_bounds.max = max(root_bounds.max, bounds.max); 158 } 159 DEREF(args.dst).aabb = root_bounds; 160 } 161 162 parent_id = fetch_parent_node(src_bvh, parent_id); 163 } 164} 165