test: add expected msg. arg. to wgpu_test::fail{,_if}

This commit is contained in:
Erich Gubler 2024-02-22 14:21:35 -05:00
parent c7a16b36b1
commit 94dba0b026
16 changed files with 652 additions and 432 deletions

View File

@ -27,10 +27,28 @@ pub use run::{execute_test, TestingContext};
pub use wgpu_macros::gpu_test;
/// Run some code in an error scope and assert that validation fails.
pub fn fail<T>(device: &wgpu::Device, callback: impl FnOnce() -> T) -> T {
pub fn fail<T>(
device: &wgpu::Device,
callback: impl FnOnce() -> T,
expected_msg_substring: Option<&'static str>,
) -> T {
device.push_error_scope(wgpu::ErrorFilter::Validation);
let result = callback();
assert!(pollster::block_on(device.pop_error_scope()).is_some());
let validation_error = pollster::block_on(device.pop_error_scope())
.expect("expected validation error in callback, but no validation error was emitted");
if let Some(expected_msg_substring) = expected_msg_substring {
let lowered_expected = expected_msg_substring.to_lowercase();
let lowered_actual = validation_error.to_string().to_lowercase();
assert!(
lowered_actual.contains(&lowered_expected),
concat!(
"expected validation error case-insensitively containing {:?}, ",
"but it was not present in actual error message:\n{:?}"
),
expected_msg_substring,
validation_error
);
}
result
}
@ -46,9 +64,14 @@ pub fn valid<T>(device: &wgpu::Device, callback: impl FnOnce() -> T) -> T {
/// Run some code in an error scope and assert that validation succeeds or fails depending on the
/// provided `should_fail` boolean.
pub fn fail_if<T>(device: &wgpu::Device, should_fail: bool, callback: impl FnOnce() -> T) -> T {
pub fn fail_if<T>(
device: &wgpu::Device,
should_fail: bool,
callback: impl FnOnce() -> T,
expected_msg_substring: Option<&'static str>,
) -> T {
if should_fail {
fail(device, callback)
fail(device, callback, expected_msg_substring)
} else {
valid(device, callback)
}

View File

@ -368,9 +368,13 @@ fn separate_programs_have_incompatible_derived_bgls(ctx: TestingContext) {
pass.set_bind_group(0, &bg2, &[]);
pass.dispatch_workgroups(1, 1, 1);
fail(&ctx.device, || {
drop(pass);
});
fail(
&ctx.device,
|| {
drop(pass);
},
None,
);
}
#[gpu_test]
@ -436,7 +440,11 @@ fn derived_bgls_incompatible_with_regular_bgls(ctx: TestingContext) {
pass.set_bind_group(0, &bg, &[]);
pass.dispatch_workgroups(1, 1, 1);
fail(&ctx.device, || {
drop(pass);
})
fail(
&ctx.device,
|| {
drop(pass);
},
None,
)
}

View File

@ -217,17 +217,21 @@ static MINIMUM_BUFFER_BINDING_SIZE_LAYOUT: GpuTestConfiguration = GpuTestConfigu
push_constant_ranges: &[],
});
wgpu_test::fail(&ctx.device, || {
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: "main",
compilation_options: Default::default(),
cache: None,
});
});
wgpu_test::fail(
&ctx.device,
|| {
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: "main",
compilation_options: Default::default(),
cache: None,
});
},
None,
);
});
/// The WebGPU algorithm [validating shader binding][vsb] requires
@ -314,21 +318,25 @@ static MINIMUM_BUFFER_BINDING_SIZE_DISPATCH: GpuTestConfiguration = GpuTestConfi
}],
});
wgpu_test::fail(&ctx.device, || {
let mut encoder = ctx.device.create_command_encoder(&Default::default());
wgpu_test::fail(
&ctx.device,
|| {
let mut encoder = ctx.device.create_command_encoder(&Default::default());
let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: None,
});
let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: None,
});
pass.set_bind_group(0, &bind_group, &[]);
pass.set_pipeline(&pipeline);
pass.dispatch_workgroups(1, 1, 1);
pass.set_bind_group(0, &bind_group, &[]);
pass.set_pipeline(&pipeline);
pass.dispatch_workgroups(1, 1, 1);
drop(pass);
let _ = encoder.finish();
});
drop(pass);
let _ = encoder.finish();
},
None,
);
});
#[gpu_test]

