1*61046927SAndroid Build Coastguard Worker/* 2*61046927SAndroid Build Coastguard Worker * Copyright © 2022 Friedrich Vock 3*61046927SAndroid Build Coastguard Worker * 4*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT 5*61046927SAndroid Build Coastguard Worker */ 6*61046927SAndroid Build Coastguard Worker 7*61046927SAndroid Build Coastguard Worker#version 460 8*61046927SAndroid Build Coastguard Worker 9*61046927SAndroid Build Coastguard Worker#extension GL_GOOGLE_include_directive : require 10*61046927SAndroid Build Coastguard Worker 11*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require 12*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require 13*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require 14*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require 15*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require 16*61046927SAndroid Build Coastguard Worker#extension GL_EXT_scalar_block_layout : require 17*61046927SAndroid Build Coastguard Worker#extension GL_EXT_buffer_reference : require 18*61046927SAndroid Build Coastguard Worker#extension GL_EXT_buffer_reference2 : require 19*61046927SAndroid Build Coastguard Worker#extension GL_KHR_memory_scope_semantics : require 20*61046927SAndroid Build Coastguard Worker 21*61046927SAndroid Build Coastguard Workerlayout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 22*61046927SAndroid Build Coastguard Worker 23*61046927SAndroid Build Coastguard Worker#include "build_helpers.h" 24*61046927SAndroid Build Coastguard Worker#include "build_interface.h" 25*61046927SAndroid Build Coastguard Worker 26*61046927SAndroid Build Coastguard Workerlayout(push_constant) uniform CONSTS { 27*61046927SAndroid Build Coastguard Worker encode_args args; 28*61046927SAndroid Build Coastguard Worker}; 29*61046927SAndroid Build Coastguard Worker 30*61046927SAndroid Build Coastguard Workervoid set_parent(uint32_t child, uint32_t parent) 31*61046927SAndroid Build Coastguard Worker{ 32*61046927SAndroid Build Coastguard Worker uint64_t addr = args.output_bvh - child / 8 * 4 - 4; 33*61046927SAndroid Build Coastguard Worker DEREF(REF(uint32_t)(addr)) = parent; 34*61046927SAndroid Build Coastguard Worker} 35*61046927SAndroid Build Coastguard Worker 36*61046927SAndroid Build Coastguard Workervoid 37*61046927SAndroid Build Coastguard Workermain() 38*61046927SAndroid Build Coastguard Worker{ 39*61046927SAndroid Build Coastguard Worker /* Revert the order so we start at the root */ 40*61046927SAndroid Build Coastguard Worker uint32_t global_id = DEREF(args.header).ir_internal_node_count - 1 - gl_GlobalInvocationID.x; 41*61046927SAndroid Build Coastguard Worker 42*61046927SAndroid Build Coastguard Worker uint32_t output_leaf_node_size; 43*61046927SAndroid Build Coastguard Worker switch (args.geometry_type) { 44*61046927SAndroid Build Coastguard Worker case VK_GEOMETRY_TYPE_TRIANGLES_KHR: 45*61046927SAndroid Build Coastguard Worker output_leaf_node_size = SIZEOF(radv_bvh_triangle_node); 46*61046927SAndroid Build Coastguard Worker break; 47*61046927SAndroid Build Coastguard Worker case VK_GEOMETRY_TYPE_AABBS_KHR: 48*61046927SAndroid Build Coastguard Worker output_leaf_node_size = SIZEOF(radv_bvh_aabb_node); 49*61046927SAndroid Build Coastguard Worker break; 50*61046927SAndroid Build Coastguard Worker default: /* instances */ 51*61046927SAndroid Build Coastguard Worker output_leaf_node_size = SIZEOF(radv_bvh_instance_node); 52*61046927SAndroid Build Coastguard Worker break; 53*61046927SAndroid Build Coastguard Worker } 54*61046927SAndroid Build Coastguard Worker 55*61046927SAndroid Build Coastguard Worker uint32_t intermediate_leaf_nodes_size = args.leaf_node_count * SIZEOF(radv_ir_node); 56*61046927SAndroid Build Coastguard Worker uint32_t dst_leaf_offset = 57*61046927SAndroid Build Coastguard Worker id_to_offset(RADV_BVH_ROOT_NODE) + SIZEOF(radv_bvh_box32_node); 58*61046927SAndroid Build Coastguard Worker uint32_t dst_internal_offset = dst_leaf_offset + args.leaf_node_count * output_leaf_node_size; 59*61046927SAndroid Build Coastguard Worker 60*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node) intermediate_internal_nodes = 61*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node)OFFSET(args.intermediate_bvh, intermediate_leaf_nodes_size); 62*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node) src_node = INDEX(radv_ir_box_node, intermediate_internal_nodes, global_id); 63*61046927SAndroid Build Coastguard Worker radv_ir_box_node src = DEREF(src_node); 64*61046927SAndroid Build Coastguard Worker 65*61046927SAndroid Build Coastguard Worker bool is_root_node = global_id == DEREF(args.header).ir_internal_node_count - 1; 66*61046927SAndroid Build Coastguard Worker 67*61046927SAndroid Build Coastguard Worker for (;;) { 68*61046927SAndroid Build Coastguard Worker /* Make changes to the current node's BVH offset value visible. */ 69*61046927SAndroid Build Coastguard Worker memoryBarrier(gl_ScopeDevice, gl_StorageSemanticsBuffer, 70*61046927SAndroid Build Coastguard Worker gl_SemanticsAcquireRelease | gl_SemanticsMakeAvailable | gl_SemanticsMakeVisible); 71*61046927SAndroid Build Coastguard Worker 72*61046927SAndroid Build Coastguard Worker uint32_t bvh_offset = is_root_node ? id_to_offset(RADV_BVH_ROOT_NODE) : DEREF(src_node).bvh_offset; 73*61046927SAndroid Build Coastguard Worker if (bvh_offset == RADV_UNKNOWN_BVH_OFFSET) 74*61046927SAndroid Build Coastguard Worker continue; 75*61046927SAndroid Build Coastguard Worker 76*61046927SAndroid Build Coastguard Worker if (bvh_offset == RADV_NULL_BVH_OFFSET) 77*61046927SAndroid Build Coastguard Worker break; 78*61046927SAndroid Build Coastguard Worker 79*61046927SAndroid Build Coastguard Worker REF(radv_bvh_box32_node) dst_node = REF(radv_bvh_box32_node)(OFFSET(args.output_bvh, bvh_offset)); 80*61046927SAndroid Build Coastguard Worker uint32_t node_id = pack_node_id(bvh_offset, radv_bvh_node_box32); 81*61046927SAndroid Build Coastguard Worker 82*61046927SAndroid Build Coastguard Worker uint32_t found_child_count = 0; 83*61046927SAndroid Build Coastguard Worker uint32_t children[4] = {RADV_BVH_INVALID_NODE, RADV_BVH_INVALID_NODE, 84*61046927SAndroid Build Coastguard Worker RADV_BVH_INVALID_NODE, RADV_BVH_INVALID_NODE}; 85*61046927SAndroid Build Coastguard Worker 86*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < 2; ++i) 87*61046927SAndroid Build Coastguard Worker if (src.children[i] != RADV_BVH_INVALID_NODE) 88*61046927SAndroid Build Coastguard Worker children[found_child_count++] = src.children[i]; 89*61046927SAndroid Build Coastguard Worker 90*61046927SAndroid Build Coastguard Worker while (found_child_count < 4) { 91*61046927SAndroid Build Coastguard Worker int32_t collapsed_child_index = -1; 92*61046927SAndroid Build Coastguard Worker float largest_surface_area = -INFINITY; 93*61046927SAndroid Build Coastguard Worker 94*61046927SAndroid Build Coastguard Worker for (int32_t i = 0; i < found_child_count; ++i) { 95*61046927SAndroid Build Coastguard Worker if (ir_id_to_type(children[i]) != radv_ir_node_internal) 96*61046927SAndroid Build Coastguard Worker continue; 97*61046927SAndroid Build Coastguard Worker 98*61046927SAndroid Build Coastguard Worker radv_aabb bounds = 99*61046927SAndroid Build Coastguard Worker DEREF(REF(radv_ir_node)OFFSET(args.intermediate_bvh, 100*61046927SAndroid Build Coastguard Worker ir_id_to_offset(children[i]))).aabb; 101*61046927SAndroid Build Coastguard Worker 102*61046927SAndroid Build Coastguard Worker float surface_area = aabb_surface_area(bounds); 103*61046927SAndroid Build Coastguard Worker if (surface_area > largest_surface_area) { 104*61046927SAndroid Build Coastguard Worker largest_surface_area = surface_area; 105*61046927SAndroid Build Coastguard Worker collapsed_child_index = i; 106*61046927SAndroid Build Coastguard Worker } 107*61046927SAndroid Build Coastguard Worker } 108*61046927SAndroid Build Coastguard Worker 109*61046927SAndroid Build Coastguard Worker if (collapsed_child_index != -1) { 110*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node) child_node = 111*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node)OFFSET(args.intermediate_bvh, 112*61046927SAndroid Build Coastguard Worker ir_id_to_offset(children[collapsed_child_index])); 113*61046927SAndroid Build Coastguard Worker uint32_t grandchildren[2] = DEREF(child_node).children; 114*61046927SAndroid Build Coastguard Worker uint32_t valid_grandchild_count = 0; 115*61046927SAndroid Build Coastguard Worker 116*61046927SAndroid Build Coastguard Worker if (grandchildren[1] != RADV_BVH_INVALID_NODE) 117*61046927SAndroid Build Coastguard Worker ++valid_grandchild_count; 118*61046927SAndroid Build Coastguard Worker 119*61046927SAndroid Build Coastguard Worker if (grandchildren[0] != RADV_BVH_INVALID_NODE) 120*61046927SAndroid Build Coastguard Worker ++valid_grandchild_count; 121*61046927SAndroid Build Coastguard Worker else 122*61046927SAndroid Build Coastguard Worker grandchildren[0] = grandchildren[1]; 123*61046927SAndroid Build Coastguard Worker 124*61046927SAndroid Build Coastguard Worker if (valid_grandchild_count > 1) 125*61046927SAndroid Build Coastguard Worker children[found_child_count++] = grandchildren[1]; 126*61046927SAndroid Build Coastguard Worker 127*61046927SAndroid Build Coastguard Worker if (valid_grandchild_count > 0) 128*61046927SAndroid Build Coastguard Worker children[collapsed_child_index] = grandchildren[0]; 129*61046927SAndroid Build Coastguard Worker else { 130*61046927SAndroid Build Coastguard Worker found_child_count--; 131*61046927SAndroid Build Coastguard Worker children[collapsed_child_index] = children[found_child_count]; 132*61046927SAndroid Build Coastguard Worker } 133*61046927SAndroid Build Coastguard Worker 134*61046927SAndroid Build Coastguard Worker DEREF(child_node).bvh_offset = RADV_NULL_BVH_OFFSET; 135*61046927SAndroid Build Coastguard Worker } else 136*61046927SAndroid Build Coastguard Worker break; 137*61046927SAndroid Build Coastguard Worker } 138*61046927SAndroid Build Coastguard Worker 139*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < found_child_count; ++i) { 140*61046927SAndroid Build Coastguard Worker uint32_t type = ir_id_to_type(children[i]); 141*61046927SAndroid Build Coastguard Worker uint32_t offset = ir_id_to_offset(children[i]); 142*61046927SAndroid Build Coastguard Worker uint32_t dst_offset; 143*61046927SAndroid Build Coastguard Worker 144*61046927SAndroid Build Coastguard Worker if (type == radv_ir_node_internal) { 145*61046927SAndroid Build Coastguard Worker#if COMPACT 146*61046927SAndroid Build Coastguard Worker dst_offset = atomicAdd(DEREF(args.header).dst_node_offset, SIZEOF(radv_bvh_box32_node)); 147*61046927SAndroid Build Coastguard Worker#else 148*61046927SAndroid Build Coastguard Worker uint32_t offset_in_internal_nodes = offset - intermediate_leaf_nodes_size; 149*61046927SAndroid Build Coastguard Worker uint32_t child_index = offset_in_internal_nodes / SIZEOF(radv_ir_box_node); 150*61046927SAndroid Build Coastguard Worker dst_offset = dst_internal_offset + child_index * SIZEOF(radv_bvh_box32_node); 151*61046927SAndroid Build Coastguard Worker#endif 152*61046927SAndroid Build Coastguard Worker 153*61046927SAndroid Build Coastguard Worker REF(radv_ir_box_node) child_node = REF(radv_ir_box_node)OFFSET(args.intermediate_bvh, offset); 154*61046927SAndroid Build Coastguard Worker DEREF(child_node).bvh_offset = dst_offset; 155*61046927SAndroid Build Coastguard Worker } else { 156*61046927SAndroid Build Coastguard Worker uint32_t child_index = offset / SIZEOF(radv_ir_node); 157*61046927SAndroid Build Coastguard Worker dst_offset = dst_leaf_offset + child_index * output_leaf_node_size; 158*61046927SAndroid Build Coastguard Worker } 159*61046927SAndroid Build Coastguard Worker 160*61046927SAndroid Build Coastguard Worker radv_aabb child_aabb = 161*61046927SAndroid Build Coastguard Worker DEREF(REF(radv_ir_node)OFFSET(args.intermediate_bvh, offset)).aabb; 162*61046927SAndroid Build Coastguard Worker 163*61046927SAndroid Build Coastguard Worker DEREF(dst_node).coords[i] = child_aabb; 164*61046927SAndroid Build Coastguard Worker 165*61046927SAndroid Build Coastguard Worker uint32_t child_id = pack_node_id(dst_offset, ir_type_to_bvh_type(type)); 166*61046927SAndroid Build Coastguard Worker children[i] = child_id; 167*61046927SAndroid Build Coastguard Worker set_parent(child_id, node_id); 168*61046927SAndroid Build Coastguard Worker } 169*61046927SAndroid Build Coastguard Worker 170*61046927SAndroid Build Coastguard Worker for (uint i = found_child_count; i < 4; ++i) { 171*61046927SAndroid Build Coastguard Worker for (uint comp = 0; comp < 3; ++comp) { 172*61046927SAndroid Build Coastguard Worker DEREF(dst_node).coords[i].min[comp] = NAN; 173*61046927SAndroid Build Coastguard Worker DEREF(dst_node).coords[i].max[comp] = NAN; 174*61046927SAndroid Build Coastguard Worker } 175*61046927SAndroid Build Coastguard Worker } 176*61046927SAndroid Build Coastguard Worker 177*61046927SAndroid Build Coastguard Worker /* Make changes to the children's BVH offset value available to the other invocations. */ 178*61046927SAndroid Build Coastguard Worker memoryBarrier(gl_ScopeDevice, gl_StorageSemanticsBuffer, 179*61046927SAndroid Build Coastguard Worker gl_SemanticsAcquireRelease | gl_SemanticsMakeAvailable | gl_SemanticsMakeVisible); 180*61046927SAndroid Build Coastguard Worker 181*61046927SAndroid Build Coastguard Worker DEREF(dst_node).children = children; 182*61046927SAndroid Build Coastguard Worker break; 183*61046927SAndroid Build Coastguard Worker } 184*61046927SAndroid Build Coastguard Worker 185*61046927SAndroid Build Coastguard Worker if (is_root_node) { 186*61046927SAndroid Build Coastguard Worker REF(radv_accel_struct_header) header = REF(radv_accel_struct_header)(args.output_bvh - args.output_bvh_offset); 187*61046927SAndroid Build Coastguard Worker DEREF(header).aabb = src.base.aabb; 188*61046927SAndroid Build Coastguard Worker DEREF(header).bvh_offset = args.output_bvh_offset; 189*61046927SAndroid Build Coastguard Worker 190*61046927SAndroid Build Coastguard Worker set_parent(RADV_BVH_ROOT_NODE, RADV_BVH_INVALID_NODE); 191*61046927SAndroid Build Coastguard Worker } 192*61046927SAndroid Build Coastguard Worker} 193