Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device valid #4163

Merged
merged 45 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fff56b6
Implement Device validity, and make it invalid when Device is lost.
bradwerth Sep 11, 2023
0d4825c
Implement device validity, and make it invalid when device is lost.
bradwerth Sep 11, 2023
dfb34f5
Fixup merge.
bradwerth Sep 15, 2023
2887ad6
Drop texture `clear_view`s in surface_texture_discard (#4057)
rajveermalviya Aug 30, 2023
74bbc7d
Bump profiling from 1.0.9 to 1.0.10 (#4102)
dependabot[bot] Sep 1, 2023
451dfeb
Fix limits interface on web. (#4107)
OptimisticPeach Sep 1, 2023
8fc3eb5
Add details to `InstanceError` and `CreateSurfaceError`. (#4066)
kpreid Sep 1, 2023
8fc8962
Skip `test_multithreaded_compute` on MoltenVK. (#4096)
jimblandy Sep 4, 2023
fef6235
Bump thiserror from 1.0.47 to 1.0.48 (#4112)
dependabot[bot] Sep 5, 2023
cc0135e
Bump serde from 1.0.186 to 1.0.188 (#4091)
dependabot[bot] Sep 5, 2023
dbf82b7
Bump actions/checkout from 3 to 4 (#4117)
dependabot[bot] Sep 5, 2023
cdcf934
hal/vulkan: `Instance::required_extensions` -> `desired_extensions` (…
jimblandy Sep 5, 2023
bbb3cd9
Enable vulkan presentation on Intel Mesa >= v21.2 (#4110)
flukejones Sep 5, 2023
7c47c49
wgpu_core: Add logging to Instance::new.
jimblandy Sep 4, 2023
1acf857
Fix D3D12 Surface Leak (#4106)
cwfitzgerald Sep 5, 2023
6ac37a5
Bump bytemuck from 1.13.1 to 1.14.0 (#4123)
dependabot[bot] Sep 6, 2023
8c75d36
Update `naga` to 0.13.0@git:cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c …
nical Sep 11, 2023
bcf544d
Bump serde_json from 1.0.105 to 1.0.106 (#4129)
dependabot[bot] Sep 11, 2023
118b7e6
Print errors in a more readable format in the player. (#4137)
nical Sep 14, 2023
cd3e1f3
Workaround NV bug (#4132)
cwfitzgerald Sep 14, 2023
e8b839d
Bump serde_json from 1.0.106 to 1.0.107 (#4133)
dependabot[bot] Sep 14, 2023
eede6bd
Bump libc from 0.2.147 to 0.2.148 (#4134)
dependabot[bot] Sep 14, 2023
2f5dc46
Add details to `RequestDeviceError`. (#4145)
kpreid Sep 16, 2023
2003dd9
Metal encoder & pass timestamp support (#4008)
Wumpf Sep 16, 2023
118359a
Tests for wgpu#4139. (#4148)
jimblandy Sep 17, 2023
4dbff2e
Update Naga to df8107b7 (2023-9-15). (#4149)
jimblandy Sep 17, 2023
36a21e4
[d3d12] Document `map_blend_factor` (#4151)
teoxoy Sep 18, 2023
573fdee
Make `StoreOp` an enum instead of a bool (#4147)
Wumpf Sep 18, 2023
c377399
Bump profiling from 1.0.10 to 1.0.11 (#4153)
dependabot[bot] Sep 19, 2023
db408aa
Bump termcolor from 1.2.0 to 1.3.0 (#4152)
dependabot[bot] Sep 19, 2023
17114ff
Support dual source blending (#4022)
freqmod Sep 19, 2023
3659bb5
Implement device validity, and make it invalid when device is lost.
bradwerth Sep 11, 2023
ef12c6a
This makes device_lose testable and adds a meaningful test.
bradwerth Sep 19, 2023
4b6d4b5
Add partial information to CHANGELOG.md.
bradwerth Sep 21, 2023
2ea06be
Update CHANGELOG.md.
bradwerth Sep 21, 2023
ba05653
Merge branch 'trunk' into deviceValid
bradwerth Sep 21, 2023
5f0ec42
Fixup merge of tests/device.rs.
bradwerth Sep 21, 2023
a4a5403
Fixup web.rs implementation of device_lose.
bradwerth Sep 21, 2023
e1f3d7c
Stub out web.rs device_lose.
bradwerth Sep 21, 2023
2feef8f
Fixup test problems on different backends, and fixup stub of web.rs d…
bradwerth Sep 21, 2023
084d036
Run rustfmt, fix issues in tests/device.rs.
bradwerth Sep 22, 2023
b756739
Test skipped in DX12 for validation errors, more comments in test, in…
bradwerth Sep 22, 2023
48b2812
Update test to use device.destroy, and remove the public exposure of …
bradwerth Sep 25, 2023
166549c
Restore config.toml.
bradwerth Sep 26, 2023
835a733
rustfmt device.rs.
bradwerth Sep 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ By @wumpf in [#4147](https://github.com/gfx-rs/wgpu/pull/4147)
- `wgpu::CreateSurfaceError` and `wgpu::RequestDeviceError` now give details of the failure, but no longer implement `PartialEq` and cannot be constructed. By @kpreid in [#4066](https://github.com/gfx-rs/wgpu/pull/4066) and [#4145](https://github.com/gfx-rs/wgpu/pull/4145)
- Make `WGPU_POWER_PREF=none` a valid value. By @fornwall in [4076](https://github.com/gfx-rs/wgpu/pull/4076)
- Support dual source blending in OpenGL ES, Metal, Vulkan & DX12. By @freqmod in [4022](https://github.com/gfx-rs/wgpu/pull/4022)
- Add stub support for device destroy and device validity. By @bradwerth in [4163](https://github.com/gfx-rs/wgpu/pull/4163)

#### Vulkan

Expand Down
354 changes: 353 additions & 1 deletion tests/tests/device.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasm_bindgen_test::*;

use wgpu_test::{initialize_test, FailureCase, TestParameters};
use wgpu_test::{fail, initialize_test, FailureCase, TestParameters};

#[test]
#[wasm_bindgen_test]
Expand Down Expand Up @@ -91,3 +91,355 @@ async fn request_device_error_message() {
}
assert!(device_error.contains(expected), "{device_error}");
}

#[test]
fn device_destroy_then_more() {
// This is a test of device behavior after device.destroy. Specifically, all operations
// should trigger errors since the device is lost.
//
// On DX12 this test fails with a validation error in the very artifical actions taken
// after lose the device. The error is "ID3D12CommandAllocator::Reset: The command
bradwerth marked this conversation as resolved.
Show resolved Hide resolved
// allocator cannot be reset because a command list is currently being recorded with the
// allocator." That may indicate that DX12 doesn't like opened command buffers staying
// open even after they return an error. For now, this test is skipped on DX12.
//
// The DX12 issue may be related to https://github.com/gfx-rs/wgpu/issues/3193.
initialize_test(
TestParameters::default()
.features(wgpu::Features::CLEAR_TEXTURE)
.skip(FailureCase::backend(wgpu::Backends::DX12)),
|ctx| {
// Create some resources on the device that we will attempt to use *after* losing
// the device.

// Create some 512 x 512 2D textures.
let texture_extent = wgpu::Extent3d {
width: 512,
height: 512,
depth_or_array_layers: 1,
};
let texture_for_view = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: texture_extent,
mip_level_count: 2,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rg8Uint,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
});
let target_view = texture_for_view.create_view(&wgpu::TextureViewDescriptor::default());

let texture_for_read = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: texture_extent,
mip_level_count: 2,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rg8Uint,
usage: wgpu::TextureUsages::COPY_SRC,
view_formats: &[],
});

let texture_for_write = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: texture_extent,
mip_level_count: 2,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rg8Uint,
usage: wgpu::TextureUsages::COPY_DST,
view_formats: &[],
});

// Create some buffers.
let buffer_source = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 256,
usage: wgpu::BufferUsages::MAP_WRITE | wgpu::BufferUsages::COPY_SRC,
mapped_at_creation: false,
});
let buffer_dest = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 256,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});

// Create a bind group layout.
let bind_group_layout =
ctx.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[],
});

// Create a shader module.
let shader_module = ctx
.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed("")),
});

// Create some command encoders.
let mut encoder_for_clear = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_compute_pass = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_render_pass = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_buffer_buffer_copy = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_buffer_texture_copy = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_texture_buffer_copy = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let mut encoder_for_texture_texture_copy = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

// Destroy the device. This will cause all other requests to return some variation of
// a device invalid error.
ctx.device.destroy();

// TODO: verify the following operations will return an invalid device error:
// * Run a compute pass
// * Run a render pass
// * Finish a render bundle encoder
// * Create a texture from HAL
// * Create a buffer from HAL
// * Create a sampler
// * Validate a surface configuration
// * Start capture
// * Stop capture
// * Buffer map

// TODO: figure out how to structure a test around these operations which panic when
// the device is invalid:
// * device.features()
// * device.limits()
// * device.downlevel_properties()
// * device.create_query_set()

// TODO: change these fail calls to check for the specific errors which indicate that
// the device is not valid.

// Creating a commmand encoder should fail.
fail(&ctx.device, || {
ctx.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
});

// 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,
});
});

// 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: &[],
});
});

bradwerth marked this conversation as resolved.
Show resolved Hide resolved
// 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,
},
);
});

// Creating a compute pass should fail.
fail(&ctx.device, || {
encoder_for_compute_pass.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: None,
timestamp_writes: 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,
});
});

// 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,
);
});

// 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,
},
},
texture_for_write.as_image_copy(),
texture_extent,
);
});

// 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,
},
},
texture_extent,
);
});

// 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,
);
});

// Creating a bind group layout should fail.
fail(&ctx.device, || {
ctx.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[],
});
});

// 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(),
),
}],
});
});

// Creating a pipeline layout should fail.
fail(&ctx.device, || {
ctx.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
});

// 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("")),
});
});

// 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(&[]),
});
});

// Creating a render pipeline should fail.
fail(&ctx.device, || {
ctx.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
module: &shader_module,
entry_point: "",
buffers: &[],
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: None,
multiview: 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: "",
});
});
},
)
}
3 changes: 3 additions & 0 deletions wgpu-core/src/command/clear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}

let device = &device_guard[cmd_buf.device_id.value];
if !device.is_valid() {
return Err(ClearError::InvalidDevice(cmd_buf.device_id.value.0));
}

clear_texture(
&*texture_guard,
Expand Down
Loading