首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以动态地索引到WebGPU存储缓冲区中?

是否可以动态地索引到WebGPU存储缓冲区中?
EN

Stack Overflow用户
提问于 2022-01-29 23:25:43
回答 1查看 731关注 0票数 4

我正在尝试编写一个WGSL着色器,它读取存储在存储缓冲区中的八叉树。问题是,编译器不喜欢我正在计算的访问存储缓冲区中的叶子的动态索引。wgpu产生以下验证错误:

代码语言:javascript
复制
thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In Device::create_shader_module
    Function [1] 'get_voxel' is invalid
    Expression [68] is invalid
    The expression [67] may only be indexed by a constant

八叉树的结构使得我可以在GPU上遍历它。本文概述了该结构:https://developer.nvidia.com/gpugems/gpugems2/part-v-image-oriented-computing/chapter-37-octree-textures-gpu

从本质上说,八叉树是一个IndirectionGrid的数组,每个IndirectionGrid的内存中正好有8个GridCell。网格单元可以表示指向另一个IndirectionGrid的指针,也可以表示某些数据。

让我们说,在其最深处,八叉树表示的是一个16x16x16网格。我想得到7,7,7的GridCell。我们知道,7,7,7在根IndirectionGrid的单元格0中,因为坐标的每个分量都小于中点。如果将坐标组件相加,就可以得到当前GridCell的索引。因为我在穿过一棵树,我在每一层都这样做。下面是演示这一点的不完整代码。

引起问题的是let cell = grid.cells[grid_index].data;

因此,最终我的问题是,动态指数是否被允许?有什么我能改变的东西能神奇地让它发挥作用吗?或者我需要更多的背景信息来了解WebGPU所做的权衡?

代码语言:javascript
复制
struct GridCell {
    data: u32;
};

struct IndirectionGrid {
    cells: array<GridCell, 8>;
};

[[block]]
struct VoxelVolume {
    resolution: vec3<f32>;
    size: vec3<f32>;
    palette: array<u32, 256>;
    indirection_pool: array<IndirectionGrid>;
};

[[group(2), binding(0)]]
var<storage, read> voxel_volume: VoxelVolume;

let COLOR_RED_MASK = 0xFF000000u;
let COLOR_GREEN_MASK = 0x00FF0000u;
let COLOR_BLUE_MASK = 0x0000FF00u;
let COLOR_ALPHA_MASK = 0x000000FFu;

let CELL_TYPE_MASK: u32 = 0xFF000000u;
let CELL_DATA_MASK: u32 = 0x00FFFFFFu;

fn get_voxel(pos: vec3<f32>) -> vec4<f32> {
    let max_depth: i32 = 12;
    let color = vec4<f32>(0.0, 0.0, 0.0, 0.0);
    
    var pool_index = 0u;
    var grid_size = max(max(voxel_volume.size.x, voxel_volume.size.y), voxel_volume.size.z);
    
    for (var i: i32 = 0; i < max_depth; i = i + 1) {
        let grid = voxel_volume.indirection_pool[pool_index];
        let grid_coord_x = select(1u, 0u, pos.x / grid_size < 0.5);
        let grid_coord_y = select(1u, 0u, pos.y / grid_size < 0.5);
        let grid_coord_z = select(1u, 0u, pos.z / grid_size < 0.5);
        let grid_index = grid_coord_x + grid_coord_y * 2u + grid_coord_z * 2u * 2u;
        let cell = grid.cells[grid_index].data;
        let cell_type = cell & CELL_TYPE_MASK >> 16u;

        switch (cell_type) {
            case 1u: {
                pool_index = cell & CELL_DATA_MASK >> 8u;
            }
            case 2u: {
                let palette_index = cell & CELL_DATA_MASK >> 8u;
                let palette_color = voxel_volume.palette[palette_index];
                
                return vec4<f32>(
                    f32(palette_color & COLOR_RED_MASK >> 24u) / 255.0,
                    f32(palette_color & COLOR_GREEN_MASK >> 16u) / 255.0,
                    f32(palette_color & COLOR_BLUE_MASK >> 8u) / 255.0,
                    f32(palette_color & COLOR_ALPHA_MASK) / 255.0
                );
            }
            default: {
                // discard;
                return vec4<f32>(pos.x / 16.0, pos.y / 16.0, pos.z / 16.0, 1.0);
            }
        }
    }

    discard;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-02 18:39:05

索引到存储缓冲区是完全可以的。Naga不喜欢的是这一行:

代码语言:javascript
复制
let cell = grid.cells[grid_index].data;

..。因为grid不是存储缓冲区,所以它只是一个“堆栈上”的值。

WGSL最近决定允许这样做,但Naga还没有实现必要的黑客攻击。就我个人而言,我不推荐任何人依赖这个。相反,您可以保留对存储缓冲区的引用:

代码语言:javascript
复制
let grid = &voxel_volume.indirection_pool[pool_index];
let cell = (*grid).cells[grid_index].data;

这条路径不需要我们在SPIR输出中做出任何黑客/变通方法。

还请注意,最新的Naga (和Firefox)打印出了一个更详细的错误:

代码语言:javascript
复制
   ┌─ indexing.wgsl:25:39
   │  
25 │   let CELL_DATA_MASK: u32 = 0x00FFFFFFu;
   │ ╭──────────────────────────────────────^
26 │ │ 
27 │ │ fn get_voxel(pos: vec3<f32>) -> vec4<f32> {
28 │ │     let max_depth: i32 = 12;
   · │
40 │ │         let cell = grid.cells[grid_index].data;
   │ │                   ^^^^^^^^^^^^^^^^^^^^^^^ naga::Expression [73]
   · │
65 │ │     discard;
66 │ │ }
   │ ╰─^ naga::Function [1]

Function [1] 'get_voxel' is invalid: 
        Expression [73] is invalid
        The expression [72] may only be indexed by a constant
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70910601

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档