View File

@ -12,9 +12,12 @@ fn try_copy(
) {
let buffer = ctx.device.create_buffer(&BUFFER_DESCRIPTOR);
let data = vec![255; size as usize];
fail_if(&ctx.device, should_fail, || {
ctx.queue.write_buffer(&buffer, offset, &data)
});
fail_if(
&ctx.device,
should_fail,
|| ctx.queue.write_buffer(&buffer, offset, &data),
None,
);
}
#[gpu_test]

View File

@ -31,14 +31,19 @@ fn try_create(ctx: TestingContext, usages: &[(bool, &[wgpu::BufferUsages])]) {
.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,
});
});
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,
);
}
}
@ -89,14 +94,19 @@ async fn map_test(
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,
}));
});
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;
}
@ -107,9 +117,14 @@ async fn map_test(
|| (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, |_| {});
});
fail_if(
&ctx.device,
map_async_validation_error,
|| {
buffer.slice(0..size).map_async(map_mode_type, |_| {});
},
None,
);
if map_async_validation_error {
return;

View File

@ -298,224 +298,317 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
// the device is not valid.
// Creating a command encoder should fail.
fail(&ctx.device, || {
ctx.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
});
fail(
&ctx.device,
|| {
ctx.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
},
None,
);
// Creating a buffer should fail.
fail(&ctx.device, || {
ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 256,
usage: wgpu::BufferUsages::MAP_WRITE | wgpu::BufferUsages::COPY_SRC,
mapped_at_creation: false,
});
});
fail(
&ctx.device,
|| {
ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 256,
usage: wgpu::BufferUsages::MAP_WRITE | wgpu::BufferUsages::COPY_SRC,
mapped_at_creation: false,
});
},
None,
);
// Creating a texture should fail.
fail(&ctx.device, || {
ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 512,
height: 512,
depth_or_array_layers: 1,
},
mip_level_count: 2,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rg8Uint,
usage: wgpu::TextureUsages::COPY_SRC,
view_formats: &[],
});
});
fail(
&ctx.device,
|| {
ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 512,
height: 512,
depth_or_array_layers: 1,
},
mip_level_count: 2,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rg8Uint,
usage: wgpu::TextureUsages::COPY_SRC,
view_formats: &[],
});
},
None,
);
// Texture clear should fail.
fail(&ctx.device, || {
encoder_for_clear.clear_texture(
&texture_for_write,
&wgpu::ImageSubresourceRange {
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
base_array_layer: 0,
array_layer_count: None,
},
);
});
fail(
&ctx.device,
|| {
encoder_for_clear.clear_texture(
&texture_for_write,
&wgpu::ImageSubresourceRange {
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
base_array_layer: 0,
array_layer_count: None,
},
);
},
None,
);
// Creating a compute pass should fail.
fail(&ctx.device, || {
encoder_for_compute_pass.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: None,
});
});
fail(
&ctx.device,
|| {
encoder_for_compute_pass.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: None,
});
},
None,
);
// Creating a render pass should fail.
fail(&ctx.device, || {
encoder_for_render_pass.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
ops: wgpu::Operations::default(),
resolve_target: None,
view: &target_view,
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
});
fail(
&ctx.device,
|| {
encoder_for_render_pass.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
ops: wgpu::Operations::default(),
resolve_target: None,
view: &target_view,
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
},
None,
);
// Copying a buffer to a buffer should fail.
fail(&ctx.device, || {
encoder_for_buffer_buffer_copy.copy_buffer_to_buffer(
&buffer_source,
0,
&buffer_dest,
0,
256,
);
});
fail(
&ctx.device,
|| {
encoder_for_buffer_buffer_copy.copy_buffer_to_buffer(
&buffer_source,
0,
&buffer_dest,
0,
256,
);
},
None,
);
// Copying a buffer to a texture should fail.
fail(&ctx.device, || {
encoder_for_buffer_texture_copy.copy_buffer_to_texture(
wgpu::ImageCopyBuffer {
buffer: &buffer_source,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(4),
rows_per_image: None,
fail(
&ctx.device,
|| {
encoder_for_buffer_texture_copy.copy_buffer_to_texture(
wgpu::ImageCopyBuffer {
buffer: &buffer_source,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(4),
rows_per_image: None,
},
},
},
texture_for_write.as_image_copy(),
texture_extent,
);
});
texture_for_write.as_image_copy(),
texture_extent,
);
},
None,
);
// Copying a texture to a buffer should fail.
fail(&ctx.device, || {
encoder_for_texture_buffer_copy.copy_texture_to_buffer(
texture_for_read.as_image_copy(),
wgpu::ImageCopyBuffer {
buffer: &buffer_source,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(4),
rows_per_image: None,
fail(
&ctx.device,
|| {
encoder_for_texture_buffer_copy.copy_texture_to_buffer(
texture_for_read.as_image_copy(),
wgpu::ImageCopyBuffer {
buffer: &buffer_source,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(4),
rows_per_image: None,
},
},
},
texture_extent,
);
});
texture_extent,
);
},
None,
);
// Copying a texture to a texture should fail.
fail(&ctx.device, || {
encoder_for_texture_texture_copy.copy_texture_to_texture(
texture_for_read.as_image_copy(),
texture_for_write.as_image_copy(),
texture_extent,
);
});
fail(
&ctx.device,
|| {
encoder_for_texture_texture_copy.copy_texture_to_texture(
texture_for_read.as_image_copy(),
texture_for_write.as_image_copy(),
texture_extent,
);
},
None,
);
// Creating a bind group layout should fail.
fail(&ctx.device, || {
ctx.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[],
});
});
fail(
&ctx.device,
|| {
ctx.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[],
});
},
None,
);
// Creating a bind group should fail.
fail(&ctx.device, || {
ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(
buffer_source.as_entire_buffer_binding(),
),
}],
});
});
fail(
&ctx.device,
|| {
ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(
buffer_source.as_entire_buffer_binding(),
),
}],
});
},
None,
);
// Creating a pipeline layout should fail.
fail(&ctx.device, || {
ctx.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
});
fail(
&ctx.device,
|| {
ctx.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
},
None,
);
// Creating a shader module should fail.
fail(&ctx.device, || {
ctx.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed("")),
});
});
fail(
&ctx.device,
|| {
ctx.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed("")),
});
},
None,
);
// Creating a shader module spirv should fail.
fail(&ctx.device, || unsafe {
ctx.device
.create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV {
label: None,
source: std::borrow::Cow::Borrowed(&[]),
});
});
fail(
&ctx.device,
|| unsafe {
ctx.device
.create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV {
label: None,
source: std::borrow::Cow::Borrowed(&[]),
});
},
None,
);
// Creating a render pipeline should fail.
fail(&ctx.device, || {
ctx.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
fail(
&ctx.device,
|| {
ctx.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
module: &shader_module,
entry_point: "",
compilation_options: Default::default(),
buffers: &[],
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: None,
multiview: None,
cache: None,
});
},
None,
);
// Creating a compute pipeline should fail.
fail(
&ctx.device,
|| {
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: None,
module: &shader_module,
entry_point: "",
compilation_options: Default::default(),
buffers: &[],
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: None,
multiview: None,
cache: None,
});
});
cache: None,
});
},
None,
);
// Creating a compute pipeline should fail.
fail(&ctx.device, || {
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: None,
module: &shader_module,
entry_point: "",
compilation_options: Default::default(),
cache: None,
});
});
fail(
&ctx.device,
|| {
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: None,
module: &shader_module,
entry_point: "",
compilation_options: Default::default(),
cache: None,
});
},
None,
);
// Buffer map should fail.
fail(&ctx.device, || {
buffer_for_map
.slice(..)
.map_async(wgpu::MapMode::Write, |_| ());
});
fail(
&ctx.device,
|| {
buffer_for_map
.slice(..)
.map_async(wgpu::MapMode::Write, |_| ());
},
None,
);
// Buffer unmap should fail.
fail(&ctx.device, || {
buffer_for_unmap.unmap();
});
fail(
&ctx.device,
|| {
buffer_for_unmap.unmap();
},
None,
);
});
#[gpu_test]

