Files
wgpu/tests/gpu-tests/bgra8unorm_storage.rs
2025-02-23 14:06:34 -05:00

160 lines
5.3 KiB
Rust

//! Tests for BGRA8UNORM_STORAGE feature
use std::borrow::Cow;
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters};
const SHADER_SRC: &str = "
@group(0) @binding(0) var tex: texture_storage_2d<bgra8unorm, write>;
@compute @workgroup_size(256)
fn main(@builtin(workgroup_id) wgid: vec3<u32>) {
var texel = vec4f(0.0, 0.0, 1.0, 1.0);
textureStore(tex, wgid.xy, texel);
}
";
#[gpu_test]
static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.limits(wgpu::Limits {
max_storage_textures_per_shader_stage: 1,
..Default::default()
})
.features(wgpu::Features::BGRA8UNORM_STORAGE),
)
.run_async(|ctx| async move {
let device = &ctx.device;
let texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 256,
height: 256,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8Unorm,
usage: wgpu::TextureUsages::STORAGE_BINDING | wgpu::TextureUsages::COPY_SRC,
view_formats: &[],
});
let view = texture.create_view(&wgpu::TextureViewDescriptor {
label: None,
format: None,
dimension: None,
usage: None,
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
base_array_layer: 0,
mip_level_count: Some(1),
array_layer_count: Some(1),
});
let readback_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 256 * 256 * 4,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
let bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::StorageTexture {
access: wgpu::StorageTextureAccess::WriteOnly,
format: wgpu::TextureFormat::Bgra8Unorm,
view_dimension: wgpu::TextureViewDimension::D2,
},
count: None,
}],
});
let bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bgl,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&view),
}],
});
let pl = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&bgl],
push_constant_ranges: &[],
});
let module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(SHADER_SRC)),
});
let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: Some(&pl),
entry_point: Some("main"),
compilation_options: Default::default(),
module: &module,
cache: None,
});
let mut encoder =
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: None,
});
pass.set_bind_group(0, &bg, &[]);
pass.set_pipeline(&pipeline);
pass.dispatch_workgroups(256, 256, 1);
}
encoder.copy_texture_to_buffer(
wgpu::TexelCopyTextureInfo {
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
aspect: wgpu::TextureAspect::All,
},
wgpu::TexelCopyBufferInfo {
buffer: &readback_buffer,
layout: wgpu::TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(256 * 4),
rows_per_image: Some(256),
},
},
wgpu::Extent3d {
width: 256,
height: 256,
depth_or_array_layers: 1,
},
);
ctx.queue.submit(Some(encoder.finish()));
let buffer_slice = readback_buffer.slice(..);
buffer_slice.map_async(wgpu::MapMode::Read, Result::unwrap);
ctx.async_poll(wgpu::PollType::wait()).await.unwrap();
{
let texels = buffer_slice.get_mapped_range();
assert_eq!(texels.len(), 256 * 256 * 4);
for texel in texels.chunks(4) {
assert_eq!(texel[0], 255); // b
assert_eq!(texel[1], 0); // g
assert_eq!(texel[2], 0); // r
assert_eq!(texel[3], 255); // a
}
}
readback_buffer.unmap();
});