diff --git a/crates/wasi-webgpu-wasmtime/src/lib.rs b/crates/wasi-webgpu-wasmtime/src/lib.rs index 25f0e8c..b558070 100644 --- a/crates/wasi-webgpu-wasmtime/src/lib.rs +++ b/crates/wasi-webgpu-wasmtime/src/lib.rs @@ -4,22 +4,19 @@ // - Remove all unwraps. // - Implement all the drop handlers. -use callback_future::CallbackFuture; -use core::slice; -use futures::executor::block_on; -use std::borrow::Cow; -use std::collections::HashMap; -use std::ptr::NonNull; -use std::sync::Arc; -use std::{future::Future, mem}; -use wasmtime::component::Resource; +use std::{future::Future, sync::Arc}; + +use wasi_graphics_context_wasmtime::{AbstractBuffer, DisplayApi, DrawApi}; use wasmtime_wasi::WasiView; use wgpu_core::id::SurfaceId; -use crate::wasi::webgpu::webgpu; -use wasi_graphics_context_wasmtime::{AbstractBuffer, Context, DisplayApi, DrawApi}; +// ToCore trait used for resources, records, and variants. +// Into trait used for enums, since they never need table access. +mod enum_conversions; +mod to_core_conversions; -use self::to_core_conversions::ToCore; +mod trait_impls; +mod wrapper_types; /// Re-export of `wgpu_core` and `wgpu_types` so that runtime implementors don't need to keep track of what version of wgpu this crate is using. pub mod reexports { @@ -49,9 +46,6 @@ pub(crate) type Backend = wgpu_core::api::Gl; pub(crate) use wgpu_core; pub(crate) use wgpu_types; -pub type RenderPass = wgpu_core::command::RenderPass; -pub type ComputePass = wgpu_core::command::ComputePass; - wasmtime::component::bindgen!({ path: "../../wit/", world: "example", @@ -62,17 +56,17 @@ wasmtime::component::bindgen!({ }, with: { "wasi:webgpu/webgpu/gpu-adapter": wgpu_core::id::AdapterId, - "wasi:webgpu/webgpu/gpu-device": Device, + "wasi:webgpu/webgpu/gpu-device": wrapper_types::Device, "wasi:webgpu/webgpu/gpu-queue": wgpu_core::id::QueueId, "wasi:webgpu/webgpu/gpu-command-encoder": wgpu_core::id::CommandEncoderId, - "wasi:webgpu/webgpu/gpu-render-pass-encoder": RenderPass, - "wasi:webgpu/webgpu/gpu-compute-pass-encoder": ComputePass, + "wasi:webgpu/webgpu/gpu-render-pass-encoder": wrapper_types::RenderPass, + "wasi:webgpu/webgpu/gpu-compute-pass-encoder": wrapper_types::ComputePass, "wasi:webgpu/webgpu/gpu-shader-module": wgpu_core::id::ShaderModuleId, "wasi:webgpu/webgpu/gpu-render-pipeline": wgpu_core::id::RenderPipelineId, "wasi:webgpu/webgpu/gpu-render-bundle-encoder": wgpu_core::command::RenderBundleEncoder, "wasi:webgpu/webgpu/gpu-command-buffer": wgpu_core::id::CommandBufferId, - "wasi:webgpu/webgpu/gpu-buffer": Buffer, - "wasi:webgpu/webgpu/non-standard-buffer": BufferPtr, + "wasi:webgpu/webgpu/gpu-buffer": wrapper_types::Buffer, + "wasi:webgpu/webgpu/non-standard-buffer": wrapper_types::BufferPtr, "wasi:webgpu/webgpu/gpu-pipeline-layout": wgpu_core::id::PipelineLayoutId, "wasi:webgpu/webgpu/gpu-bind-group-layout": wgpu_core::id::BindGroupLayoutId, "wasi:webgpu/webgpu/gpu-sampler": wgpu_core::id::SamplerId, @@ -84,7 +78,7 @@ wasmtime::component::bindgen!({ "wasi:webgpu/webgpu/gpu-adapter-info": wgpu_types::AdapterInfo, "wasi:webgpu/webgpu/gpu-query-set": wgpu_core::id::QuerySetId, "wasi:webgpu/webgpu/gpu-supported-limits": wgpu_types::Limits, - "wasi:webgpu/webgpu/record-gpu-pipeline-constant-value": RecordGpuPipelineConstantValue, + "wasi:webgpu/webgpu/record-gpu-pipeline-constant-value": wrapper_types::RecordGpuPipelineConstantValue, "wasi:webgpu/graphics-context": wasi_graphics_context_wasmtime, }, }); @@ -151,7 +145,7 @@ pub trait MainThreadSpawner: Send + Sync + 'static { T: Send + Sync + 'static; } -pub struct WebGpuSurface +struct WebGpuSurface where I: AsRef, GI: Fn() -> I, @@ -218,2526 +212,3 @@ where self.surface_id = Some(surface_id); } } - -// ToCore trait used for resources, records, and variants. -// Into trait used for enums, since they never need table access. -mod enum_conversions; -mod to_core_conversions; - -pub struct BufferPtr { - // See https://bytecodealliance.zulipchat.com/#narrow/stream/206238-general/topic/Should.20wasi.20resources.20be.20stored.20behind.20a.20mutex.3F - pub(crate) ptr: NonNull, - pub(crate) len: u64, -} -impl BufferPtr { - pub fn slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) } - } - pub fn slice_mut(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) } - } -} -unsafe impl Send for BufferPtr {} -unsafe impl Sync for BufferPtr {} - -pub struct Buffer { - buffer: wgpu_core::id::BufferId, - size: u64, -} - -#[derive(Clone, Copy)] -pub struct Device { - pub device: wgpu_core::id::DeviceId, - pub queue: wgpu_core::id::QueueId, - // only needed when calling surface.get_capabilities in connect_graphics_context. If table would have a way to get parent from child, we could get it from device. - pub adapter: wgpu_core::id::AdapterId, -} - -pub type RecordGpuPipelineConstantValue = HashMap; - -impl webgpu::Host for WasiWebGpuImpl { - fn get_gpu(&mut self) -> Resource { - Resource::new_own(0) - } -} - -impl webgpu::HostGpuColorWrite for WasiWebGpuImpl { - fn red(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ColorWrites::RED.bits() - } - - fn green(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ColorWrites::GREEN.bits() - } - - fn blue(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ColorWrites::BLUE.bits() - } - - fn alpha(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ColorWrites::ALPHA.bits() - } - - fn all(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ColorWrites::ALL.bits() - } - - fn drop(&mut self, _self_: Resource) -> wasmtime::Result<()> { - todo!() - } -} - -impl webgpu::HostRecordGpuPipelineConstantValue for WasiWebGpuImpl { - fn new(&mut self) -> Resource { - todo!() - } - - fn add( - &mut self, - _record: Resource, - _key: String, - _value: webgpu::GpuPipelineConstantValue, - ) { - todo!() - } - - // fn get(&mut self, _record: Resource, _key: String) -> Option { - fn get( - &mut self, - _record: Resource, - _key: String, - ) -> webgpu::GpuPipelineConstantValue { - todo!() - } - - fn has( - &mut self, - _record: Resource, - _key: String, - ) -> bool { - todo!() - } - - fn remove(&mut self, _record: Resource, _key: String) { - todo!() - } - - fn keys(&mut self, _record: Resource) -> Vec { - todo!() - } - - fn values( - &mut self, - _record: Resource, - ) -> Vec { - todo!() - } - - // fn entries(&mut self, _record: Resource) -> Vec<(String, webgpu::GpuPipelineConstantValue)> { - fn entries( - &mut self, - _record: Resource, - ) -> (String, webgpu::GpuPipelineConstantValue) { - todo!() - } - - fn drop( - &mut self, - _self_: Resource, - ) -> wasmtime::Result<()> { - todo!() - } -} -impl webgpu::HostGpuShaderStage for WasiWebGpuImpl { - fn vertex(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ShaderStages::VERTEX.bits() - } - - fn fragment(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ShaderStages::FRAGMENT.bits() - } - - fn compute(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::ShaderStages::COMPUTE.bits() - } - - fn drop(&mut self, _: Resource) -> wasmtime::Result<()> { - todo!() - } -} -impl webgpu::HostGpuTextureUsage for WasiWebGpuImpl { - fn copy_src(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::TextureUsages::COPY_SRC.bits() - } - fn copy_dst(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::TextureUsages::COPY_DST.bits() - } - fn texture_binding(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::TextureUsages::TEXTURE_BINDING.bits() - } - fn storage_binding(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::TextureUsages::STORAGE_BINDING.bits() - } - fn render_attachment(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::TextureUsages::RENDER_ATTACHMENT.bits() - } - fn drop( - &mut self, - _rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - todo!() - } -} -impl webgpu::HostGpuMapMode for WasiWebGpuImpl { - fn read(&mut self) -> webgpu::GpuFlagsConstant { - // https://www.w3.org/TR/webgpu/#buffer-mapping - 0x0001 - } - fn write(&mut self) -> webgpu::GpuFlagsConstant { - // https://www.w3.org/TR/webgpu/#buffer-mapping - 0x0002 - } - fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { - todo!() - } -} -impl webgpu::HostGpuBufferUsage for WasiWebGpuImpl { - fn map_read(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::MAP_READ.bits() - } - fn map_write(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::MAP_WRITE.bits() - } - fn copy_src(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::COPY_SRC.bits() - } - fn copy_dst(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::COPY_DST.bits() - } - fn index(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::INDEX.bits() - } - fn vertex(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::VERTEX.bits() - } - fn uniform(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::UNIFORM.bits() - } - fn storage(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::STORAGE.bits() - } - fn indirect(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::INDIRECT.bits() - } - fn query_resolve(&mut self) -> webgpu::GpuFlagsConstant { - wgpu_types::BufferUsages::QUERY_RESOLVE.bits() - } - fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { - todo!() - } -} - -impl webgpu::HostRecordGpuSize64 for WasiWebGpuImpl { - fn new(&mut self) -> Resource { - todo!() - } - fn add( - &mut self, - _self_: Resource, - _key: String, - _value: webgpu::GpuSize64, - ) { - todo!() - } - fn get( - &mut self, - _self_: Resource, - _key: String, - ) -> webgpu::GpuSize64 { - todo!() - } - fn has(&mut self, _self_: Resource, _key: String) -> bool { - todo!() - } - fn remove(&mut self, _self_: Resource, _key: String) { - todo!() - } - fn keys(&mut self, _self_: Resource) -> Vec { - todo!() - } - fn values(&mut self, _self_: Resource) -> Vec { - todo!() - } - fn entries( - &mut self, - _self_: Resource, - ) -> (String, webgpu::GpuSize64) { - todo!() - } - fn drop( - &mut self, - _rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - todo!() - } -} - -impl webgpu::HostNonStandardBuffer for WasiWebGpuImpl { - fn get(&mut self, buffer: Resource) -> Vec { - let buffer = self.0.table().get_mut(&buffer).unwrap(); - buffer.slice_mut().to_vec() - } - - fn set(&mut self, buffer: Resource, val: Vec) { - let buffer = self.0.table().get_mut(&buffer).unwrap(); - buffer.slice_mut().copy_from_slice(&val); - } - - fn drop(&mut self, buffer: Resource) -> wasmtime::Result<()> { - self.table().delete(buffer).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuDevice for WasiWebGpuImpl { - fn connect_graphics_context(&mut self, device: Resource, context: Resource) { - let device = self.0.table().get(&device).unwrap(); - let device_id = device.device; - let adapter_id = device.adapter; - - let instance = Arc::downgrade(&self.0.instance()); - let surface_creator = self.0.ui_thread_spawner(); - - let context = self.0.table().get_mut(&context).unwrap(); - - let surface = WebGpuSurface { - get_instance: { - let instance = instance.clone(); - move || instance.upgrade().unwrap() - }, - create_surface: { - let instance = instance.clone(); - move |display: &(dyn DisplayApi + Send + Sync)| { - let instance = instance.upgrade().unwrap(); - - // TODO: make spawn behave similar to `std::thread::scope` so that we don't have to unsafely transmute display to `&'static`. - // Something like the following: - // ```rust - // let surface_id = std::thread::scope(|s| { - // s.spawn(move || unsafe { - // instance - // .instance_create_surface( - // display.display_handle().unwrap().as_raw(), - // display.window_handle().unwrap().as_raw(), - // None, - // ) - // .unwrap() - // }).join().unwrap() - // }); - // surface_id - // ``` - - let display: &'static (dyn DisplayApi + Send + Sync) = - unsafe { mem::transmute(display) }; - block_on(surface_creator.spawn(move || unsafe { - instance - .instance_create_surface( - display.display_handle().unwrap().as_raw(), - display.window_handle().unwrap().as_raw(), - None, - ) - .unwrap() - })) - } - }, - device_id, - adapter_id, - surface_id: None, - }; - - context.connect_draw_api(Box::new(surface)); - } - - fn configure( - &mut self, - _device: Resource, - _descriptor: webgpu::GpuDeviceConfiguration, - ) { - todo!() - } - - fn create_command_encoder( - &mut self, - device: Resource, - descriptor: Option, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let command_encoder = core_result( - self.0 - .instance() - .device_create_command_encoder::( - device, - &descriptor - .map(|d| d.to_core(&self.0.table())) - .unwrap_or_default(), - None, - ), - ) - .unwrap(); - - self.0.table().push(command_encoder).unwrap() - } - - fn create_shader_module( - &mut self, - device: Resource, - descriptor: webgpu::GpuShaderModuleDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let code = - wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::Owned(descriptor.code.to_owned())); - let shader = core_result( - self.0 - .instance() - .device_create_shader_module::( - device, - &descriptor.to_core(&self.0.table()), - code, - None, - ), - ) - .unwrap(); - - self.0.table().push(shader).unwrap() - } - - fn create_render_pipeline( - &mut self, - device: Resource, - descriptor: webgpu::GpuRenderPipelineDescriptor, - ) -> Resource { - let host_device = self.0.table().get(&device).unwrap().device; - let render_pipeline = core_result( - self.0 - .instance() - .device_create_render_pipeline::( - host_device, - &descriptor.to_core(&self.0.table()), - None, - None, - ), - ) - .unwrap(); - - self.0.table().push_child(render_pipeline, &device).unwrap() - } - - fn queue(&mut self, device: Resource) -> Resource { - let queue = self.0.table().get(&device).unwrap().queue; - self.0.table().push(queue).unwrap() - } - - fn features( - &mut self, - device: Resource, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let features = self - .0 - .instance() - .device_features::(device) - .unwrap(); - self.0.table().push(features).unwrap() - } - - fn limits( - &mut self, - device: Resource, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let limits = self - .0 - .instance() - .device_limits::(device) - .unwrap(); - self.0.table().push(limits).unwrap() - } - - fn destroy(&mut self, device: Resource) { - let device_id = self.0.table().get(&device).unwrap().device; - self.instance().device_destroy::(device_id); - } - - fn create_buffer( - &mut self, - device: Resource, - descriptor: webgpu::GpuBufferDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let size = descriptor.size; - let buffer = core_result(self.0.instance().device_create_buffer::( - device, - &descriptor.to_core(&self.0.table()), - None, - )) - .unwrap(); - - let buffer = Buffer { buffer, size }; - - self.0.table().push(buffer).unwrap() - } - - fn create_texture( - &mut self, - device: Resource, - descriptor: webgpu::GpuTextureDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let texture = core_result(self.0.instance().device_create_texture::( - device, - &descriptor.to_core(&self.0.table()), - None, - )) - .unwrap(); - - self.0.table().push(texture).unwrap() - } - - fn create_sampler( - &mut self, - device: Resource, - descriptor: Option, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let descriptor = descriptor.unwrap(); - - let sampler = core_result(self.0.instance().device_create_sampler::( - device, - &descriptor.to_core(&self.0.table()), - None, - )) - .unwrap(); - - self.0.table().push(sampler).unwrap() - } - - fn create_bind_group_layout( - &mut self, - device: Resource, - descriptor: webgpu::GpuBindGroupLayoutDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let bind_group_layout = core_result( - self.0 - .instance() - .device_create_bind_group_layout::( - device, - &descriptor.to_core(&self.0.table()), - None, - ), - ) - .unwrap(); - - self.0.table().push(bind_group_layout).unwrap() - } - - fn create_pipeline_layout( - &mut self, - device: Resource, - descriptor: webgpu::GpuPipelineLayoutDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let pipeline_layout = core_result( - self.0 - .instance() - .device_create_pipeline_layout::( - device, - &descriptor.to_core(&self.0.table()), - None, - ), - ) - .unwrap(); - - self.0.table().push(pipeline_layout).unwrap() - } - - fn create_bind_group( - &mut self, - device: Resource, - descriptor: webgpu::GpuBindGroupDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - - let bind_group = core_result( - self.0 - .instance() - .device_create_bind_group::( - device, - &descriptor.to_core(&self.0.table()), - None, - ), - ) - .unwrap(); - - self.0.table().push(bind_group).unwrap() - } - - fn create_compute_pipeline( - &mut self, - device: Resource, - descriptor: webgpu::GpuComputePipelineDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let compute_pipeline = core_result( - self.0 - .instance() - .device_create_compute_pipeline::( - device, - &descriptor.to_core(&self.0.table()), - None, - None, - ), - ) - .unwrap(); - self.0.table().push(compute_pipeline).unwrap() - } - - fn create_compute_pipeline_async( - &mut self, - _self_: Resource, - _descriptor: webgpu::GpuComputePipelineDescriptor, - ) -> Resource { - todo!() - } - - fn create_render_pipeline_async( - &mut self, - _self_: Resource, - _descriptor: webgpu::GpuRenderPipelineDescriptor, - ) -> Resource { - todo!() - } - - fn create_render_bundle_encoder( - &mut self, - device: Resource, - descriptor: webgpu::GpuRenderBundleEncoderDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let render_bundle_encoder = wgpu_core::command::RenderBundleEncoder::new( - &descriptor.to_core(&self.0.table()), - device, - None, - ) - .unwrap(); - self.0.table().push(render_bundle_encoder).unwrap() - } - - fn create_query_set( - &mut self, - device: Resource, - descriptor: webgpu::GpuQuerySetDescriptor, - ) -> Resource { - let device = self.0.table().get(&device).unwrap().device; - let query_set = core_result(self.0.instance().device_create_query_set::( - device, - &descriptor.to_core(&self.0.table()), - None, - )) - .unwrap(); - self.0.table().push(query_set).unwrap() - } - - fn label(&mut self, _device: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _device: Resource, _label: String) -> () { - todo!() - } - - fn lost( - &mut self, - _device: Resource, - ) -> Resource { - todo!() - } - - fn push_error_scope( - &mut self, - _device: Resource, - _filter: webgpu::GpuErrorFilter, - ) -> () { - todo!() - } - - fn pop_error_scope( - &mut self, - _device: Resource, - ) -> Option> { - todo!() - } - - fn uncaptured_errors(&mut self, _device: Resource) { - todo!() - } - - fn drop(&mut self, device: Resource) -> wasmtime::Result<()> { - self.table().delete(device).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuTexture for WasiWebGpuImpl { - fn from_graphics_buffer( - &mut self, - buffer: Resource, - ) -> Resource { - let host_buffer = self.table().delete(buffer).unwrap(); - let host_buffer: wgpu_core::id::TextureId = host_buffer.inner_type(); - self.0.table().push(host_buffer).unwrap() - } - - fn create_view( - &mut self, - texture: Resource, - descriptor: Option, - ) -> Resource { - let texture_id = *self.0.table().get(&texture).unwrap(); - let texture_view = core_result( - self.0.instance().texture_create_view::( - texture_id, - &descriptor - .map(|d| d.to_core(&self.0.table())) - .unwrap_or_default(), - None, - ), - ) - .unwrap(); - self.0.table().push(texture_view).unwrap() - } - - fn destroy(&mut self, texture: Resource) { - let texture_id = *self.0.table().get(&texture).unwrap(); - self.instance() - .texture_destroy::(texture_id) - .unwrap(); - } - - fn width(&mut self, _self_: Resource) -> webgpu::GpuIntegerCoordinateOut { - todo!() - } - - fn height(&mut self, _self_: Resource) -> webgpu::GpuIntegerCoordinateOut { - todo!() - } - - fn depth_or_array_layers( - &mut self, - _self_: Resource, - ) -> webgpu::GpuIntegerCoordinateOut { - todo!() - } - - fn mip_level_count( - &mut self, - _self_: Resource, - ) -> webgpu::GpuIntegerCoordinateOut { - todo!() - } - - fn sample_count(&mut self, _self_: Resource) -> webgpu::GpuSize32Out { - todo!() - } - - fn dimension(&mut self, _self_: Resource) -> webgpu::GpuTextureDimension { - todo!() - } - - fn format(&mut self, _self_: Resource) -> webgpu::GpuTextureFormat { - todo!() - } - - fn usage(&mut self, _self_: Resource) -> webgpu::GpuFlagsConstant { - todo!() - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, texture: Resource) -> wasmtime::Result<()> { - self.table().delete(texture).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuTextureView for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, view: Resource) -> wasmtime::Result<()> { - self.table().delete(view).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuCommandBuffer for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, command_buffer: Resource) -> wasmtime::Result<()> { - self.table().delete(command_buffer).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuShaderModule for WasiWebGpuImpl { - fn get_compilation_info( - &mut self, - _self_: Resource, - ) -> Resource { - todo!() - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, shader: Resource) -> wasmtime::Result<()> { - self.table().delete(shader).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuRenderPipeline for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn get_bind_group_layout( - &mut self, - pipeline: Resource, - index: u32, - ) -> Resource { - let pipeline_id = *self.0.table().get(&pipeline).unwrap(); - let layout = core_result( - self.instance() - .render_pipeline_get_bind_group_layout::(pipeline_id, index, None), - ) - .unwrap(); - self.0.table().push(layout).unwrap() - } - - fn drop(&mut self, pipeline: Resource) -> wasmtime::Result<()> { - self.table().delete(pipeline).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuAdapter for WasiWebGpuImpl { - fn request_device( - &mut self, - adapter: Resource, - descriptor: Option, - ) -> Resource { - let adapter_id = *self.0.table().get(&adapter).unwrap(); - - let (device_id, queue_id) = core_results_2( - self.0.instance().adapter_request_device::( - adapter_id, - &descriptor - .map(|d| d.to_core(&self.0.table())) - .unwrap_or_default(), - None, - None, - None, - ), - ) - .unwrap(); - - let device = self - .0 - .table() - .push(Device { - device: device_id, - queue: queue_id, - adapter: adapter_id, - }) - .unwrap(); - - device - } - - fn features( - &mut self, - adapter: wasmtime::component::Resource, - ) -> wasmtime::component::Resource { - let adapter = *self.0.table().get(&adapter).unwrap(); - let features = self - .instance() - .adapter_features::(adapter) - .unwrap(); - self.0.table().push(features).unwrap() - } - - fn limits( - &mut self, - adapter: Resource, - ) -> Resource { - let adapter = *self.0.table().get(&adapter).unwrap(); - let limits = self - .0 - .instance() - .adapter_limits::(adapter) - .unwrap(); - self.0.table().push(limits).unwrap() - } - - fn is_fallback_adapter( - &mut self, - _self_: wasmtime::component::Resource, - ) -> bool { - todo!() - } - - fn info( - &mut self, - adapter: Resource, - ) -> Resource { - let adapter_id = *self.0.table().get(&adapter).unwrap(); - let info = self - .instance() - .adapter_get_info::(adapter_id) - .unwrap(); - let info = self.0.table().push(info).unwrap(); - info - } - - fn drop(&mut self, adapter: Resource) -> wasmtime::Result<()> { - self.table().delete(adapter).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuQueue for WasiWebGpuImpl { - fn submit( - &mut self, - queue: Resource, - val: Vec>, - ) { - let command_buffers = val - .into_iter() - .map(|buffer| *self.0.table().get(&buffer).unwrap()) - .collect::>(); - let queue = *self.0.table().get(&queue).unwrap(); - self.0 - .instance() - .queue_submit::(queue, &command_buffers) - .unwrap(); - } - - fn on_submitted_work_done(&mut self, _self_: Resource) { - todo!() - } - - fn write_buffer( - &mut self, - queue: Resource, - buffer: Resource, - buffer_offset: webgpu::GpuSize64, - data_offset: Option, - data: Vec, - size: Option, - ) { - let queue = *self.0.table().get(&queue).unwrap(); - let buffer = self.0.table().get(&buffer).unwrap().buffer; - let mut data = &data[..]; - if let Some(data_offset) = data_offset { - let data_offset = data_offset as usize; - data = &data[data_offset..]; - } - if let Some(size) = size { - let size = size as usize; - data = &data[..size]; - } - self.0 - .instance() - .queue_write_buffer::(queue, buffer, buffer_offset, &data) - .unwrap(); - } - - fn write_texture( - &mut self, - queue: Resource, - destination: webgpu::GpuImageCopyTexture, - data: Vec, - data_layout: webgpu::GpuImageDataLayout, - size: webgpu::GpuExtent3D, - ) { - let queue = *self.0.table().get(&queue).unwrap(); - self.0 - .instance() - .queue_write_texture::( - queue, - &destination.to_core(&self.0.table()), - &data, - &data_layout.to_core(&self.0.table()), - &size.to_core(&self.0.table()), - ) - .unwrap(); - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, queue: Resource) -> wasmtime::Result<()> { - self.table().delete(queue).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuCommandEncoder for WasiWebGpuImpl { - fn begin_render_pass( - &mut self, - command_encoder: Resource, - descriptor: webgpu::GpuRenderPassDescriptor, - ) -> Resource { - let command_encoder = *self.0.table().get(&command_encoder).unwrap(); - let timestamp_writes = descriptor - .timestamp_writes - .map(|tw| tw.to_core(&self.0.table())); - // can't use to_core because depth_stencil_attachment is Option<&x>. - let depth_stencil_attachment = descriptor - .depth_stencil_attachment - .map(|d| d.to_core(&self.0.table())); - let descriptor = wgpu_core::command::RenderPassDescriptor { - label: descriptor.label.map(|l| l.into()), - color_attachments: descriptor - .color_attachments - .into_iter() - .map(|c| c.map(|c| c.to_core(&self.0.table()))) - .collect::>() - .into(), - depth_stencil_attachment: depth_stencil_attachment.as_ref(), - timestamp_writes: timestamp_writes.as_ref(), - occlusion_query_set: descriptor - .occlusion_query_set - .map(|oqs| oqs.to_core(&self.0.table())), - // TODO: self.max_draw_count not used - }; - let render_pass = core_result_t( - self.0 - .instance() - .command_encoder_create_render_pass::(command_encoder, &descriptor), - ) - .unwrap(); - - self.0.table().push(render_pass).unwrap() - } - - fn finish( - &mut self, - command_encoder: Resource, - descriptor: Option, - ) -> Resource { - let command_encoder = *self.0.table().get(&command_encoder).unwrap(); - let command_buffer = core_result( - self.0.instance().command_encoder_finish::( - command_encoder, - &descriptor - .map(|d| d.to_core(&self.0.table())) - .unwrap_or_default(), - ), - ) - .unwrap(); - self.0.table().push(command_buffer).unwrap() - } - - fn begin_compute_pass( - &mut self, - command_encoder: Resource, - descriptor: Option, - ) -> Resource { - let command_encoder = *self.0.table().get(&command_encoder).unwrap(); - let compute_pass = core_result_t( - self.0 - .instance() - .command_encoder_create_compute_pass::( - command_encoder, - // can't use to_core because timestamp_writes is Option<&x>. - &wgpu_core::command::ComputePassDescriptor { - // TODO: can we get rid of the clone here? - label: descriptor - .as_ref() - .map(|d| d.label.clone().map(|l| l.into())) - .flatten(), - timestamp_writes: descriptor - .map(|d| d.timestamp_writes.map(|tw| tw.to_core(&self.0.table()))) - .flatten() - .as_ref(), - }, - ), - ) - .unwrap(); - self.0.table().push(compute_pass).unwrap() - } - - fn copy_buffer_to_buffer( - &mut self, - command_encoder: Resource, - source: Resource, - source_offset: webgpu::GpuSize64, - destination: Resource, - destination_offset: webgpu::GpuSize64, - size: webgpu::GpuSize64, - ) { - let command_encoder = *self.0.table().get(&command_encoder).unwrap(); - let source = self.0.table().get(&source).unwrap().buffer; - let destination = self.0.table().get(&destination).unwrap().buffer; - self.0 - .instance() - .command_encoder_copy_buffer_to_buffer::( - command_encoder, - source, - source_offset, - destination, - destination_offset, - size, - ) - .unwrap(); - } - - fn copy_buffer_to_texture( - &mut self, - command_encoder: Resource, - source: webgpu::GpuImageCopyBuffer, - destination: webgpu::GpuImageCopyTexture, - copy_size: webgpu::GpuExtent3D, - ) { - let command_encoder = *self.table().get(&command_encoder).unwrap(); - self.instance() - .command_encoder_copy_buffer_to_texture::( - command_encoder, - &source.to_core(&self.table()), - &destination.to_core(&self.table()), - ©_size.to_core(self.table()), - ) - .unwrap(); - } - - fn copy_texture_to_buffer( - &mut self, - command_encoder: Resource, - source: webgpu::GpuImageCopyTexture, - destination: webgpu::GpuImageCopyBuffer, - copy_size: webgpu::GpuExtent3D, - ) { - let command_encoder = *self.table().get(&command_encoder).unwrap(); - self.instance() - .command_encoder_copy_texture_to_buffer::( - command_encoder, - &source.to_core(&self.table()), - &destination.to_core(&self.table()), - ©_size.to_core(&self.table()), - ) - .unwrap(); - } - - fn copy_texture_to_texture( - &mut self, - _self_: Resource, - _source: webgpu::GpuImageCopyTexture, - _destination: webgpu::GpuImageCopyTexture, - _copy_size: webgpu::GpuExtent3D, - ) { - todo!() - } - - fn clear_buffer( - &mut self, - _self_: Resource, - _buffer: Resource, - _offset: Option, - _size: Option, - ) { - todo!() - } - - fn resolve_query_set( - &mut self, - _self_: Resource, - _query_set: Resource, - _first_query: webgpu::GpuSize32, - _query_count: webgpu::GpuSize32, - _destination: Resource, - _destination_offset: webgpu::GpuSize64, - ) { - todo!() - } - - fn label(&mut self, command_encoder: Resource) -> String { - let _command_encoder = self.0.table().get(&command_encoder).unwrap(); - // TODO: return real label - String::new() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn push_debug_group( - &mut self, - command_encoder: Resource, - group_label: String, - ) { - let command_encoder = *self.table().get(&command_encoder).unwrap(); - self.instance() - .command_encoder_push_debug_group::(command_encoder, &group_label) - .unwrap(); - } - - fn pop_debug_group(&mut self, command_encoder: Resource) { - let command_encoder = *self.table().get(&command_encoder).unwrap(); - self.instance() - .command_encoder_pop_debug_group::(command_encoder) - .unwrap(); - } - - fn insert_debug_marker( - &mut self, - command_encoder: Resource, - marker_label: String, - ) { - let command_encoder = *self.table().get(&command_encoder).unwrap(); - self.instance() - .command_encoder_insert_debug_marker::(command_encoder, &marker_label) - .unwrap(); - } - - fn drop( - &mut self, - command_encoder: Resource, - ) -> wasmtime::Result<()> { - self.table().delete(command_encoder).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuRenderPassEncoder for WasiWebGpuImpl { - fn set_pipeline( - &mut self, - render_pass: Resource>, - pipeline: Resource, - ) { - let instance = self.0.instance(); - let pipeline = pipeline.to_core(&self.0.table()); - let render_pass = self.0.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_set_pipeline(render_pass, pipeline) - .unwrap() - } - - fn draw( - &mut self, - rpass: Resource>, - vertex_count: webgpu::GpuSize32, - instance_count: Option, - first_vertex: Option, - first_instance: Option, - ) { - let instance = self.0.instance(); - let rpass = self.0.table().get_mut(&rpass).unwrap(); - instance - .render_pass_draw( - rpass, - vertex_count, - instance_count.unwrap_or(1), - first_vertex.unwrap_or(0), - first_instance.unwrap_or(0), - ) - .unwrap() - } - - fn end(&mut self, rpass: Resource>) { - let instance = self.0.instance(); - let mut rpass = self.0.table().get_mut(&rpass).unwrap(); - instance - .render_pass_end::(&mut rpass) - .unwrap(); - } - - fn set_viewport( - &mut self, - render_pass: Resource>, - x: f32, - y: f32, - width: f32, - height: f32, - min_depth: f32, - max_depth: f32, - ) { - let instance = self.0.instance(); - let render_pass = self.0.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_set_viewport(render_pass, x, y, width, height, min_depth, max_depth) - .unwrap(); - } - - fn set_scissor_rect( - &mut self, - render_pass: Resource>, - x: webgpu::GpuIntegerCoordinate, - y: webgpu::GpuIntegerCoordinate, - width: webgpu::GpuIntegerCoordinate, - height: webgpu::GpuIntegerCoordinate, - ) { - let instance = self.0.instance(); - let render_pass = self.0.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_set_scissor_rect(render_pass, x, y, width, height) - .unwrap(); - } - - fn set_blend_constant( - &mut self, - _self_: Resource>, - _color: webgpu::GpuColor, - ) { - todo!() - } - - fn set_stencil_reference( - &mut self, - _self_: Resource>, - _reference: webgpu::GpuStencilValue, - ) { - todo!() - } - - fn begin_occlusion_query( - &mut self, - _self_: Resource>, - _query_index: webgpu::GpuSize32, - ) { - todo!() - } - - fn end_occlusion_query( - &mut self, - _self_: Resource>, - ) { - todo!() - } - - fn execute_bundles( - &mut self, - _self_: Resource>, - _bundles: Vec>, - ) { - todo!() - } - - fn label( - &mut self, - _self_: Resource>, - ) -> String { - todo!() - } - - fn set_label( - &mut self, - _self_: Resource>, - _label: String, - ) { - todo!() - } - - fn push_debug_group( - &mut self, - _self_: Resource>, - _group_label: String, - ) { - todo!() - } - - fn pop_debug_group( - &mut self, - _self_: Resource>, - ) { - todo!() - } - - fn insert_debug_marker( - &mut self, - _self_: Resource>, - _marker_label: String, - ) { - todo!() - } - - fn set_bind_group( - &mut self, - render_pass: Resource>, - index: webgpu::GpuIndex32, - bind_group: Option>, - dynamic_offsets: Option>, - ) { - let instance = self.0.instance(); - let bind_group = *self - .0 - .table() - .get(&bind_group.expect("TODO: deal with null bind_groups")) - .unwrap(); - let mut render_pass = self.0.table().get_mut(&render_pass).unwrap(); - let dynamic_offsets = dynamic_offsets.unwrap(); - instance - .render_pass_set_bind_group(&mut render_pass, index, bind_group, &dynamic_offsets) - .unwrap() - } - - fn set_index_buffer( - &mut self, - render_pass: Resource>, - buffer: Resource, - index_format: webgpu::GpuIndexFormat, - offset: Option, - size: Option, - ) { - let instance = self.0.instance(); - let (buffer_id, buffer_size) = { - let buffer = self.table().get(&buffer).unwrap(); - (buffer.buffer, buffer.size) - }; - let render_pass = self.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_set_index_buffer( - render_pass, - buffer_id, - index_format.into(), - offset.unwrap_or(0), - core::num::NonZeroU64::new(size.unwrap_or(buffer_size)), - ) - .unwrap() - } - - fn set_vertex_buffer( - &mut self, - render_pass: Resource>, - slot: webgpu::GpuIndex32, - buffer: Option>, - offset: Option, - size: Option, - ) { - let instance = self.0.instance(); - let (buffer_id, buffer_size) = { - let buffer = self - .table() - .get(&buffer.expect("TODO: deal null buffers")) - .unwrap(); - (buffer.buffer, buffer.size) - }; - let mut render_pass = self.0.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_set_vertex_buffer( - &mut render_pass, - slot, - buffer_id, - offset.unwrap_or(0), - core::num::NonZeroU64::new(size.unwrap_or(buffer_size)), - ) - .unwrap() - } - - fn draw_indexed( - &mut self, - render_pass: Resource>, - index_count: webgpu::GpuSize32, - instance_count: Option, - first_index: Option, - base_vertex: Option, - first_instance: Option, - ) { - let instance = self.0.instance(); - let render_pass = self.table().get_mut(&render_pass).unwrap(); - instance - .render_pass_draw_indexed( - render_pass, - index_count, - instance_count.unwrap_or(1), - first_index.unwrap_or(0), - base_vertex.unwrap_or(0), - first_instance.unwrap_or(0), - ) - .unwrap() - } - - fn draw_indirect( - &mut self, - _self_: Resource>, - _indirect_buffer: Resource, - _indirect_offset: webgpu::GpuSize64, - ) { - todo!() - } - - fn draw_indexed_indirect( - &mut self, - _self_: Resource>, - _indirect_buffer: Resource, - _indirect_offset: webgpu::GpuSize64, - ) { - todo!() - } - - fn drop( - &mut self, - render_pass: Resource>, - ) -> wasmtime::Result<()> { - self.table().delete(render_pass).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuUncapturedErrorEvent for WasiWebGpuImpl { - fn new( - &mut self, - _type_: String, - _gpu_uncaptured_error_event_init_dict: webgpu::GpuUncapturedErrorEventInit, - ) -> Resource { - todo!() - } - - fn error( - &mut self, - _self_: Resource, - ) -> Resource { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuInternalError for WasiWebGpuImpl { - fn new(&mut self, _message: String) -> Resource { - todo!() - } - - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuOutOfMemoryError for WasiWebGpuImpl { - fn new(&mut self, _message: String) -> Resource { - todo!() - } - - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuValidationError for WasiWebGpuImpl { - fn new(&mut self, _message: String) -> Resource { - todo!() - } - - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuError for WasiWebGpuImpl { - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuDeviceLostInfo for WasiWebGpuImpl { - fn reason( - &mut self, - _self_: Resource, - ) -> webgpu::GpuDeviceLostReason { - todo!() - } - - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { - self.table().delete(info).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuCanvasContext for WasiWebGpuImpl { - fn configure( - &mut self, - _self_: Resource, - _configuration: webgpu::GpuCanvasConfiguration, - ) { - todo!() - } - - fn unconfigure(&mut self, _self_: Resource) { - todo!() - } - - fn get_current_texture( - &mut self, - _self_: Resource, - ) -> Resource { - todo!() - } - - fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { - todo!() - } -} -impl webgpu::HostGpuRenderBundle for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, bundle: Resource) -> wasmtime::Result<()> { - self.table().delete(bundle).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuComputePassEncoder for WasiWebGpuImpl { - fn set_pipeline( - &mut self, - encoder: Resource, - pipeline: Resource, - ) { - let instance = self.0.instance(); - let pipeline = *self.0.table().get(&pipeline).unwrap(); - let encoder = self.0.table().get_mut(&encoder).unwrap(); - instance - .compute_pass_set_pipeline(encoder, pipeline) - .unwrap(); - } - - fn dispatch_workgroups( - &mut self, - encoder: Resource, - workgroup_count_x: webgpu::GpuSize32, - workgroup_count_y: Option, - workgroup_count_z: Option, - ) { - let instance = self.0.instance(); - let encoder = self.0.table().get_mut(&encoder).unwrap(); - instance - .compute_pass_dispatch_workgroups( - encoder, - workgroup_count_x, - workgroup_count_y.unwrap(), - workgroup_count_z.unwrap(), - ) - .unwrap() - } - - fn dispatch_workgroups_indirect( - &mut self, - encoder: Resource, - indirect_buffer: Resource, - indirect_offset: webgpu::GpuSize64, - ) { - let instance = self.instance(); - let indirect_buffer = self.0.table().get(&indirect_buffer).unwrap().buffer; - let encoder = self.0.table().get_mut(&encoder).unwrap(); - instance - .compute_pass_dispatch_workgroups_indirect(encoder, indirect_buffer, indirect_offset) - .unwrap(); - } - - fn end(&mut self, cpass: Resource>) { - let instance = self.0.instance(); - let mut cpass = self.0.table().get_mut(&cpass).unwrap(); - instance - .compute_pass_end::(&mut cpass) - .unwrap(); - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn push_debug_group( - &mut self, - cpass: Resource, - group_label: String, - ) { - let instance = self.instance(); - let cpass = self.table().get_mut(&cpass).unwrap(); - instance - .compute_pass_push_debug_group(cpass, &group_label, 0) - .unwrap(); - } - - fn pop_debug_group(&mut self, cpass: Resource) { - let instance = self.instance(); - let cpass = self.table().get_mut(&cpass).unwrap(); - instance.compute_pass_pop_debug_group(cpass).unwrap(); - } - - fn insert_debug_marker( - &mut self, - cpass: Resource, - label: String, - ) { - let instance = self.0.instance(); - let cpass = self.0.table().get_mut(&cpass).unwrap(); - instance - .compute_pass_insert_debug_marker(cpass, &label, 0) - .unwrap() - } - - fn set_bind_group( - &mut self, - encoder: Resource, - index: webgpu::GpuIndex32, - bind_group: Option>, - dynamic_offsets: Option>, - ) { - let instance = self.0.instance(); - let bind_group = *self - .0 - .table() - .get(&bind_group.expect("TODO: deal with null bind_groups")) - .unwrap(); - let encoder = self.0.table().get_mut(&encoder).unwrap(); - let dynamic_offsets = dynamic_offsets.unwrap(); - instance - .compute_pass_set_bind_group(encoder, index, bind_group, &dynamic_offsets) - .unwrap() - } - - fn drop(&mut self, encoder: Resource) -> wasmtime::Result<()> { - self.table().delete(encoder).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuPipelineError for WasiWebGpuImpl { - fn new( - &mut self, - _message: Option, - _options: webgpu::GpuPipelineErrorInit, - ) -> Resource { - todo!() - } - - fn reason( - &mut self, - _self_: Resource, - ) -> webgpu::GpuPipelineErrorReason { - todo!() - } - - fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { - self.table().delete(error).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuCompilationMessage for WasiWebGpuImpl { - fn message(&mut self, _self_: Resource) -> String { - todo!() - } - - fn type_( - &mut self, - _self_: Resource, - ) -> webgpu::GpuCompilationMessageType { - todo!() - } - - fn line_num(&mut self, _self_: Resource) -> u64 { - todo!() - } - - fn line_pos(&mut self, _self_: Resource) -> u64 { - todo!() - } - - fn offset(&mut self, _self_: Resource) -> u64 { - todo!() - } - - fn length(&mut self, _self_: Resource) -> u64 { - todo!() - } - - fn drop(&mut self, cm: Resource) -> wasmtime::Result<()> { - self.table().delete(cm).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuCompilationInfo for WasiWebGpuImpl { - fn messages( - &mut self, - _self_: Resource, - ) -> Vec> { - todo!() - } - - fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { - self.table().delete(info).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuQuerySet for WasiWebGpuImpl { - fn destroy(&mut self, _self_: Resource) { - todo!() - } - - fn type_(&mut self, _self_: Resource) -> webgpu::GpuQueryType { - todo!() - } - - fn count(&mut self, _self_: Resource) -> webgpu::GpuSize32Out { - todo!() - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, query_set: Resource) -> wasmtime::Result<()> { - self.table().delete(query_set).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuRenderBundleEncoder for WasiWebGpuImpl { - fn finish( - &mut self, - _self_: Resource, - _descriptor: Option, - ) -> Resource { - todo!() - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn push_debug_group( - &mut self, - _self_: Resource, - _group_label: String, - ) { - todo!() - } - - fn pop_debug_group(&mut self, _self_: Resource) { - todo!() - } - - fn insert_debug_marker( - &mut self, - _self_: Resource, - _marker_label: String, - ) { - todo!() - } - - fn set_bind_group( - &mut self, - _self_: Resource, - _index: webgpu::GpuIndex32, - _bind_group: Option>, - _dynamic_offsets: Option>, - ) { - todo!() - } - - fn set_pipeline( - &mut self, - _self_: Resource, - _pipeline: Resource, - ) { - todo!() - } - - fn set_index_buffer( - &mut self, - _self_: Resource, - _buffer: Resource, - _index_format: webgpu::GpuIndexFormat, - _offset: Option, - _size: Option, - ) { - todo!() - } - - fn set_vertex_buffer( - &mut self, - _self_: Resource, - _slot: webgpu::GpuIndex32, - _buffer: Option>, - _offset: Option, - _size: Option, - ) { - todo!() - } - - fn draw( - &mut self, - _self_: Resource, - _vertex_count: webgpu::GpuSize32, - _instance_count: Option, - _first_vertex: Option, - _first_instance: Option, - ) { - todo!() - } - - fn draw_indexed( - &mut self, - _self_: Resource, - _index_count: webgpu::GpuSize32, - _instance_count: Option, - _first_index: Option, - _base_vertex: Option, - _first_instance: Option, - ) { - todo!() - } - - fn draw_indirect( - &mut self, - _self_: Resource, - _indirect_buffer: Resource, - _indirect_offset: webgpu::GpuSize64, - ) { - todo!() - } - - fn draw_indexed_indirect( - &mut self, - _self_: Resource, - _indirect_buffer: Resource, - _indirect_offset: webgpu::GpuSize64, - ) { - todo!() - } - - fn drop(&mut self, encoder: Resource) -> wasmtime::Result<()> { - self.table().delete(encoder).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuComputePipeline for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn get_bind_group_layout( - &mut self, - compute_pipeline: Resource, - index: u32, - ) -> Resource { - let pipeline_id = *self.0.table().get(&compute_pipeline).unwrap(); - let bind_group_layout = core_result( - self.0 - .instance() - .compute_pipeline_get_bind_group_layout::(pipeline_id, index, None), - ) - .unwrap(); - self.0.table().push(bind_group_layout).unwrap() - } - - fn drop(&mut self, pipeline: Resource) -> wasmtime::Result<()> { - self.table().delete(pipeline).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuBindGroup for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, bind_group: Resource) -> wasmtime::Result<()> { - self.table().delete(bind_group).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuPipelineLayout for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, layout: Resource) -> wasmtime::Result<()> { - self.table().delete(layout).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuBindGroupLayout for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, layout: Resource) -> wasmtime::Result<()> { - self.table().delete(layout).unwrap(); - Ok(()) - } -} - -impl webgpu::HostGpuSampler for WasiWebGpuImpl { - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, sampler: Resource) -> wasmtime::Result<()> { - self.table().delete(sampler).unwrap(); - Ok(()) - } -} - -#[async_trait::async_trait] -impl webgpu::HostGpuBuffer for WasiWebGpuImpl { - fn size(&mut self, buffer: Resource) -> webgpu::GpuSize64Out { - let buffer = self.table().get(&buffer).unwrap(); - buffer.size - } - - fn usage(&mut self, _self_: Resource) -> webgpu::GpuFlagsConstant { - todo!() - } - - fn map_state(&mut self, _self_: Resource) -> webgpu::GpuBufferMapState { - todo!() - } - - async fn map_async( - &mut self, - buffer: Resource, - mode: webgpu::GpuMapModeFlags, - offset: Option, - size: Option, - ) { - let buffer = self.0.table().get(&buffer).unwrap().buffer; - let instance = self.0.instance(); - CallbackFuture::new(Box::new( - move |resolve: Box< - dyn FnOnce(Box>) + Send, - >| { - // TODO: move to convertion function - // source: https://www.w3.org/TR/webgpu/#typedefdef-gpumapmodeflags - let host = match mode { - 1 => wgpu_core::device::HostMap::Read, - 2 => wgpu_core::device::HostMap::Write, - _ => panic!(), - }; - let op = wgpu_core::resource::BufferMapOperation { - host, - callback: Some(wgpu_core::resource::BufferMapCallback::from_rust(Box::new( - move |result| { - resolve(Box::new(result)); - }, - ))), - }; - - let offset = offset.unwrap(); - instance - .buffer_map_async::(buffer, offset, size, op) - .unwrap(); - // TODO: only poll this device. - instance.poll_all_devices(true).unwrap(); - }, - )) - .await - .unwrap(); - } - - fn get_mapped_range( - &mut self, - buffer: Resource, - offset: Option, - size: Option, - ) -> Resource { - let buffer_id = self.0.table().get(&buffer).unwrap().buffer; - let (ptr, len) = self - .0 - .instance() - .buffer_get_mapped_range::(buffer_id, offset.unwrap_or(0), size) - .unwrap(); - let remote_buffer = BufferPtr { ptr, len }; - self.0.table().push(remote_buffer).unwrap() - } - - fn unmap(&mut self, buffer: Resource) { - let buffer = self.0.table().get_mut(&buffer).unwrap(); - let buffer_id = buffer.buffer; - self.0 - .instance() - .buffer_unmap::(buffer_id) - .unwrap(); - } - - fn destroy(&mut self, _self_: Resource) { - todo!() - } - - fn label(&mut self, _self_: Resource) -> String { - todo!() - } - - fn set_label(&mut self, _self_: Resource, _label: String) { - todo!() - } - - fn drop(&mut self, buffer: Resource) -> wasmtime::Result<()> { - self.table().delete(buffer).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpu for WasiWebGpuImpl { - fn request_adapter( - &mut self, - _self_: Resource, - options: Option, - ) -> Option> { - let adapter = self.0.instance().request_adapter( - &options.map(|o| o.to_core(self.table())).unwrap_or_default(), - wgpu_core::instance::AdapterInputs::Mask(wgpu_types::Backends::all(), |_| None), - ); - if let Err(wgpu_core::instance::RequestAdapterError::NotFound) = adapter { - return None; - } - let adapter = adapter.unwrap(); - Some(self.0.table().push(adapter).unwrap()) - } - - fn get_preferred_canvas_format( - &mut self, - _gpu: Resource, - ) -> webgpu::GpuTextureFormat { - // https://searchfox.org/mozilla-central/source/dom/webgpu/Instance.h#42 - #[cfg(target_os = "android")] - return webgpu::GpuTextureFormat::Rgba8unorm; - #[cfg(not(target_os = "android"))] - return webgpu::GpuTextureFormat::Bgra8unorm; - } - - fn wgsl_language_features( - &mut self, - _self_: Resource, - ) -> Resource { - todo!() - } - - fn drop(&mut self, _gpu: Resource) -> wasmtime::Result<()> { - // not actually a resource in the table - Ok(()) - } -} -impl webgpu::HostGpuAdapterInfo for WasiWebGpuImpl { - fn vendor(&mut self, _self_: Resource) -> String { - todo!() - } - - fn architecture(&mut self, _self_: Resource) -> String { - todo!() - } - - fn device(&mut self, _self_: Resource) -> String { - todo!() - } - - fn description(&mut self, _self_: Resource) -> String { - todo!() - } - - fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { - self.table().delete(info).unwrap(); - Ok(()) - } -} -impl webgpu::HostWgslLanguageFeatures for WasiWebGpuImpl { - fn has(&mut self, _self_: Resource, _key: String) -> bool { - todo!() - } - - fn drop(&mut self, features: Resource) -> wasmtime::Result<()> { - self.table().delete(features).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuSupportedFeatures for WasiWebGpuImpl { - fn has(&mut self, features: Resource, query: String) -> bool { - let features = self.0.table().get(&features).unwrap(); - match query.as_str() { - "depth-clip-control" => features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL), - "timestamp-query" => features.contains(wgpu_types::Features::TIMESTAMP_QUERY), - "indirect-first-instance" => { - features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) - } - "shader-f16" => features.contains(wgpu_types::Features::SHADER_F16), - "depth32float-stencil8" => { - features.contains(wgpu_types::Features::DEPTH32FLOAT_STENCIL8) - } - "texture-compression-bc" => { - features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_BC) - } - "texture-compression-etc2" => { - features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2) - } - "texture-compression-astc" => { - features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC) - } - "rg11b10ufloat-renderable" => { - features.contains(wgpu_types::Features::RG11B10UFLOAT_RENDERABLE) - } - "bgra8unorm-storage" => features.contains(wgpu_types::Features::BGRA8UNORM_STORAGE), - "float32-filterable" => features.contains(wgpu_types::Features::FLOAT32_FILTERABLE), - _ => todo!(), - } - } - - fn drop(&mut self, features: Resource) -> wasmtime::Result<()> { - self.table().delete(features).unwrap(); - Ok(()) - } -} -impl webgpu::HostGpuSupportedLimits for WasiWebGpuImpl { - fn max_texture_dimension1_d(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_texture_dimension_1d - } - - fn max_texture_dimension2_d(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_texture_dimension_2d - } - - fn max_texture_dimension3_d(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_texture_dimension_3d - } - - fn max_texture_array_layers(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_texture_array_layers - } - - fn max_bind_groups(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_bind_groups - } - - fn max_bind_groups_plus_vertex_buffers( - &mut self, - _limits: Resource, - ) -> u32 { - todo!() - } - - fn max_bindings_per_bind_group(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_bindings_per_bind_group - } - - fn max_dynamic_uniform_buffers_per_pipeline_layout( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_dynamic_uniform_buffers_per_pipeline_layout - } - - fn max_dynamic_storage_buffers_per_pipeline_layout( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_dynamic_storage_buffers_per_pipeline_layout - } - - fn max_sampled_textures_per_shader_stage( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_sampled_textures_per_shader_stage - } - - fn max_samplers_per_shader_stage( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_samplers_per_shader_stage - } - - fn max_storage_buffers_per_shader_stage( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_storage_buffers_per_shader_stage - } - - fn max_storage_textures_per_shader_stage( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_storage_textures_per_shader_stage - } - - fn max_uniform_buffers_per_shader_stage( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_uniform_buffers_per_shader_stage - } - - fn max_uniform_buffer_binding_size( - &mut self, - limits: Resource, - ) -> u64 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_uniform_buffer_binding_size as u64 - } - - fn max_storage_buffer_binding_size( - &mut self, - limits: Resource, - ) -> u64 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_storage_buffer_binding_size as u64 - } - - fn min_uniform_buffer_offset_alignment( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.min_uniform_buffer_offset_alignment - } - - fn min_storage_buffer_offset_alignment( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.min_storage_buffer_offset_alignment - } - - fn max_vertex_buffers(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_vertex_buffers - } - - fn max_buffer_size(&mut self, limits: Resource) -> u64 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_buffer_size - } - - fn max_vertex_attributes(&mut self, limits: Resource) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_vertex_attributes - } - - fn max_vertex_buffer_array_stride( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_vertex_buffer_array_stride - } - - fn max_inter_stage_shader_variables( - &mut self, - _limits: Resource, - ) -> u32 { - todo!() - } - - fn max_color_attachments(&mut self, _limits: Resource) -> u32 { - todo!() - } - - fn max_color_attachment_bytes_per_sample( - &mut self, - _limits: Resource, - ) -> u32 { - todo!() - } - - fn max_compute_workgroup_storage_size( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_workgroup_storage_size - } - - fn max_compute_invocations_per_workgroup( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_invocations_per_workgroup - } - - fn max_compute_workgroup_size_x( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_workgroup_size_x - } - - fn max_compute_workgroup_size_y( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_workgroup_size_y - } - - fn max_compute_workgroup_size_z( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_workgroup_size_z - } - - fn max_compute_workgroups_per_dimension( - &mut self, - limits: Resource, - ) -> u32 { - let limits = self.0.table().get(&limits).unwrap(); - limits.max_compute_workgroups_per_dimension - } - - fn drop(&mut self, limits: Resource) -> wasmtime::Result<()> { - self.table().delete(limits).unwrap(); - Ok(()) - } -} - -fn core_result( - (id, error): (wgpu_core::id::Id, Option), -) -> Result, E> -where - I: wgpu_core::id::Marker, -{ - match error { - Some(error) => Err(error), - None => Ok(id), - } -} - -// same as core_result, but but result doesn't need to be id. -fn core_result_t((t, error): (T, Option)) -> Result { - match error { - Some(error) => Err(error), - None => Ok(t), - } -} - -// same as core_result, but handles tuple of two ids for Ok. -fn core_results_2( - (a, b, error): (wgpu_core::id::Id, wgpu_core::id::Id, Option), -) -> Result<(wgpu_core::id::Id, wgpu_core::id::Id), E> -where - I1: wgpu_core::id::Marker, - I2: wgpu_core::id::Marker, -{ - match error { - Some(error) => Err(error), - None => Ok((a, b)), - } -} diff --git a/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs b/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs index d6791dd..14543cd 100644 --- a/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs +++ b/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs @@ -92,7 +92,7 @@ impl<'a> ToCore for webgpu::GpuBufferBi let buffer = table.get(&self.buffer).unwrap(); // https://www.w3.org/TR/webgpu/#dictdef-gpubufferbinding wgpu_core::binding_model::BufferBinding { - buffer_id: buffer.buffer, + buffer_id: buffer.buffer_id, offset: self.offset.unwrap_or(0), size: self.size.map(|s| s.try_into().unwrap()), } @@ -905,7 +905,7 @@ impl ToCore> for webgpu::Gp ) -> wgpu_types::ImageCopyBuffer { // https://www.w3.org/TR/webgpu/#gputexelcopybufferlayout wgpu_types::ImageCopyBuffer { - buffer: table.get(&self.buffer).unwrap().buffer, + buffer: table.get(&self.buffer).unwrap().buffer_id, layout: wgpu_types::ImageDataLayout { offset: self.offset.unwrap_or(0), bytes_per_row: self.bytes_per_row, diff --git a/crates/wasi-webgpu-wasmtime/src/trait_impls.rs b/crates/wasi-webgpu-wasmtime/src/trait_impls.rs new file mode 100644 index 0000000..b011567 --- /dev/null +++ b/crates/wasi-webgpu-wasmtime/src/trait_impls.rs @@ -0,0 +1,2500 @@ +use std::{borrow::Cow, mem, sync::Arc}; + +use callback_future::CallbackFuture; +use futures::executor::block_on; +use wasi_graphics_context_wasmtime::{Context, DisplayApi}; +use wasmtime::component::Resource; +use wasmtime_wasi::WasiView; + +use crate::{ + to_core_conversions::ToCore, + wasi::webgpu::webgpu, + wrapper_types::{Buffer, BufferPtr, Device}, + AbstractBuffer, MainThreadSpawner, WasiWebGpuImpl, WasiWebGpuView, WebGpuSurface, +}; + +impl webgpu::Host for WasiWebGpuImpl { + fn get_gpu(&mut self) -> Resource { + Resource::new_own(0) + } +} + +impl webgpu::HostGpuColorWrite for WasiWebGpuImpl { + fn red(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ColorWrites::RED.bits() + } + + fn green(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ColorWrites::GREEN.bits() + } + + fn blue(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ColorWrites::BLUE.bits() + } + + fn alpha(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ColorWrites::ALPHA.bits() + } + + fn all(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ColorWrites::ALL.bits() + } + + fn drop(&mut self, _self_: Resource) -> wasmtime::Result<()> { + todo!() + } +} + +impl webgpu::HostRecordGpuPipelineConstantValue for WasiWebGpuImpl { + fn new(&mut self) -> Resource { + todo!() + } + + fn add( + &mut self, + _record: Resource, + _key: String, + _value: webgpu::GpuPipelineConstantValue, + ) { + todo!() + } + + // fn get(&mut self, _record: Resource, _key: String) -> Option { + fn get( + &mut self, + _record: Resource, + _key: String, + ) -> webgpu::GpuPipelineConstantValue { + todo!() + } + + fn has( + &mut self, + _record: Resource, + _key: String, + ) -> bool { + todo!() + } + + fn remove(&mut self, _record: Resource, _key: String) { + todo!() + } + + fn keys(&mut self, _record: Resource) -> Vec { + todo!() + } + + fn values( + &mut self, + _record: Resource, + ) -> Vec { + todo!() + } + + // fn entries(&mut self, _record: Resource) -> Vec<(String, webgpu::GpuPipelineConstantValue)> { + fn entries( + &mut self, + _record: Resource, + ) -> (String, webgpu::GpuPipelineConstantValue) { + todo!() + } + + fn drop( + &mut self, + _self_: Resource, + ) -> wasmtime::Result<()> { + todo!() + } +} +impl webgpu::HostGpuShaderStage for WasiWebGpuImpl { + fn vertex(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ShaderStages::VERTEX.bits() + } + + fn fragment(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ShaderStages::FRAGMENT.bits() + } + + fn compute(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::ShaderStages::COMPUTE.bits() + } + + fn drop(&mut self, _: Resource) -> wasmtime::Result<()> { + todo!() + } +} +impl webgpu::HostGpuTextureUsage for WasiWebGpuImpl { + fn copy_src(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::TextureUsages::COPY_SRC.bits() + } + fn copy_dst(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::TextureUsages::COPY_DST.bits() + } + fn texture_binding(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::TextureUsages::TEXTURE_BINDING.bits() + } + fn storage_binding(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::TextureUsages::STORAGE_BINDING.bits() + } + fn render_attachment(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::TextureUsages::RENDER_ATTACHMENT.bits() + } + fn drop( + &mut self, + _rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + todo!() + } +} +impl webgpu::HostGpuMapMode for WasiWebGpuImpl { + fn read(&mut self) -> webgpu::GpuFlagsConstant { + // https://www.w3.org/TR/webgpu/#buffer-mapping + 0x0001 + } + fn write(&mut self) -> webgpu::GpuFlagsConstant { + // https://www.w3.org/TR/webgpu/#buffer-mapping + 0x0002 + } + fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { + todo!() + } +} +impl webgpu::HostGpuBufferUsage for WasiWebGpuImpl { + fn map_read(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::MAP_READ.bits() + } + fn map_write(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::MAP_WRITE.bits() + } + fn copy_src(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::COPY_SRC.bits() + } + fn copy_dst(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::COPY_DST.bits() + } + fn index(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::INDEX.bits() + } + fn vertex(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::VERTEX.bits() + } + fn uniform(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::UNIFORM.bits() + } + fn storage(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::STORAGE.bits() + } + fn indirect(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::INDIRECT.bits() + } + fn query_resolve(&mut self) -> webgpu::GpuFlagsConstant { + wgpu_types::BufferUsages::QUERY_RESOLVE.bits() + } + fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { + todo!() + } +} + +impl webgpu::HostRecordGpuSize64 for WasiWebGpuImpl { + fn new(&mut self) -> Resource { + todo!() + } + fn add( + &mut self, + _self_: Resource, + _key: String, + _value: webgpu::GpuSize64, + ) { + todo!() + } + fn get( + &mut self, + _self_: Resource, + _key: String, + ) -> webgpu::GpuSize64 { + todo!() + } + fn has(&mut self, _self_: Resource, _key: String) -> bool { + todo!() + } + fn remove(&mut self, _self_: Resource, _key: String) { + todo!() + } + fn keys(&mut self, _self_: Resource) -> Vec { + todo!() + } + fn values(&mut self, _self_: Resource) -> Vec { + todo!() + } + fn entries( + &mut self, + _self_: Resource, + ) -> (String, webgpu::GpuSize64) { + todo!() + } + fn drop( + &mut self, + _rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + todo!() + } +} + +impl webgpu::HostNonStandardBuffer for WasiWebGpuImpl { + fn get(&mut self, buffer: Resource) -> Vec { + let buffer = self.0.table().get_mut(&buffer).unwrap(); + buffer.slice_mut().to_vec() + } + + fn set(&mut self, buffer: Resource, val: Vec) { + let buffer = self.0.table().get_mut(&buffer).unwrap(); + buffer.slice_mut().copy_from_slice(&val); + } + + fn drop(&mut self, buffer: Resource) -> wasmtime::Result<()> { + self.table().delete(buffer).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuDevice for WasiWebGpuImpl { + fn connect_graphics_context(&mut self, device: Resource, context: Resource) { + let device = self.0.table().get(&device).unwrap(); + let device_id = device.device; + let adapter_id = device.adapter; + + let instance = Arc::downgrade(&self.0.instance()); + let surface_creator = self.0.ui_thread_spawner(); + + let context = self.0.table().get_mut(&context).unwrap(); + + let surface = WebGpuSurface { + get_instance: { + let instance = instance.clone(); + move || instance.upgrade().unwrap() + }, + create_surface: { + let instance = instance.clone(); + move |display: &(dyn DisplayApi + Send + Sync)| { + let instance = instance.upgrade().unwrap(); + + // TODO: make spawn behave similar to `std::thread::scope` so that we don't have to unsafely transmute display to `&'static`. + // Something like the following: + // ```rust + // let surface_id = std::thread::scope(|s| { + // s.spawn(move || unsafe { + // instance + // .instance_create_surface( + // display.display_handle().unwrap().as_raw(), + // display.window_handle().unwrap().as_raw(), + // None, + // ) + // .unwrap() + // }).join().unwrap() + // }); + // surface_id + // ``` + + let display: &'static (dyn DisplayApi + Send + Sync) = + unsafe { mem::transmute(display) }; + block_on(surface_creator.spawn(move || unsafe { + instance + .instance_create_surface( + display.display_handle().unwrap().as_raw(), + display.window_handle().unwrap().as_raw(), + None, + ) + .unwrap() + })) + } + }, + device_id, + adapter_id, + surface_id: None, + }; + + context.connect_draw_api(Box::new(surface)); + } + + fn configure( + &mut self, + _device: Resource, + _descriptor: webgpu::GpuDeviceConfiguration, + ) { + todo!() + } + + fn create_command_encoder( + &mut self, + device: Resource, + descriptor: Option, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let command_encoder = core_result( + self.0 + .instance() + .device_create_command_encoder::( + device, + &descriptor + .map(|d| d.to_core(&self.0.table())) + .unwrap_or_default(), + None, + ), + ) + .unwrap(); + + self.0.table().push(command_encoder).unwrap() + } + + fn create_shader_module( + &mut self, + device: Resource, + descriptor: webgpu::GpuShaderModuleDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let code = + wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::Owned(descriptor.code.to_owned())); + let shader = core_result( + self.0 + .instance() + .device_create_shader_module::( + device, + &descriptor.to_core(&self.0.table()), + code, + None, + ), + ) + .unwrap(); + + self.0.table().push(shader).unwrap() + } + + fn create_render_pipeline( + &mut self, + device: Resource, + descriptor: webgpu::GpuRenderPipelineDescriptor, + ) -> Resource { + let host_device = self.0.table().get(&device).unwrap().device; + let render_pipeline = core_result( + self.0 + .instance() + .device_create_render_pipeline::( + host_device, + &descriptor.to_core(&self.0.table()), + None, + None, + ), + ) + .unwrap(); + + self.0.table().push_child(render_pipeline, &device).unwrap() + } + + fn queue(&mut self, device: Resource) -> Resource { + let queue = self.0.table().get(&device).unwrap().queue; + self.0.table().push(queue).unwrap() + } + + fn features( + &mut self, + device: Resource, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let features = self + .0 + .instance() + .device_features::(device) + .unwrap(); + self.0.table().push(features).unwrap() + } + + fn limits( + &mut self, + device: Resource, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let limits = self + .0 + .instance() + .device_limits::(device) + .unwrap(); + self.0.table().push(limits).unwrap() + } + + fn destroy(&mut self, device: Resource) { + let device_id = self.0.table().get(&device).unwrap().device; + self.instance().device_destroy::(device_id); + } + + fn create_buffer( + &mut self, + device: Resource, + descriptor: webgpu::GpuBufferDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let size = descriptor.size; + let buffer_id = core_result(self.0.instance().device_create_buffer::( + device, + &descriptor.to_core(&self.0.table()), + None, + )) + .unwrap(); + + let buffer = Buffer { buffer_id, size }; + + self.0.table().push(buffer).unwrap() + } + + fn create_texture( + &mut self, + device: Resource, + descriptor: webgpu::GpuTextureDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let texture = core_result(self.0.instance().device_create_texture::( + device, + &descriptor.to_core(&self.0.table()), + None, + )) + .unwrap(); + + self.0.table().push(texture).unwrap() + } + + fn create_sampler( + &mut self, + device: Resource, + descriptor: Option, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let descriptor = descriptor.unwrap(); + + let sampler = core_result(self.0.instance().device_create_sampler::( + device, + &descriptor.to_core(&self.0.table()), + None, + )) + .unwrap(); + + self.0.table().push(sampler).unwrap() + } + + fn create_bind_group_layout( + &mut self, + device: Resource, + descriptor: webgpu::GpuBindGroupLayoutDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let bind_group_layout = core_result( + self.0 + .instance() + .device_create_bind_group_layout::( + device, + &descriptor.to_core(&self.0.table()), + None, + ), + ) + .unwrap(); + + self.0.table().push(bind_group_layout).unwrap() + } + + fn create_pipeline_layout( + &mut self, + device: Resource, + descriptor: webgpu::GpuPipelineLayoutDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let pipeline_layout = core_result( + self.0 + .instance() + .device_create_pipeline_layout::( + device, + &descriptor.to_core(&self.0.table()), + None, + ), + ) + .unwrap(); + + self.0.table().push(pipeline_layout).unwrap() + } + + fn create_bind_group( + &mut self, + device: Resource, + descriptor: webgpu::GpuBindGroupDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + + let bind_group = core_result( + self.0 + .instance() + .device_create_bind_group::( + device, + &descriptor.to_core(&self.0.table()), + None, + ), + ) + .unwrap(); + + self.0.table().push(bind_group).unwrap() + } + + fn create_compute_pipeline( + &mut self, + device: Resource, + descriptor: webgpu::GpuComputePipelineDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let compute_pipeline = core_result( + self.0 + .instance() + .device_create_compute_pipeline::( + device, + &descriptor.to_core(&self.0.table()), + None, + None, + ), + ) + .unwrap(); + self.0.table().push(compute_pipeline).unwrap() + } + + fn create_compute_pipeline_async( + &mut self, + _self_: Resource, + _descriptor: webgpu::GpuComputePipelineDescriptor, + ) -> Resource { + todo!() + } + + fn create_render_pipeline_async( + &mut self, + _self_: Resource, + _descriptor: webgpu::GpuRenderPipelineDescriptor, + ) -> Resource { + todo!() + } + + fn create_render_bundle_encoder( + &mut self, + device: Resource, + descriptor: webgpu::GpuRenderBundleEncoderDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let render_bundle_encoder = wgpu_core::command::RenderBundleEncoder::new( + &descriptor.to_core(&self.0.table()), + device, + None, + ) + .unwrap(); + self.0.table().push(render_bundle_encoder).unwrap() + } + + fn create_query_set( + &mut self, + device: Resource, + descriptor: webgpu::GpuQuerySetDescriptor, + ) -> Resource { + let device = self.0.table().get(&device).unwrap().device; + let query_set = core_result(self.0.instance().device_create_query_set::( + device, + &descriptor.to_core(&self.0.table()), + None, + )) + .unwrap(); + self.0.table().push(query_set).unwrap() + } + + fn label(&mut self, _device: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _device: Resource, _label: String) -> () { + todo!() + } + + fn lost( + &mut self, + _device: Resource, + ) -> Resource { + todo!() + } + + fn push_error_scope( + &mut self, + _device: Resource, + _filter: webgpu::GpuErrorFilter, + ) -> () { + todo!() + } + + fn pop_error_scope( + &mut self, + _device: Resource, + ) -> Option> { + todo!() + } + + fn uncaptured_errors(&mut self, _device: Resource) { + todo!() + } + + fn drop(&mut self, device: Resource) -> wasmtime::Result<()> { + self.table().delete(device).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuTexture for WasiWebGpuImpl { + fn from_graphics_buffer( + &mut self, + buffer: Resource, + ) -> Resource { + let host_buffer = self.table().delete(buffer).unwrap(); + let host_buffer: wgpu_core::id::TextureId = host_buffer.inner_type(); + self.0.table().push(host_buffer).unwrap() + } + + fn create_view( + &mut self, + texture: Resource, + descriptor: Option, + ) -> Resource { + let texture_id = *self.0.table().get(&texture).unwrap(); + let texture_view = core_result( + self.0.instance().texture_create_view::( + texture_id, + &descriptor + .map(|d| d.to_core(&self.0.table())) + .unwrap_or_default(), + None, + ), + ) + .unwrap(); + self.0.table().push(texture_view).unwrap() + } + + fn destroy(&mut self, texture: Resource) { + let texture_id = *self.0.table().get(&texture).unwrap(); + self.instance() + .texture_destroy::(texture_id) + .unwrap(); + } + + fn width(&mut self, _self_: Resource) -> webgpu::GpuIntegerCoordinateOut { + todo!() + } + + fn height(&mut self, _self_: Resource) -> webgpu::GpuIntegerCoordinateOut { + todo!() + } + + fn depth_or_array_layers( + &mut self, + _self_: Resource, + ) -> webgpu::GpuIntegerCoordinateOut { + todo!() + } + + fn mip_level_count( + &mut self, + _self_: Resource, + ) -> webgpu::GpuIntegerCoordinateOut { + todo!() + } + + fn sample_count(&mut self, _self_: Resource) -> webgpu::GpuSize32Out { + todo!() + } + + fn dimension(&mut self, _self_: Resource) -> webgpu::GpuTextureDimension { + todo!() + } + + fn format(&mut self, _self_: Resource) -> webgpu::GpuTextureFormat { + todo!() + } + + fn usage(&mut self, _self_: Resource) -> webgpu::GpuFlagsConstant { + todo!() + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, texture: Resource) -> wasmtime::Result<()> { + self.table().delete(texture).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuTextureView for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, view: Resource) -> wasmtime::Result<()> { + self.table().delete(view).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuCommandBuffer for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, command_buffer: Resource) -> wasmtime::Result<()> { + self.table().delete(command_buffer).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuShaderModule for WasiWebGpuImpl { + fn get_compilation_info( + &mut self, + _self_: Resource, + ) -> Resource { + todo!() + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, shader: Resource) -> wasmtime::Result<()> { + self.table().delete(shader).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuRenderPipeline for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn get_bind_group_layout( + &mut self, + pipeline: Resource, + index: u32, + ) -> Resource { + let pipeline_id = *self.0.table().get(&pipeline).unwrap(); + let layout = core_result( + self.instance() + .render_pipeline_get_bind_group_layout::(pipeline_id, index, None), + ) + .unwrap(); + self.0.table().push(layout).unwrap() + } + + fn drop(&mut self, pipeline: Resource) -> wasmtime::Result<()> { + self.table().delete(pipeline).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuAdapter for WasiWebGpuImpl { + fn request_device( + &mut self, + adapter: Resource, + descriptor: Option, + ) -> Resource { + let adapter_id = *self.0.table().get(&adapter).unwrap(); + + let (device_id, queue_id) = core_results_2( + self.0.instance().adapter_request_device::( + adapter_id, + &descriptor + .map(|d| d.to_core(&self.0.table())) + .unwrap_or_default(), + None, + None, + None, + ), + ) + .unwrap(); + + let device = self + .0 + .table() + .push(Device { + device: device_id, + queue: queue_id, + adapter: adapter_id, + }) + .unwrap(); + + device + } + + fn features( + &mut self, + adapter: wasmtime::component::Resource, + ) -> wasmtime::component::Resource { + let adapter = *self.0.table().get(&adapter).unwrap(); + let features = self + .instance() + .adapter_features::(adapter) + .unwrap(); + self.0.table().push(features).unwrap() + } + + fn limits( + &mut self, + adapter: Resource, + ) -> Resource { + let adapter = *self.0.table().get(&adapter).unwrap(); + let limits = self + .0 + .instance() + .adapter_limits::(adapter) + .unwrap(); + self.0.table().push(limits).unwrap() + } + + fn is_fallback_adapter( + &mut self, + _self_: wasmtime::component::Resource, + ) -> bool { + todo!() + } + + fn info( + &mut self, + adapter: Resource, + ) -> Resource { + let adapter_id = *self.0.table().get(&adapter).unwrap(); + let info = self + .instance() + .adapter_get_info::(adapter_id) + .unwrap(); + let info = self.0.table().push(info).unwrap(); + info + } + + fn drop(&mut self, adapter: Resource) -> wasmtime::Result<()> { + self.table().delete(adapter).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuQueue for WasiWebGpuImpl { + fn submit( + &mut self, + queue: Resource, + val: Vec>, + ) { + let command_buffers = val + .into_iter() + .map(|buffer| *self.0.table().get(&buffer).unwrap()) + .collect::>(); + let queue = *self.0.table().get(&queue).unwrap(); + self.0 + .instance() + .queue_submit::(queue, &command_buffers) + .unwrap(); + } + + fn on_submitted_work_done(&mut self, _self_: Resource) { + todo!() + } + + fn write_buffer( + &mut self, + queue: Resource, + buffer: Resource, + buffer_offset: webgpu::GpuSize64, + data_offset: Option, + data: Vec, + size: Option, + ) { + let queue = *self.0.table().get(&queue).unwrap(); + let buffer_id = self.0.table().get(&buffer).unwrap().buffer_id; + let mut data = &data[..]; + if let Some(data_offset) = data_offset { + let data_offset = data_offset as usize; + data = &data[data_offset..]; + } + if let Some(size) = size { + let size = size as usize; + data = &data[..size]; + } + self.0 + .instance() + .queue_write_buffer::(queue, buffer_id, buffer_offset, &data) + .unwrap(); + } + + fn write_texture( + &mut self, + queue: Resource, + destination: webgpu::GpuImageCopyTexture, + data: Vec, + data_layout: webgpu::GpuImageDataLayout, + size: webgpu::GpuExtent3D, + ) { + let queue = *self.0.table().get(&queue).unwrap(); + self.0 + .instance() + .queue_write_texture::( + queue, + &destination.to_core(&self.0.table()), + &data, + &data_layout.to_core(&self.0.table()), + &size.to_core(&self.0.table()), + ) + .unwrap(); + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, queue: Resource) -> wasmtime::Result<()> { + self.table().delete(queue).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuCommandEncoder for WasiWebGpuImpl { + fn begin_render_pass( + &mut self, + command_encoder: Resource, + descriptor: webgpu::GpuRenderPassDescriptor, + ) -> Resource { + let command_encoder = *self.0.table().get(&command_encoder).unwrap(); + let timestamp_writes = descriptor + .timestamp_writes + .map(|tw| tw.to_core(&self.0.table())); + // can't use to_core because depth_stencil_attachment is Option<&x>. + let depth_stencil_attachment = descriptor + .depth_stencil_attachment + .map(|d| d.to_core(&self.0.table())); + let descriptor = wgpu_core::command::RenderPassDescriptor { + label: descriptor.label.map(|l| l.into()), + color_attachments: descriptor + .color_attachments + .into_iter() + .map(|c| c.map(|c| c.to_core(&self.0.table()))) + .collect::>() + .into(), + depth_stencil_attachment: depth_stencil_attachment.as_ref(), + timestamp_writes: timestamp_writes.as_ref(), + occlusion_query_set: descriptor + .occlusion_query_set + .map(|oqs| oqs.to_core(&self.0.table())), + // TODO: self.max_draw_count not used + }; + let render_pass = core_result_t( + self.0 + .instance() + .command_encoder_create_render_pass::(command_encoder, &descriptor), + ) + .unwrap(); + + self.0.table().push(render_pass).unwrap() + } + + fn finish( + &mut self, + command_encoder: Resource, + descriptor: Option, + ) -> Resource { + let command_encoder = *self.0.table().get(&command_encoder).unwrap(); + let command_buffer = core_result( + self.0.instance().command_encoder_finish::( + command_encoder, + &descriptor + .map(|d| d.to_core(&self.0.table())) + .unwrap_or_default(), + ), + ) + .unwrap(); + self.0.table().push(command_buffer).unwrap() + } + + fn begin_compute_pass( + &mut self, + command_encoder: Resource, + descriptor: Option, + ) -> Resource { + let command_encoder = *self.0.table().get(&command_encoder).unwrap(); + let compute_pass = core_result_t( + self.0 + .instance() + .command_encoder_create_compute_pass::( + command_encoder, + // can't use to_core because timestamp_writes is Option<&x>. + &wgpu_core::command::ComputePassDescriptor { + // TODO: can we get rid of the clone here? + label: descriptor + .as_ref() + .map(|d| d.label.clone().map(|l| l.into())) + .flatten(), + timestamp_writes: descriptor + .map(|d| d.timestamp_writes.map(|tw| tw.to_core(&self.0.table()))) + .flatten() + .as_ref(), + }, + ), + ) + .unwrap(); + self.0.table().push(compute_pass).unwrap() + } + + fn copy_buffer_to_buffer( + &mut self, + command_encoder: Resource, + source: Resource, + source_offset: webgpu::GpuSize64, + destination: Resource, + destination_offset: webgpu::GpuSize64, + size: webgpu::GpuSize64, + ) { + let command_encoder = *self.0.table().get(&command_encoder).unwrap(); + let source = self.0.table().get(&source).unwrap().buffer_id; + let destination = self.0.table().get(&destination).unwrap().buffer_id; + self.0 + .instance() + .command_encoder_copy_buffer_to_buffer::( + command_encoder, + source, + source_offset, + destination, + destination_offset, + size, + ) + .unwrap(); + } + + fn copy_buffer_to_texture( + &mut self, + command_encoder: Resource, + source: webgpu::GpuImageCopyBuffer, + destination: webgpu::GpuImageCopyTexture, + copy_size: webgpu::GpuExtent3D, + ) { + let command_encoder = *self.table().get(&command_encoder).unwrap(); + self.instance() + .command_encoder_copy_buffer_to_texture::( + command_encoder, + &source.to_core(&self.table()), + &destination.to_core(&self.table()), + ©_size.to_core(self.table()), + ) + .unwrap(); + } + + fn copy_texture_to_buffer( + &mut self, + command_encoder: Resource, + source: webgpu::GpuImageCopyTexture, + destination: webgpu::GpuImageCopyBuffer, + copy_size: webgpu::GpuExtent3D, + ) { + let command_encoder = *self.table().get(&command_encoder).unwrap(); + self.instance() + .command_encoder_copy_texture_to_buffer::( + command_encoder, + &source.to_core(&self.table()), + &destination.to_core(&self.table()), + ©_size.to_core(&self.table()), + ) + .unwrap(); + } + + fn copy_texture_to_texture( + &mut self, + _self_: Resource, + _source: webgpu::GpuImageCopyTexture, + _destination: webgpu::GpuImageCopyTexture, + _copy_size: webgpu::GpuExtent3D, + ) { + todo!() + } + + fn clear_buffer( + &mut self, + _self_: Resource, + _buffer: Resource, + _offset: Option, + _size: Option, + ) { + todo!() + } + + fn resolve_query_set( + &mut self, + _self_: Resource, + _query_set: Resource, + _first_query: webgpu::GpuSize32, + _query_count: webgpu::GpuSize32, + _destination: Resource, + _destination_offset: webgpu::GpuSize64, + ) { + todo!() + } + + fn label(&mut self, command_encoder: Resource) -> String { + let _command_encoder = self.0.table().get(&command_encoder).unwrap(); + // TODO: return real label + String::new() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn push_debug_group( + &mut self, + command_encoder: Resource, + group_label: String, + ) { + let command_encoder = *self.table().get(&command_encoder).unwrap(); + self.instance() + .command_encoder_push_debug_group::(command_encoder, &group_label) + .unwrap(); + } + + fn pop_debug_group(&mut self, command_encoder: Resource) { + let command_encoder = *self.table().get(&command_encoder).unwrap(); + self.instance() + .command_encoder_pop_debug_group::(command_encoder) + .unwrap(); + } + + fn insert_debug_marker( + &mut self, + command_encoder: Resource, + marker_label: String, + ) { + let command_encoder = *self.table().get(&command_encoder).unwrap(); + self.instance() + .command_encoder_insert_debug_marker::(command_encoder, &marker_label) + .unwrap(); + } + + fn drop( + &mut self, + command_encoder: Resource, + ) -> wasmtime::Result<()> { + self.table().delete(command_encoder).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuRenderPassEncoder for WasiWebGpuImpl { + fn set_pipeline( + &mut self, + render_pass: Resource>, + pipeline: Resource, + ) { + let instance = self.0.instance(); + let pipeline = pipeline.to_core(&self.0.table()); + let render_pass = self.0.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_set_pipeline(render_pass, pipeline) + .unwrap() + } + + fn draw( + &mut self, + rpass: Resource>, + vertex_count: webgpu::GpuSize32, + instance_count: Option, + first_vertex: Option, + first_instance: Option, + ) { + let instance = self.0.instance(); + let rpass = self.0.table().get_mut(&rpass).unwrap(); + instance + .render_pass_draw( + rpass, + vertex_count, + instance_count.unwrap_or(1), + first_vertex.unwrap_or(0), + first_instance.unwrap_or(0), + ) + .unwrap() + } + + fn end(&mut self, rpass: Resource>) { + let instance = self.0.instance(); + let mut rpass = self.0.table().get_mut(&rpass).unwrap(); + instance + .render_pass_end::(&mut rpass) + .unwrap(); + } + + fn set_viewport( + &mut self, + render_pass: Resource>, + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, + ) { + let instance = self.0.instance(); + let render_pass = self.0.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_set_viewport(render_pass, x, y, width, height, min_depth, max_depth) + .unwrap(); + } + + fn set_scissor_rect( + &mut self, + render_pass: Resource>, + x: webgpu::GpuIntegerCoordinate, + y: webgpu::GpuIntegerCoordinate, + width: webgpu::GpuIntegerCoordinate, + height: webgpu::GpuIntegerCoordinate, + ) { + let instance = self.0.instance(); + let render_pass = self.0.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_set_scissor_rect(render_pass, x, y, width, height) + .unwrap(); + } + + fn set_blend_constant( + &mut self, + _self_: Resource>, + _color: webgpu::GpuColor, + ) { + todo!() + } + + fn set_stencil_reference( + &mut self, + _self_: Resource>, + _reference: webgpu::GpuStencilValue, + ) { + todo!() + } + + fn begin_occlusion_query( + &mut self, + _self_: Resource>, + _query_index: webgpu::GpuSize32, + ) { + todo!() + } + + fn end_occlusion_query( + &mut self, + _self_: Resource>, + ) { + todo!() + } + + fn execute_bundles( + &mut self, + _self_: Resource>, + _bundles: Vec>, + ) { + todo!() + } + + fn label( + &mut self, + _self_: Resource>, + ) -> String { + todo!() + } + + fn set_label( + &mut self, + _self_: Resource>, + _label: String, + ) { + todo!() + } + + fn push_debug_group( + &mut self, + _self_: Resource>, + _group_label: String, + ) { + todo!() + } + + fn pop_debug_group( + &mut self, + _self_: Resource>, + ) { + todo!() + } + + fn insert_debug_marker( + &mut self, + _self_: Resource>, + _marker_label: String, + ) { + todo!() + } + + fn set_bind_group( + &mut self, + render_pass: Resource>, + index: webgpu::GpuIndex32, + bind_group: Option>, + dynamic_offsets: Option>, + ) { + let instance = self.0.instance(); + let bind_group = *self + .0 + .table() + .get(&bind_group.expect("TODO: deal with null bind_groups")) + .unwrap(); + let mut render_pass = self.0.table().get_mut(&render_pass).unwrap(); + let dynamic_offsets = dynamic_offsets.unwrap(); + instance + .render_pass_set_bind_group(&mut render_pass, index, bind_group, &dynamic_offsets) + .unwrap() + } + + fn set_index_buffer( + &mut self, + render_pass: Resource>, + buffer: Resource, + index_format: webgpu::GpuIndexFormat, + offset: Option, + size: Option, + ) { + let instance = self.0.instance(); + let (buffer_id, buffer_size) = { + let buffer = self.table().get(&buffer).unwrap(); + (buffer.buffer_id, buffer.size) + }; + let render_pass = self.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_set_index_buffer( + render_pass, + buffer_id, + index_format.into(), + offset.unwrap_or(0), + core::num::NonZeroU64::new(size.unwrap_or(buffer_size)), + ) + .unwrap() + } + + fn set_vertex_buffer( + &mut self, + render_pass: Resource>, + slot: webgpu::GpuIndex32, + buffer: Option>, + offset: Option, + size: Option, + ) { + let instance = self.0.instance(); + let (buffer_id, buffer_size) = { + let buffer = self + .table() + .get(&buffer.expect("TODO: deal null buffers")) + .unwrap(); + (buffer.buffer_id, buffer.size) + }; + let mut render_pass = self.0.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_set_vertex_buffer( + &mut render_pass, + slot, + buffer_id, + offset.unwrap_or(0), + core::num::NonZeroU64::new(size.unwrap_or(buffer_size)), + ) + .unwrap() + } + + fn draw_indexed( + &mut self, + render_pass: Resource>, + index_count: webgpu::GpuSize32, + instance_count: Option, + first_index: Option, + base_vertex: Option, + first_instance: Option, + ) { + let instance = self.0.instance(); + let render_pass = self.table().get_mut(&render_pass).unwrap(); + instance + .render_pass_draw_indexed( + render_pass, + index_count, + instance_count.unwrap_or(1), + first_index.unwrap_or(0), + base_vertex.unwrap_or(0), + first_instance.unwrap_or(0), + ) + .unwrap() + } + + fn draw_indirect( + &mut self, + _self_: Resource>, + _indirect_buffer: Resource, + _indirect_offset: webgpu::GpuSize64, + ) { + todo!() + } + + fn draw_indexed_indirect( + &mut self, + _self_: Resource>, + _indirect_buffer: Resource, + _indirect_offset: webgpu::GpuSize64, + ) { + todo!() + } + + fn drop( + &mut self, + render_pass: Resource>, + ) -> wasmtime::Result<()> { + self.table().delete(render_pass).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuUncapturedErrorEvent for WasiWebGpuImpl { + fn new( + &mut self, + _type_: String, + _gpu_uncaptured_error_event_init_dict: webgpu::GpuUncapturedErrorEventInit, + ) -> Resource { + todo!() + } + + fn error( + &mut self, + _self_: Resource, + ) -> Resource { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuInternalError for WasiWebGpuImpl { + fn new(&mut self, _message: String) -> Resource { + todo!() + } + + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuOutOfMemoryError for WasiWebGpuImpl { + fn new(&mut self, _message: String) -> Resource { + todo!() + } + + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuValidationError for WasiWebGpuImpl { + fn new(&mut self, _message: String) -> Resource { + todo!() + } + + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuError for WasiWebGpuImpl { + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuDeviceLostInfo for WasiWebGpuImpl { + fn reason( + &mut self, + _self_: Resource, + ) -> webgpu::GpuDeviceLostReason { + todo!() + } + + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { + self.table().delete(info).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuCanvasContext for WasiWebGpuImpl { + fn configure( + &mut self, + _self_: Resource, + _configuration: webgpu::GpuCanvasConfiguration, + ) { + todo!() + } + + fn unconfigure(&mut self, _self_: Resource) { + todo!() + } + + fn get_current_texture( + &mut self, + _self_: Resource, + ) -> Resource { + todo!() + } + + fn drop(&mut self, _rep: Resource) -> wasmtime::Result<()> { + todo!() + } +} +impl webgpu::HostGpuRenderBundle for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, bundle: Resource) -> wasmtime::Result<()> { + self.table().delete(bundle).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuComputePassEncoder for WasiWebGpuImpl { + fn set_pipeline( + &mut self, + encoder: Resource, + pipeline: Resource, + ) { + let instance = self.0.instance(); + let pipeline = *self.0.table().get(&pipeline).unwrap(); + let encoder = self.0.table().get_mut(&encoder).unwrap(); + instance + .compute_pass_set_pipeline(encoder, pipeline) + .unwrap(); + } + + fn dispatch_workgroups( + &mut self, + encoder: Resource, + workgroup_count_x: webgpu::GpuSize32, + workgroup_count_y: Option, + workgroup_count_z: Option, + ) { + let instance = self.0.instance(); + let encoder = self.0.table().get_mut(&encoder).unwrap(); + instance + .compute_pass_dispatch_workgroups( + encoder, + workgroup_count_x, + workgroup_count_y.unwrap(), + workgroup_count_z.unwrap(), + ) + .unwrap() + } + + fn dispatch_workgroups_indirect( + &mut self, + encoder: Resource, + indirect_buffer: Resource, + indirect_offset: webgpu::GpuSize64, + ) { + let instance = self.instance(); + let indirect_buffer = self.0.table().get(&indirect_buffer).unwrap().buffer_id; + let encoder = self.0.table().get_mut(&encoder).unwrap(); + instance + .compute_pass_dispatch_workgroups_indirect(encoder, indirect_buffer, indirect_offset) + .unwrap(); + } + + fn end(&mut self, cpass: Resource>) { + let instance = self.0.instance(); + let mut cpass = self.0.table().get_mut(&cpass).unwrap(); + instance + .compute_pass_end::(&mut cpass) + .unwrap(); + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn push_debug_group( + &mut self, + cpass: Resource, + group_label: String, + ) { + let instance = self.instance(); + let cpass = self.table().get_mut(&cpass).unwrap(); + instance + .compute_pass_push_debug_group(cpass, &group_label, 0) + .unwrap(); + } + + fn pop_debug_group(&mut self, cpass: Resource) { + let instance = self.instance(); + let cpass = self.table().get_mut(&cpass).unwrap(); + instance.compute_pass_pop_debug_group(cpass).unwrap(); + } + + fn insert_debug_marker( + &mut self, + cpass: Resource, + label: String, + ) { + let instance = self.0.instance(); + let cpass = self.0.table().get_mut(&cpass).unwrap(); + instance + .compute_pass_insert_debug_marker(cpass, &label, 0) + .unwrap() + } + + fn set_bind_group( + &mut self, + encoder: Resource, + index: webgpu::GpuIndex32, + bind_group: Option>, + dynamic_offsets: Option>, + ) { + let instance = self.0.instance(); + let bind_group = *self + .0 + .table() + .get(&bind_group.expect("TODO: deal with null bind_groups")) + .unwrap(); + let encoder = self.0.table().get_mut(&encoder).unwrap(); + let dynamic_offsets = dynamic_offsets.unwrap(); + instance + .compute_pass_set_bind_group(encoder, index, bind_group, &dynamic_offsets) + .unwrap() + } + + fn drop(&mut self, encoder: Resource) -> wasmtime::Result<()> { + self.table().delete(encoder).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuPipelineError for WasiWebGpuImpl { + fn new( + &mut self, + _message: Option, + _options: webgpu::GpuPipelineErrorInit, + ) -> Resource { + todo!() + } + + fn reason( + &mut self, + _self_: Resource, + ) -> webgpu::GpuPipelineErrorReason { + todo!() + } + + fn drop(&mut self, error: Resource) -> wasmtime::Result<()> { + self.table().delete(error).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuCompilationMessage for WasiWebGpuImpl { + fn message(&mut self, _self_: Resource) -> String { + todo!() + } + + fn type_( + &mut self, + _self_: Resource, + ) -> webgpu::GpuCompilationMessageType { + todo!() + } + + fn line_num(&mut self, _self_: Resource) -> u64 { + todo!() + } + + fn line_pos(&mut self, _self_: Resource) -> u64 { + todo!() + } + + fn offset(&mut self, _self_: Resource) -> u64 { + todo!() + } + + fn length(&mut self, _self_: Resource) -> u64 { + todo!() + } + + fn drop(&mut self, cm: Resource) -> wasmtime::Result<()> { + self.table().delete(cm).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuCompilationInfo for WasiWebGpuImpl { + fn messages( + &mut self, + _self_: Resource, + ) -> Vec> { + todo!() + } + + fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { + self.table().delete(info).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuQuerySet for WasiWebGpuImpl { + fn destroy(&mut self, _self_: Resource) { + todo!() + } + + fn type_(&mut self, _self_: Resource) -> webgpu::GpuQueryType { + todo!() + } + + fn count(&mut self, _self_: Resource) -> webgpu::GpuSize32Out { + todo!() + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, query_set: Resource) -> wasmtime::Result<()> { + self.table().delete(query_set).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuRenderBundleEncoder for WasiWebGpuImpl { + fn finish( + &mut self, + _self_: Resource, + _descriptor: Option, + ) -> Resource { + todo!() + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn push_debug_group( + &mut self, + _self_: Resource, + _group_label: String, + ) { + todo!() + } + + fn pop_debug_group(&mut self, _self_: Resource) { + todo!() + } + + fn insert_debug_marker( + &mut self, + _self_: Resource, + _marker_label: String, + ) { + todo!() + } + + fn set_bind_group( + &mut self, + _self_: Resource, + _index: webgpu::GpuIndex32, + _bind_group: Option>, + _dynamic_offsets: Option>, + ) { + todo!() + } + + fn set_pipeline( + &mut self, + _self_: Resource, + _pipeline: Resource, + ) { + todo!() + } + + fn set_index_buffer( + &mut self, + _self_: Resource, + _buffer: Resource, + _index_format: webgpu::GpuIndexFormat, + _offset: Option, + _size: Option, + ) { + todo!() + } + + fn set_vertex_buffer( + &mut self, + _self_: Resource, + _slot: webgpu::GpuIndex32, + _buffer: Option>, + _offset: Option, + _size: Option, + ) { + todo!() + } + + fn draw( + &mut self, + _self_: Resource, + _vertex_count: webgpu::GpuSize32, + _instance_count: Option, + _first_vertex: Option, + _first_instance: Option, + ) { + todo!() + } + + fn draw_indexed( + &mut self, + _self_: Resource, + _index_count: webgpu::GpuSize32, + _instance_count: Option, + _first_index: Option, + _base_vertex: Option, + _first_instance: Option, + ) { + todo!() + } + + fn draw_indirect( + &mut self, + _self_: Resource, + _indirect_buffer: Resource, + _indirect_offset: webgpu::GpuSize64, + ) { + todo!() + } + + fn draw_indexed_indirect( + &mut self, + _self_: Resource, + _indirect_buffer: Resource, + _indirect_offset: webgpu::GpuSize64, + ) { + todo!() + } + + fn drop(&mut self, encoder: Resource) -> wasmtime::Result<()> { + self.table().delete(encoder).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuComputePipeline for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn get_bind_group_layout( + &mut self, + compute_pipeline: Resource, + index: u32, + ) -> Resource { + let pipeline_id = *self.0.table().get(&compute_pipeline).unwrap(); + let bind_group_layout = core_result( + self.0 + .instance() + .compute_pipeline_get_bind_group_layout::(pipeline_id, index, None), + ) + .unwrap(); + self.0.table().push(bind_group_layout).unwrap() + } + + fn drop(&mut self, pipeline: Resource) -> wasmtime::Result<()> { + self.table().delete(pipeline).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuBindGroup for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, bind_group: Resource) -> wasmtime::Result<()> { + self.table().delete(bind_group).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuPipelineLayout for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, layout: Resource) -> wasmtime::Result<()> { + self.table().delete(layout).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuBindGroupLayout for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, layout: Resource) -> wasmtime::Result<()> { + self.table().delete(layout).unwrap(); + Ok(()) + } +} + +impl webgpu::HostGpuSampler for WasiWebGpuImpl { + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, sampler: Resource) -> wasmtime::Result<()> { + self.table().delete(sampler).unwrap(); + Ok(()) + } +} + +#[async_trait::async_trait] +impl webgpu::HostGpuBuffer for WasiWebGpuImpl { + fn size(&mut self, buffer: Resource) -> webgpu::GpuSize64Out { + let buffer = self.table().get(&buffer).unwrap(); + buffer.size + } + + fn usage(&mut self, _self_: Resource) -> webgpu::GpuFlagsConstant { + todo!() + } + + fn map_state(&mut self, _self_: Resource) -> webgpu::GpuBufferMapState { + todo!() + } + + async fn map_async( + &mut self, + buffer: Resource, + mode: webgpu::GpuMapModeFlags, + offset: Option, + size: Option, + ) { + let buffer_id = self.0.table().get(&buffer).unwrap().buffer_id; + let instance = self.0.instance(); + CallbackFuture::new(Box::new( + move |resolve: Box< + dyn FnOnce(Box>) + Send, + >| { + // TODO: move to convertion function + // source: https://www.w3.org/TR/webgpu/#typedefdef-gpumapmodeflags + let host = match mode { + 1 => wgpu_core::device::HostMap::Read, + 2 => wgpu_core::device::HostMap::Write, + _ => panic!(), + }; + let op = wgpu_core::resource::BufferMapOperation { + host, + callback: Some(wgpu_core::resource::BufferMapCallback::from_rust(Box::new( + move |result| { + resolve(Box::new(result)); + }, + ))), + }; + + let offset = offset.unwrap(); + instance + .buffer_map_async::(buffer_id, offset, size, op) + .unwrap(); + // TODO: only poll this device. + instance.poll_all_devices(true).unwrap(); + }, + )) + .await + .unwrap(); + } + + fn get_mapped_range( + &mut self, + buffer: Resource, + offset: Option, + size: Option, + ) -> Resource { + let buffer_id = self.0.table().get(&buffer).unwrap().buffer_id; + let (ptr, len) = self + .0 + .instance() + .buffer_get_mapped_range::(buffer_id, offset.unwrap_or(0), size) + .unwrap(); + let remote_buffer = BufferPtr { ptr, len }; + self.0.table().push(remote_buffer).unwrap() + } + + fn unmap(&mut self, buffer: Resource) { + let buffer_id = self.0.table().get_mut(&buffer).unwrap().buffer_id; + self.0 + .instance() + .buffer_unmap::(buffer_id) + .unwrap(); + } + + fn destroy(&mut self, _self_: Resource) { + todo!() + } + + fn label(&mut self, _self_: Resource) -> String { + todo!() + } + + fn set_label(&mut self, _self_: Resource, _label: String) { + todo!() + } + + fn drop(&mut self, buffer: Resource) -> wasmtime::Result<()> { + self.table().delete(buffer).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpu for WasiWebGpuImpl { + fn request_adapter( + &mut self, + _self_: Resource, + options: Option, + ) -> Option> { + let adapter = self.0.instance().request_adapter( + &options.map(|o| o.to_core(self.table())).unwrap_or_default(), + wgpu_core::instance::AdapterInputs::Mask(wgpu_types::Backends::all(), |_| None), + ); + if let Err(wgpu_core::instance::RequestAdapterError::NotFound) = adapter { + return None; + } + let adapter = adapter.unwrap(); + Some(self.0.table().push(adapter).unwrap()) + } + + fn get_preferred_canvas_format( + &mut self, + _gpu: Resource, + ) -> webgpu::GpuTextureFormat { + // https://searchfox.org/mozilla-central/source/dom/webgpu/Instance.h#42 + #[cfg(target_os = "android")] + return webgpu::GpuTextureFormat::Rgba8unorm; + #[cfg(not(target_os = "android"))] + return webgpu::GpuTextureFormat::Bgra8unorm; + } + + fn wgsl_language_features( + &mut self, + _self_: Resource, + ) -> Resource { + todo!() + } + + fn drop(&mut self, _gpu: Resource) -> wasmtime::Result<()> { + // not actually a resource in the table + Ok(()) + } +} +impl webgpu::HostGpuAdapterInfo for WasiWebGpuImpl { + fn vendor(&mut self, _self_: Resource) -> String { + todo!() + } + + fn architecture(&mut self, _self_: Resource) -> String { + todo!() + } + + fn device(&mut self, _self_: Resource) -> String { + todo!() + } + + fn description(&mut self, _self_: Resource) -> String { + todo!() + } + + fn drop(&mut self, info: Resource) -> wasmtime::Result<()> { + self.table().delete(info).unwrap(); + Ok(()) + } +} +impl webgpu::HostWgslLanguageFeatures for WasiWebGpuImpl { + fn has(&mut self, _self_: Resource, _key: String) -> bool { + todo!() + } + + fn drop(&mut self, features: Resource) -> wasmtime::Result<()> { + self.table().delete(features).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuSupportedFeatures for WasiWebGpuImpl { + fn has(&mut self, features: Resource, query: String) -> bool { + let features = self.0.table().get(&features).unwrap(); + match query.as_str() { + "depth-clip-control" => features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL), + "timestamp-query" => features.contains(wgpu_types::Features::TIMESTAMP_QUERY), + "indirect-first-instance" => { + features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) + } + "shader-f16" => features.contains(wgpu_types::Features::SHADER_F16), + "depth32float-stencil8" => { + features.contains(wgpu_types::Features::DEPTH32FLOAT_STENCIL8) + } + "texture-compression-bc" => { + features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_BC) + } + "texture-compression-etc2" => { + features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2) + } + "texture-compression-astc" => { + features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC) + } + "rg11b10ufloat-renderable" => { + features.contains(wgpu_types::Features::RG11B10UFLOAT_RENDERABLE) + } + "bgra8unorm-storage" => features.contains(wgpu_types::Features::BGRA8UNORM_STORAGE), + "float32-filterable" => features.contains(wgpu_types::Features::FLOAT32_FILTERABLE), + _ => todo!(), + } + } + + fn drop(&mut self, features: Resource) -> wasmtime::Result<()> { + self.table().delete(features).unwrap(); + Ok(()) + } +} +impl webgpu::HostGpuSupportedLimits for WasiWebGpuImpl { + fn max_texture_dimension1_d(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_texture_dimension_1d + } + + fn max_texture_dimension2_d(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_texture_dimension_2d + } + + fn max_texture_dimension3_d(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_texture_dimension_3d + } + + fn max_texture_array_layers(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_texture_array_layers + } + + fn max_bind_groups(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_bind_groups + } + + fn max_bind_groups_plus_vertex_buffers( + &mut self, + _limits: Resource, + ) -> u32 { + todo!() + } + + fn max_bindings_per_bind_group(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_bindings_per_bind_group + } + + fn max_dynamic_uniform_buffers_per_pipeline_layout( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_dynamic_uniform_buffers_per_pipeline_layout + } + + fn max_dynamic_storage_buffers_per_pipeline_layout( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_dynamic_storage_buffers_per_pipeline_layout + } + + fn max_sampled_textures_per_shader_stage( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_sampled_textures_per_shader_stage + } + + fn max_samplers_per_shader_stage( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_samplers_per_shader_stage + } + + fn max_storage_buffers_per_shader_stage( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_storage_buffers_per_shader_stage + } + + fn max_storage_textures_per_shader_stage( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_storage_textures_per_shader_stage + } + + fn max_uniform_buffers_per_shader_stage( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_uniform_buffers_per_shader_stage + } + + fn max_uniform_buffer_binding_size( + &mut self, + limits: Resource, + ) -> u64 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_uniform_buffer_binding_size as u64 + } + + fn max_storage_buffer_binding_size( + &mut self, + limits: Resource, + ) -> u64 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_storage_buffer_binding_size as u64 + } + + fn min_uniform_buffer_offset_alignment( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.min_uniform_buffer_offset_alignment + } + + fn min_storage_buffer_offset_alignment( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.min_storage_buffer_offset_alignment + } + + fn max_vertex_buffers(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_vertex_buffers + } + + fn max_buffer_size(&mut self, limits: Resource) -> u64 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_buffer_size + } + + fn max_vertex_attributes(&mut self, limits: Resource) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_vertex_attributes + } + + fn max_vertex_buffer_array_stride( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_vertex_buffer_array_stride + } + + fn max_inter_stage_shader_variables( + &mut self, + _limits: Resource, + ) -> u32 { + todo!() + } + + fn max_color_attachments(&mut self, _limits: Resource) -> u32 { + todo!() + } + + fn max_color_attachment_bytes_per_sample( + &mut self, + _limits: Resource, + ) -> u32 { + todo!() + } + + fn max_compute_workgroup_storage_size( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_workgroup_storage_size + } + + fn max_compute_invocations_per_workgroup( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_invocations_per_workgroup + } + + fn max_compute_workgroup_size_x( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_workgroup_size_x + } + + fn max_compute_workgroup_size_y( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_workgroup_size_y + } + + fn max_compute_workgroup_size_z( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_workgroup_size_z + } + + fn max_compute_workgroups_per_dimension( + &mut self, + limits: Resource, + ) -> u32 { + let limits = self.0.table().get(&limits).unwrap(); + limits.max_compute_workgroups_per_dimension + } + + fn drop(&mut self, limits: Resource) -> wasmtime::Result<()> { + self.table().delete(limits).unwrap(); + Ok(()) + } +} + +fn core_result( + (id, error): (wgpu_core::id::Id, Option), +) -> Result, E> +where + I: wgpu_core::id::Marker, +{ + match error { + Some(error) => Err(error), + None => Ok(id), + } +} + +// same as core_result, but but result doesn't need to be id. +fn core_result_t((t, error): (T, Option)) -> Result { + match error { + Some(error) => Err(error), + None => Ok(t), + } +} + +// same as core_result, but handles tuple of two ids for Ok. +fn core_results_2( + (a, b, error): (wgpu_core::id::Id, wgpu_core::id::Id, Option), +) -> Result<(wgpu_core::id::Id, wgpu_core::id::Id), E> +where + I1: wgpu_core::id::Marker, + I2: wgpu_core::id::Marker, +{ + match error { + Some(error) => Err(error), + None => Ok((a, b)), + } +} diff --git a/crates/wasi-webgpu-wasmtime/src/wrapper_types.rs b/crates/wasi-webgpu-wasmtime/src/wrapper_types.rs new file mode 100644 index 0000000..544bc5e --- /dev/null +++ b/crates/wasi-webgpu-wasmtime/src/wrapper_types.rs @@ -0,0 +1,43 @@ +// Wrappers around `wgpu_*` types +// Every type here should have an explanation as to why we can't use the type directly. + +use std::{collections::HashMap, ptr::NonNull, slice}; + +use crate::wasi::webgpu::webgpu; + +// can't pass generics to `wasmtime::component::bindgen` +pub type RenderPass = wgpu_core::command::RenderPass; +pub type ComputePass = wgpu_core::command::ComputePass; +pub type RecordGpuPipelineConstantValue = HashMap; + +// needed just to group the pointer and length together +pub struct BufferPtr { + // See https://bytecodealliance.zulipchat.com/#narrow/stream/206238-general/topic/Should.20wasi.20resources.20be.20stored.20behind.20a.20mutex.3F + pub(crate) ptr: NonNull, + pub(crate) len: u64, +} +impl BufferPtr { + pub fn slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) } + } + pub fn slice_mut(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) } + } +} +unsafe impl Send for BufferPtr {} +unsafe impl Sync for BufferPtr {} + +// size needed in `GpuBuffer.size`, `RenderPass.set_index_buffer`, `RenderPass.set_vertex_buffer` +pub struct Buffer { + pub(crate) buffer_id: wgpu_core::id::BufferId, + pub(crate) size: u64, +} + +// queue needed for Device.queue +// adapter needed for surface_get_capabilities in connect_graphics_context +#[derive(Clone, Copy)] +pub struct Device { + pub(crate) device: wgpu_core::id::DeviceId, + pub(crate) queue: wgpu_core::id::QueueId, + pub(crate) adapter: wgpu_core::id::AdapterId, +}