View File

@ -58,10 +58,14 @@ static DROP_ENCODER_AFTER_ERROR: GpuTestConfiguration = GpuTestConfiguration::ne
});
// Set a bad viewport on renderpass, triggering an error.
fail(&ctx.device, || {
renderpass.set_viewport(0.0, 0.0, -1.0, -1.0, 0.0, 1.0);
drop(renderpass);
});
fail(
&ctx.device,
|| {
renderpass.set_viewport(0.0, 0.0, -1.0, -1.0, 0.0, 1.0);
drop(renderpass);
},
None,
);
// This is the actual interesting error condition. We've created
// a CommandEncoder which errored out when processing a command.

View File

@ -264,24 +264,29 @@ static IMAGE_BITMAP_IMPORT: GpuTestConfiguration =
view_formats: &[],
});
fail_if(&ctx.device, !valid, || {
ctx.queue.copy_external_image_to_texture(
&wgpu::ImageCopyExternalImage {
source: source.clone(),
origin: src_origin,
flip_y: src_flip_y,
},
wgpu::ImageCopyTextureTagged {
texture: &texture,
mip_level: 0,
origin: dest_origin,
aspect: wgpu::TextureAspect::All,
color_space: dest_color_space,
premultiplied_alpha: dest_premultiplied,
},
copy_size,
);
});
fail_if(
&ctx.device,
!valid,
|| {
ctx.queue.copy_external_image_to_texture(
&wgpu::ImageCopyExternalImage {
source: source.clone(),
origin: src_origin,
flip_y: src_flip_y,
},
wgpu::ImageCopyTextureTagged {
texture: &texture,
mip_level: 0,
origin: dest_origin,
aspect: wgpu::TextureAspect::All,
color_space: dest_color_space,
premultiplied_alpha: dest_premultiplied,
},
copy_size,
);
},
None,
);
let readback_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("readback buffer"),

