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

Convert Tests to Use Async Poll #5053

Merged
merged 2 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion deno_webgpu/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub async fn op_webgpu_buffer_get_map_async(
{
let state = state.borrow();
let instance = state.borrow::<super::Instance>();
gfx_select!(device => instance.device_poll(device, wgpu_types::Maintain::Wait))
gfx_select!(device => instance.device_poll(device, wgpu_types::Maintain::wait()))
.unwrap();
}
tokio::time::sleep(Duration::from_millis(10)).await;
Expand Down
4 changes: 3 additions & 1 deletion examples/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,9 @@ impl<E: Example + wgpu::WasmNotSendSync> From<ExampleTestParams<E>>

let dst_buffer_slice = dst_buffer.slice(..);
dst_buffer_slice.map_async(wgpu::MapMode::Read, |_| ());
ctx.device.poll(wgpu::Maintain::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();
let bytes = dst_buffer_slice.get_mapped_range().to_vec();

wgpu_test::image::compare_image_output(
Expand Down
2 changes: 1 addition & 1 deletion examples/src/hello_compute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async fn execute_gpu_inner(
// Poll the device in a blocking manner so that our future resolves.
// In an actual application, `device.poll(...)` should
// be called in an event loop or on another thread.
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();

// Awaits until `buffer_future` can be read from
if let Ok(Ok(())) = receiver.recv_async().await {
Expand Down
2 changes: 1 addition & 1 deletion examples/src/hello_synchronization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ async fn get_data<T: bytemuck::Pod>(
let buffer_slice = staging_buffer.slice(..);
let (sender, receiver) = flume::bounded(1);
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
receiver.recv_async().await.unwrap().unwrap();
output.copy_from_slice(bytemuck::cast_slice(&buffer_slice.get_mapped_range()[..]));
staging_buffer.unmap();
Expand Down
2 changes: 1 addition & 1 deletion examples/src/hello_workgroups/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ async fn get_data<T: bytemuck::Pod>(
let buffer_slice = staging_buffer.slice(..);
let (sender, receiver) = flume::bounded(1);
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
receiver.recv_async().await.unwrap().unwrap();
output.copy_from_slice(bytemuck::cast_slice(&buffer_slice.get_mapped_range()[..]));
staging_buffer.unmap();
Expand Down
2 changes: 1 addition & 1 deletion examples/src/mipmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ impl crate::framework::Example for Example {
.slice(..)
.map_async(wgpu::MapMode::Read, |_| ());
// Wait for device to be done rendering mipmaps
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
// This is guaranteed to be ready.
let timestamp_view = query_sets
.mapping_buffer
Expand Down
2 changes: 1 addition & 1 deletion examples/src/render_to_texture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ async fn run(_path: Option<String>) {
let buffer_slice = output_staging_buffer.slice(..);
let (sender, receiver) = flume::bounded(1);
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
receiver.recv_async().await.unwrap().unwrap();
log::info!("Output buffer mapped.");
{
Expand Down
5 changes: 4 additions & 1 deletion examples/src/repeated_compute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ async fn compute(local_buffer: &mut [u32], context: &WgpuContext) {
// One of those can be calling `Device::poll`. This isn't necessary on the web as devices
// are polled automatically but natively, we need to make sure this happens manually.
// `Maintain::Wait` will cause the thread to wait on native but not the web.
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
context.device.poll(wgpu::Maintain::Wait);
context
.device
.poll(wgpu::Maintain::wait())
.panic_on_timeout();
log::info!("Device polled.");
// Now we await the receiving and panic if anything went wrong because we're lazy.
receiver.recv_async().await.unwrap().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/src/storage_texture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ async fn run(_path: Option<String>) {
let buffer_slice = output_staging_buffer.slice(..);
let (sender, receiver) = flume::bounded(1);
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
receiver.recv_async().await.unwrap().unwrap();
log::info!("Output buffer mapped");
{
Expand Down
2 changes: 1 addition & 1 deletion examples/src/timestamp_queries/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Queries {
self.destination_buffer
.slice(..)
.map_async(wgpu::MapMode::Read, |_| ());
device.poll(wgpu::Maintain::Wait);
device.poll(wgpu::Maintain::wait()).panic_on_timeout();

let timestamps = {
let timestamp_view = self
Expand Down
4 changes: 2 additions & 2 deletions player/src/bin/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ fn main() {
}

gfx_select!(device => global.device_stop_capture(device));
gfx_select!(device => global.device_poll(device, wgt::Maintain::Wait)).unwrap();
gfx_select!(device => global.device_poll(device, wgt::Maintain::wait())).unwrap();
}
#[cfg(feature = "winit")]
{
Expand Down Expand Up @@ -196,7 +196,7 @@ fn main() {
},
Event::LoopExiting => {
log::info!("Closing");
gfx_select!(device => global.device_poll(device, wgt::Maintain::Wait)).unwrap();
gfx_select!(device => global.device_poll(device, wgt::Maintain::wait())).unwrap();
}
_ => {}
}
Expand Down
3 changes: 2 additions & 1 deletion player/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ impl Test<'_> {
}

println!("\t\t\tWaiting...");
wgc::gfx_select!(device_id => global.device_poll(device_id, wgt::Maintain::Wait)).unwrap();
wgc::gfx_select!(device_id => global.device_poll(device_id, wgt::Maintain::wait()))
.unwrap();

for expect in self.expectations {
println!("\t\t\tChecking {}", expect.name);
Expand Down
44 changes: 28 additions & 16 deletions tests/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::{borrow::Cow, ffi::OsStr, path::Path};
use wgpu::util::{align_to, DeviceExt};
use wgpu::*;

use crate::TestingContext;

#[cfg(not(target_arch = "wasm32"))]
async fn read_png(path: impl AsRef<Path>, width: u32, height: u32) -> Option<Vec<u8>> {
let data = match std::fs::read(&path) {
Expand Down Expand Up @@ -563,15 +565,15 @@ impl ReadbackBuffers {
copy_texture_to_buffer(device, encoder, texture, &self.buffer, &self.buffer_stencil);
}

fn retrieve_buffer(
async fn retrieve_buffer(
&self,
device: &Device,
ctx: &TestingContext,
buffer: &Buffer,
aspect: Option<TextureAspect>,
) -> Vec<u8> {
let buffer_slice = buffer.slice(..);
buffer_slice.map_async(MapMode::Read, |_| ());
device.poll(Maintain::Wait);
ctx.async_poll(Maintain::wait()).await.panic_on_timeout();
let (block_width, block_height) = self.texture_format.block_dimensions();
let expected_bytes_per_row = (self.texture_width / block_width)
* self.texture_format.block_copy_size(aspect).unwrap_or(4);
Expand Down Expand Up @@ -600,26 +602,36 @@ impl ReadbackBuffers {
}
}

pub fn are_zero(&self, device: &Device) -> bool {
let is_zero = |device: &Device, buffer: &Buffer, aspect: Option<TextureAspect>| -> bool {
let is_zero = self
.retrieve_buffer(device, buffer, aspect)
.iter()
.all(|b| *b == 0);
buffer.unmap();
is_zero
};
async fn is_zero(
&self,
ctx: &TestingContext,
buffer: &Buffer,
aspect: Option<TextureAspect>,
) -> bool {
let is_zero = self
.retrieve_buffer(ctx, buffer, aspect)
.await
.iter()
.all(|b| *b == 0);
buffer.unmap();
is_zero
}

let buffer_zero = is_zero(device, &self.buffer, self.buffer_aspect());
pub async fn are_zero(&self, ctx: &TestingContext) -> bool {
let buffer_zero = self.is_zero(ctx, &self.buffer, self.buffer_aspect()).await;
let mut stencil_buffer_zero = true;
if let Some(buffer) = &self.buffer_stencil {
stencil_buffer_zero = is_zero(device, buffer, Some(TextureAspect::StencilOnly));
stencil_buffer_zero = self
.is_zero(ctx, buffer, Some(TextureAspect::StencilOnly))
.await;
};
buffer_zero && stencil_buffer_zero
}

pub fn assert_buffer_contents(&self, device: &Device, expected_data: &[u8]) {
let result_buffer = self.retrieve_buffer(device, &self.buffer, self.buffer_aspect());
pub async fn assert_buffer_contents(&self, ctx: &TestingContext, expected_data: &[u8]) {
let result_buffer = self
.retrieve_buffer(ctx, &self.buffer, self.buffer_aspect())
.await;
assert!(
result_buffer.len() >= expected_data.len(),
"Result buffer ({}) smaller than expected buffer ({})",
Expand Down
1 change: 1 addition & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod init;
mod isolation;
pub mod native;
mod params;
mod poll;
mod report;
mod run;

Expand Down
8 changes: 8 additions & 0 deletions tests/src/poll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::TestingContext;

impl TestingContext {
/// Utility to allow future asynchronous polling.
pub async fn async_poll(&self, maintain: wgpu::Maintain) -> wgpu::MaintainResult {
self.device.poll(maintain)
}
}
11 changes: 8 additions & 3 deletions tests/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::panic::AssertUnwindSafe;
use std::{panic::AssertUnwindSafe, sync::Arc};

use futures_lite::FutureExt;
use wgpu::{Adapter, Device, Instance, Queue};
Expand All @@ -18,7 +18,7 @@ pub struct TestingContext {
pub adapter: Adapter,
pub adapter_info: wgpu::AdapterInfo,
pub adapter_downlevel_capabilities: wgpu::DownlevelCapabilities,
pub device: Device,
pub device: Arc<Device>,
pub device_features: wgpu::Features,
pub device_limits: wgpu::Limits,
pub queue: Queue,
Expand Down Expand Up @@ -58,6 +58,9 @@ pub async fn execute_test(
return;
}

// Print the name of the test.
log::info!("TEST: {}", config.name);

let (device, queue) = pollster::block_on(initialize_device(
&adapter,
config.params.required_features,
Expand All @@ -69,7 +72,7 @@ pub async fn execute_test(
adapter,
adapter_info,
adapter_downlevel_capabilities,
device,
device: Arc::new(device),
device_features: config.params.required_features,
device_limits: config.params.required_limits.clone(),
queue,
Expand Down Expand Up @@ -109,4 +112,6 @@ pub async fn execute_test(
if expectations_match_failures(&test_info.failures, failures) == ExpectationMatchResult::Panic {
panic!();
}
// Print the name of the test.
log::info!("TEST FINISHED: {}", config.name);
}
6 changes: 4 additions & 2 deletions tests/tests/bgra8unorm_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new()
})
.features(wgpu::Features::BGRA8UNORM_STORAGE),
)
.run_sync(|ctx| {
.run_async(|ctx| async move {
let device = &ctx.device;
let texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
Expand Down Expand Up @@ -139,7 +139,9 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new()

let buffer_slice = readback_buffer.slice(..);
buffer_slice.map_async(wgpu::MapMode::Read, Result::unwrap);
device.poll(wgpu::Maintain::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

{
let texels = buffer_slice.get_mapped_range();
Expand Down
8 changes: 5 additions & 3 deletions tests/tests/bind_group_layout_dedup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const ENTRY: wgpu::BindGroupLayoutEntry = wgpu::BindGroupLayoutEntry {
#[gpu_test]
static BIND_GROUP_LAYOUT_DEDUPLICATION: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(TestParameters::default().test_features_limits())
.run_sync(bgl_dedupe);
.run_async(bgl_dedupe);

fn bgl_dedupe(ctx: TestingContext) {
async fn bgl_dedupe(ctx: TestingContext) {
let entries_1 = &[];

let entries_2 = &[ENTRY];
Expand Down Expand Up @@ -126,7 +126,9 @@ fn bgl_dedupe(ctx: TestingContext) {
}
}

ctx.device.poll(wgpu::Maintain::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

if ctx.adapter_info.backend != wgt::Backend::BrowserWebGpu {
// Now all of the BGL ids should be dead, so we should get the same ids again.
Expand Down
30 changes: 20 additions & 10 deletions tests/tests/buffer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, TestingContext};

fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str) {
async fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str) {
let r = wgpu::BufferUsages::MAP_READ;
let rw = wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::MAP_WRITE;
for usage in [r, rw] {
Expand All @@ -14,7 +14,9 @@ fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str)
b0.slice(0..0)
.map_async(wgpu::MapMode::Read, Result::unwrap);

ctx.device.poll(wgpu::MaintainBase::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

{
let view = b0.slice(0..0).get_mapped_range();
Expand Down Expand Up @@ -48,7 +50,9 @@ fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str)
b0.slice(0..0)
.map_async(wgpu::MapMode::Write, Result::unwrap);

ctx.device.poll(wgpu::MaintainBase::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

//{
// let view = b0.slice(0..0).get_mapped_range_mut();
Expand Down Expand Up @@ -77,19 +81,21 @@ fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str)

b1.unmap();

ctx.device.poll(wgpu::MaintainBase::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();
}

#[gpu_test]
static EMPTY_BUFFER: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(TestParameters::default().expect_fail(FailureCase::always()))
.run_sync(|ctx| {
test_empty_buffer_range(&ctx, 2048, "regular buffer");
test_empty_buffer_range(&ctx, 0, "zero-sized buffer");
.run_async(|ctx| async move {
test_empty_buffer_range(&ctx, 2048, "regular buffer").await;
test_empty_buffer_range(&ctx, 0, "zero-sized buffer").await;
});

#[gpu_test]
static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|ctx| {
static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_async(|ctx| async move {
// This test writes 16 bytes at the beginning of buffer mapped mapped with
// an offset of 32 bytes. Then the buffer is copied into another buffer that
// is read back and we check that the written bytes are correctly placed at
Expand All @@ -116,7 +122,9 @@ static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|
result.unwrap();
});

ctx.device.poll(wgpu::MaintainBase::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

{
let slice = write_buf.slice(32..48);
Expand All @@ -140,7 +148,9 @@ static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(|
.slice(..)
.map_async(wgpu::MapMode::Read, Result::unwrap);

ctx.device.poll(wgpu::MaintainBase::Wait);
ctx.async_poll(wgpu::Maintain::wait())
.await
.panic_on_timeout();

let slice = read_buf.slice(..);
let view = slice.get_mapped_range();
Expand Down
Loading