From 166eed43ac26f0f18024ca0b04e3fdddadb161b2 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 13 Sep 2022 00:00:19 -0500 Subject: [PATCH] WIP: Context dynamic dispatch --- Cargo.lock | 7 - wgpu/src/backend/direct.rs | 150 +-- wgpu/src/backend/mod.rs | 4 +- wgpu/src/backend/web.rs | 121 ++- wgpu/src/context.rs | 1872 ++++++++++++++++++++++++++++++++++++ wgpu/src/lib.rs | 592 ++++++++---- wgpu/src/util/mod.rs | 2 +- wgpu/tests/poll.rs | 3 +- 8 files changed, 2442 insertions(+), 309 deletions(-) create mode 100644 wgpu/src/context.rs diff --git a/Cargo.lock b/Cargo.lock index 5e2ac814c2..6eda8fa13c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,12 +337,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - [[package]] name = "core-foundation" version = "0.9.3" @@ -2249,7 +2243,6 @@ dependencies = [ "bitflags", "cfg_aliases", "codespan-reporting", - "copyless", "fxhash", "log", "naga", diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 8ec8bc6f66..de6f7aa4ef 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -4,14 +4,15 @@ use crate::{ DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, Operations, PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, ShaderSource, - SurfaceStatus, TextureDescriptor, TextureFormat, TextureViewDescriptor, + SurfaceStatus, TextureDescriptor, TextureFormat, TextureViewDescriptor, UncapturedErrorHandler, }; use arrayvec::ArrayVec; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ - borrow::Cow::Borrowed, + any::Any, + borrow::Cow::{Borrowed, Owned}, error::Error, fmt, future::{ready, Ready}, @@ -173,14 +174,11 @@ impl Context { pub unsafe fn create_surface_from_core_animation_layer( self: &Arc, layer: *mut std::ffi::c_void, - ) -> crate::Surface { + ) -> Surface { let id = self.0.instance_create_surface_metal(layer, ()); - crate::Surface { - context: Arc::clone(self), - id: Surface { - id, - configured_device: Mutex::default(), - }, + Surface { + id, + configured_device: Mutex::default(), } } @@ -191,7 +189,7 @@ impl Context { ) -> Surface { let id = self.0.create_surface_webgl_canvas(canvas, ()); Surface { - id, + id: IdSendSync::upcast(id), configured_device: Mutex::default(), } } @@ -212,14 +210,11 @@ impl Context { pub unsafe fn create_surface_from_visual( self: &Arc, visual: *mut std::ffi::c_void, - ) -> crate::Surface { + ) -> Surface { let id = self.0.instance_create_surface_from_visual(visual, ()); - crate::Surface { - context: Arc::clone(self), - id: Surface { - id, - configured_device: Mutex::default(), - }, + Surface { + id, + configured_device: Mutex::default(), } } @@ -714,14 +709,24 @@ mod pass_impl { fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> wgc::command::ImageCopyBuffer { wgc::command::ImageCopyBuffer { - buffer: view.buffer.id.id, + buffer: view + .buffer + .id + .downcast_id::<::BufferId>() + .id, layout: view.layout, } } fn map_texture_copy_view(view: crate::ImageCopyTexture) -> wgc::command::ImageCopyTexture { + dbg!(std::any::TypeId::of::()); + dbg!(view.texture.id.type_id()); wgc::command::ImageCopyTexture { - texture: view.texture.id.id, + texture: view + .texture + .id + .downcast_id::<::TextureId>() + .id, mip_level: view.mip_level, origin: view.origin, aspect: view.aspect, @@ -862,7 +867,9 @@ impl crate::Context for Context { &wgc::instance::RequestAdapterOptions { power_preference: options.power_preference, force_fallback_adapter: options.force_fallback_adapter, - compatible_surface: options.compatible_surface.map(|surface| surface.id.id), + compatible_surface: options + .compatible_surface + .map(|surface| *surface.id.downcast_id()), }, wgc::instance::AdapterInputs::Mask(wgt::Backends::all(), |_| ()), ); @@ -1116,7 +1123,7 @@ impl crate::Context for Context { }; let parser = naga::front::spv::Parser::new(spv.iter().cloned(), &options); let module = parser.parse().unwrap(); - wgc::pipeline::ShaderModuleSource::Naga(std::borrow::Cow::Owned(module)) + wgc::pipeline::ShaderModuleSource::Naga(Owned(module)) } #[cfg(feature = "glsl")] ShaderSource::Glsl { @@ -1132,7 +1139,7 @@ impl crate::Context for Context { let mut parser = naga::front::glsl::Parser::default(); let module = parser.parse(&options, shader).unwrap(); - wgc::pipeline::ShaderModuleSource::Naga(std::borrow::Cow::Owned(module)) + wgc::pipeline::ShaderModuleSource::Naga(Owned(module)) } ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)), #[cfg(feature = "naga")] @@ -1218,10 +1225,10 @@ impl crate::Context for Context { // gather all the array view IDs first for entry in desc.entries.iter() { if let BindingResource::TextureViewArray(array) = entry.resource { - arrayed_texture_views.extend(array.iter().map(|view| view.id)); + arrayed_texture_views.extend(array.iter().map(|view| &view.id)); } if let BindingResource::SamplerArray(array) = entry.resource { - arrayed_samplers.extend(array.iter().map(|sampler| sampler.id)); + arrayed_samplers.extend(array.iter().map(|sampler| &sampler.id)); } } } @@ -1234,7 +1241,7 @@ impl crate::Context for Context { for entry in desc.entries.iter() { if let BindingResource::BufferArray(array) = entry.resource { arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding { - buffer_id: binding.buffer.id.id, + buffer_id: *binding.buffer.id.downcast_id(), offset: binding.offset, size: binding.size, })); @@ -1254,7 +1261,7 @@ impl crate::Context for Context { offset, size, }) => bm::BindingResource::Buffer(bm::BufferBinding { - buffer_id: buffer.id.id, + buffer_id: buffer.id.downcast_id::().id, offset, size, }), @@ -1264,27 +1271,35 @@ impl crate::Context for Context { &remaining_arrayed_buffer_bindings[array.len()..]; bm::BindingResource::BufferArray(Borrowed(slice)) } - BindingResource::Sampler(sampler) => bm::BindingResource::Sampler(sampler.id), + BindingResource::Sampler(sampler) => { + bm::BindingResource::Sampler(*sampler.id.downcast_id::()) + } BindingResource::SamplerArray(array) => { - let slice = &remaining_arrayed_samplers[..array.len()]; + let samplers = remaining_arrayed_samplers[..array.len()] + .iter() + .map(|id| *id.downcast_id::()) + .collect::>(); remaining_arrayed_samplers = &remaining_arrayed_samplers[array.len()..]; - bm::BindingResource::SamplerArray(Borrowed(slice)) - } - BindingResource::TextureView(texture_view) => { - bm::BindingResource::TextureView(texture_view.id) + bm::BindingResource::SamplerArray(Owned(samplers)) } + BindingResource::TextureView(texture_view) => bm::BindingResource::TextureView( + *texture_view.id.downcast_id::(), + ), BindingResource::TextureViewArray(array) => { - let slice = &remaining_arrayed_texture_views[..array.len()]; + let views = remaining_arrayed_texture_views[..array.len()] + .iter() + .map(|id| *id.downcast_id::()) + .collect::>(); remaining_arrayed_texture_views = &remaining_arrayed_texture_views[array.len()..]; - bm::BindingResource::TextureViewArray(Borrowed(slice)) + bm::BindingResource::TextureViewArray(Owned(views)) } }, }) .collect::>(); let descriptor = bm::BindGroupDescriptor { label: desc.label.as_ref().map(|label| Borrowed(&label[..])), - layout: desc.layout.id, + layout: *desc.layout.id.downcast_id(), entries: Borrowed(&entries), }; @@ -1323,7 +1338,7 @@ impl crate::Context for Context { let temp_layouts = desc .bind_group_layouts .iter() - .map(|bgl| bgl.id) + .map(|bgl| *bgl.id.downcast_id()) .collect::>(); let descriptor = wgc::binding_model::PipelineLayoutDescriptor { label: desc.label.map(Borrowed), @@ -1376,10 +1391,10 @@ impl crate::Context for Context { }; let descriptor = pipe::RenderPipelineDescriptor { label: desc.label.map(Borrowed), - layout: desc.layout.map(|l| l.id), + layout: desc.layout.map(|l| *l.id.downcast_id()), vertex: pipe::VertexState { stage: pipe::ProgrammableStageDescriptor { - module: desc.vertex.module.id, + module: *desc.vertex.module.id.downcast_id(), entry_point: Borrowed(desc.vertex.entry_point), }, buffers: Borrowed(&vertex_buffers), @@ -1389,7 +1404,7 @@ impl crate::Context for Context { multisample: desc.multisample, fragment: desc.fragment.as_ref().map(|frag| pipe::FragmentState { stage: pipe::ProgrammableStageDescriptor { - module: frag.module.id, + module: *frag.module.id.downcast_id(), entry_point: Borrowed(frag.entry_point), }, targets: Borrowed(frag.targets), @@ -1436,9 +1451,9 @@ impl crate::Context for Context { }; let descriptor = pipe::ComputePipelineDescriptor { label: desc.label.map(Borrowed), - layout: desc.layout.map(|l| l.id), + layout: desc.layout.map(|l| *l.id.downcast_id()), stage: pipe::ProgrammableStageDescriptor { - module: desc.module.id, + module: *desc.module.id.downcast_id(), entry_point: Borrowed(desc.entry_point), }, }; @@ -1642,7 +1657,7 @@ impl crate::Context for Context { fn device_poll(&self, device: &Self::DeviceId, maintain: crate::Maintain) -> bool { let global = &self.0; - let maintain_inner = maintain.map_index(|i| i.0); + let maintain_inner = maintain.map_index(|i| *i.0.downcast_id::()); match wgc::gfx_select!(device.id => global.device_poll( device.id, maintain_inner @@ -1655,10 +1670,10 @@ impl crate::Context for Context { fn device_on_uncaptured_error( &self, device: &Self::DeviceId, - handler: impl crate::UncapturedErrorHandler, + handler: Box, ) { let mut error_sink = device.error_sink.lock(); - error_sink.uncaptured_handler = Box::new(handler); + error_sink.uncaptured_handler = handler; } fn device_push_error_scope(&self, device: &Self::DeviceId, filter: crate::ErrorFilter) { @@ -1675,15 +1690,13 @@ impl crate::Context for Context { ready(scope.error) } - fn buffer_map_async( + fn buffer_map_async( &self, buffer: &Self::BufferId, mode: MapMode, range: Range, - callback: F, - ) where - F: FnOnce(Result<(), crate::BufferAsyncError>) + Send + 'static, - { + callback: Box) + Send + 'static>, + ) { let operation = wgc::resource::BufferMapOperation { host: match mode { MapMode::Read => wgc::device::HostMap::Read, @@ -2061,8 +2074,8 @@ impl crate::Context for Context { .map(|ca| { ca.as_ref() .map(|at| wgc::command::RenderPassColorAttachment { - view: at.view.id, - resolve_target: at.resolve_target.map(|rt| rt.id), + view: *at.view.id.downcast_id(), + resolve_target: at.resolve_target.map(|rt| *rt.id.downcast_id()), channel: map_pass_channel(Some(&at.ops)), }) }) @@ -2070,7 +2083,7 @@ impl crate::Context for Context { let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| { wgc::command::RenderPassDepthStencilAttachment { - view: dsa.view.id, + view: *dsa.view.id.downcast_id(), depth: map_pass_channel(dsa.depth_ops.as_ref()), stencil: map_pass_channel(dsa.stencil_ops.as_ref()), } @@ -2127,7 +2140,7 @@ impl crate::Context for Context { let global = &self.0; if let Err(cause) = wgc::gfx_select!(encoder.id => global.command_encoder_clear_texture( encoder.id, - texture.id.id, + texture.id.downcast_id::().id, subresource_range )) { self.handle_error_nolabel(&encoder.error_sink, cause, "CommandEncoder::clear_texture"); @@ -2144,7 +2157,7 @@ impl crate::Context for Context { let global = &self.0; if let Err(cause) = wgc::gfx_select!(encoder.id => global.command_encoder_clear_buffer( encoder.id, - buffer.id.id, + *buffer.id.downcast_id(), offset, size )) { self.handle_error_nolabel(&encoder.error_sink, cause, "CommandEncoder::fill_buffer"); @@ -2239,18 +2252,18 @@ impl crate::Context for Context { &self, queue: &Self::QueueId, size: wgt::BufferSize, - ) -> QueueWriteBuffer { + ) -> Box { let global = &self.0; match wgc::gfx_select!( *queue => global.queue_create_staging_buffer(*queue, size, ()) ) { - Ok((buffer_id, ptr)) => QueueWriteBuffer { + Ok((buffer_id, ptr)) => Box::new(QueueWriteBuffer { buffer_id, mapping: BufferMappedRange { ptr, size: size.get() as usize, }, - }, + }), Err(err) => self.handle_error_fatal(err, "Queue::write_buffer_with"), } } @@ -2260,9 +2273,13 @@ impl crate::Context for Context { queue: &Self::QueueId, buffer: &Self::BufferId, offset: wgt::BufferAddress, - staging_buffer: &QueueWriteBuffer, + staging_buffer: &dyn crate::context::QueueWriteBuffer, ) { let global = &self.0; + let staging_buffer = staging_buffer + .as_any() + .downcast_ref::() + .unwrap(); match wgc::gfx_select!( *queue => global.queue_write_staging_buffer(*queue, buffer.id, offset, staging_buffer.buffer_id) ) { @@ -2409,19 +2426,20 @@ pub struct QueueWriteBuffer { mapping: BufferMappedRange, } -impl std::ops::Deref for QueueWriteBuffer { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - panic!("QueueWriteBuffer is write-only!"); +impl crate::context::QueueWriteBuffer for QueueWriteBuffer { + fn slice(&self) -> &[u8] { + use crate::BufferMappedRangeSlice; + self.mapping.slice() } -} -impl std::ops::DerefMut for QueueWriteBuffer { - fn deref_mut(&mut self) -> &mut Self::Target { + fn slice_mut(&mut self) -> &mut [u8] { use crate::BufferMappedRangeSlice; self.mapping.slice_mut() } + + fn as_any(&self) -> &dyn Any { + self + } } #[derive(Debug)] diff --git a/wgpu/src/backend/mod.rs b/wgpu/src/backend/mod.rs index d3f88c6928..abd090e086 100644 --- a/wgpu/src/backend/mod.rs +++ b/wgpu/src/backend/mod.rs @@ -1,9 +1,9 @@ #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))] mod web; #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))] -pub(crate) use web::{BufferMappedRange, Context, QueueWriteBuffer}; +pub(crate) use web::{BufferMappedRange, Context}; #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))] mod direct; #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))] -pub(crate) use direct::{BufferMappedRange, Context, QueueWriteBuffer}; +pub(crate) use direct::{BufferMappedRange, Context}; diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index c366529756..ac6f6c530f 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -2,6 +2,7 @@ use js_sys::Promise; use std::{ + any::Any, cell::RefCell, fmt, future::Future, @@ -12,6 +13,8 @@ use std::{ }; use wasm_bindgen::{prelude::*, JsCast}; +use crate::{context::QueueWriteBuffer, UncapturedErrorHandler}; + // We need to make a wrapper for some of the handle types returned by the web backend to make them // implement `Send` and `Sync` to match native. // @@ -816,7 +819,8 @@ fn map_texture_view_dimension( } fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBuffer { - let mut mapped = web_sys::GpuImageCopyBuffer::new(&view.buffer.id.0); + let mut mapped = + web_sys::GpuImageCopyBuffer::new(&view.buffer.id.downcast_id::>().0); if let Some(bytes_per_row) = view.layout.bytes_per_row { mapped.bytes_per_row(bytes_per_row.get()); } @@ -828,7 +832,8 @@ fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBu } fn map_texture_copy_view(view: crate::ImageCopyTexture) -> web_sys::GpuImageCopyTexture { - let mut mapped = web_sys::GpuImageCopyTexture::new(&view.texture.id.0); + let mut mapped = + web_sys::GpuImageCopyTexture::new(&view.texture.id.downcast_id::>().0); mapped.mip_level(view.mip_level); mapped.origin(&map_origin_3d(view.origin)); mapped @@ -1511,8 +1516,9 @@ impl crate::Context for Context { offset, size, }) => { - let mut mapped_buffer_binding = - web_sys::GpuBufferBinding::new(&buffer.id.0); + let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new( + &buffer.id.downcast_id::>().0, + ); mapped_buffer_binding.offset(offset as f64); if let Some(s) = size { mapped_buffer_binding.size(s.get() as f64); @@ -1522,13 +1528,25 @@ impl crate::Context for Context { crate::BindingResource::BufferArray(..) => { panic!("Web backend does not support arrays of buffers") } - crate::BindingResource::Sampler(sampler) => JsValue::from(sampler.id.0.clone()), + crate::BindingResource::Sampler(sampler) => JsValue::from( + sampler + .id + .downcast_id::>() + .0 + .clone() + .0, + ), crate::BindingResource::SamplerArray(..) => { panic!("Web backend does not support arrays of samplers") } - crate::BindingResource::TextureView(texture_view) => { - JsValue::from(texture_view.id.0.clone()) - } + crate::BindingResource::TextureView(texture_view) => JsValue::from( + texture_view + .id + .downcast_id::>() + .0 + .clone() + .0, + ), crate::BindingResource::TextureViewArray(..) => { panic!("Web backend does not support BINDING_INDEXING extension") } @@ -1538,8 +1556,10 @@ impl crate::Context for Context { }) .collect::(); - let mut mapped_desc = - web_sys::GpuBindGroupDescriptor::new(&mapped_entries, &desc.layout.id.0); + let mut mapped_desc = web_sys::GpuBindGroupDescriptor::new( + &mapped_entries, + desc.layout.id.downcast_id::>().0, + ); if let Some(label) = desc.label { mapped_desc.label(label); } @@ -1554,7 +1574,13 @@ impl crate::Context for Context { let temp_layouts = desc .bind_group_layouts .iter() - .map(|bgl| bgl.id.0.clone()) + .map(|bgl| { + bgl.id + .downcast_id::>() + .0 + .clone() + .0 + }) .collect::(); let mut mapped_desc = web_sys::GpuPipelineLayoutDescriptor::new(&temp_layouts); if let Some(label) = desc.label { @@ -1568,8 +1594,10 @@ impl crate::Context for Context { device: &Self::DeviceId, desc: &crate::RenderPipelineDescriptor, ) -> Self::RenderPipelineId { - let mut mapped_vertex_state = - web_sys::GpuVertexState::new(desc.vertex.entry_point, &desc.vertex.module.id.0); + let mut mapped_vertex_state = web_sys::GpuVertexState::new( + desc.vertex.entry_point, + desc.vertex.module.id.downcast_id::>().0, + ); let buffers = desc .vertex @@ -1602,7 +1630,7 @@ impl crate::Context for Context { let auto_layout = wasm_bindgen::JsValue::from(web_sys::GpuAutoLayoutMode::Auto); let mut mapped_desc = web_sys::GpuRenderPipelineDescriptor::new( match desc.layout { - Some(layout) => &layout.id.0, + Some(layout) => layout.id.downcast_id::>().0, None => &auto_layout, }, &mapped_vertex_state, @@ -1637,8 +1665,11 @@ impl crate::Context for Context { None => wasm_bindgen::JsValue::null(), }) .collect::(); - let mapped_fragment_desc = - web_sys::GpuFragmentState::new(frag.entry_point, &frag.module.id.0, &targets); + let mapped_fragment_desc = web_sys::GpuFragmentState::new( + frag.entry_point, + frag.module.id.downcast_id::>().0, + &targets, + ); mapped_desc.fragment(&mapped_fragment_desc); } @@ -1659,12 +1690,14 @@ impl crate::Context for Context { device: &Self::DeviceId, desc: &crate::ComputePipelineDescriptor, ) -> Self::ComputePipelineId { - let mapped_compute_stage = - web_sys::GpuProgrammableStage::new(desc.entry_point, &desc.module.id.0); + let mapped_compute_stage = web_sys::GpuProgrammableStage::new( + desc.entry_point, + desc.module.id.downcast_id::>().0, + ); let auto_layout = wasm_bindgen::JsValue::from(web_sys::GpuAutoLayoutMode::Auto); let mut mapped_desc = web_sys::GpuComputePipelineDescriptor::new( match desc.layout { - Some(layout) => &layout.id.0, + Some(layout) => layout.id.downcast_id::>().0, None => &auto_layout, }, &mapped_compute_stage, @@ -1792,7 +1825,7 @@ impl crate::Context for Context { fn device_on_uncaptured_error( &self, device: &Self::DeviceId, - handler: impl crate::UncapturedErrorHandler, + handler: Box, ) { let f = Closure::wrap(Box::new(move |event: web_sys::GpuUncapturedErrorEvent| { let error = crate::Error::from_js(event.error().value_of()); @@ -1820,15 +1853,13 @@ impl crate::Context for Context { ) } - fn buffer_map_async( + fn buffer_map_async( &self, buffer: &Self::BufferId, mode: crate::MapMode, range: Range, - callback: F, - ) where - F: FnOnce(Result<(), crate::BufferAsyncError>) + Send + 'static, - { + callback: Box) + Send + 'static>, + ) { let map_promise = buffer.0.map_async_with_f64_and_f64( map_map_mode(mode), range.start as f64, @@ -2076,13 +2107,14 @@ impl crate::Context for Context { let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachment::new( load_value, map_store_op(ca.ops.store), - &ca.view.id.0, + ca.view.id.downcast_id::>().0, ); if let Some(cv) = clear_value { mapped_color_attachment.clear_value(&cv); } if let Some(rt) = ca.resolve_target { - mapped_color_attachment.resolve_target(&rt.id.0); + mapped_color_attachment + .resolve_target(rt.id.downcast_id::>().0); } mapped_color_attachment.store_op(map_store_op(ca.ops.store)); @@ -2128,7 +2160,9 @@ impl crate::Context for Context { None => (web_sys::GpuLoadOp::Load, web_sys::GpuStoreOp::Store), }; let mut mapped_depth_stencil_attachment = - web_sys::GpuRenderPassDepthStencilAttachment::new(&dsa.view.id.0); + web_sys::GpuRenderPassDepthStencilAttachment::new( + dsa.view.id.downcast_id::>().0, + ); mapped_depth_stencil_attachment.depth_clear_value(depth_clear_value); mapped_depth_stencil_attachment.depth_load_op(depth_load_op); mapped_depth_stencil_attachment.depth_store_op(depth_store_op); @@ -2271,8 +2305,10 @@ impl crate::Context for Context { &self, _queue: &Self::QueueId, size: wgt::BufferSize, - ) -> QueueWriteBuffer { - QueueWriteBuffer(vec![0; size.get() as usize].into_boxed_slice()) + ) -> Box { + Box::new(WebQueueWriteBuffer( + vec![0; size.get() as usize].into_boxed_slice(), + )) } fn queue_write_staging_buffer( @@ -2280,8 +2316,13 @@ impl crate::Context for Context { queue: &Self::QueueId, buffer: &Self::BufferId, offset: wgt::BufferAddress, - staging_buffer: &QueueWriteBuffer, + staging_buffer: &dyn QueueWriteBuffer, ) { + let staging_buffer = staging_buffer + .as_any() + .downcast_ref::() + .unwrap() + .slice(); self.queue_write_buffer(queue, buffer, offset, staging_buffer) } @@ -2351,20 +2392,20 @@ impl crate::Context for Context { pub(crate) type SurfaceOutputDetail = (); #[derive(Debug)] -pub struct QueueWriteBuffer(Box<[u8]>); +pub struct WebQueueWriteBuffer(Box<[u8]>); -impl std::ops::Deref for QueueWriteBuffer { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - panic!("QueueWriteBuffer is write-only!"); +impl QueueWriteBuffer for WebQueueWriteBuffer { + fn slice(&self) -> &[u8] { + &self.0 } -} -impl std::ops::DerefMut for QueueWriteBuffer { - fn deref_mut(&mut self) -> &mut Self::Target { + fn slice_mut(&mut self) -> &mut [u8] { &mut self.0 } + + fn as_any(&self) -> &dyn Any { + self + } } #[derive(Debug)] diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs new file mode 100644 index 0000000000..889f4d4a0d --- /dev/null +++ b/wgpu/src/context.rs @@ -0,0 +1,1872 @@ +use std::{any::Any, fmt::Debug, future::Future, ops::Range, pin::Pin}; + +use wgt::{ + AdapterInfo, BufferAddress, BufferSize, Color, CompositeAlphaMode, DownlevelCapabilities, + DynamicOffset, Extent3d, Features, ImageDataLayout, ImageSubresourceRange, IndexFormat, Limits, + PresentMode, ShaderStages, SurfaceConfiguration, SurfaceStatus, TextureFormat, + TextureFormatFeatures, +}; + +use crate::{ + backend::BufferMappedRange, BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, + BufferAsyncError, BufferDescriptor, CommandEncoderDescriptor, ComputePassDescriptor, + ComputePassInner, ComputePipelineDescriptor, Context, DeviceDescriptor, Error, ErrorFilter, + ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode, PipelineLayoutDescriptor, + QuerySetDescriptor, RenderBundleDescriptor, RenderBundleEncoderDescriptor, RenderInner, + RenderPassDescriptor, RenderPassInner, RenderPipelineDescriptor, RequestAdapterOptions, + RequestDeviceError, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, + Texture, TextureDescriptor, TextureViewDescriptor, UncapturedErrorHandler, +}; + +pub struct IdSendSync { + inner: Box, +} +static_assertions::assert_impl_all!(IdSendSync: Send, Sync); + +impl IdSendSync { + pub fn upcast(id: T) -> Self { + Self { + inner: Box::new(id), + } + } + + /// Returns a reference to the inner id value if it is `T`. + pub fn downcast_id(&self) -> &T { + // FIXME: Better error message + self.inner + .downcast_ref() + .expect("IdSendSync was downcast to the wrong type") + } + + /// Consumes the id, returning the inner id value if it is `T`. + pub fn into_id(self) -> T { + // TODO: Box::into_inner would be more clear but it is nightly still: https://github.com/rust-lang/rust/issues/80437 + *self.inner.downcast::().unwrap() + } +} + +impl Debug for IdSendSync { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "IdSendSync") + } +} + +/// A type erased id. +pub struct Id { + inner: Box, +} + +impl Debug for Id { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Id") + } +} + +impl Id { + pub fn upcast(id: T) -> Self { + Self { + inner: Box::new(id), + } + } + + /// Returns a reference to the inner id value if it is `T`. + pub fn downcast_id_mut(&mut self) -> &mut T { + // FIXME: Better error message + self.inner + .downcast_mut() + .expect("IdSendSync was downcast to the wrong type") + } + + /// Consumes the id, returning the inner id value if it is `T`. + pub fn into_id(self) -> T { + // TODO: Box::into_inner would be more clear but it is nightly still: https://github.com/rust-lang/rust/issues/80437 + *self.inner.downcast::().unwrap() + } +} + +/// An object safe variant of [`Context`] implemented by all types that implement [`Context`]. +pub trait DynContext: Debug + Send + Sync { + fn as_any(&self) -> &dyn Any; + + fn instance_create_surface( + &self, + display_handle: raw_window_handle::RawDisplayHandle, + window_handle: raw_window_handle::RawWindowHandle, + ) -> IdSendSync; + fn instance_request_adapter( + &self, + options: &RequestAdapterOptions<'_>, + ) -> Pin> + Send>>; + #[allow(clippy::type_complexity)] + fn adapter_request_device( + &self, + adapter: &IdSendSync, + desc: &DeviceDescriptor, + trace_dir: Option<&std::path::Path>, + ) -> Pin> + Send>>; + + fn instance_poll_all_devices(&self, force_wait: bool) -> bool; + fn adapter_is_surface_supported(&self, adapter: &IdSendSync, surface: &IdSendSync) -> bool; + fn adapter_features(&self, adapter: &IdSendSync) -> Features; + fn adapter_limits(&self, adapter: &IdSendSync) -> Limits; + fn adapter_downlevel_capabilities(&self, adapter: &IdSendSync) -> DownlevelCapabilities; + fn adapter_get_info(&self, adapter: &IdSendSync) -> AdapterInfo; + fn adapter_get_texture_format_features( + &self, + adapter: &IdSendSync, + format: TextureFormat, + ) -> TextureFormatFeatures; + fn surface_get_supported_formats( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec; + fn surface_get_supported_present_modes( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec; + fn surface_get_supported_alpha_modes( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec; + fn surface_configure( + &self, + surface: &IdSendSync, + device: &IdSendSync, + config: &SurfaceConfiguration, + ); + fn surface_get_current_texture( + &self, + surface: &IdSendSync, + ) -> ( + Option, + SurfaceStatus, + Box, + ); + fn surface_present(&self, texture: &IdSendSync, detail: &(dyn Any + Send + Sync)); + fn surface_texture_discard(&self, texture: &IdSendSync, detail: &(dyn Any + Send + Sync)); + + fn device_features(&self, device: &IdSendSync) -> Features; + fn device_limits(&self, device: &IdSendSync) -> Limits; + fn device_downlevel_properties(&self, device: &IdSendSync) -> DownlevelCapabilities; + fn device_create_shader_module( + &self, + device: &IdSendSync, + desc: ShaderModuleDescriptor, + shader_bound_checks: wgt::ShaderBoundChecks, + ) -> IdSendSync; + unsafe fn device_create_shader_module_spirv( + &self, + device: &IdSendSync, + desc: &ShaderModuleDescriptorSpirV, + ) -> IdSendSync; + fn device_create_bind_group_layout( + &self, + device: &IdSendSync, + desc: &BindGroupLayoutDescriptor, + ) -> IdSendSync; + fn device_create_bind_group( + &self, + device: &IdSendSync, + desc: &BindGroupDescriptor, + ) -> IdSendSync; + fn device_create_pipeline_layout( + &self, + device: &IdSendSync, + desc: &PipelineLayoutDescriptor, + ) -> IdSendSync; + fn device_create_render_pipeline( + &self, + device: &IdSendSync, + desc: &RenderPipelineDescriptor, + ) -> IdSendSync; + fn device_create_compute_pipeline( + &self, + device: &IdSendSync, + desc: &ComputePipelineDescriptor, + ) -> IdSendSync; + fn device_create_buffer(&self, device: &IdSendSync, desc: &BufferDescriptor) -> IdSendSync; + fn device_create_texture(&self, device: &IdSendSync, desc: &TextureDescriptor) -> IdSendSync; + fn device_create_sampler(&self, device: &IdSendSync, desc: &SamplerDescriptor) -> IdSendSync; + fn device_create_query_set(&self, device: &IdSendSync, desc: &QuerySetDescriptor) + -> IdSendSync; + fn device_create_command_encoder( + &self, + device: &IdSendSync, + desc: &CommandEncoderDescriptor, + ) -> IdSendSync; + fn device_create_render_bundle_encoder( + &self, + device: &IdSendSync, + desc: &RenderBundleEncoderDescriptor, + ) -> Id; + fn device_drop(&self, device: &IdSendSync); + fn device_poll(&self, device: &IdSendSync, maintain: Maintain) -> bool; + fn device_on_uncaptured_error( + &self, + device: &IdSendSync, + handler: Box, + ); + fn device_push_error_scope(&self, device: &IdSendSync, filter: ErrorFilter); + fn device_pop_error_scope( + &self, + device: &IdSendSync, + ) -> Pin> + Send + 'static>>; + fn buffer_map_async( + &self, + buffer: &IdSendSync, + mode: MapMode, + range: Range, + callback: Box) + Send + 'static>, + ); + fn buffer_get_mapped_range( + &self, + buffer: &IdSendSync, + sub_range: Range, + ) -> BufferMappedRange; + fn buffer_unmap(&self, buffer: &IdSendSync); + fn texture_create_view(&self, texture: &IdSendSync, desc: &TextureViewDescriptor) + -> IdSendSync; + + fn surface_drop(&self, surface: &IdSendSync); + fn adapter_drop(&self, adapter: &IdSendSync); + fn buffer_destroy(&self, buffer: &IdSendSync); + fn buffer_drop(&self, buffer: &IdSendSync); + fn texture_destroy(&self, buffer: &IdSendSync); + fn texture_drop(&self, texture: &IdSendSync); + fn texture_view_drop(&self, texture_view: &IdSendSync); + fn sampler_drop(&self, sampler: &IdSendSync); + fn query_set_drop(&self, query_set: &IdSendSync); + fn bind_group_drop(&self, bind_group: &IdSendSync); + fn bind_group_layout_drop(&self, bind_group_layout: &IdSendSync); + fn pipeline_layout_drop(&self, pipeline_layout: &IdSendSync); + fn shader_module_drop(&self, shader_module: &IdSendSync); + fn command_encoder_drop(&self, command_encoder: &IdSendSync); + fn command_buffer_drop(&self, command_buffer: &IdSendSync); + fn render_bundle_drop(&self, render_bundle: &IdSendSync); + fn compute_pipeline_drop(&self, pipeline: &IdSendSync); + fn render_pipeline_drop(&self, pipeline: &IdSendSync); + + fn compute_pipeline_get_bind_group_layout( + &self, + pipeline: &IdSendSync, + index: u32, + ) -> IdSendSync; + fn render_pipeline_get_bind_group_layout( + &self, + pipeline: &IdSendSync, + index: u32, + ) -> IdSendSync; + + fn command_encoder_copy_buffer_to_buffer( + &self, + encoder: &IdSendSync, + source: &IdSendSync, + source_offset: BufferAddress, + destination: &IdSendSync, + destination_offset: BufferAddress, + copy_size: BufferAddress, + ); + fn command_encoder_copy_buffer_to_texture( + &self, + encoder: &IdSendSync, + source: ImageCopyBuffer, + destination: ImageCopyTexture, + copy_size: Extent3d, + ); + fn command_encoder_copy_texture_to_buffer( + &self, + encoder: &IdSendSync, + source: ImageCopyTexture, + destination: ImageCopyBuffer, + copy_size: Extent3d, + ); + fn command_encoder_copy_texture_to_texture( + &self, + encoder: &IdSendSync, + source: ImageCopyTexture, + destination: ImageCopyTexture, + copy_size: Extent3d, + ); + + fn command_encoder_begin_compute_pass( + &self, + encoder: &IdSendSync, + desc: &ComputePassDescriptor, + ) -> Id; + fn command_encoder_end_compute_pass(&self, encoder: &IdSendSync, pass: &mut Id); + fn command_encoder_begin_render_pass<'a>( + &self, + encoder: &IdSendSync, + desc: &RenderPassDescriptor<'a, '_>, + ) -> Id; + fn command_encoder_end_render_pass(&self, encoder: &IdSendSync, pass: &mut Id); + fn command_encoder_finish(&self, encoder: IdSendSync) -> IdSendSync; + + fn command_encoder_clear_texture( + &self, + encoder: &IdSendSync, + texture: &Texture, + subresource_range: &ImageSubresourceRange, + ); + fn command_encoder_clear_buffer( + &self, + encoder: &IdSendSync, + buffer: &Buffer, + offset: BufferAddress, + size: Option, + ); + + fn command_encoder_insert_debug_marker(&self, encoder: &IdSendSync, label: &str); + fn command_encoder_push_debug_group(&self, encoder: &IdSendSync, label: &str); + fn command_encoder_pop_debug_group(&self, encoder: &IdSendSync); + + fn command_encoder_write_timestamp( + &self, + encoder: &IdSendSync, + query_set: &IdSendSync, + query_index: u32, + ); + fn command_encoder_resolve_query_set( + &self, + encoder: &IdSendSync, + query_set: &IdSendSync, + first_query: u32, + query_count: u32, + destination: &IdSendSync, + destination_offset: BufferAddress, + ); + + fn render_bundle_encoder_finish( + &self, + encoder: Id, + desc: &RenderBundleDescriptor, + ) -> IdSendSync; + fn queue_write_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: BufferAddress, + data: &[u8], + ); + fn queue_validate_write_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: wgt::BufferAddress, + size: wgt::BufferSize, + ); + fn queue_create_staging_buffer( + &self, + queue: &IdSendSync, + size: BufferSize, + ) -> Box; + fn queue_write_staging_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: BufferAddress, + staging_buffer: &dyn QueueWriteBuffer, + ); + fn queue_write_texture( + &self, + queue: &IdSendSync, + texture: ImageCopyTexture, + data: &[u8], + data_layout: ImageDataLayout, + size: Extent3d, + ); + fn queue_submit<'a>( + &self, + queue: &IdSendSync, + command_buffers: Box + 'a>, + ) -> IdSendSync; + fn queue_get_timestamp_period(&self, queue: &IdSendSync) -> f32; + fn queue_on_submitted_work_done( + &self, + queue: &IdSendSync, + callback: Box, + ); + + fn device_start_capture(&self, device: &IdSendSync); + fn device_stop_capture(&self, device: &IdSendSync); + + // TODO: ComputePassInner + fn compute_pass_set_pipeline(&self, pass: &mut Id, pipeline: &IdSendSync); + fn compute_pass_set_bind_group( + &self, + pass: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ); + fn compute_pass_set_push_constants(&self, pass: &mut Id, offset: u32, data: &[u8]); + fn compute_pass_insert_debug_marker(&self, pass: &mut Id, label: &str); + fn compute_pass_push_debug_group(&self, pass: &mut Id, group_label: &str); + fn compute_pass_pop_debug_group(&self, pass: &mut Id); + fn compute_pass_write_timestamp(&self, pass: &mut Id, query_set: &IdSendSync, query_index: u32); + fn compute_pass_begin_pipeline_statistics_query( + &self, + pass: &mut Id, + query_set: &IdSendSync, + query_index: u32, + ); + fn compute_pass_end_pipeline_statistics_query(&self, pass: &mut Id); + fn compute_pass_dispatch_workgroups(&self, pass: &mut Id, x: u32, y: u32, z: u32); + fn compute_pass_dispatch_workgroups_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ); + + fn render_bundle_encoder_set_pipeline(&self, encoder: &mut Id, pipeline: &IdSendSync); + fn render_bundle_encoder_set_bind_group( + &self, + encoder: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ); + fn render_bundle_encoder_set_index_buffer( + &self, + encoder: &mut Id, + buffer: &IdSendSync, + index_format: IndexFormat, + offset: BufferAddress, + size: Option, + ); + fn render_bundle_encoder_set_vertex_buffer( + &self, + encoder: &mut Id, + slot: u32, + buffer: &IdSendSync, + offset: BufferAddress, + size: Option, + ); + fn render_bundle_encoder_set_push_constants( + &self, + encoder: &mut Id, + stages: ShaderStages, + offset: u32, + data: &[u8], + ); + fn render_bundle_encoder_draw( + &self, + encoder: &mut Id, + vertices: Range, + instances: Range, + ); + fn render_bundle_encoder_draw_indexed( + &self, + encoder: &mut Id, + indices: Range, + base_vertex: i32, + instances: Range, + ); + fn render_bundle_encoder_draw_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ); + fn render_bundle_encoder_draw_indexed_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ); + fn render_bundle_encoder_multi_draw_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ); + fn render_bundle_encoder_multi_draw_indexed_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ); + fn render_bundle_encoder_multi_draw_indirect_count( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ); + fn render_bundle_encoder_multi_draw_indexed_indirect_count( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ); + + fn render_pass_set_pipeline(&self, pass: &mut Id, pipeline: &IdSendSync); + fn render_pass_set_bind_group( + &self, + pass: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ); + fn render_pass_set_index_buffer( + &self, + pass: &mut Id, + buffer: &IdSendSync, + index_format: IndexFormat, + offset: BufferAddress, + size: Option, + ); + fn render_pass_set_vertex_buffer( + &self, + pass: &mut Id, + slot: u32, + buffer: &IdSendSync, + offset: BufferAddress, + size: Option, + ); + fn render_pass_set_push_constants( + &self, + pass: &mut Id, + stages: ShaderStages, + offset: u32, + data: &[u8], + ); + fn render_pass_draw(&self, pass: &mut Id, vertices: Range, instances: Range); + fn render_pass_draw_indexed( + &self, + pass: &mut Id, + indices: Range, + base_vertex: i32, + instances: Range, + ); + fn render_pass_draw_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ); + fn render_pass_draw_indexed_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ); + fn render_pass_multi_draw_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ); + fn render_pass_multi_draw_indexed_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ); + fn render_pass_multi_draw_indirect_count( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ); + fn render_pass_multi_draw_indexed_indirect_count( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ); + fn render_pass_set_blend_constant(&self, pass: &mut Id, color: Color); + fn render_pass_set_scissor_rect(&self, pass: &mut Id, x: u32, y: u32, width: u32, height: u32); + #[allow(clippy::too_many_arguments)] + fn render_pass_set_viewport( + &self, + pass: &mut Id, + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, + ); + fn render_pass_set_stencil_reference(&self, pass: &mut Id, reference: u32); + fn render_pass_insert_debug_marker(&self, pass: &mut Id, label: &str); + fn render_pass_push_debug_group(&self, pass: &mut Id, group_label: &str); + fn render_pass_pop_debug_group(&self, pass: &mut Id); + fn render_pass_write_timestamp(&self, pass: &mut Id, query_set: &IdSendSync, query_index: u32); + fn render_pass_begin_pipeline_statistics_query( + &self, + pass: &mut Id, + query_set: &IdSendSync, + query_index: u32, + ); + fn render_pass_end_pipeline_statistics_query(&self, pass: &mut Id); + fn render_pass_execute_bundles<'a>( + &self, + pass: &mut Id, + render_bundles: Box + 'a>, + ); +} + +// Blanket impl of DynContext for all types which implement Context. +impl DynContext for T +where + T: Context + 'static, +{ + fn as_any(&self) -> &dyn Any { + self + } + + fn instance_create_surface( + &self, + display_handle: raw_window_handle::RawDisplayHandle, + window_handle: raw_window_handle::RawWindowHandle, + ) -> IdSendSync { + IdSendSync::upcast(Context::instance_create_surface( + self, + display_handle, + window_handle, + )) + } + + fn instance_request_adapter( + &self, + options: &RequestAdapterOptions<'_>, + ) -> Pin> + Send>> { + let future = Context::instance_request_adapter(self, options); + Box::pin(async move { future.await.map(IdSendSync::upcast) }) + } + + fn adapter_request_device( + &self, + adapter: &IdSendSync, + desc: &DeviceDescriptor, + trace_dir: Option<&std::path::Path>, + ) -> Pin> + Send>> + { + let adapter = adapter.downcast_id::(); + let future = Context::adapter_request_device(self, adapter, desc, trace_dir); + + Box::pin(async move { + let (device, queue) = future.await?; + Ok((IdSendSync::upcast(device), IdSendSync::upcast(queue))) + }) + } + + fn instance_poll_all_devices(&self, force_wait: bool) -> bool { + Context::instance_poll_all_devices(self, force_wait) + } + + fn adapter_is_surface_supported(&self, adapter: &IdSendSync, surface: &IdSendSync) -> bool { + let adapter = adapter.downcast_id::(); + let surface = surface.downcast_id::(); + Context::adapter_is_surface_supported(self, adapter, surface) + } + + fn adapter_features(&self, adapter: &IdSendSync) -> Features { + let adapter = adapter.downcast_id::(); + Context::adapter_features(self, adapter) + } + + fn adapter_limits(&self, adapter: &IdSendSync) -> Limits { + let adapter = adapter.downcast_id::(); + Context::adapter_limits(self, adapter) + } + + fn adapter_downlevel_capabilities(&self, adapter: &IdSendSync) -> DownlevelCapabilities { + let adapter = adapter.downcast_id::(); + Context::adapter_downlevel_capabilities(self, adapter) + } + + fn adapter_get_info(&self, adapter: &IdSendSync) -> AdapterInfo { + let adapter = adapter.downcast_id::(); + Context::adapter_get_info(self, adapter) + } + + fn adapter_get_texture_format_features( + &self, + adapter: &IdSendSync, + format: TextureFormat, + ) -> TextureFormatFeatures { + let adapter = adapter.downcast_id::(); + Context::adapter_get_texture_format_features(self, adapter, format) + } + + fn surface_get_supported_formats( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec { + let surface = surface.downcast_id::(); + let adapter = adapter.downcast_id::(); + Context::surface_get_supported_formats(self, surface, adapter) + } + + fn surface_get_supported_present_modes( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec { + let surface = surface.downcast_id::(); + let adapter = adapter.downcast_id::(); + Context::surface_get_supported_present_modes(self, surface, adapter) + } + + fn surface_get_supported_alpha_modes( + &self, + surface: &IdSendSync, + adapter: &IdSendSync, + ) -> Vec { + let surface = surface.downcast_id::(); + let adapter = adapter.downcast_id::(); + Context::surface_get_supported_alpha_modes(self, surface, adapter) + } + + fn surface_configure( + &self, + surface: &IdSendSync, + device: &IdSendSync, + config: &SurfaceConfiguration, + ) { + let surface = surface.downcast_id::(); + let device = device.downcast_id::(); + Context::surface_configure(self, surface, device, config) + } + + fn surface_get_current_texture( + &self, + surface: &IdSendSync, + ) -> ( + Option, + SurfaceStatus, + Box, + ) { + let surface = surface.downcast_id::(); + let (texture, status, detail) = Context::surface_get_current_texture(self, surface); + (texture.map(IdSendSync::upcast), status, Box::new(detail)) + } + + fn surface_present(&self, texture: &IdSendSync, detail: &(dyn Any + Send + Sync)) { + let texture = texture.downcast_id::(); + Context::surface_present(self, texture, detail.downcast_ref().unwrap()) + } + + fn surface_texture_discard(&self, texture: &IdSendSync, detail: &(dyn Any + Send + Sync)) { + let texture = texture.downcast_id::(); + Context::surface_texture_discard(self, texture, detail.downcast_ref().unwrap()) + } + + fn device_features(&self, device: &IdSendSync) -> Features { + let device = device.downcast_id::(); + Context::device_features(self, device) + } + + fn device_limits(&self, device: &IdSendSync) -> Limits { + let device = device.downcast_id::(); + Context::device_limits(self, device) + } + + fn device_downlevel_properties(&self, device: &IdSendSync) -> DownlevelCapabilities { + let device = device.downcast_id::(); + Context::device_downlevel_properties(self, device) + } + + fn device_create_shader_module( + &self, + device: &IdSendSync, + desc: ShaderModuleDescriptor, + shader_bound_checks: wgt::ShaderBoundChecks, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_shader_module( + self, + device, + desc, + shader_bound_checks, + )) + } + + unsafe fn device_create_shader_module_spirv( + &self, + device: &IdSendSync, + desc: &ShaderModuleDescriptorSpirV, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_shader_module_spirv( + self, device, desc, + )) + } + + fn device_create_bind_group_layout( + &self, + device: &IdSendSync, + desc: &BindGroupLayoutDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_bind_group_layout(self, device, desc)) + } + + fn device_create_bind_group( + &self, + device: &IdSendSync, + desc: &BindGroupDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_bind_group(self, device, desc)) + } + + fn device_create_pipeline_layout( + &self, + device: &IdSendSync, + desc: &PipelineLayoutDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_pipeline_layout(self, device, desc)) + } + + fn device_create_render_pipeline( + &self, + device: &IdSendSync, + desc: &RenderPipelineDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_render_pipeline(self, device, desc)) + } + + fn device_create_compute_pipeline( + &self, + device: &IdSendSync, + desc: &ComputePipelineDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_compute_pipeline(self, device, desc)) + } + + fn device_create_buffer(&self, device: &IdSendSync, desc: &BufferDescriptor) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_buffer(self, device, desc)) + } + + fn device_create_texture(&self, device: &IdSendSync, desc: &TextureDescriptor) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_texture(self, device, desc)) + } + + fn device_create_sampler(&self, device: &IdSendSync, desc: &SamplerDescriptor) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_sampler(self, device, desc)) + } + + fn device_create_query_set( + &self, + device: &IdSendSync, + desc: &QuerySetDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_query_set(self, device, desc)) + } + + fn device_create_command_encoder( + &self, + device: &IdSendSync, + desc: &CommandEncoderDescriptor, + ) -> IdSendSync { + let device = device.downcast_id::(); + IdSendSync::upcast(Context::device_create_command_encoder(self, device, desc)) + } + + fn device_create_render_bundle_encoder( + &self, + device: &IdSendSync, + desc: &RenderBundleEncoderDescriptor, + ) -> Id { + let device = device.downcast_id::(); + Id::upcast(Context::device_create_render_bundle_encoder( + self, device, desc, + )) + } + + fn device_drop(&self, device: &IdSendSync) { + let device = device.downcast_id::(); + Context::device_drop(self, device) + } + + fn device_poll(&self, device: &IdSendSync, maintain: Maintain) -> bool { + let device = device.downcast_id::(); + Context::device_poll(self, device, maintain) + } + + fn device_on_uncaptured_error( + &self, + device: &IdSendSync, + handler: Box, + ) { + let device = device.downcast_id::(); + Context::device_on_uncaptured_error(self, device, handler) + } + + fn device_push_error_scope(&self, device: &IdSendSync, filter: ErrorFilter) { + let device = device.downcast_id::(); + Context::device_push_error_scope(self, device, filter) + } + + fn device_pop_error_scope( + &self, + device: &IdSendSync, + ) -> Pin> + Send + 'static>> { + let device = device.downcast_id::(); + Box::pin(Context::device_pop_error_scope(self, device)) + } + + fn buffer_map_async( + &self, + buffer: &IdSendSync, + mode: MapMode, + range: Range, + callback: Box) + Send + 'static>, + ) { + let buffer = buffer.downcast_id::(); + Context::buffer_map_async(self, buffer, mode, range, callback) + } + + fn buffer_get_mapped_range( + &self, + buffer: &IdSendSync, + sub_range: Range, + ) -> BufferMappedRange { + let buffer = buffer.downcast_id::(); + Context::buffer_get_mapped_range(self, buffer, sub_range) + } + + fn buffer_unmap(&self, buffer: &IdSendSync) { + let buffer = buffer.downcast_id::(); + Context::buffer_unmap(self, buffer) + } + + fn texture_create_view( + &self, + texture: &IdSendSync, + desc: &TextureViewDescriptor, + ) -> IdSendSync { + let texture = texture.downcast_id::(); + IdSendSync::upcast(Context::texture_create_view(self, texture, desc)) + } + + fn surface_drop(&self, surface: &IdSendSync) { + let surface = surface.downcast_id::(); + Context::surface_drop(self, surface) + } + + fn adapter_drop(&self, adapter: &IdSendSync) { + let adapter = adapter.downcast_id::(); + Context::adapter_drop(self, adapter) + } + + fn buffer_destroy(&self, buffer: &IdSendSync) { + let buffer = buffer.downcast_id::(); + Context::buffer_destroy(self, buffer) + } + + fn buffer_drop(&self, buffer: &IdSendSync) { + let buffer = buffer.downcast_id::(); + Context::buffer_drop(self, buffer) + } + + fn texture_destroy(&self, texture: &IdSendSync) { + let texture = texture.downcast_id::(); + Context::texture_destroy(self, texture) + } + + fn texture_drop(&self, texture: &IdSendSync) { + let texture = texture.downcast_id::(); + Context::texture_drop(self, texture) + } + + fn texture_view_drop(&self, texture_view: &IdSendSync) { + let texture_view = texture_view.downcast_id::(); + Context::texture_view_drop(self, texture_view) + } + + fn sampler_drop(&self, sampler: &IdSendSync) { + let sampler = sampler.downcast_id::(); + Context::sampler_drop(self, sampler) + } + + fn query_set_drop(&self, query_set: &IdSendSync) { + let query_set = query_set.downcast_id::(); + Context::query_set_drop(self, query_set) + } + + fn bind_group_drop(&self, bind_group: &IdSendSync) { + let bind_group = bind_group.downcast_id::(); + Context::bind_group_drop(self, bind_group) + } + + fn bind_group_layout_drop(&self, bind_group_layout: &IdSendSync) { + let bind_group_layout = bind_group_layout.downcast_id::(); + Context::bind_group_layout_drop(self, bind_group_layout) + } + + fn pipeline_layout_drop(&self, pipeline_layout: &IdSendSync) { + let pipeline_layout = pipeline_layout.downcast_id::(); + Context::pipeline_layout_drop(self, pipeline_layout) + } + + fn shader_module_drop(&self, shader_module: &IdSendSync) { + let shader_module = shader_module.downcast_id::(); + Context::shader_module_drop(self, shader_module) + } + + fn command_encoder_drop(&self, command_encoder: &IdSendSync) { + let command_encoder = command_encoder.downcast_id::(); + Context::command_encoder_drop(self, command_encoder) + } + + fn command_buffer_drop(&self, command_buffer: &IdSendSync) { + let command_buffer = command_buffer.downcast_id::(); + Context::command_buffer_drop(self, command_buffer) + } + + fn render_bundle_drop(&self, render_bundle: &IdSendSync) { + let render_bundle = render_bundle.downcast_id::(); + Context::render_bundle_drop(self, render_bundle) + } + + fn compute_pipeline_drop(&self, pipeline: &IdSendSync) { + let pipeline = pipeline.downcast_id::(); + Context::compute_pipeline_drop(self, pipeline) + } + + fn render_pipeline_drop(&self, pipeline: &IdSendSync) { + let pipeline = pipeline.downcast_id::(); + Context::render_pipeline_drop(self, pipeline) + } + + fn compute_pipeline_get_bind_group_layout( + &self, + pipeline: &IdSendSync, + index: u32, + ) -> IdSendSync { + let pipeline = pipeline.downcast_id::(); + IdSendSync::upcast(Context::compute_pipeline_get_bind_group_layout( + self, pipeline, index, + )) + } + + fn render_pipeline_get_bind_group_layout( + &self, + pipeline: &IdSendSync, + index: u32, + ) -> IdSendSync { + let pipeline = pipeline.downcast_id::(); + IdSendSync::upcast(Context::render_pipeline_get_bind_group_layout( + self, pipeline, index, + )) + } + + fn command_encoder_copy_buffer_to_buffer( + &self, + encoder: &IdSendSync, + source: &IdSendSync, + source_offset: BufferAddress, + destination: &IdSendSync, + destination_offset: BufferAddress, + copy_size: BufferAddress, + ) { + let encoder = encoder.downcast_id::(); + let source = source.downcast_id::(); + let destination = destination.downcast_id::(); + Context::command_encoder_copy_buffer_to_buffer( + self, + encoder, + source, + source_offset, + destination, + destination_offset, + copy_size, + ) + } + + fn command_encoder_copy_buffer_to_texture( + &self, + encoder: &IdSendSync, + source: ImageCopyBuffer, + destination: ImageCopyTexture, + copy_size: Extent3d, + ) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_copy_buffer_to_texture( + self, + encoder, + source, + destination, + copy_size, + ) + } + + fn command_encoder_copy_texture_to_buffer( + &self, + encoder: &IdSendSync, + source: ImageCopyTexture, + destination: ImageCopyBuffer, + copy_size: Extent3d, + ) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_copy_texture_to_buffer( + self, + encoder, + source, + destination, + copy_size, + ) + } + + fn command_encoder_copy_texture_to_texture( + &self, + encoder: &IdSendSync, + source: ImageCopyTexture, + destination: ImageCopyTexture, + copy_size: Extent3d, + ) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_copy_texture_to_texture( + self, + encoder, + source, + destination, + copy_size, + ) + } + + fn command_encoder_begin_compute_pass( + &self, + encoder: &IdSendSync, + desc: &ComputePassDescriptor, + ) -> Id { + let encoder = encoder.downcast_id::(); + Id::upcast(Context::command_encoder_begin_compute_pass( + self, encoder, desc, + )) + } + + fn command_encoder_end_compute_pass(&self, encoder: &IdSendSync, pass: &mut Id) { + let encoder = encoder.downcast_id::(); + let pass = pass.downcast_id_mut::(); + Context::command_encoder_end_compute_pass(self, encoder, pass) + } + + fn command_encoder_begin_render_pass<'a>( + &self, + encoder: &IdSendSync, + desc: &RenderPassDescriptor<'a, '_>, + ) -> Id { + let encoder = encoder.downcast_id::(); + Id::upcast(Context::command_encoder_begin_render_pass( + self, encoder, desc, + )) + } + + fn command_encoder_end_render_pass(&self, encoder: &IdSendSync, pass: &mut Id) { + let encoder = encoder.downcast_id::(); + let pass = pass.downcast_id_mut::(); + Context::command_encoder_end_render_pass(self, encoder, pass) + } + + fn command_encoder_finish(&self, encoder: IdSendSync) -> IdSendSync { + let encoder = encoder.into_id::(); + IdSendSync::upcast(Context::command_encoder_finish(self, encoder)) + } + + fn command_encoder_clear_texture( + &self, + encoder: &IdSendSync, + texture: &Texture, + subresource_range: &ImageSubresourceRange, + ) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_clear_texture(self, encoder, texture, subresource_range) + } + + fn command_encoder_clear_buffer( + &self, + encoder: &IdSendSync, + buffer: &Buffer, + offset: BufferAddress, + size: Option, + ) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_clear_buffer(self, encoder, buffer, offset, size) + } + + fn command_encoder_insert_debug_marker(&self, encoder: &IdSendSync, label: &str) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_insert_debug_marker(self, encoder, label) + } + + fn command_encoder_push_debug_group(&self, encoder: &IdSendSync, label: &str) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_push_debug_group(self, encoder, label) + } + + fn command_encoder_pop_debug_group(&self, encoder: &IdSendSync) { + let encoder = encoder.downcast_id::(); + Context::command_encoder_pop_debug_group(self, encoder) + } + + fn command_encoder_write_timestamp( + &self, + encoder: &IdSendSync, + query_set: &IdSendSync, + query_index: u32, + ) { + let encoder = encoder.downcast_id::(); + let query_set = query_set.downcast_id::(); + Context::command_encoder_write_timestamp(self, encoder, query_set, query_index) + } + + fn command_encoder_resolve_query_set( + &self, + encoder: &IdSendSync, + query_set: &IdSendSync, + first_query: u32, + query_count: u32, + destination: &IdSendSync, + destination_offset: BufferAddress, + ) { + let encoder = encoder.downcast_id::(); + let query_set = query_set.downcast_id::(); + let destination = destination.downcast_id::(); + Context::command_encoder_resolve_query_set( + self, + encoder, + query_set, + first_query, + query_count, + destination, + destination_offset, + ) + } + + fn render_bundle_encoder_finish( + &self, + encoder: Id, + desc: &RenderBundleDescriptor, + ) -> IdSendSync { + let encoder = encoder.into_id::(); + IdSendSync::upcast(Context::render_bundle_encoder_finish(self, encoder, desc)) + } + + fn queue_write_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: BufferAddress, + data: &[u8], + ) { + let queue = queue.downcast_id::(); + let buffer = buffer.downcast_id::(); + Context::queue_write_buffer(self, queue, buffer, offset, data) + } + + fn queue_validate_write_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: wgt::BufferAddress, + size: wgt::BufferSize, + ) { + let queue = queue.downcast_id::(); + let buffer = buffer.downcast_id::(); + Context::queue_validate_write_buffer(self, queue, buffer, offset, size) + } + + fn queue_create_staging_buffer( + &self, + queue: &IdSendSync, + size: BufferSize, + ) -> Box { + let queue = queue.downcast_id::(); + Context::queue_create_staging_buffer(self, queue, size) + } + + fn queue_write_staging_buffer( + &self, + queue: &IdSendSync, + buffer: &IdSendSync, + offset: BufferAddress, + staging_buffer: &dyn QueueWriteBuffer, + ) { + let queue = queue.downcast_id::(); + let buffer = buffer.downcast_id::(); + Context::queue_write_staging_buffer(self, queue, buffer, offset, staging_buffer) + } + + fn queue_write_texture( + &self, + queue: &IdSendSync, + texture: ImageCopyTexture, + data: &[u8], + data_layout: ImageDataLayout, + size: Extent3d, + ) { + let queue = queue.downcast_id::(); + Context::queue_write_texture(self, queue, texture, data, data_layout, size) + } + + fn queue_submit<'a>( + &self, + queue: &IdSendSync, + command_buffers: Box + 'a>, + ) -> IdSendSync { + let queue = queue.downcast_id::(); + let command_buffers = command_buffers.into_iter().map(IdSendSync::into_id); + IdSendSync::upcast(Context::queue_submit(self, queue, command_buffers)) + } + + fn queue_get_timestamp_period(&self, queue: &IdSendSync) -> f32 { + let queue = queue.downcast_id::(); + Context::queue_get_timestamp_period(self, queue) + } + + fn queue_on_submitted_work_done( + &self, + queue: &IdSendSync, + callback: Box, + ) { + let queue = queue.downcast_id::(); + Context::queue_on_submitted_work_done(self, queue, callback) + } + + fn device_start_capture(&self, device: &IdSendSync) { + let device = device.downcast_id::(); + Context::device_start_capture(self, device) + } + + fn device_stop_capture(&self, device: &IdSendSync) { + let device = device.downcast_id::(); + Context::device_stop_capture(self, device) + } + + fn compute_pass_set_pipeline(&self, pass: &mut Id, pipeline: &IdSendSync) { + let pass = pass.downcast_id_mut::(); + let pipeline = pipeline.downcast_id::(); + ComputePassInner::set_pipeline(pass, pipeline) + } + + fn compute_pass_set_bind_group( + &self, + pass: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ) { + let pass = pass.downcast_id_mut::(); + let bind_group = bind_group.downcast_id::(); + ComputePassInner::set_bind_group(pass, index, bind_group, offsets) + } + + fn compute_pass_set_push_constants(&self, pass: &mut Id, offset: u32, data: &[u8]) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::set_push_constants(pass, offset, data) + } + + fn compute_pass_insert_debug_marker(&self, pass: &mut Id, label: &str) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::insert_debug_marker(pass, label) + } + + fn compute_pass_push_debug_group(&self, pass: &mut Id, group_label: &str) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::push_debug_group(pass, group_label) + } + + fn compute_pass_pop_debug_group(&self, pass: &mut Id) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::pop_debug_group(pass) + } + + fn compute_pass_write_timestamp( + &self, + pass: &mut Id, + query_set: &IdSendSync, + query_index: u32, + ) { + let pass = pass.downcast_id_mut::(); + let query_set = query_set.downcast_id::(); + ComputePassInner::write_timestamp(pass, query_set, query_index) + } + + fn compute_pass_begin_pipeline_statistics_query( + &self, + pass: &mut Id, + query_set: &IdSendSync, + query_index: u32, + ) { + let pass = pass.downcast_id_mut::(); + let query_set = query_set.downcast_id::(); + ComputePassInner::begin_pipeline_statistics_query(pass, query_set, query_index) + } + + fn compute_pass_end_pipeline_statistics_query(&self, pass: &mut Id) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::end_pipeline_statistics_query(pass) + } + + fn compute_pass_dispatch_workgroups(&self, pass: &mut Id, x: u32, y: u32, z: u32) { + let pass = pass.downcast_id_mut::(); + ComputePassInner::dispatch_workgroups(pass, x, y, z) + } + + fn compute_pass_dispatch_workgroups_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + ComputePassInner::dispatch_workgroups_indirect(pass, indirect_buffer, indirect_offset) + } + + fn render_bundle_encoder_set_pipeline(&self, encoder: &mut Id, pipeline: &IdSendSync) { + let encoder = encoder.downcast_id_mut::(); + let pipeline = pipeline.downcast_id::(); + RenderInner::set_pipeline(encoder, pipeline) + } + + fn render_bundle_encoder_set_bind_group( + &self, + encoder: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ) { + let encoder = encoder.downcast_id_mut::(); + let bind_group = bind_group.downcast_id::(); + RenderInner::set_bind_group(encoder, index, bind_group, offsets) + } + + fn render_bundle_encoder_set_index_buffer( + &self, + encoder: &mut Id, + buffer: &IdSendSync, + index_format: IndexFormat, + offset: BufferAddress, + size: Option, + ) { + let encoder = encoder.downcast_id_mut::(); + let buffer = buffer.downcast_id::(); + RenderInner::set_index_buffer(encoder, buffer, index_format, offset, size) + } + + fn render_bundle_encoder_set_vertex_buffer( + &self, + encoder: &mut Id, + slot: u32, + buffer: &IdSendSync, + offset: BufferAddress, + size: Option, + ) { + let encoder = encoder.downcast_id_mut::(); + let buffer = buffer.downcast_id::(); + RenderInner::set_vertex_buffer(encoder, slot, buffer, offset, size) + } + + fn render_bundle_encoder_set_push_constants( + &self, + encoder: &mut Id, + stages: ShaderStages, + offset: u32, + data: &[u8], + ) { + let encoder = encoder.downcast_id_mut::(); + RenderInner::set_push_constants(encoder, stages, offset, data) + } + + fn render_bundle_encoder_draw( + &self, + encoder: &mut Id, + vertices: Range, + instances: Range, + ) { + let encoder = encoder.downcast_id_mut::(); + RenderInner::draw(encoder, vertices, instances) + } + + fn render_bundle_encoder_draw_indexed( + &self, + encoder: &mut Id, + indices: Range, + base_vertex: i32, + instances: Range, + ) { + let encoder = encoder.downcast_id_mut::(); + RenderInner::draw_indexed(encoder, indices, base_vertex, instances) + } + + fn render_bundle_encoder_draw_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::draw_indirect(encoder, indirect_buffer, indirect_offset) + } + + fn render_bundle_encoder_draw_indexed_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::draw_indexed_indirect(encoder, indirect_buffer, indirect_offset) + } + + fn render_bundle_encoder_multi_draw_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::multi_draw_indirect(encoder, indirect_buffer, indirect_offset, count) + } + + fn render_bundle_encoder_multi_draw_indexed_indirect( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::multi_draw_indexed_indirect(encoder, indirect_buffer, indirect_offset, count) + } + + fn render_bundle_encoder_multi_draw_indirect_count( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + let count_buffer = count_buffer.downcast_id::(); + RenderInner::multi_draw_indirect_count( + encoder, + indirect_buffer, + indirect_offset, + count_buffer, + count_buffer_offset, + max_count, + ) + } + + fn render_bundle_encoder_multi_draw_indexed_indirect_count( + &self, + encoder: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ) { + let encoder = encoder.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + let count_buffer = count_buffer.downcast_id::(); + RenderInner::multi_draw_indexed_indirect_count( + encoder, + indirect_buffer, + indirect_offset, + count_buffer, + count_buffer_offset, + max_count, + ) + } + + fn render_pass_set_pipeline(&self, pass: &mut Id, pipeline: &IdSendSync) { + let pass = pass.downcast_id_mut::(); + let pipeline = pipeline.downcast_id::(); + RenderInner::set_pipeline(pass, pipeline) + } + + fn render_pass_set_bind_group( + &self, + pass: &mut Id, + index: u32, + bind_group: &IdSendSync, + offsets: &[DynamicOffset], + ) { + let pass = pass.downcast_id_mut::(); + let bind_group = bind_group.downcast_id::(); + RenderInner::set_bind_group(pass, index, bind_group, offsets) + } + + fn render_pass_set_index_buffer( + &self, + pass: &mut Id, + buffer: &IdSendSync, + index_format: IndexFormat, + offset: BufferAddress, + size: Option, + ) { + let pass = pass.downcast_id_mut::(); + let buffer = buffer.downcast_id::(); + RenderInner::set_index_buffer(pass, buffer, index_format, offset, size) + } + + fn render_pass_set_vertex_buffer( + &self, + pass: &mut Id, + slot: u32, + buffer: &IdSendSync, + offset: BufferAddress, + size: Option, + ) { + let pass = pass.downcast_id_mut::(); + let buffer = buffer.downcast_id::(); + RenderInner::set_vertex_buffer(pass, slot, buffer, offset, size) + } + + fn render_pass_set_push_constants( + &self, + pass: &mut Id, + stages: ShaderStages, + offset: u32, + data: &[u8], + ) { + let pass = pass.downcast_id_mut::(); + RenderInner::set_push_constants(pass, stages, offset, data) + } + + fn render_pass_draw(&self, pass: &mut Id, vertices: Range, instances: Range) { + let pass = pass.downcast_id_mut::(); + RenderInner::draw(pass, vertices, instances) + } + + fn render_pass_draw_indexed( + &self, + pass: &mut Id, + indices: Range, + base_vertex: i32, + instances: Range, + ) { + let pass = pass.downcast_id_mut::(); + RenderInner::draw_indexed(pass, indices, base_vertex, instances) + } + + fn render_pass_draw_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::draw_indirect(pass, indirect_buffer, indirect_offset) + } + + fn render_pass_draw_indexed_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::draw_indexed_indirect(pass, indirect_buffer, indirect_offset) + } + + fn render_pass_multi_draw_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::multi_draw_indirect(pass, indirect_buffer, indirect_offset, count) + } + + fn render_pass_multi_draw_indexed_indirect( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count: u32, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + RenderInner::multi_draw_indexed_indirect(pass, indirect_buffer, indirect_offset, count) + } + + fn render_pass_multi_draw_indirect_count( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + let count_buffer = count_buffer.downcast_id::(); + RenderInner::multi_draw_indirect_count( + pass, + indirect_buffer, + indirect_offset, + count_buffer, + count_buffer_offset, + max_count, + ) + } + + fn render_pass_multi_draw_indexed_indirect_count( + &self, + pass: &mut Id, + indirect_buffer: &IdSendSync, + indirect_offset: BufferAddress, + count_buffer: &IdSendSync, + count_buffer_offset: BufferAddress, + max_count: u32, + ) { + let pass = pass.downcast_id_mut::(); + let indirect_buffer = indirect_buffer.downcast_id::(); + let count_buffer = count_buffer.downcast_id::(); + RenderInner::multi_draw_indexed_indirect_count( + pass, + indirect_buffer, + indirect_offset, + count_buffer, + count_buffer_offset, + max_count, + ) + } + + fn render_pass_set_blend_constant(&self, pass: &mut Id, color: Color) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::set_blend_constant(pass, color) + } + + fn render_pass_set_scissor_rect(&self, pass: &mut Id, x: u32, y: u32, width: u32, height: u32) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::set_scissor_rect(pass, x, y, width, height) + } + + fn render_pass_set_viewport( + &self, + pass: &mut Id, + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, + ) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::set_viewport(pass, x, y, width, height, min_depth, max_depth) + } + + fn render_pass_set_stencil_reference(&self, pass: &mut Id, reference: u32) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::set_stencil_reference(pass, reference) + } + + fn render_pass_insert_debug_marker(&self, pass: &mut Id, label: &str) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::insert_debug_marker(pass, label) + } + + fn render_pass_push_debug_group(&self, pass: &mut Id, group_label: &str) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::push_debug_group(pass, group_label) + } + + fn render_pass_pop_debug_group(&self, pass: &mut Id) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::pop_debug_group(pass) + } + + fn render_pass_write_timestamp(&self, pass: &mut Id, query_set: &IdSendSync, query_index: u32) { + let pass = pass.downcast_id_mut::(); + let query_set = query_set.downcast_id::(); + RenderPassInner::write_timestamp(pass, query_set, query_index) + } + + fn render_pass_begin_pipeline_statistics_query( + &self, + pass: &mut Id, + query_set: &IdSendSync, + query_index: u32, + ) { + let pass = pass.downcast_id_mut::(); + let query_set = query_set.downcast_id::(); + RenderPassInner::begin_pipeline_statistics_query(pass, query_set, query_index) + } + + fn render_pass_end_pipeline_statistics_query(&self, pass: &mut Id) { + let pass = pass.downcast_id_mut::(); + RenderPassInner::end_pipeline_statistics_query(pass) + } + + fn render_pass_execute_bundles<'a>( + &self, + pass: &mut Id, + render_bundles: Box + 'a>, + ) { + let pass = pass.downcast_id_mut::(); + let render_bundles = render_bundles.into_iter().map(IdSendSync::downcast_id); + RenderPassInner::execute_bundles(pass, render_bundles) + } +} + +pub trait QueueWriteBuffer: Send + Sync { + fn slice(&self) -> &[u8]; + + fn slice_mut(&mut self) -> &mut [u8]; + + fn as_any(&self) -> &dyn Any; +} + +#[cfg(test)] +mod tests { + use super::DynContext; + + fn compiles() {} + + /// Assert that DynContext is object safe. + #[test] + fn object_safe() { + compiles::>(); + } +} diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 9bdcd9d32e..6f403bde1f 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -7,11 +7,13 @@ #![warn(missing_docs)] mod backend; +mod context; pub mod util; #[macro_use] mod macros; use std::{ + any::Any, borrow::Cow, error, fmt::{Debug, Display}, @@ -23,6 +25,7 @@ use std::{ thread, }; +use context::{DynContext, Id, IdSendSync}; use parking_lot::Mutex; pub use wgt::{ @@ -43,7 +46,7 @@ pub use wgt::{ QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT, }; -use backend::{BufferMappedRange, Context as C, QueueWriteBuffer}; +use backend::BufferMappedRange; /// Filter for error scopes. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] @@ -179,21 +182,22 @@ trait Context: Debug + Send + Sized + Sync { type PipelineLayoutId: Debug + Send + Sync + 'static; type RenderPipelineId: Debug + Send + Sync + 'static; type ComputePipelineId: Debug + Send + Sync + 'static; - type CommandEncoderId: Debug; - type ComputePassId: Debug + ComputePassInner; - type RenderPassId: Debug + RenderPassInner; - type CommandBufferId: Debug + Send + Sync; - type RenderBundleEncoderId: Debug + RenderInner; + type CommandEncoderId: Debug + Send + Sync + 'static; + type ComputePassId: Debug + ComputePassInner + 'static; + type RenderPassId: Debug + RenderPassInner + 'static; + type CommandBufferId: Debug + Send + Sync + 'static; + type RenderBundleEncoderId: Debug + RenderInner + 'static; type RenderBundleId: Debug + Send + Sync + 'static; type SurfaceId: Debug + Send + Sync + 'static; - type SurfaceOutputDetail: Send; - type SubmissionIndex: Debug + Copy + Clone + Send + 'static; + type SurfaceOutputDetail: Send + Sync + 'static; + type SubmissionIndex: Debug + Clone + Send + Sync + 'static; - type RequestAdapterFuture: Future> + Send; + type RequestAdapterFuture: Future> + Send + 'static; type RequestDeviceFuture: Future> - + Send; - type PopErrorScopeFuture: Future> + Send; + + Send + + 'static; + type PopErrorScopeFuture: Future> + Send + 'static; fn init(backends: Backends) -> Self; fn instance_create_surface( @@ -337,12 +341,12 @@ trait Context: Debug + Send + Sized + Sync { fn device_on_uncaptured_error( &self, device: &Self::DeviceId, - handler: impl UncapturedErrorHandler, + handler: Box, ); fn device_push_error_scope(&self, device: &Self::DeviceId, filter: ErrorFilter); fn device_pop_error_scope(&self, device: &Self::DeviceId) -> Self::PopErrorScopeFuture; - fn buffer_map_async( + fn buffer_map_async( &self, buffer: &Self::BufferId, mode: MapMode, @@ -350,9 +354,8 @@ trait Context: Debug + Send + Sized + Sync { // Note: we keep this as an `impl` through the context because the native backend // needs to wrap it with a wrapping closure. queue_on_submitted_work_done doesn't // need this wrapping closure, so can be made a Box immediately. - callback: F, - ) where - F: FnOnce(Result<(), BufferAsyncError>) + Send + 'static; + callback: Box) + Send + 'static>, + ); fn buffer_get_mapped_range( &self, buffer: &Self::BufferId, @@ -369,7 +372,7 @@ trait Context: Debug + Send + Sized + Sync { fn adapter_drop(&self, adapter: &Self::AdapterId); fn buffer_destroy(&self, buffer: &Self::BufferId); fn buffer_drop(&self, buffer: &Self::BufferId); - fn texture_destroy(&self, buffer: &Self::TextureId); + fn texture_destroy(&self, texture: &Self::TextureId); fn texture_drop(&self, texture: &Self::TextureId); fn texture_view_drop(&self, texture_view: &Self::TextureViewId); fn sampler_drop(&self, sampler: &Self::SamplerId); @@ -505,13 +508,13 @@ trait Context: Debug + Send + Sized + Sync { &self, queue: &Self::QueueId, size: BufferSize, - ) -> QueueWriteBuffer; + ) -> Box; fn queue_write_staging_buffer( &self, queue: &Self::QueueId, buffer: &Self::BufferId, offset: BufferAddress, - staging_buffer: &QueueWriteBuffer, + staging_buffer: &dyn context::QueueWriteBuffer, ); fn queue_write_texture( &self, @@ -541,6 +544,8 @@ trait Context: Debug + Send + Sized + Sync { fn device_stop_capture(&self, device: &Self::DeviceId); } +type C = dyn DynContext; + /// Context for all other wgpu objects. Instance of wgpu. /// /// This is the first thing you create when using wgpu. @@ -566,7 +571,7 @@ static_assertions::assert_impl_all!(Instance: Send, Sync); #[derive(Debug)] pub struct Adapter { context: Arc, - id: ::AdapterId, + id: IdSendSync, } static_assertions::assert_impl_all!(Adapter: Send, Sync); @@ -589,15 +594,15 @@ impl Drop for Adapter { #[derive(Debug)] pub struct Device { context: Arc, - id: ::DeviceId, + id: IdSendSync, } static_assertions::assert_impl_all!(Device: Send, Sync); /// Identifier for a particular call to [`Queue::submit`]. Can be used /// as part of an argument to [`Device::poll`] to block for a particular /// submission to finish. -#[derive(Debug, Copy, Clone)] -pub struct SubmissionIndex(::SubmissionIndex); +#[derive(Debug, Clone)] +pub struct SubmissionIndex(Arc); static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync); /// The main purpose of this struct is to resolve mapped ranges (convert sizes @@ -668,7 +673,7 @@ impl MapContext { #[derive(Debug)] pub struct Buffer { context: Arc, - id: ::BufferId, + id: IdSendSync, map_context: Mutex, size: wgt::BufferAddress, usage: BufferUsages, @@ -696,7 +701,7 @@ static_assertions::assert_impl_all!(BufferSlice: Send, Sync); #[derive(Debug)] pub struct Texture { context: Arc, - id: ::TextureId, + id: IdSendSync, owned: bool, } static_assertions::assert_impl_all!(Texture: Send, Sync); @@ -710,7 +715,7 @@ static_assertions::assert_impl_all!(Texture: Send, Sync); #[derive(Debug)] pub struct TextureView { context: Arc, - id: ::TextureViewId, + id: IdSendSync, } static_assertions::assert_impl_all!(TextureView: Send, Sync); @@ -726,7 +731,7 @@ static_assertions::assert_impl_all!(TextureView: Send, Sync); #[derive(Debug)] pub struct Sampler { context: Arc, - id: ::SamplerId, + id: IdSendSync, } static_assertions::assert_impl_all!(Sampler: Send, Sync); @@ -745,7 +750,7 @@ impl Drop for Sampler { #[derive(Debug)] pub struct Surface { context: Arc, - id: ::SurfaceId, + id: IdSendSync, } static_assertions::assert_impl_all!(Surface: Send, Sync); @@ -771,7 +776,7 @@ impl Drop for Surface { #[derive(Debug)] pub struct BindGroupLayout { context: Arc, - id: ::BindGroupLayoutId, + id: IdSendSync, } static_assertions::assert_impl_all!(BindGroupLayout: Send, Sync); @@ -794,7 +799,7 @@ impl Drop for BindGroupLayout { #[derive(Debug)] pub struct BindGroup { context: Arc, - id: ::BindGroupId, + id: IdSendSync, } static_assertions::assert_impl_all!(BindGroup: Send, Sync); @@ -817,7 +822,7 @@ impl Drop for BindGroup { #[derive(Debug)] pub struct ShaderModule { context: Arc, - id: ::ShaderModuleId, + id: IdSendSync, } static_assertions::assert_impl_all!(ShaderModule: Send, Sync); @@ -896,7 +901,7 @@ static_assertions::assert_impl_all!(ShaderModuleDescriptorSpirV: Send, Sync); #[derive(Debug)] pub struct PipelineLayout { context: Arc, - id: ::PipelineLayoutId, + id: IdSendSync, } static_assertions::assert_impl_all!(PipelineLayout: Send, Sync); @@ -917,7 +922,7 @@ impl Drop for PipelineLayout { #[derive(Debug)] pub struct RenderPipeline { context: Arc, - id: ::RenderPipelineId, + id: IdSendSync, } static_assertions::assert_impl_all!(RenderPipeline: Send, Sync); @@ -951,7 +956,7 @@ impl RenderPipeline { #[derive(Debug)] pub struct ComputePipeline { context: Arc, - id: ::ComputePipelineId, + id: IdSendSync, } static_assertions::assert_impl_all!(ComputePipeline: Send, Sync); @@ -986,7 +991,7 @@ impl ComputePipeline { #[derive(Debug)] pub struct CommandBuffer { context: Arc, - id: Option<::CommandBufferId>, + id: Option, } static_assertions::assert_impl_all!(CommandBuffer: Send, Sync); @@ -1012,7 +1017,7 @@ impl Drop for CommandBuffer { #[derive(Debug)] pub struct CommandEncoder { context: Arc, - id: Option<::CommandEncoderId>, + id: Option, } static_assertions::assert_impl_all!(CommandEncoder: Send, Sync); @@ -1034,7 +1039,7 @@ impl Drop for CommandEncoder { /// https://gpuweb.github.io/gpuweb/#render-pass-encoder). #[derive(Debug)] pub struct RenderPass<'a> { - id: ::RenderPassId, + id: Id, parent: &'a mut CommandEncoder, } @@ -1046,7 +1051,7 @@ pub struct RenderPass<'a> { /// https://gpuweb.github.io/gpuweb/#compute-pass-encoder). #[derive(Debug)] pub struct ComputePass<'a> { - id: ::ComputePassId, + id: Id, parent: &'a mut CommandEncoder, } @@ -1064,8 +1069,8 @@ pub struct ComputePass<'a> { #[derive(Debug)] pub struct RenderBundleEncoder<'a> { context: Arc, - id: ::RenderBundleEncoderId, - _parent: &'a Device, + id: Id, + parent: &'a Device, /// This type should be !Send !Sync, because it represents an allocation on this thread's /// command buffer. _p: PhantomData<*const u8>, @@ -1084,7 +1089,7 @@ static_assertions::assert_not_impl_any!(RenderBundleEncoder<'_>: Send, Sync); #[derive(Debug)] pub struct RenderBundle { context: Arc, - id: ::RenderBundleId, + id: IdSendSync, } static_assertions::assert_impl_all!(RenderBundle: Send, Sync); @@ -1103,7 +1108,7 @@ impl Drop for RenderBundle { /// Corresponds to [WebGPU `GPUQuerySet`](https://gpuweb.github.io/gpuweb/#queryset). pub struct QuerySet { context: Arc, - id: ::QuerySetId, + id: IdSendSync, } static_assertions::assert_impl_all!(QuerySet: Send, Sync); @@ -1125,7 +1130,7 @@ impl Drop for QuerySet { #[derive(Debug)] pub struct Queue { context: Arc, - id: ::QueueId, + id: IdSendSync, } static_assertions::assert_impl_all!(Queue: Send, Sync); @@ -1674,7 +1679,7 @@ pub struct SurfaceTexture { /// but should be recreated for maximum performance. pub suboptimal: bool, presented: bool, - detail: ::SurfaceOutputDetail, + detail: Box, } static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync); @@ -1714,7 +1719,7 @@ impl Instance { /// during instantiation. pub fn new(backends: Backends) -> Self { Self { - context: Arc::new(C::init(backends)), + context: Arc::from(crate::backend::Context::init(backends)), } } @@ -1730,7 +1735,9 @@ impl Instance { #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn from_hal(hal_instance: A::Instance) -> Self { Self { - context: Arc::new(C::from_hal_instance::(hal_instance)), + context: Arc::new(crate::backend::Context::from_hal_instance::( + hal_instance, + )), } } @@ -1746,7 +1753,11 @@ impl Instance { /// [`Instance`]: hal::Api::Instance #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))] pub unsafe fn as_hal(&self) -> Option<&A::Instance> { - self.context.instance_as_hal::() + self.context + .as_any() + .downcast_ref::() + .unwrap() + .instance_as_hal::() } /// Create an new instance of wgpu from a wgpu-core instance. @@ -1761,7 +1772,7 @@ impl Instance { #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))] pub unsafe fn from_core(core_instance: wgc::instance::Instance) -> Self { Self { - context: Arc::new(C::from_core_instance(core_instance)), + context: Arc::new(crate::backend::Context::from_core_instance(core_instance)), } } @@ -1774,10 +1785,13 @@ impl Instance { pub fn enumerate_adapters(&self, backends: Backends) -> impl Iterator { let context = Arc::clone(&self.context); self.context + .as_any() + .downcast_ref::() + .unwrap() .enumerate_adapters(backends) .into_iter() .map(move |id| crate::Adapter { - id, + id: IdSendSync::upcast(id), context: Arc::clone(&context), }) } @@ -1807,7 +1821,13 @@ impl Instance { hal_adapter: hal::ExposedAdapter, ) -> Adapter { let context = Arc::clone(&self.context); - let id = context.create_adapter_from_hal(hal_adapter); + let id = IdSendSync::upcast( + context + .as_any() + .downcast_ref::() + .unwrap() + .create_adapter_from_hal(hal_adapter), + ); Adapter { context, id } } @@ -1826,7 +1846,7 @@ impl Instance { ) -> Surface { Surface { context: Arc::clone(&self.context), - id: Context::instance_create_surface( + id: DynContext::instance_create_surface( &*self.context, raw_window_handle::HasRawDisplayHandle::raw_display_handle(window), raw_window_handle::HasRawWindowHandle::raw_window_handle(window), @@ -1844,7 +1864,16 @@ impl Instance { &self, layer: *mut std::ffi::c_void, ) -> Surface { - self.context.create_surface_from_core_animation_layer(layer) + Surface { + context: Arc::clone(&self.context), + id: IdSendSync::upcast( + self.context + .as_any() + .downcast_ref::() + .unwrap() + .create_surface_from_core_animation_layer(layer), + ), + } } /// Creates a surface from `IDCompositionVisual`. @@ -1854,7 +1883,16 @@ impl Instance { /// - visual must be a valid IDCompositionVisual to create a surface upon. #[cfg(target_os = "windows")] pub unsafe fn create_surface_from_visual(&self, visual: *mut std::ffi::c_void) -> Surface { - self.context.create_surface_from_visual(visual) + Surface { + context: Arc::clone(&self.context), + id: IdSendSync::upcast( + self.context + .as_any() + .downcast_ref::() + .unwrap() + .create_surface_from_visual(visual), + ), + } } /// Creates a surface from a `web_sys::HtmlCanvasElement`. @@ -1865,7 +1903,13 @@ impl Instance { pub fn create_surface_from_canvas(&self, canvas: &web_sys::HtmlCanvasElement) -> Surface { Surface { context: Arc::clone(&self.context), - id: self.context.instance_create_surface_from_canvas(canvas), + id: IdSendSync::upcast( + self.context + .as_any() + .downcast_ref::() + .unwrap() + .instance_create_surface_from_canvas(canvas), + ), } } @@ -1880,9 +1924,13 @@ impl Instance { ) -> Surface { Surface { context: Arc::clone(&self.context), - id: self - .context - .instance_create_surface_from_offscreen_canvas(canvas), + id: IdSendSync::upcast( + self.context + .as_any() + .downcast_ref::() + .unwrap() + .instance_create_surface_from_offscreen_canvas(canvas), + ), } } @@ -1909,7 +1957,11 @@ impl Instance { /// Generates memory report. #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub fn generate_report(&self) -> wgc::hub::GlobalReport { - self.context.generate_report() + self.context + .as_any() + .downcast_ref::() + .unwrap() + .generate_report() } } @@ -1936,7 +1988,7 @@ impl Adapter { trace_path: Option<&std::path::Path>, ) -> impl Future> + Send { let context = Arc::clone(&self.context); - let device = Context::adapter_request_device(&*self.context, &self.id, desc, trace_path); + let device = DynContext::adapter_request_device(&*self.context, &self.id, desc, trace_path); async move { device.await.map(|(device_id, queue_id)| { ( @@ -1968,16 +2020,19 @@ impl Adapter { ) -> Result<(Device, Queue), RequestDeviceError> { let context = Arc::clone(&self.context); self.context - .create_device_from_hal(&self.id, hal_device, desc, trace_path) + .as_any() + .downcast_ref::() + .unwrap() + .create_device_from_hal(self.id.downcast_id(), hal_device, desc, trace_path) .map(|(device_id, queue_id)| { ( Device { context: Arc::clone(&context), - id: device_id, + id: IdSendSync::upcast(device_id), }, Queue { context, - id: queue_id, + id: IdSendSync::upcast(queue_id), }, ) }) @@ -2008,12 +2063,15 @@ impl Adapter { hal_adapter_callback: F, ) -> R { self.context - .adapter_as_hal::(self.id, hal_adapter_callback) + .as_any() + .downcast_ref::() + .unwrap() + .adapter_as_hal::(*self.id.downcast_id(), hal_adapter_callback) } /// Returns whether this adapter may present to the passed surface. pub fn is_surface_supported(&self, surface: &Surface) -> bool { - Context::adapter_is_surface_supported(&*self.context, &self.id, &surface.id) + DynContext::adapter_is_surface_supported(&*self.context, &self.id, &surface.id) } /// List all features that are supported with this adapter. @@ -2021,7 +2079,7 @@ impl Adapter { /// Features must be explicitly requested in [`Adapter::request_device`] in order /// to use them. pub fn features(&self) -> Features { - Context::adapter_features(&*self.context, &self.id) + DynContext::adapter_features(&*self.context, &self.id) } /// List the "best" limits that are supported by this adapter. @@ -2029,17 +2087,17 @@ impl Adapter { /// Limits must be explicitly requested in [`Adapter::request_device`] to set /// the values that you are allowed to use. pub fn limits(&self) -> Limits { - Context::adapter_limits(&*self.context, &self.id) + DynContext::adapter_limits(&*self.context, &self.id) } /// Get info about the adapter itself. pub fn get_info(&self) -> AdapterInfo { - Context::adapter_get_info(&*self.context, &self.id) + DynContext::adapter_get_info(&*self.context, &self.id) } /// Get info about the adapter itself. pub fn get_downlevel_capabilities(&self) -> DownlevelCapabilities { - Context::adapter_downlevel_capabilities(&*self.context, &self.id) + DynContext::adapter_downlevel_capabilities(&*self.context, &self.id) } /// Returns the features supported for a given texture format by this adapter. @@ -2047,7 +2105,7 @@ impl Adapter { /// Note that the WebGPU spec further restricts the available usages/features. /// To disable these restrictions on a device, request the [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] feature. pub fn get_texture_format_features(&self, format: TextureFormat) -> TextureFormatFeatures { - Context::adapter_get_texture_format_features(&*self.context, &self.id, format) + DynContext::adapter_get_texture_format_features(&*self.context, &self.id, format) } } @@ -2062,28 +2120,28 @@ impl Device { /// /// On the web, this is a no-op. `Device`s are automatically polled. pub fn poll(&self, maintain: Maintain) -> bool { - Context::device_poll(&*self.context, &self.id, maintain) + DynContext::device_poll(&*self.context, &self.id, maintain) } /// List all features that may be used with this device. /// /// Functions may panic if you use unsupported features. pub fn features(&self) -> Features { - Context::device_features(&*self.context, &self.id) + DynContext::device_features(&*self.context, &self.id) } /// List all limits that were requested of this device. /// /// If any of these limits are exceeded, functions may panic. pub fn limits(&self) -> Limits { - Context::device_limits(&*self.context, &self.id) + DynContext::device_limits(&*self.context, &self.id) } /// Creates a shader module from either SPIR-V or WGSL source code. pub fn create_shader_module(&self, desc: ShaderModuleDescriptor) -> ShaderModule { ShaderModule { context: Arc::clone(&self.context), - id: Context::device_create_shader_module( + id: DynContext::device_create_shader_module( &*self.context, &self.id, desc, @@ -2108,7 +2166,7 @@ impl Device { ) -> ShaderModule { ShaderModule { context: Arc::clone(&self.context), - id: Context::device_create_shader_module( + id: DynContext::device_create_shader_module( &*self.context, &self.id, desc, @@ -2131,7 +2189,7 @@ impl Device { ) -> ShaderModule { ShaderModule { context: Arc::clone(&self.context), - id: Context::device_create_shader_module_spirv(&*self.context, &self.id, desc), + id: DynContext::device_create_shader_module_spirv(&*self.context, &self.id, desc), } } @@ -2139,7 +2197,7 @@ impl Device { pub fn create_command_encoder(&self, desc: &CommandEncoderDescriptor) -> CommandEncoder { CommandEncoder { context: Arc::clone(&self.context), - id: Some(Context::device_create_command_encoder( + id: Some(DynContext::device_create_command_encoder( &*self.context, &self.id, desc, @@ -2154,8 +2212,8 @@ impl Device { ) -> RenderBundleEncoder { RenderBundleEncoder { context: Arc::clone(&self.context), - id: Context::device_create_render_bundle_encoder(&*self.context, &self.id, desc), - _parent: self, + id: DynContext::device_create_render_bundle_encoder(&*self.context, &self.id, desc), + parent: self, _p: Default::default(), } } @@ -2164,7 +2222,7 @@ impl Device { pub fn create_bind_group(&self, desc: &BindGroupDescriptor) -> BindGroup { BindGroup { context: Arc::clone(&self.context), - id: Context::device_create_bind_group(&*self.context, &self.id, desc), + id: DynContext::device_create_bind_group(&*self.context, &self.id, desc), } } @@ -2172,7 +2230,7 @@ impl Device { pub fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> BindGroupLayout { BindGroupLayout { context: Arc::clone(&self.context), - id: Context::device_create_bind_group_layout(&*self.context, &self.id, desc), + id: DynContext::device_create_bind_group_layout(&*self.context, &self.id, desc), } } @@ -2180,7 +2238,7 @@ impl Device { pub fn create_pipeline_layout(&self, desc: &PipelineLayoutDescriptor) -> PipelineLayout { PipelineLayout { context: Arc::clone(&self.context), - id: Context::device_create_pipeline_layout(&*self.context, &self.id, desc), + id: DynContext::device_create_pipeline_layout(&*self.context, &self.id, desc), } } @@ -2188,7 +2246,7 @@ impl Device { pub fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> RenderPipeline { RenderPipeline { context: Arc::clone(&self.context), - id: Context::device_create_render_pipeline(&*self.context, &self.id, desc), + id: DynContext::device_create_render_pipeline(&*self.context, &self.id, desc), } } @@ -2196,7 +2254,7 @@ impl Device { pub fn create_compute_pipeline(&self, desc: &ComputePipelineDescriptor) -> ComputePipeline { ComputePipeline { context: Arc::clone(&self.context), - id: Context::device_create_compute_pipeline(&*self.context, &self.id, desc), + id: DynContext::device_create_compute_pipeline(&*self.context, &self.id, desc), } } @@ -2208,7 +2266,7 @@ impl Device { } Buffer { context: Arc::clone(&self.context), - id: Context::device_create_buffer(&*self.context, &self.id, desc), + id: DynContext::device_create_buffer(&*self.context, &self.id, desc), map_context: Mutex::new(map_context), size: desc.size, usage: desc.usage, @@ -2221,7 +2279,7 @@ impl Device { pub fn create_texture(&self, desc: &TextureDescriptor) -> Texture { Texture { context: Arc::clone(&self.context), - id: Context::device_create_texture(&*self.context, &self.id, desc), + id: DynContext::device_create_texture(&*self.context, &self.id, desc), owned: true, } } @@ -2241,9 +2299,13 @@ impl Device { ) -> Texture { Texture { context: Arc::clone(&self.context), - id: self - .context - .create_texture_from_hal::(hal_texture, &self.id, desc), + id: IdSendSync::upcast( + self.context + .as_any() + .downcast_ref::() + .unwrap() + .create_texture_from_hal::(hal_texture, self.id.downcast_id(), desc), + ), owned: true, } } @@ -2254,7 +2316,7 @@ impl Device { pub fn create_sampler(&self, desc: &SamplerDescriptor) -> Sampler { Sampler { context: Arc::clone(&self.context), - id: Context::device_create_sampler(&*self.context, &self.id, desc), + id: DynContext::device_create_sampler(&*self.context, &self.id, desc), } } @@ -2262,12 +2324,12 @@ impl Device { pub fn create_query_set(&self, desc: &QuerySetDescriptor) -> QuerySet { QuerySet { context: Arc::clone(&self.context), - id: Context::device_create_query_set(&*self.context, &self.id, desc), + id: DynContext::device_create_query_set(&*self.context, &self.id, desc), } } /// Set a callback for errors that are not handled in error scopes. - pub fn on_uncaptured_error(&self, handler: impl UncapturedErrorHandler) { + pub fn on_uncaptured_error(&self, handler: Box) { self.context.device_on_uncaptured_error(&self.id, handler); } @@ -2283,12 +2345,12 @@ impl Device { /// Starts frame capture. pub fn start_capture(&self) { - Context::device_start_capture(&*self.context, &self.id) + DynContext::device_start_capture(&*self.context, &self.id) } /// Stops frame capture. pub fn stop_capture(&self) { - Context::device_stop_capture(&*self.context, &self.id) + DynContext::device_stop_capture(&*self.context, &self.id) } /// Apply a callback to this `Device`'s underlying backend device. @@ -2316,7 +2378,10 @@ impl Device { hal_device_callback: F, ) -> R { self.context - .device_as_hal::(&self.id, hal_device_callback) + .as_any() + .downcast_ref::() + .unwrap() + .device_as_hal::(self.id.downcast_id(), hal_device_callback) } } @@ -2517,12 +2582,12 @@ impl Buffer { /// Flushes any pending write operations and unmaps the buffer from host memory. pub fn unmap(&self) { self.map_context.lock().reset(); - Context::buffer_unmap(&*self.context, &self.id); + DynContext::buffer_unmap(&*self.context, &self.id); } /// Destroy the associated native resources as soon as possible. pub fn destroy(&self) { - Context::buffer_destroy(&*self.context, &self.id); + DynContext::buffer_destroy(&*self.context, &self.id); } /// Returns the length of the buffer allocation in bytes. @@ -2568,12 +2633,12 @@ impl<'a> BufferSlice<'a> { }; mc.initial_range = self.offset..end; - Context::buffer_map_async( + DynContext::buffer_map_async( &*self.buffer.context, &self.buffer.id, mode, self.offset..end, - callback, + Box::new(callback), ) } @@ -2581,7 +2646,7 @@ impl<'a> BufferSlice<'a> { /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic. pub fn get_mapped_range(&self) -> BufferView<'a> { let end = self.buffer.map_context.lock().add(self.offset, self.size); - let data = Context::buffer_get_mapped_range( + let data = DynContext::buffer_get_mapped_range( &*self.buffer.context, &self.buffer.id, self.offset..end, @@ -2593,7 +2658,7 @@ impl<'a> BufferSlice<'a> { /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic. pub fn get_mapped_range_mut(&self) -> BufferViewMut<'a> { let end = self.buffer.map_context.lock().add(self.offset, self.size); - let data = Context::buffer_get_mapped_range( + let data = DynContext::buffer_get_mapped_range( &*self.buffer.context, &self.buffer.id, self.offset..end, @@ -2627,20 +2692,23 @@ impl Texture { hal_texture_callback: F, ) { self.context - .texture_as_hal::(&self.id, hal_texture_callback) + .as_any() + .downcast_ref::() + .unwrap() + .texture_as_hal::(self.id.downcast_id(), hal_texture_callback) } /// Creates a view of this texture. pub fn create_view(&self, desc: &TextureViewDescriptor) -> TextureView { TextureView { context: Arc::clone(&self.context), - id: Context::texture_create_view(&*self.context, &self.id, desc), + id: DynContext::texture_create_view(&*self.context, &self.id, desc), } } /// Destroy the associated native resources as soon as possible. pub fn destroy(&self) { - Context::texture_destroy(&*self.context, &self.id); + DynContext::texture_destroy(&*self.context, &self.id); } /// Make an `ImageCopyTexture` representing the whole texture. @@ -2675,7 +2743,7 @@ impl CommandEncoder { pub fn finish(mut self) -> CommandBuffer { CommandBuffer { context: Arc::clone(&self.context), - id: Some(Context::command_encoder_finish( + id: Some(DynContext::command_encoder_finish( &*self.context, self.id.take().unwrap(), )), @@ -2691,7 +2759,7 @@ impl CommandEncoder { ) -> RenderPass<'pass> { let id = self.id.as_ref().unwrap(); RenderPass { - id: Context::command_encoder_begin_render_pass(&*self.context, id, desc), + id: DynContext::command_encoder_begin_render_pass(&*self.context, id, desc), parent: self, } } @@ -2702,7 +2770,7 @@ impl CommandEncoder { pub fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor) -> ComputePass { let id = self.id.as_ref().unwrap(); ComputePass { - id: Context::command_encoder_begin_compute_pass(&*self.context, id, desc), + id: DynContext::command_encoder_begin_compute_pass(&*self.context, id, desc), parent: self, } } @@ -2722,7 +2790,7 @@ impl CommandEncoder { destination_offset: BufferAddress, copy_size: BufferAddress, ) { - Context::command_encoder_copy_buffer_to_buffer( + DynContext::command_encoder_copy_buffer_to_buffer( &*self.context, self.id.as_ref().unwrap(), &source.id, @@ -2746,7 +2814,7 @@ impl CommandEncoder { destination: ImageCopyTexture, copy_size: Extent3d, ) { - Context::command_encoder_copy_buffer_to_texture( + DynContext::command_encoder_copy_buffer_to_texture( &*self.context, self.id.as_ref().unwrap(), source, @@ -2768,7 +2836,7 @@ impl CommandEncoder { destination: ImageCopyBuffer, copy_size: Extent3d, ) { - Context::command_encoder_copy_texture_to_buffer( + DynContext::command_encoder_copy_texture_to_buffer( &*self.context, self.id.as_ref().unwrap(), source, @@ -2790,7 +2858,7 @@ impl CommandEncoder { destination: ImageCopyTexture, copy_size: Extent3d, ) { - Context::command_encoder_copy_texture_to_texture( + DynContext::command_encoder_copy_texture_to_texture( &*self.context, self.id.as_ref().unwrap(), source, @@ -2813,7 +2881,7 @@ impl CommandEncoder { /// - `CLEAR_TEXTURE` extension not enabled /// - Range is out of bounds pub fn clear_texture(&mut self, texture: &Texture, subresource_range: &ImageSubresourceRange) { - Context::command_encoder_clear_texture( + DynContext::command_encoder_clear_texture( &*self.context, self.id.as_ref().unwrap(), texture, @@ -2833,7 +2901,7 @@ impl CommandEncoder { offset: BufferAddress, size: Option, ) { - Context::command_encoder_clear_buffer( + DynContext::command_encoder_clear_buffer( &*self.context, self.id.as_ref().unwrap(), buffer, @@ -2845,19 +2913,19 @@ impl CommandEncoder { /// Inserts debug marker. pub fn insert_debug_marker(&mut self, label: &str) { let id = self.id.as_ref().unwrap(); - Context::command_encoder_insert_debug_marker(&*self.context, id, label); + DynContext::command_encoder_insert_debug_marker(&*self.context, id, label); } /// Start record commands and group it into debug marker group. pub fn push_debug_group(&mut self, label: &str) { let id = self.id.as_ref().unwrap(); - Context::command_encoder_push_debug_group(&*self.context, id, label); + DynContext::command_encoder_push_debug_group(&*self.context, id, label); } /// Stops command recording and creates debug group. pub fn pop_debug_group(&mut self) { let id = self.id.as_ref().unwrap(); - Context::command_encoder_pop_debug_group(&*self.context, id); + DynContext::command_encoder_pop_debug_group(&*self.context, id); } } @@ -2871,7 +2939,7 @@ impl CommandEncoder { /// but timestamps can be subtracted to get the time it takes /// for a string of operations to complete. pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) { - Context::command_encoder_write_timestamp( + DynContext::command_encoder_write_timestamp( &*self.context, self.id.as_ref().unwrap(), &query_set.id, @@ -2892,7 +2960,7 @@ impl CommandEncoder { destination: &Buffer, destination_offset: BufferAddress, ) { - Context::command_encoder_resolve_query_set( + DynContext::command_encoder_resolve_query_set( &*self.context, self.id.as_ref().unwrap(), &query_set.id, @@ -2917,21 +2985,27 @@ impl<'a> RenderPass<'a> { bind_group: &'a BindGroup, offsets: &[DynamicOffset], ) { - RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets) + DynContext::render_pass_set_bind_group( + &*self.parent.context, + &mut self.id, + index, + &bind_group.id, + offsets, + ) } /// Sets the active render pipeline. /// /// Subsequent draw calls will exhibit the behavior defined by `pipeline`. pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - RenderInner::set_pipeline(&mut self.id, &pipeline.id) + DynContext::render_pass_set_pipeline(&*self.parent.context, &mut self.id, &pipeline.id) } /// Sets the blend color as used by some of the blending modes. /// /// Subsequent blending tests will test against this value. pub fn set_blend_constant(&mut self, color: Color) { - self.id.set_blend_constant(color) + DynContext::render_pass_set_blend_constant(&*self.parent.context, &mut self.id, color) } /// Sets the active index buffer. @@ -2939,7 +3013,8 @@ impl<'a> RenderPass<'a> { /// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will /// use `buffer` as the source index buffer. pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - RenderInner::set_index_buffer( + DynContext::render_pass_set_index_buffer( + &*self.parent.context, &mut self.id, &buffer_slice.buffer.id, index_format, @@ -2959,7 +3034,8 @@ impl<'a> RenderPass<'a> { /// [`draw`]: RenderPass::draw /// [`draw_indexed`]: RenderPass::draw_indexed pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - RenderInner::set_vertex_buffer( + DynContext::render_pass_set_vertex_buffer( + &*self.parent.context, &mut self.id, slot, &buffer_slice.buffer.id, @@ -2972,43 +3048,63 @@ impl<'a> RenderPass<'a> { /// /// Subsequent draw calls will discard any fragments that fall outside this region. pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) { - self.id.set_scissor_rect(x, y, width, height); + DynContext::render_pass_set_scissor_rect( + &*self.parent.context, + &mut self.id, + x, + y, + width, + height, + ); } /// Sets the viewport region. /// /// Subsequent draw calls will draw any fragments in this region. pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) { - self.id.set_viewport(x, y, w, h, min_depth, max_depth); + DynContext::render_pass_set_viewport( + &*self.parent.context, + &mut self.id, + x, + y, + w, + h, + min_depth, + max_depth, + ); } /// Sets the stencil reference. /// /// Subsequent stencil tests will test against this value. pub fn set_stencil_reference(&mut self, reference: u32) { - self.id.set_stencil_reference(reference); + DynContext::render_pass_set_stencil_reference( + &*self.parent.context, + &mut self.id, + reference, + ); } /// Draws primitives from the active vertex buffer(s). /// /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`]. pub fn draw(&mut self, vertices: Range, instances: Range) { - RenderInner::draw(&mut self.id, vertices, instances) + DynContext::render_pass_draw(&*self.parent.context, &mut self.id, vertices, instances) } /// Inserts debug marker. pub fn insert_debug_marker(&mut self, label: &str) { - self.id.insert_debug_marker(label); + DynContext::render_pass_insert_debug_marker(&*self.parent.context, &mut self.id, label); } /// Start record commands and group it into debug marker group. pub fn push_debug_group(&mut self, label: &str) { - self.id.push_debug_group(label); + DynContext::render_pass_push_debug_group(&*self.parent.context, &mut self.id, label); } /// Stops command recording and creates debug group. pub fn pop_debug_group(&mut self) { - self.id.pop_debug_group(); + DynContext::render_pass_pop_debug_group(&*self.parent.context, &mut self.id); } /// Draws indexed primitives using the active index buffer and the active vertex buffers. @@ -3016,7 +3112,13 @@ impl<'a> RenderPass<'a> { /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`]. pub fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances); + DynContext::render_pass_draw_indexed( + &*self.parent.context, + &mut self.id, + indices, + base_vertex, + instances, + ); } /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. @@ -3025,7 +3127,12 @@ impl<'a> RenderPass<'a> { /// /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect). pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - self.id.draw_indirect(&indirect_buffer.id, indirect_offset); + DynContext::render_pass_draw_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + ); } /// Draws indexed primitives using the active index buffer and the active vertex buffers, @@ -3040,15 +3147,25 @@ impl<'a> RenderPass<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - self.id - .draw_indexed_indirect(&indirect_buffer.id, indirect_offset); + DynContext::render_pass_draw_indexed_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + ); } /// Execute a [render bundle][RenderBundle], which is a set of pre-recorded commands /// that can be run together. - pub fn execute_bundles>(&mut self, render_bundles: I) { - self.id - .execute_bundles(render_bundles.into_iter().map(|rb| &rb.id)) + pub fn execute_bundles + 'a>( + &mut self, + render_bundles: I, + ) { + DynContext::render_pass_execute_bundles( + &*self.parent.context, + &mut self.id, + Box::new(render_bundles.into_iter().map(|rb| &rb.id)), + ) } } @@ -3068,8 +3185,13 @@ impl<'a> RenderPass<'a> { indirect_offset: BufferAddress, count: u32, ) { - self.id - .multi_draw_indirect(&indirect_buffer.id, indirect_offset, count); + DynContext::render_pass_multi_draw_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + count, + ); } /// Dispatches multiple draw calls from the active index buffer and the active vertex buffers, @@ -3087,8 +3209,13 @@ impl<'a> RenderPass<'a> { indirect_offset: BufferAddress, count: u32, ) { - self.id - .multi_draw_indexed_indirect(&indirect_buffer.id, indirect_offset, count); + DynContext::render_pass_multi_draw_indexed_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + count, + ); } } @@ -3122,7 +3249,9 @@ impl<'a> RenderPass<'a> { count_offset: BufferAddress, max_count: u32, ) { - self.id.multi_draw_indirect_count( + DynContext::render_pass_multi_draw_indirect_count( + &*self.parent.context, + &mut self.id, &indirect_buffer.id, indirect_offset, &count_buffer.id, @@ -3161,7 +3290,9 @@ impl<'a> RenderPass<'a> { count_offset: BufferAddress, max_count: u32, ) { - self.id.multi_draw_indexed_indirect_count( + DynContext::render_pass_multi_draw_indexed_indirect_count( + &*self.parent.context, + &mut self.id, &indirect_buffer.id, indirect_offset, &count_buffer.id, @@ -3214,7 +3345,13 @@ impl<'a> RenderPass<'a> { /// /// [`PushConstant`]: https://docs.rs/naga/latest/naga/enum.StorageClass.html#variant.PushConstant pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) { - self.id.set_push_constants(stages, offset, data); + DynContext::render_pass_set_push_constants( + &*self.parent.context, + &mut self.id, + stages, + offset, + data, + ); } } @@ -3228,7 +3365,12 @@ impl<'a> RenderPass<'a> { /// but timestamps can be subtracted to get the time it takes /// for a string of operations to complete. pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) { - self.id.write_timestamp(&query_set.id, query_index) + DynContext::render_pass_write_timestamp( + &*self.parent.context, + &mut self.id, + &query_set.id, + query_index, + ) } } @@ -3237,14 +3379,18 @@ impl<'a> RenderPass<'a> { /// Start a pipeline statistics query on this render pass. It can be ended with /// `end_pipeline_statistics_query`. Pipeline statistics queries may not be nested. pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) { - self.id - .begin_pipeline_statistics_query(&query_set.id, query_index); + DynContext::render_pass_begin_pipeline_statistics_query( + &*self.parent.context, + &mut self.id, + &query_set.id, + query_index, + ); } /// End the pipeline statistics query on this render pass. It can be started with /// `begin_pipeline_statistics_query`. Pipeline statistics queries may not be nested. pub fn end_pipeline_statistics_query(&mut self) { - self.id.end_pipeline_statistics_query(); + DynContext::render_pass_end_pipeline_statistics_query(&*self.parent.context, &mut self.id); } } @@ -3272,34 +3418,40 @@ impl<'a> ComputePass<'a> { bind_group: &'a BindGroup, offsets: &[DynamicOffset], ) { - ComputePassInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets); + DynContext::compute_pass_set_bind_group( + &*self.parent.context, + &mut self.id, + index, + &bind_group.id, + offsets, + ); } /// Sets the active compute pipeline. pub fn set_pipeline(&mut self, pipeline: &'a ComputePipeline) { - ComputePassInner::set_pipeline(&mut self.id, &pipeline.id); + DynContext::compute_pass_set_pipeline(&*self.parent.context, &mut self.id, &pipeline.id); } /// Inserts debug marker. pub fn insert_debug_marker(&mut self, label: &str) { - self.id.insert_debug_marker(label); + DynContext::compute_pass_insert_debug_marker(&*self.parent.context, &mut self.id, label); } /// Start record commands and group it into debug marker group. pub fn push_debug_group(&mut self, label: &str) { - self.id.push_debug_group(label); + DynContext::compute_pass_push_debug_group(&*self.parent.context, &mut self.id, label); } /// Stops command recording and creates debug group. pub fn pop_debug_group(&mut self) { - self.id.pop_debug_group(); + DynContext::compute_pass_pop_debug_group(&*self.parent.context, &mut self.id); } /// Dispatches compute work operations. /// /// `x`, `y` and `z` denote the number of work groups to dispatch in each dimension. pub fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) { - ComputePassInner::dispatch_workgroups(&mut self.id, x, y, z); + DynContext::compute_pass_dispatch_workgroups(&*self.parent.context, &mut self.id, x, y, z); } /// Dispatches compute work operations, based on the contents of the `indirect_buffer`. @@ -3310,7 +3462,8 @@ impl<'a> ComputePass<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - ComputePassInner::dispatch_workgroups_indirect( + DynContext::compute_pass_dispatch_workgroups_indirect( + &*self.parent.context, &mut self.id, &indirect_buffer.id, indirect_offset, @@ -3329,7 +3482,12 @@ impl<'a> ComputePass<'a> { /// For example, if `offset` is `4` and `data` is eight bytes long, this /// call will write `data` to bytes `4..12` of push constant storage. pub fn set_push_constants(&mut self, offset: u32, data: &[u8]) { - self.id.set_push_constants(offset, data); + DynContext::compute_pass_set_push_constants( + &*self.parent.context, + &mut self.id, + offset, + data, + ); } } @@ -3342,7 +3500,12 @@ impl<'a> ComputePass<'a> { /// but timestamps can be subtracted to get the time it takes /// for a string of operations to complete. pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) { - self.id.write_timestamp(&query_set.id, query_index) + DynContext::compute_pass_write_timestamp( + &*self.parent.context, + &mut self.id, + &query_set.id, + query_index, + ) } } @@ -3351,14 +3514,18 @@ impl<'a> ComputePass<'a> { /// Start a pipeline statistics query on this render pass. It can be ended with /// `end_pipeline_statistics_query`. Pipeline statistics queries may not be nested. pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) { - self.id - .begin_pipeline_statistics_query(&query_set.id, query_index); + DynContext::compute_pass_begin_pipeline_statistics_query( + &*self.parent.context, + &mut self.id, + &query_set.id, + query_index, + ); } /// End the pipeline statistics query on this render pass. It can be started with /// `begin_pipeline_statistics_query`. Pipeline statistics queries may not be nested. pub fn end_pipeline_statistics_query(&mut self) { - self.id.end_pipeline_statistics_query(); + DynContext::compute_pass_end_pipeline_statistics_query(&*self.parent.context, &mut self.id); } } @@ -3378,7 +3545,7 @@ impl<'a> RenderBundleEncoder<'a> { pub fn finish(self, desc: &RenderBundleDescriptor) -> RenderBundle { RenderBundle { context: Arc::clone(&self.context), - id: Context::render_bundle_encoder_finish(&*self.context, self.id, desc), + id: DynContext::render_bundle_encoder_finish(&*self.context, self.id, desc), } } @@ -3392,14 +3559,24 @@ impl<'a> RenderBundleEncoder<'a> { bind_group: &'a BindGroup, offsets: &[DynamicOffset], ) { - RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets) + DynContext::render_bundle_encoder_set_bind_group( + &*self.parent.context, + &mut self.id, + index, + &bind_group.id, + offsets, + ) } /// Sets the active render pipeline. /// /// Subsequent draw calls will exhibit the behavior defined by `pipeline`. pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - RenderInner::set_pipeline(&mut self.id, &pipeline.id) + DynContext::render_bundle_encoder_set_pipeline( + &*self.parent.context, + &mut self.id, + &pipeline.id, + ) } /// Sets the active index buffer. @@ -3407,7 +3584,8 @@ impl<'a> RenderBundleEncoder<'a> { /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will /// use `buffer` as the source index buffer. pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - RenderInner::set_index_buffer( + DynContext::render_bundle_encoder_set_index_buffer( + &*self.parent.context, &mut self.id, &buffer_slice.buffer.id, index_format, @@ -3427,7 +3605,8 @@ impl<'a> RenderBundleEncoder<'a> { /// [`draw`]: RenderBundleEncoder::draw /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - RenderInner::set_vertex_buffer( + DynContext::render_bundle_encoder_set_vertex_buffer( + &*self.parent.context, &mut self.id, slot, &buffer_slice.buffer.id, @@ -3440,7 +3619,12 @@ impl<'a> RenderBundleEncoder<'a> { /// /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. pub fn draw(&mut self, vertices: Range, instances: Range) { - RenderInner::draw(&mut self.id, vertices, instances) + DynContext::render_bundle_encoder_draw( + &*self.parent.context, + &mut self.id, + vertices, + instances, + ) } /// Draws indexed primitives using the active index buffer and the active vertex buffers. @@ -3448,7 +3632,13 @@ impl<'a> RenderBundleEncoder<'a> { /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. pub fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances); + DynContext::render_bundle_encoder_draw_indexed( + &*self.parent.context, + &mut self.id, + indices, + base_vertex, + instances, + ); } /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. @@ -3457,7 +3647,12 @@ impl<'a> RenderBundleEncoder<'a> { /// /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect). pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - self.id.draw_indirect(&indirect_buffer.id, indirect_offset); + DynContext::render_bundle_encoder_draw_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + ); } /// Draws indexed primitives using the active index buffer and the active vertex buffers, @@ -3472,8 +3667,12 @@ impl<'a> RenderBundleEncoder<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - self.id - .draw_indexed_indirect(&indirect_buffer.id, indirect_offset); + DynContext::render_bundle_encoder_draw_indexed_indirect( + &*self.parent.context, + &mut self.id, + &indirect_buffer.id, + indirect_offset, + ); } } @@ -3508,7 +3707,13 @@ impl<'a> RenderBundleEncoder<'a> { /// You would need to upload this in three set_push_constants calls. First for the `Vertex` only range 0..4, second /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12. pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) { - self.id.set_push_constants(stages, offset, data); + DynContext::render_bundle_encoder_set_push_constants( + &*self.parent.context, + &mut self.id, + stages, + offset, + data, + ); } } @@ -3517,7 +3722,7 @@ pub struct QueueWriteBufferView<'a> { queue: &'a Queue, buffer: &'a Buffer, offset: BufferAddress, - inner: QueueWriteBuffer, + inner: Box, } static_assertions::assert_impl_all!(QueueWriteBufferView: Send, Sync); @@ -3531,18 +3736,18 @@ impl<'a> std::ops::Deref for QueueWriteBufferView<'a> { impl<'a> std::ops::DerefMut for QueueWriteBufferView<'a> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner + self.inner.slice_mut() } } impl<'a> Drop for QueueWriteBufferView<'a> { fn drop(&mut self) { - Context::queue_write_staging_buffer( + DynContext::queue_write_staging_buffer( &*self.queue.context, &self.queue.id, &self.buffer.id, self.offset, - &self.inner, + &*self.inner, ); } } @@ -3556,7 +3761,7 @@ impl Queue { /// /// This method fails if `data` overruns the size of `buffer` starting at `offset`. pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) { - Context::queue_write_buffer(&*self.context, &self.id, &buffer.id, offset, data) + DynContext::queue_write_buffer(&*self.context, &self.id, &buffer.id, offset, data) } /// Schedule a data write into `buffer` starting at `offset` via the returned @@ -3579,8 +3784,9 @@ impl Queue { offset: BufferAddress, size: BufferSize, ) -> QueueWriteBufferView<'a> { - Context::queue_validate_write_buffer(&*self.context, &self.id, &buffer.id, offset, size); - let staging_buffer = Context::queue_create_staging_buffer(&*self.context, &self.id, size); + DynContext::queue_validate_write_buffer(&*self.context, &self.id, &buffer.id, offset, size); + let staging_buffer = + DynContext::queue_create_staging_buffer(&*self.context, &self.id, size); QueueWriteBufferView { queue: self, buffer, @@ -3603,7 +3809,7 @@ impl Queue { data_layout: ImageDataLayout, size: Extent3d, ) { - Context::queue_write_texture(&*self.context, &self.id, texture, data, data_layout, size) + DynContext::queue_write_texture(&*self.context, &self.id, texture, data, data_layout, size) } /// Submits a series of finished command buffers for execution. @@ -3611,22 +3817,24 @@ impl Queue { &self, command_buffers: I, ) -> SubmissionIndex { - let raw = Context::queue_submit( + let raw = DynContext::queue_submit( &*self.context, &self.id, - command_buffers - .into_iter() - .map(|mut comb| comb.id.take().unwrap()), + Box::new( + command_buffers + .into_iter() + .map(|mut comb| comb.id.take().unwrap()), + ), ); - SubmissionIndex(raw) + SubmissionIndex(Arc::new(raw)) } /// Gets the amount of nanoseconds each tick of a timestamp query represents. /// /// Returns zero if timestamp queries are unsupported. pub fn get_timestamp_period(&self) -> f32 { - Context::queue_get_timestamp_period(&*self.context, &self.id) + DynContext::queue_get_timestamp_period(&*self.context, &self.id) } /// Registers a callback when the previous call to submit finishes running on the gpu. This callback @@ -3641,7 +3849,7 @@ impl Queue { /// call to the function will not complete until the callback returns, so prefer keeping callbacks short /// and used to set flags, send messages, etc. pub fn on_submitted_work_done(&self, callback: impl FnOnce() + Send + 'static) { - Context::queue_on_submitted_work_done(&*self.context, &self.id, Box::new(callback)) + DynContext::queue_on_submitted_work_done(&*self.context, &self.id, Box::new(callback)) } } @@ -3651,14 +3859,14 @@ impl SurfaceTexture { /// Needs to be called after any work on the texture is scheduled via [`Queue::submit`]. pub fn present(mut self) { self.presented = true; - Context::surface_present(&*self.texture.context, &self.texture.id, &self.detail); + DynContext::surface_present(&*self.texture.context, &self.texture.id, &self.detail); } } impl Drop for SurfaceTexture { fn drop(&mut self) { if !self.presented && !thread::panicking() { - Context::surface_texture_discard( + DynContext::surface_texture_discard( &*self.texture.context, &self.texture.id, &self.detail, @@ -3673,21 +3881,21 @@ impl Surface { /// /// Returns an empty vector if the surface is incompatible with the adapter. pub fn get_supported_formats(&self, adapter: &Adapter) -> Vec { - Context::surface_get_supported_formats(&*self.context, &self.id, &adapter.id) + DynContext::surface_get_supported_formats(&*self.context, &self.id, &adapter.id) } /// Returns a vec of supported presentation modes to use for the [`Surface`] with this adapter. /// /// Returns an empty vector if the surface is incompatible with the adapter. pub fn get_supported_present_modes(&self, adapter: &Adapter) -> Vec { - Context::surface_get_supported_present_modes(&*self.context, &self.id, &adapter.id) + DynContext::surface_get_supported_present_modes(&*self.context, &self.id, &adapter.id) } /// Returns a vec of supported alpha modes to use for the [`Surface`] with this adapter. /// /// Will return at least one element, CompositeAlphaMode::Opaque or CompositeAlphaMode::Inherit. pub fn get_supported_alpha_modes(&self, adapter: &Adapter) -> Vec { - Context::surface_get_supported_alpha_modes(&*self.context, &self.id, &adapter.id) + DynContext::surface_get_supported_alpha_modes(&*self.context, &self.id, &adapter.id) } /// Initializes [`Surface`] for presentation. @@ -3697,7 +3905,7 @@ impl Surface { /// - A old [`SurfaceTexture`] is still alive referencing an old surface. /// - Texture format requested is unsupported on the surface. pub fn configure(&self, device: &Device, config: &SurfaceConfiguration) { - Context::surface_configure(&*self.context, &self.id, &device.id, config) + DynContext::surface_configure(&*self.context, &self.id, &device.id, config) } /// Returns the next texture to be presented by the swapchain for drawing. @@ -3710,7 +3918,7 @@ impl Surface { /// recreating the swapchain will panic. pub fn get_current_texture(&self) -> Result { let (texture_id, status, detail) = - Context::surface_get_current_texture(&*self.context, &self.id); + DynContext::surface_get_current_texture(&*self.context, &self.id); let suboptimal = match status { SurfaceStatus::Good => false, diff --git a/wgpu/src/util/mod.rs b/wgpu/src/util/mod.rs index 906c07233e..f24037e12d 100644 --- a/wgpu/src/util/mod.rs +++ b/wgpu/src/util/mod.rs @@ -108,7 +108,7 @@ impl DownloadBuffer { return; } - let mapped_range = super::Context::buffer_get_mapped_range( + let mapped_range = super::DynContext::buffer_get_mapped_range( &*download.context, &download.id, 0..size, diff --git a/wgpu/tests/poll.rs b/wgpu/tests/poll.rs index 6113436d0b..9b8f08ca27 100644 --- a/wgpu/tests/poll.rs +++ b/wgpu/tests/poll.rs @@ -89,7 +89,8 @@ fn double_wait_on_submission() { let cmd_buf = generate_dummy_work(&ctx); let index = ctx.queue.submit(Some(cmd_buf)); - ctx.device.poll(Maintain::WaitForSubmissionIndex(index)); + ctx.device + .poll(Maintain::WaitForSubmissionIndex(index.clone())); ctx.device.poll(Maintain::WaitForSubmissionIndex(index)); }) }