diff --git a/all-is-cubes-gpu/benches/wgpu.rs b/all-is-cubes-gpu/benches/wgpu.rs index c0dbf5948..1f16e9f1a 100644 --- a/all-is-cubes-gpu/benches/wgpu.rs +++ b/all-is-cubes-gpu/benches/wgpu.rs @@ -40,7 +40,8 @@ fn render_benches(runtime: &Runtime, c: &mut Criterion, instance: &wgpu::Instanc // Benchmark for running update() only. Insofar as this touches the GPU it will // naturally fill up the pipeline as Criterion iterates it. g.bench_function("update-only", |b| { - let (mut universe, space, renderer) = runtime.block_on(create_updated_renderer(instance)); + let (mut universe, space, renderer) = + runtime.block_on(create_updated_renderer("update-only", instance)); let [block] = make_some_blocks(); let txn1 = @@ -61,7 +62,8 @@ fn render_benches(runtime: &Runtime, c: &mut Criterion, instance: &wgpu::Instanc // latency since it must wait for the image to be fetched. TODO: Figure out how to // improve that. g.bench_function("draw-only", |b| { - let (_universe, _space, renderer) = runtime.block_on(create_updated_renderer(instance)); + let (_universe, _space, renderer) = + runtime.block_on(create_updated_renderer("draw-only", instance)); b.to_async(runtime).iter_with_large_drop(move || { let renderer = renderer.clone(); @@ -80,6 +82,7 @@ fn render_benches(runtime: &Runtime, c: &mut Criterion, instance: &wgpu::Instanc } async fn create_updated_renderer( + device_label: &str, instance: &wgpu::Instance, ) -> ( Universe, @@ -100,7 +103,7 @@ async fn create_updated_renderer( .unwrap(); let adapter = init::create_adapter_for_test(instance).await; - let mut renderer = headless::Builder::from_adapter(adapter) + let mut renderer = headless::Builder::from_adapter(device_label, adapter) .await .unwrap() .build(StandardCameras::from_constant_for_test( @@ -125,7 +128,13 @@ fn module_benches(runtime: &Runtime, c: &mut Criterion, instance: &wgpu::Instanc .block_on(async { let adapter = init::create_adapter_for_test(instance).await; adapter - .request_device(&wgpu::DeviceDescriptor::default(), None) + .request_device( + &all_is_cubes_gpu::in_wgpu::device_descriptor( + "module_benches", + adapter.limits(), + ), + None, + ) .await }) .unwrap(); diff --git a/all-is-cubes-gpu/src/in_wgpu.rs b/all-is-cubes-gpu/src/in_wgpu.rs index 670ba6964..a5148c54b 100644 --- a/all-is-cubes-gpu/src/in_wgpu.rs +++ b/all-is-cubes-gpu/src/in_wgpu.rs @@ -88,8 +88,20 @@ impl all_is_cubes_mesh::dynamic::DynamicMeshTypes for WgpuMt wgpu::DeviceDescriptor<'_> { + EverythingRenderer::::device_descriptor(label, available_limits) +} + /// Entry point for [`wgpu`] rendering. Construct this and hand it the [`wgpu::Surface`] /// to draw on. +/// +/// If you wish to render to an image rather than a surface, use [`headless`] instead. #[derive(Debug)] pub struct SurfaceRenderer { surface: wgpu::Surface<'static>, @@ -115,7 +127,10 @@ impl SurfaceRenderer { ) -> Result { let (device, queue) = adapter .request_device( - &EverythingRenderer::::device_descriptor(adapter.limits()), + &EverythingRenderer::::device_descriptor( + "SurfaceRenderer::device", + adapter.limits(), + ), None, ) .await?; @@ -337,9 +352,12 @@ impl fmt::Debug for EverythingRenderer { impl EverythingRenderer { /// A device descriptor suitable for the expectations of [`EverythingRenderer`]. - pub fn device_descriptor(available_limits: wgpu::Limits) -> wgpu::DeviceDescriptor<'static> { + pub fn device_descriptor( + label: &str, + available_limits: wgpu::Limits, + ) -> wgpu::DeviceDescriptor<'_> { wgpu::DeviceDescriptor { - label: None, + label: Some(label), required_features: wgpu::Features::empty(), required_limits: wgpu::Limits { max_inter_stage_shader_components: 32, // number used by blocks-and-lines shader diff --git a/all-is-cubes-gpu/src/in_wgpu/headless.rs b/all-is-cubes-gpu/src/in_wgpu/headless.rs index c0b82a3c2..45dc3ff87 100644 --- a/all-is-cubes-gpu/src/in_wgpu/headless.rs +++ b/all-is-cubes-gpu/src/in_wgpu/headless.rs @@ -29,10 +29,16 @@ pub struct Builder { impl Builder { /// Create a [`Builder`] by obtaining a new [`wgpu::Device`] from the given adapter. #[cfg_attr(target_family = "wasm", allow(clippy::arc_with_non_send_sync))] - pub async fn from_adapter(adapter: wgpu::Adapter) -> Result { + pub async fn from_adapter( + label: &str, + adapter: wgpu::Adapter, + ) -> Result { let (device, queue) = adapter .request_device( - &in_wgpu::EverythingRenderer::::device_descriptor(adapter.limits()), + &in_wgpu::EverythingRenderer::::device_descriptor( + label, + adapter.limits(), + ), None, ) .await?; diff --git a/all-is-cubes-gpu/src/in_wgpu/shader_testing.rs b/all-is-cubes-gpu/src/in_wgpu/shader_testing.rs index 45917c4b1..18d9f8cca 100644 --- a/all-is-cubes-gpu/src/in_wgpu/shader_testing.rs +++ b/all-is-cubes-gpu/src/in_wgpu/shader_testing.rs @@ -32,6 +32,7 @@ use crate::in_wgpu::{ // TODO: T is bad abstraction since it silently has to be f16 pub async fn run_shader_test( + device_label: &str, adapter: &wgpu::Adapter, output_viewport: Viewport, test_wgsl: &str, @@ -41,7 +42,7 @@ where { let (device, queue) = adapter .request_device( - &in_wgpu::EverythingRenderer::::device_descriptor(adapter.limits()), + &in_wgpu::EverythingRenderer::::device_descriptor(device_label, adapter.limits()), None, ) .await diff --git a/all-is-cubes-gpu/tests/shaders/harness.rs b/all-is-cubes-gpu/tests/shaders/harness.rs index ddf829b87..f6ce0def6 100644 --- a/all-is-cubes-gpu/tests/shaders/harness.rs +++ b/all-is-cubes-gpu/tests/shaders/harness.rs @@ -16,7 +16,7 @@ pub(crate) async fn instance() -> &'static wgpu::Instance { } /// TODO: image probably isn't the best output format, just what I prototyped with -pub(crate) async fn run_shader_test(test_wgsl: &str) -> image::Rgba32FImage { +pub(crate) async fn run_shader_test(device_label: &str, test_wgsl: &str) -> image::Rgba32FImage { let instance = instance().await; let adapter = init::create_adapter_for_test(instance).await; @@ -24,7 +24,7 @@ pub(crate) async fn run_shader_test(test_wgsl: &str) -> image::Rgba32FImage { let output_viewport = camera::Viewport::with_scale(1.0, [32, 32]); let f16_pixels: Vec = - shader_testing::run_shader_test(&adapter, output_viewport, test_wgsl).await; + shader_testing::run_shader_test(device_label, &adapter, output_viewport, test_wgsl).await; // Convert f16 pixels to f32 image::ImageBuffer::from_raw( diff --git a/all-is-cubes-gpu/tests/shaders/tests.rs b/all-is-cubes-gpu/tests/shaders/tests.rs index 01cbce05b..e53147b8b 100644 --- a/all-is-cubes-gpu/tests/shaders/tests.rs +++ b/all-is-cubes-gpu/tests/shaders/tests.rs @@ -6,7 +6,11 @@ use crate::wgsl::{frag_expr, to_wgsl}; /// Test that our test framework does what we want. #[tokio::test] async fn meta_smoke_test() { - let image = run_shader_test(&frag_expr("vec4(4.0, 3.0, 2.0, 1.0)")).await; + let image = run_shader_test( + "meta_smoke_test", + &frag_expr("vec4(4.0, 3.0, 2.0, 1.0)"), + ) + .await; // for color in image.pixels() { // let image::Rgba([r, g, b, a]) = *color; // print!("{r} {g} {b} {a} "); @@ -18,11 +22,14 @@ async fn meta_smoke_test() { #[tokio::test] pub(crate) async fn modulo() { assert_eq!( - run_shader_test(&frag_expr( - "vec4( + run_shader_test( + "modulo", + &frag_expr( + "vec4( modulo(10.0, 4.0), modulo(-0.5, 4.0), modulo(10.125, 1.0), modulo(-1.0, 1.0) )" - )) + ) + ) .await .get_pixel(0, 0), &image::Rgba([ @@ -39,13 +46,16 @@ pub(crate) async fn scale_to_integer_step_test() { for case @ (s, ds) in [(0.5f32, 0.25), (0.0, 0.25), (0.5, -0.125)] { dbg!(case); assert_eq!( - run_shader_test(&frag_expr(&format!( - "vec4( + run_shader_test( + &format!("scale_to_integer_step_test({case:?})"), + &frag_expr(&format!( + "vec4( partial_scale_to_integer_step({s}, {ds}) )", - s = to_wgsl(s), - ds = to_wgsl(ds) - ))) + s = to_wgsl(s), + ds = to_wgsl(ds) + )) + ) .await .get_pixel(0, 0), &image::Rgba([scale_to_integer_step(f64::from(s), f64::from(ds)) as f32; 4]) diff --git a/all-is-cubes-wasm/tests/browser/render.rs b/all-is-cubes-wasm/tests/browser/render.rs index 98e772a04..21011c766 100644 --- a/all-is-cubes-wasm/tests/browser/render.rs +++ b/all-is-cubes-wasm/tests/browser/render.rs @@ -47,10 +47,11 @@ async fn renderer_test() { ); let world_space = cameras.world_space().snapshot().unwrap(); - let mut renderer = all_is_cubes_gpu::in_wgpu::headless::Builder::from_adapter(adapter) - .await - .unwrap() - .build(cameras.clone()); + let mut renderer = + all_is_cubes_gpu::in_wgpu::headless::Builder::from_adapter("renderer_test", adapter) + .await + .unwrap() + .build(cameras.clone()); renderer.update(None).await.unwrap(); let image = renderer.draw("").await.unwrap(); diff --git a/test-renderers/src/harness.rs b/test-renderers/src/harness.rs index c2370b71f..cbed18f93 100644 --- a/test-renderers/src/harness.rs +++ b/test-renderers/src/harness.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use std::{fs, io}; -use async_fn_traits::{AsyncFn0, AsyncFn1, AsyncFn2}; +use async_fn_traits::{AsyncFn1, AsyncFn2}; use futures_core::future::BoxFuture; use futures_util::future::Shared; use futures_util::stream; @@ -256,7 +256,7 @@ pub async fn harness_main( ) -> HarnessResult where Factory: RendererFactory + 'static, - Ff: AsyncFn0 + Send + Sync + 'static, + Ff: AsyncFn1 + Send + Sync + 'static, { let HarnessArgs { ignored, @@ -350,7 +350,7 @@ where test: test_name.clone(), }; let comparison_log: Arc>> = Default::default(); - let factory_future = factory_factory(); + let factory_future = factory_factory(test_id.to_string()); let universe_future = test_case.universe_source.clone(); async { let test_id_tc = test_id.clone(); diff --git a/test-renderers/tests/ray-render.rs b/test-renderers/tests/ray-render.rs index d1358eac3..1b9859a9d 100644 --- a/test-renderers/tests/ray-render.rs +++ b/test-renderers/tests/ray-render.rs @@ -12,7 +12,7 @@ async fn main() -> test_renderers::HarnessResult { test_renderers::RendererId::Raytracer, test_renderers::SuiteId::Renderers, test_renderers::test_cases::all_tests, - || std::future::ready(test_renderers::RtFactory), + |_| std::future::ready(test_renderers::RtFactory), None, ) .await diff --git a/test-renderers/tests/ui.rs b/test-renderers/tests/ui.rs index ed9938935..1af51e266 100644 --- a/test-renderers/tests/ui.rs +++ b/test-renderers/tests/ui.rs @@ -36,7 +36,7 @@ async fn main() -> test_renderers::HarnessResult { test_renderers::RendererId::Raytracer, test_renderers::SuiteId::Ui, ui_render_tests, - || std::future::ready(test_renderers::RtFactory), + |_| std::future::ready(test_renderers::RtFactory), None, ) .await diff --git a/test-renderers/tests/wgpu-render.rs b/test-renderers/tests/wgpu-render.rs index 80e51b93a..5d40c7ac0 100644 --- a/test-renderers/tests/wgpu-render.rs +++ b/test-renderers/tests/wgpu-render.rs @@ -29,7 +29,7 @@ async fn main() -> test_renderers::HarnessResult { RendererId::Wgpu, test_renderers::SuiteId::Renderers, test_renderers::test_cases::all_tests, - move || async move { get_factory().await.unwrap() }, + move |label| async move { get_factory(label).await.unwrap() }, parallelism, ) .await @@ -39,14 +39,16 @@ async fn main() -> test_renderers::HarnessResult { /// but we can use just one [`wgpu::Instance`] to create all of them. static WGPU_INSTANCE: OnceCell = OnceCell::const_new(); -async fn get_factory() -> Result> { +async fn get_factory( + label: String, +) -> Result> { // Temporary workaround for : // Create a new adapter every time, rather than sharing one. // TODO: Either remove this or keep it and remove WGPU_ADAPTER. let adapter = init::create_adapter_for_test(WGPU_INSTANCE.get().expect("instance not initialized")).await; - let builder = headless::Builder::from_adapter(adapter).await?; + let builder = headless::Builder::from_adapter(&label, adapter).await?; Ok(WgpuFactory { builder }) }