View File

@ -58,9 +58,13 @@ static FLOAT32_FILTERABLE_WITHOUT_FEATURE: GpuTestConfiguration = GpuTestConfigu
// Float 32 textures can be used as non-filterable only
create_texture_binding(device, wgpu::TextureFormat::R32Float, false);
// This is supposed to fail, since we have not activated the feature
fail(&ctx.device, || {
create_texture_binding(device, wgpu::TextureFormat::R32Float, true);
});
fail(
&ctx.device,
|| {
create_texture_binding(device, wgpu::TextureFormat::R32Float, true);
},
None,
);
});
#[gpu_test]

View File

@ -18,11 +18,15 @@ static BUFFER_DESTROY: GpuTestConfiguration =
.await
.panic_on_timeout();
fail(&ctx.device, || {
buffer
.slice(..)
.map_async(wgpu::MapMode::Write, move |_| {});
});
fail(
&ctx.device,
|| {
buffer
.slice(..)
.map_async(wgpu::MapMode::Write, move |_| {});
},
None,
);
buffer.destroy();

View File

@ -141,12 +141,16 @@ static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration =
sample_count: 1,
view_formats: &[],
});
fail(&ctx.device, || {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
aspect: wgpu::TextureAspect::Plane0,
..Default::default()
});
});
fail(
&ctx.device,
|| {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
aspect: wgpu::TextureAspect::Plane0,
..Default::default()
});
},
None,
);
});
#[gpu_test]
@ -168,13 +172,17 @@ static NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS: GpuTestConfiguration = GpuTestConf
sample_count: 1,
view_formats: &[],
});
fail(&ctx.device, || {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
format: Some(wgpu::TextureFormat::R8Unorm),
aspect: wgpu::TextureAspect::Plane2,
..Default::default()
});
});
fail(
&ctx.device,
|| {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
format: Some(wgpu::TextureFormat::R8Unorm),
aspect: wgpu::TextureAspect::Plane2,
..Default::default()
});
},
None,
);
});
#[gpu_test]
@ -196,13 +204,17 @@ static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfigu
sample_count: 1,
view_formats: &[],
});
fail(&ctx.device, || {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
format: Some(wgpu::TextureFormat::Rg8Unorm),
aspect: wgpu::TextureAspect::Plane0,
..Default::default()
});
});
fail(
&ctx.device,
|| {
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
format: Some(wgpu::TextureFormat::Rg8Unorm),
aspect: wgpu::TextureAspect::Plane0,
..Default::default()
});
},
None,
);
});
#[gpu_test]
@ -215,16 +227,20 @@ static NV12_TEXTURE_BAD_SIZE: GpuTestConfiguration = GpuTestConfiguration::new()
depth_or_array_layers: 1,
};
fail(&ctx.device, || {
let _ = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
dimension: wgpu::TextureDimension::D2,
size,
format: wgpu::TextureFormat::NV12,
usage: wgpu::TextureUsages::TEXTURE_BINDING,
mip_level_count: 1,
sample_count: 1,
view_formats: &[],
});
});
fail(
&ctx.device,
|| {
let _ = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
dimension: wgpu::TextureDimension::D2,
size,
format: wgpu::TextureFormat::NV12,
usage: wgpu::TextureUsages::TEXTURE_BINDING,
mip_level_count: 1,
sample_count: 1,
view_formats: &[],
});
},
None,
);
});

