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

139 lines
4.8 KiB
Rust

use std::num::NonZeroU64;
use wgpu::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry,
BindingResource, BindingType, BufferBindingType, BufferDescriptor, BufferUsages, CommandBuffer,
CommandEncoderDescriptor, ComputePassDescriptor, PollType, ShaderStages,
};
use wgpu_test::{gpu_test, GpuTestConfiguration, TestingContext};
fn generate_dummy_work(ctx: &TestingContext) -> CommandBuffer {
let buffer = ctx.device.create_buffer(&BufferDescriptor {
label: None,
size: 16,
usage: BufferUsages::UNIFORM,
mapped_at_creation: false,
});
let bind_group_layout = ctx
.device
.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: None,
entries: &[BindGroupLayoutEntry {
binding: 0,
visibility: ShaderStages::COMPUTE,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: Some(NonZeroU64::new(16).unwrap()),
},
count: None,
}],
});
let bind_group = ctx.device.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[BindGroupEntry {
binding: 0,
resource: BindingResource::Buffer(buffer.as_entire_buffer_binding()),
}],
});
let mut cmd_buf = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor::default());
let mut cpass = cmd_buf.begin_compute_pass(&ComputePassDescriptor::default());
cpass.set_bind_group(0, &bind_group, &[]);
drop(cpass);
cmd_buf.finish()
}
#[gpu_test]
static WAIT: GpuTestConfiguration = GpuTestConfiguration::new().run_async(|ctx| async move {
let cmd_buf = generate_dummy_work(&ctx);
ctx.queue.submit(Some(cmd_buf));
ctx.async_poll(PollType::wait()).await.unwrap();
});
#[gpu_test]
static DOUBLE_WAIT: GpuTestConfiguration =
GpuTestConfiguration::new().run_async(|ctx| async move {
let cmd_buf = generate_dummy_work(&ctx);
ctx.queue.submit(Some(cmd_buf));
ctx.async_poll(PollType::wait()).await.unwrap();
ctx.async_poll(PollType::wait()).await.unwrap();
});
#[gpu_test]
static WAIT_ON_SUBMISSION: GpuTestConfiguration =
GpuTestConfiguration::new().run_async(|ctx| async move {
let cmd_buf = generate_dummy_work(&ctx);
let index = ctx.queue.submit(Some(cmd_buf));
ctx.async_poll(PollType::wait_for(index)).await.unwrap();
});
#[gpu_test]
static DOUBLE_WAIT_ON_SUBMISSION: GpuTestConfiguration =
GpuTestConfiguration::new().run_async(|ctx| async move {
let cmd_buf = generate_dummy_work(&ctx);
let index = ctx.queue.submit(Some(cmd_buf));
ctx.async_poll(PollType::wait_for(index.clone()))
.await
.unwrap();
ctx.async_poll(PollType::wait_for(index)).await.unwrap();
});
#[gpu_test]
static WAIT_OUT_OF_ORDER: GpuTestConfiguration =
GpuTestConfiguration::new().run_async(|ctx| async move {
let cmd_buf1 = generate_dummy_work(&ctx);
let cmd_buf2 = generate_dummy_work(&ctx);
let index1 = ctx.queue.submit(Some(cmd_buf1));
let index2 = ctx.queue.submit(Some(cmd_buf2));
ctx.async_poll(PollType::wait_for(index2)).await.unwrap();
ctx.async_poll(PollType::wait_for(index1)).await.unwrap();
});
/// Submit a command buffer to the wrong device. A wait poll shouldn't hang.
///
/// We can't catch panics on Wasm, since they get reported directly to the
/// console.
#[gpu_test]
static WAIT_AFTER_BAD_SUBMISSION: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(wgpu_test::TestParameters::default().skip(wgpu_test::FailureCase::webgl2()))
.run_async(wait_after_bad_submission);
async fn wait_after_bad_submission(ctx: TestingContext) {
let (device2, queue2) =
wgpu_test::initialize_device(&ctx.adapter, ctx.device_features, ctx.device_limits.clone())
.await;
let command_buffer1 = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor::default())
.finish();
// This should panic, since the command buffer belongs to the wrong
// device, and queue submission errors seem to be fatal errors?
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
queue2.submit([command_buffer1]);
}));
assert!(result.is_err());
// This should not hang.
//
// Specifically, the failed submission should not cause a new fence value to
// be allocated that will not be signalled until further work is
// successfully submitted, causing a greater fence value to be signalled.
device2.poll(wgpu::PollType::Wait).unwrap();
}