mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
187 lines
5.6 KiB
Rust
187 lines
5.6 KiB
Rust
//! Tests for buffer usages validation.
|
|
|
|
use wgpu::BufferAddress;
|
|
use wgpu::{BufferUsages as Bu, MapMode as Ma};
|
|
use wgpu_test::{fail_if, gpu_test, GpuTestConfiguration, TestParameters, TestingContext};
|
|
|
|
const BUFFER_SIZE: BufferAddress = 1234;
|
|
|
|
const ALWAYS_VALID: &[Bu; 4] = &[
|
|
Bu::MAP_READ,
|
|
Bu::MAP_WRITE,
|
|
Bu::MAP_READ.union(Bu::COPY_DST),
|
|
Bu::MAP_WRITE.union(Bu::COPY_SRC),
|
|
];
|
|
// MAP_READ can only be paired with COPY_DST and MAP_WRITE can only be paired with COPY_SRC
|
|
// (unless Features::MAPPABlE_PRIMARY_BUFFERS is enabled).
|
|
const NEEDS_MAPPABLE_PRIMARY_BUFFERS: &[Bu; 7] = &[
|
|
Bu::MAP_READ.union(Bu::COPY_DST.union(Bu::COPY_SRC)),
|
|
Bu::MAP_WRITE.union(Bu::COPY_SRC.union(Bu::COPY_DST)),
|
|
Bu::MAP_READ.union(Bu::MAP_WRITE),
|
|
Bu::MAP_WRITE.union(Bu::MAP_READ),
|
|
Bu::MAP_READ.union(Bu::COPY_DST.union(Bu::STORAGE)),
|
|
Bu::MAP_WRITE.union(Bu::COPY_SRC.union(Bu::STORAGE)),
|
|
// these two require acceleration_structures feature
|
|
Bu::all().intersection(Bu::BLAS_INPUT.union(Bu::TLAS_INPUT).complement()),
|
|
];
|
|
const INVALID_BITS: Bu = Bu::from_bits_retain(0b1111111111111);
|
|
const ALWAYS_FAIL: &[Bu; 2] = &[Bu::empty(), INVALID_BITS];
|
|
|
|
fn try_create(ctx: TestingContext, usages: &[(bool, &[wgpu::BufferUsages])]) {
|
|
for (expect_validation_error, usage) in usages
|
|
.iter()
|
|
.flat_map(|&(expect_error, usages)| usages.iter().copied().map(move |u| (expect_error, u)))
|
|
{
|
|
fail_if(
|
|
&ctx.device,
|
|
expect_validation_error,
|
|
|| {
|
|
let _buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: None,
|
|
size: BUFFER_SIZE,
|
|
usage,
|
|
mapped_at_creation: false,
|
|
});
|
|
},
|
|
None,
|
|
);
|
|
}
|
|
}
|
|
|
|
#[gpu_test]
|
|
static BUFFER_USAGE: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|ctx| {
|
|
try_create(
|
|
ctx,
|
|
&[
|
|
(false, ALWAYS_VALID),
|
|
(true, NEEDS_MAPPABLE_PRIMARY_BUFFERS),
|
|
(true, ALWAYS_FAIL),
|
|
],
|
|
);
|
|
});
|
|
|
|
#[gpu_test]
|
|
static BUFFER_USAGE_MAPPABLE_PRIMARY_BUFFERS: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(TestParameters::default().features(wgpu::Features::MAPPABLE_PRIMARY_BUFFERS))
|
|
.run_sync(|ctx| {
|
|
try_create(
|
|
ctx,
|
|
&[
|
|
(false, ALWAYS_VALID),
|
|
(false, NEEDS_MAPPABLE_PRIMARY_BUFFERS),
|
|
(true, ALWAYS_FAIL),
|
|
],
|
|
);
|
|
});
|
|
|
|
async fn map_test(
|
|
ctx: &TestingContext,
|
|
usage_type: &str,
|
|
map_mode_type: Ma,
|
|
before_unmap: bool,
|
|
before_destroy: bool,
|
|
after_unmap: bool,
|
|
after_destroy: bool,
|
|
) {
|
|
log::info!("map_test usage_type:{usage_type} map_mode_type:{:?} before_unmap:{before_unmap} before_destroy:{before_destroy} after_unmap:{after_unmap} after_destroy:{after_destroy}", map_mode_type);
|
|
|
|
let size = 8;
|
|
let usage = match usage_type {
|
|
"read" => Bu::COPY_DST | Bu::MAP_READ,
|
|
"write" => Bu::COPY_SRC | Bu::MAP_WRITE,
|
|
_ => Bu::from_bits(0).unwrap(),
|
|
};
|
|
let buffer_creation_validation_error = usage.is_empty();
|
|
|
|
let mut buffer = None;
|
|
|
|
fail_if(
|
|
&ctx.device,
|
|
buffer_creation_validation_error,
|
|
|| {
|
|
buffer = Some(ctx.device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: None,
|
|
size,
|
|
usage,
|
|
mapped_at_creation: false,
|
|
}));
|
|
},
|
|
None,
|
|
);
|
|
if buffer_creation_validation_error {
|
|
return;
|
|
}
|
|
|
|
let buffer = buffer.unwrap();
|
|
|
|
let map_async_validation_error = buffer_creation_validation_error
|
|
|| (map_mode_type == Ma::Read && !usage.contains(Bu::MAP_READ))
|
|
|| (map_mode_type == Ma::Write && !usage.contains(Bu::MAP_WRITE));
|
|
|
|
fail_if(
|
|
&ctx.device,
|
|
map_async_validation_error,
|
|
|| {
|
|
buffer.slice(0..size).map_async(map_mode_type, |_| {});
|
|
},
|
|
None,
|
|
);
|
|
|
|
if map_async_validation_error {
|
|
return;
|
|
}
|
|
|
|
if before_unmap {
|
|
buffer.unmap();
|
|
}
|
|
|
|
if before_destroy {
|
|
buffer.destroy();
|
|
}
|
|
|
|
ctx.async_poll(wgpu::PollType::wait()).await.unwrap();
|
|
|
|
if !before_unmap && !before_destroy {
|
|
{
|
|
let view = buffer.slice(0..size).get_mapped_range();
|
|
assert!(!view.is_empty());
|
|
}
|
|
|
|
if after_unmap {
|
|
buffer.unmap();
|
|
}
|
|
|
|
if after_destroy {
|
|
buffer.destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
#[gpu_test]
|
|
static BUFFER_MAP_ASYNC_MAP_STATE: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(TestParameters::default().features(wgpu::Features::MAPPABLE_PRIMARY_BUFFERS))
|
|
.run_async(move |ctx| async move {
|
|
for usage_type in ["invalid", "read", "write"] {
|
|
for map_mode_type in [Ma::Read, Ma::Write] {
|
|
for before_unmap in [false, true] {
|
|
for before_destroy in [false, true] {
|
|
for after_unmap in [false, true] {
|
|
for after_destroy in [false, true] {
|
|
map_test(
|
|
&ctx,
|
|
usage_type,
|
|
map_mode_type,
|
|
before_unmap,
|
|
before_destroy,
|
|
after_unmap,
|
|
after_destroy,
|
|
)
|
|
.await
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|