View File

@ -13,27 +13,31 @@ static PIPELINE_DEFAULT_LAYOUT_BAD_MODULE: GpuTestConfiguration = GpuTestConfigu
.run_sync(|ctx| {
ctx.device.push_error_scope(wgpu::ErrorFilter::Validation);
fail(&ctx.device, || {
let module = ctx
.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl("not valid wgsl".into()),
});
fail(
&ctx.device,
|| {
let module = ctx
.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl("not valid wgsl".into()),
});
let pipeline = ctx
.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some("mandelbrot compute pipeline"),
layout: None,
module: &module,
entry_point: "doesn't exist",
compilation_options: Default::default(),
cache: None,
});
let pipeline =
ctx.device
.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some("mandelbrot compute pipeline"),
layout: None,
module: &module,
entry_point: "doesn't exist",
compilation_options: Default::default(),
cache: None,
});
pipeline.get_bind_group_layout(0);
});
pipeline.get_bind_group_layout(0);
},
None,
);
});
const TRIVIAL_VERTEX_SHADER_DESC: wgpu::ShaderModuleDescriptor = wgpu::ShaderModuleDescriptor {
@ -47,33 +51,39 @@ const TRIVIAL_VERTEX_SHADER_DESC: wgpu::ShaderModuleDescriptor = wgpu::ShaderMod
static NO_TARGETLESS_RENDER: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(TestParameters::default())
.run_sync(|ctx| {
fail(&ctx.device, || {
// Testing multisampling is important, because some backends don't behave well if one
// tries to compile code in an unsupported multisample count. Failing to validate here
// has historically resulted in requesting the back end to compile code.
for power_of_two in [1, 2, 4, 8, 16, 32, 64] {
ctx.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
module: &ctx.device.create_shader_module(TRIVIAL_VERTEX_SHADER_DESC),
entry_point: "main",
compilation_options: Default::default(),
buffers: &[],
},
primitive: Default::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: power_of_two,
..Default::default()
},
fragment: None,
multiview: None,
cache: None,
});
}
})
fail(
&ctx.device,
|| {
// Testing multisampling is important, because some backends don't behave well if one
// tries to compile code in an unsupported multisample count. Failing to validate here
// has historically resulted in requesting the back end to compile code.
for power_of_two in [1, 2, 4, 8, 16, 32, 64] {
ctx.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
module: &ctx
.device
.create_shader_module(TRIVIAL_VERTEX_SHADER_DESC),
entry_point: "main",
compilation_options: Default::default(),
buffers: &[],
},
primitive: Default::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: power_of_two,
..Default::default()
},
fragment: None,
multiview: None,
cache: None,
});
}
},
None,
)
// TODO: concrete error message:
// At least one color attachment or depth-stencil attachment was expected, but no
// render target for the pipeline was specified.

View File

@ -22,26 +22,30 @@ static QUEUE_WRITE_TEXTURE_OVERFLOW: GpuTestConfiguration =
let data = vec![255; 128];
fail(&ctx.device, || {
ctx.queue.write_texture(
wgpu::ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d { x: 0, y: 0, z: 1 },
aspect: wgpu::TextureAspect::All,
},
&data,
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(879161360),
//bytes_per_image: 4294967295,
rows_per_image: Some(4294967295 / 879161360),
},
wgpu::Extent3d {
width: 3056263286,
height: 64,
depth_or_array_layers: 4294967295,
},
);
});
fail(
&ctx.device,
|| {
ctx.queue.write_texture(
wgpu::ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d { x: 0, y: 0, z: 1 },
aspect: wgpu::TextureAspect::All,
},
&data,
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(879161360),
//bytes_per_image: 4294967295,
rows_per_image: Some(4294967295 / 879161360),
},
wgpu::Extent3d {
width: 3056263286,
height: 64,
depth_or_array_layers: 4294967295,
},
);
},
None,
);
});

