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
相关产品推荐
相关产品推荐

