You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Bevy 0.12计算着色器时遇缓冲区越界错误求助

问题:Bevy 0.12 + bevy_app_compute 实现数组相加时出现wgpu验证错误

运行时触发如下panic:

thread 'Compute Task Pool (6)' panicked at C:\Users\bramb\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wgpu-0.17.2\src\backend\direct.rs:3056:5:
wgpu error: Validation Error

Caused by:
    In Queue::write_buffer
    Copy of 0..32 would end up overrunning the bounds of the Destination buffer of size 16

Rust代码

// calc_gpu_things每帧执行
fn calc_gpu_things(mut compute_worker: ResMut<AppComputeWorker<SimpleComputeWorker>>) {
    if !compute_worker.ready() {
        return;
    };

    compute_worker.write("firstArray", &[2.0, 3.0, 4.0, 5.0]);
    compute_worker.write("secondArray", &[2.0, 3.0, 4.0, 5.0]);
    let result: [f32; 4] = compute_worker.read("resultArray");

    println!("got {:?}", result);
}

#[derive(TypeUuid)]
#[uuid = "2545ae14-a9bc-4f03-9ea4-4eb43d1075a7"]
struct SimpleShader;

impl ComputeShader for SimpleShader {
    fn shader() -> ShaderRef {
        "compute1.wgsl".into()
    }
}

#[derive(Resource)]
struct SimpleComputeWorker;

impl ComputeWorker for SimpleComputeWorker {
    fn build(world: &mut World) -> AppComputeWorker<Self> {
        let worker = AppComputeWorkerBuilder::new(world)
            // Add a staging buffer, it will be available from
            // both CPU and GPU land.
            .add_staging("firstArray", &[2.0, 3.0, 4.0, 5.0])
            .add_staging("secondArray", &[2.0, 3.0, 4.0, 5.0])
            .add_staging("resultArray", &[0.0, 0.0, 0.0, 0.0])
            // Create a compute pass from your compute shader
            // and define used variables
            .add_pass::<SimpleShader>([1, 1, 1], &["firstArray", "secondArray", "resultArray"])
            .build();

        worker
    }
}

WGSLL着色器代码

@group(0) @binding(0) var<storage,read> firstArray: array<f32>;
@group(0) @binding(1) var<storage,read> secondArray: array<f32>;
@group(0) @binding(2) var<storage,read_write> resultArray: array<f32>;

@compute @workgroup_size(1, 1, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let index: u32 = global_id.x;

    resultArray[index] = firstArray[index] + secondArray[index];
}

解决方案

1. 修复缓冲区写入的类型不匹配问题

错误根源是Rust字面量类型推断错误:2.0默认是f64类型(单元素8字节),而你初始化缓冲区时用的是f32(单元素4字节),导致write时传入的4个f64总字节数(32)超过缓冲区容量(16)。

修改write方法的参数,明确标注为f32类型:

compute_worker.write("firstArray", &[2.0f32, 3.0f32, 4.0f32, 5.0f32]);
compute_worker.write("secondArray", &[2.0f32, 3.0f32, 4.0f32, 5.0f32]);

2. 修复计算着色器仅处理单个元素的问题

当前配置仅启动1个工作线程,只会处理数组的第0个元素,其余3个元素不会被计算。可以通过以下两种方式调整线程数量:

方法一:调整工作组数量

在add_pass中将工作组数量设为[4, 1, 1],总线程数变为4:

.add_pass::<SimpleShader>([4, 1, 1], &["firstArray", "secondArray", "resultArray"])

方法二:调整工作组内线程数

修改着色器的workgroup_size为4, 1, 1,保持工作组数量为[1, 1, 1]:

@compute @workgroup_size(4, 1, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let index: u32 = global_id.x;

    resultArray[index] = firstArray[index] + secondArray[index];
}

两种方法都能让计算着色器覆盖数组所有4个元素,返回正确的相加结果。


内容的提问来源于stack exchange,提问作者NewUser69420

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:35:07