View File

@ -4,45 +4,59 @@ use wgpu_test::{fail, gpu_test, valid, GpuTestConfiguration};
static BAD_BUFFER: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|ctx| {
// Create a buffer with bad parameters and call a few methods.
// Validation should fail but there should be not panic.
let buffer = fail(&ctx.device, || {
ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 99999999,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::STORAGE,
mapped_at_creation: false,
})
});
let buffer = fail(
&ctx.device,
|| {
ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 99999999,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::STORAGE,
mapped_at_creation: false,
})
},
None,
);
fail(&ctx.device, || {
buffer.slice(..).map_async(wgpu::MapMode::Write, |_| {})
});
fail(&ctx.device, || buffer.unmap());
fail(
&ctx.device,
|| buffer.slice(..).map_async(wgpu::MapMode::Write, |_| {}),
None,
);
fail(&ctx.device, || buffer.unmap(), None);
valid(&ctx.device, || buffer.destroy());
valid(&ctx.device, || buffer.destroy());
});
#[gpu_test]
static BAD_TEXTURE: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|ctx| {
let texture = fail(&ctx.device, || {
ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 0,
height: 12345678,
depth_or_array_layers: 9001,
},
mip_level_count: 2000,
sample_count: 27,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::all(),
view_formats: &[],
})
});
let texture = fail(
&ctx.device,
|| {
ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 0,
height: 12345678,
depth_or_array_layers: 9001,
},
mip_level_count: 2000,
sample_count: 27,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::all(),
view_formats: &[],
})
},
None,
);
fail(&ctx.device, || {
let _ = texture.create_view(&wgpu::TextureViewDescriptor::default());
});
fail(
&ctx.device,
|| {
let _ = texture.create_view(&wgpu::TextureViewDescriptor::default());
},
None,
);
valid(&ctx.device, || texture.destroy());
valid(&ctx.device, || texture.destroy());
});

View File

@ -8,19 +8,24 @@ static BAD_COPY_ORIGIN_TEST: GpuTestConfiguration = GpuTestConfiguration::new().
let texture = ctx.device.create_texture(&TEXTURE_DESCRIPTOR);
let data = vec![255; BUFFER_SIZE as usize];
fail_if(&ctx.device, should_panic, || {
ctx.queue.write_texture(
wgpu::ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin,
aspect: wgpu::TextureAspect::All,
},
&data,
BUFFER_COPY_LAYOUT,
size,
)
});
fail_if(
&ctx.device,
should_panic,
|| {
ctx.queue.write_texture(
wgpu::ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin,
aspect: wgpu::TextureAspect::All,
},
&data,
BUFFER_COPY_LAYOUT,
size,
)
},
None,
);
};
try_origin(wgpu::Origin3d { x: 0, y: 0, z: 0 }, TEXTURE_SIZE, false);

View File

@ -35,31 +35,35 @@ static COPY_OVERFLOW_Z: GpuTestConfiguration = GpuTestConfiguration::new().run_s
view_formats: &[],
});
fail(&ctx.device, || {
// Validation should catch the silly selected z layer range without panicking.
encoder.copy_texture_to_texture(
wgpu::ImageCopyTexture {
texture: &t1,
mip_level: 1,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
wgpu::ImageCopyTexture {
texture: &t2,
mip_level: 1,
origin: wgpu::Origin3d {
x: 0,
y: 0,
z: 3824276442,
fail(
&ctx.device,
|| {
// Validation should catch the silly selected z layer range without panicking.
encoder.copy_texture_to_texture(
wgpu::ImageCopyTexture {
texture: &t1,
mip_level: 1,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
aspect: wgpu::TextureAspect::All,
},
wgpu::Extent3d {
width: 100,
height: 3,
depth_or_array_layers: 613286111,
},
);
ctx.queue.submit(Some(encoder.finish()));
});
wgpu::ImageCopyTexture {
texture: &t2,
mip_level: 1,
origin: wgpu::Origin3d {
x: 0,
y: 0,
z: 3824276442,
},
aspect: wgpu::TextureAspect::All,
},
wgpu::Extent3d {
width: 100,
height: 3,
depth_or_array_layers: 613286111,
},
);
ctx.queue.submit(Some(encoder.finish()));
},
None,
);
});