• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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