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

wgpu 0.19中get_mapped_range()返回全0值的问题求助

问题原因

你遇到的get_mapped_range()返回全0的问题,核心原因是create_buffer_init内部通过命令队列将数据从临时staging buffer复制到目标buffer,但代码没有等待这个复制操作完成就立即映射读取——此时GPU还未完成数据写入,读取到的是目标buffer的初始零值。

解决方法

提供两种可行的修复方案:

方案一:等待GPU复制操作完成(使用Fence)

在创建buffer后,添加Fence等待逻辑,确保GPU完成数据复制:

// 创建buffer之后添加以下代码
let fence = device.create_fence(&wgpu::FenceDescriptor { label: None });
queue.signal_fence(&fence, 1);
// 等待Fence触发,确认复制完成
while fence.get_completed_value().unwrap_or(0) < 1 {
    device.poll(wgpu::Maintain::Poll);
    std::thread::sleep(std::time::Duration::from_millis(1));
}

方案二:直接创建映射Buffer写入数据(更简洁)

绕过staging buffer的复制流程,直接创建可映射的Buffer并写入数据,无需等待GPU操作:

// 替换原有的create_buffer_init代码
let rand_buffer = device.create_buffer(&wgpu::BufferDescriptor {
    label: Some("to sort"),
    size: noisy_data.len() as u64,
    usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::MAP_WRITE | wgpu::BufferUsages::MAP_READ,
    mapped_at_creation: true,
});
{
    let mut mapping = rand_buffer.slice(..).get_mapped_range_mut();
    mapping.copy_from_slice(&noisy_data);
}
rand_buffer.unmap();
完整修复代码(方案二)
use rand::RngCore;
use wgpu::util::DeviceExt;
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ft = async {
        let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
            backends: wgpu::Backends::all(),
            ..Default::default()
        });
        let (device, queue) = instance
            .request_adapter(&wgpu::RequestAdapterOptions {
                power_preference: wgpu::PowerPreference::default(),
                compatible_surface: None,
                force_fallback_adapter: false,
            })
            .await
            .unwrap()
            .request_device(
                &wgpu::DeviceDescriptor {
                    label: None,
                    required_limits: wgpu::Limits::default(),
                    required_features: wgpu::Features::MAPPABLE_PRIMARY_BUFFERS,
                },
                None,
            )
            .await
            .unwrap();

        let mut noisy_data = [5; 4096 * 4];
        rand::thread_rng().fill_bytes(&mut noisy_data);
        println!("{:?}", &noisy_data[0..10]);
        
        // 直接创建映射Buffer并写入数据
        let rand_buffer = device.create_buffer(&wgpu::BufferDescriptor {
            label: Some("to sort"),
            size: noisy_data.len() as u64,
            usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::MAP_WRITE | wgpu::BufferUsages::MAP_READ,
            mapped_at_creation: true,
        });
        {
            let mut mapping = rand_buffer.slice(..).get_mapped_range_mut();
            mapping.copy_from_slice(&noisy_data);
        }
        rand_buffer.unmap();

        let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel();
        rand_buffer
            .slice(..)
            .map_async(wgpu::MapMode::Read, move |result| {
                tx.send(result).unwrap();
            });
        device.poll(wgpu::Maintain::Wait);
        rx.receive().await.unwrap().unwrap();
        let mapped_data: &[u8] = &rand_buffer.slice(..).get_mapped_range();
        println!("{:?}", &mapped_data[0..10]);
        
    };
    pollster::block_on(ft);
    Ok(())
}

执行后即可输出与初始数据一致的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 11:07:22