From 12698ad236c4db4cc1ad08cc9b8168d816f00ed8 Mon Sep 17 00:00:00 2001 From: Mendy Berger <12537668+MendyBerger@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:38 -0500 Subject: [PATCH] Replace unwrap and default with hardcoded or user-provided values --- .../src/enum_conversions.rs | 11 + crates/wasi-webgpu-wasmtime/src/lib.rs | 33 +- .../src/to_core_conversions.rs | 377 +++++++++++++----- 3 files changed, 323 insertions(+), 98 deletions(-) diff --git a/crates/wasi-webgpu-wasmtime/src/enum_conversions.rs b/crates/wasi-webgpu-wasmtime/src/enum_conversions.rs index cf5b14d..0e5be88 100644 --- a/crates/wasi-webgpu-wasmtime/src/enum_conversions.rs +++ b/crates/wasi-webgpu-wasmtime/src/enum_conversions.rs @@ -1,5 +1,16 @@ use crate::wasi::webgpu::webgpu; +impl From for wgpu_types::PowerPreference { + fn from(value: webgpu::GpuPowerPreference) -> Self { + match value { + webgpu::GpuPowerPreference::LowPower => wgpu_types::PowerPreference::LowPower, + webgpu::GpuPowerPreference::HighPerformance => { + wgpu_types::PowerPreference::HighPerformance + } + } + } +} + impl From for webgpu::GpuTextureFormat { fn from(value: wgpu_types::TextureFormat) -> Self { match value { diff --git a/crates/wasi-webgpu-wasmtime/src/lib.rs b/crates/wasi-webgpu-wasmtime/src/lib.rs index 5938c1a..669940c 100644 --- a/crates/wasi-webgpu-wasmtime/src/lib.rs +++ b/crates/wasi-webgpu-wasmtime/src/lib.rs @@ -8,6 +8,7 @@ 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}; @@ -83,6 +84,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/graphics-context": wasi_graphics_context_wasmtime, }, }); @@ -251,6 +253,8 @@ pub struct 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) @@ -824,7 +828,12 @@ impl webgpu::HostGpuDevice for WasiWebGpuImpl { 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(); + 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() } @@ -1213,6 +1222,9 @@ impl webgpu::HostGpuCommandEncoder for WasiWebGpuImpl { 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 @@ -1226,11 +1238,11 @@ impl webgpu::HostGpuCommandEncoder for WasiWebGpuImpl { .collect::>() .into(), depth_stencil_attachment: depth_stencil_attachment.as_ref(), - // timestamp_writes: self.timestamp_writes, - // occlusion_query_set: self.occlusion_query_set, + 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 - // TODO: remove default - ..Default::default() }; let render_pass = core_result_t( self.0 @@ -1279,8 +1291,13 @@ impl webgpu::HostGpuCommandEncoder for WasiWebGpuImpl { .instance() .command_encoder_create_compute_pass::( command_encoder, + // can't use to_core because timestamp_writes is Option<&x>. &wgpu_core::command::ComputePassDescriptor { - label: Default::default(), + // 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() @@ -2317,10 +2334,10 @@ impl webgpu::HostGpu for WasiWebGpuImpl { fn request_adapter( &mut self, _self_: Resource, - _options: Option, + options: Option, ) -> Option> { let adapter = self.0.instance().request_adapter( - &Default::default(), + &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 { diff --git a/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs b/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs index 24b0d1a..d6791dd 100644 --- a/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs +++ b/crates/wasi-webgpu-wasmtime/src/to_core_conversions.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use wasmtime::component::ResourceTable; use crate::wasi::webgpu::webgpu; @@ -15,12 +17,32 @@ where } } +impl ToCore> + for webgpu::GpuRequestAdapterOptions +{ + fn to_core( + self, + _table: &ResourceTable, + ) -> wgpu_types::RequestAdapterOptions { + wgpu_types::RequestAdapterOptions { + power_preference: self + .power_preference + .map(|pp| pp.into()) + .unwrap_or(wgpu_types::PowerPreference::None), + // https://www.w3.org/TR/webgpu/#adapter-selection + force_fallback_adapter: self.force_fallback_adapter.unwrap_or(false), + compatible_surface: None, + } + } +} + impl ToCore for webgpu::GpuExtent3D { fn to_core(self, _table: &ResourceTable) -> wgpu_types::Extent3d { + // https://www.w3.org/TR/webgpu/#dictdef-gpuextent3ddict wgpu_types::Extent3d { width: self.width, - height: self.height.unwrap(), - depth_or_array_layers: self.depth_or_array_layers.unwrap(), + height: self.height.unwrap_or(1), + depth_or_array_layers: self.depth_or_array_layers.unwrap_or(1), } } } @@ -68,9 +90,10 @@ impl<'a> ToCore> for webgpu::GpuBi impl<'a> ToCore for webgpu::GpuBufferBinding { fn to_core(self, table: &ResourceTable) -> wgpu_core::binding_model::BufferBinding { let buffer = table.get(&self.buffer).unwrap(); + // https://www.w3.org/TR/webgpu/#dictdef-gpubufferbinding wgpu_core::binding_model::BufferBinding { buffer_id: buffer.buffer, - offset: self.offset.unwrap(), + offset: self.offset.unwrap_or(0), size: self.size.map(|s| s.try_into().unwrap()), } } @@ -108,15 +131,17 @@ impl<'a> ToCore> label: self.label.map(|l| l.into()), format: self.format.map(|f| f.into()), dimension: self.dimension.map(|d| d.into()), - // TODO: Don't default - range: Default::default(), - // range: wgpu_types::ImageSubresourceRange { - // aspect: self.aspect, - // base_mip_level: self.base_mip_level, - // mip_level_count: self.mip_level_count, - // base_array_layer: self.base_array_layer, - // array_layer_count: self.array_layer_count, - // } + // https://www.w3.org/TR/webgpu/#texture-view-creation + range: wgpu_types::ImageSubresourceRange { + aspect: self + .aspect + .map(|a| a.into()) + .unwrap_or(wgpu_types::TextureAspect::All), + base_mip_level: self.base_mip_level.unwrap_or(0), + mip_level_count: self.mip_level_count, + base_array_layer: self.base_array_layer.unwrap_or(0), + array_layer_count: self.array_layer_count, + }, } } } @@ -154,15 +179,15 @@ impl<'a> ToCore> }, }, vertex: self.vertex.to_core(table), - primitive: self.primitive.map(|p| p.to_core(table)).unwrap(), + primitive: self.primitive.map(|p| p.to_core(table)).unwrap_or_default(), depth_stencil: self.depth_stencil.map(|ds| ds.to_core(table)), multisample: self .multisample .map(|ms| ms.to_core(table)) .unwrap_or_default(), fragment: self.fragment.map(|f| f.to_core(table)), - // TODO: remove default - multiview: Default::default(), + // multiview and cache are not present in WebGPU + multiview: None, cache: None, } } @@ -170,20 +195,22 @@ impl<'a> ToCore> impl ToCore for webgpu::GpuMultisampleState { fn to_core(self, _table: &ResourceTable) -> wgpu_types::MultisampleState { + // https://www.w3.org/TR/webgpu/#dictdef-gpumultisamplestate wgpu_types::MultisampleState { - count: self.count.unwrap(), - mask: self.mask.unwrap().into(), - alpha_to_coverage_enabled: self.alpha_to_coverage_enabled.unwrap(), + count: self.count.unwrap_or(1), + mask: self.mask.unwrap_or(0xFFFFFFFF).into(), + alpha_to_coverage_enabled: self.alpha_to_coverage_enabled.unwrap_or(false), } } } impl ToCore for webgpu::GpuDepthStencilState { fn to_core(self, table: &ResourceTable) -> wgpu_types::DepthStencilState { + // https://www.w3.org/TR/webgpu/#depth-stencil-state wgpu_types::DepthStencilState { format: self.format.into(), - depth_write_enabled: self.depth_write_enabled.unwrap().into(), - depth_compare: self.depth_compare.unwrap().into(), + depth_write_enabled: self.depth_write_enabled.expect("TODO: handle null").into(), + depth_compare: self.depth_compare.expect("TODO: handle null").into(), stencil: wgpu_types::StencilState { front: self .stencil_front @@ -193,13 +220,13 @@ impl ToCore for webgpu::GpuDepthStencilState { .stencil_back .map(|b| b.to_core(table)) .unwrap_or_default(), - read_mask: self.stencil_read_mask.unwrap_or_default(), - write_mask: self.stencil_write_mask.unwrap_or_default(), + read_mask: self.stencil_read_mask.unwrap_or(0xFFFFFFFF), + write_mask: self.stencil_write_mask.unwrap_or(0xFFFFFFFF), }, bias: wgpu_types::DepthBiasState { - constant: self.depth_bias.unwrap_or_default(), - slope_scale: self.depth_bias_slope_scale.unwrap_or_default(), - clamp: self.depth_bias_clamp.unwrap_or_default(), + constant: self.depth_bias.unwrap_or(0), + slope_scale: self.depth_bias_slope_scale.unwrap_or(0.0), + clamp: self.depth_bias_clamp.unwrap_or(0.0), }, } } @@ -230,15 +257,22 @@ impl ToCore for webgpu::GpuStencilFaceState { impl ToCore for webgpu::GpuPrimitiveState { fn to_core(self, _table: &ResourceTable) -> wgpu_types::PrimitiveState { + // https://www.w3.org/TR/webgpu/#dictdef-gpuprimitivestate wgpu_types::PrimitiveState { - topology: self.topology.map(|t| t.into()).unwrap_or_default(), + topology: self + .topology + .map(|t| t.into()) + .unwrap_or(wgpu_types::PrimitiveTopology::TriangleList), strip_index_format: self.strip_index_format.map(|f| f.into()), - front_face: self.front_face.map(|x| x.into()).unwrap_or_default(), + front_face: self + .front_face + .map(|x| x.into()) + .unwrap_or(wgpu_types::FrontFace::Ccw), cull_mode: self.cull_mode.map(|cm| cm.into()), - unclipped_depth: self.unclipped_depth.unwrap_or_default(), - // TODO: remove defaults - polygon_mode: Default::default(), - conservative: Default::default(), + unclipped_depth: self.unclipped_depth.unwrap_or(false), + // polygon_mode and conservative are not present in WebGPU + polygon_mode: wgpu_types::PolygonMode::Fill, + conservative: false, } } } @@ -248,8 +282,15 @@ impl<'a> ToCore> for webgpu::GpuFragmentS wgpu_core::pipeline::FragmentState { stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: self.module.to_core(table), - entry_point: Some(self.entry_point.unwrap_or_default().into()), - constants: Default::default(), + entry_point: self.entry_point.map(|ep| ep.into()), + constants: self + .constants + .map(|constants| { + // TODO: can we get rid of the clone here? + let constants = table.get(&constants).unwrap().clone(); + Cow::Owned(constants) + }) + .unwrap_or_default(), zero_initialize_workgroup_memory: true, vertex_pulling_transform: false, }, @@ -265,13 +306,11 @@ impl<'a> ToCore> for webgpu::GpuFragmentS impl ToCore for webgpu::GpuColorTargetState { fn to_core(self, table: &ResourceTable) -> wgpu_types::ColorTargetState { + // https://www.w3.org/TR/webgpu/#color-target-state wgpu_types::ColorTargetState { format: self.format.into(), blend: self.blend.map(|b| b.to_core(table)), - write_mask: self - .write_mask - .map(|wm| wgpu_types::ColorWrites::from_bits(wm).unwrap()) - .unwrap_or_default(), + write_mask: wgpu_types::ColorWrites::from_bits(self.write_mask.unwrap_or(0xF)).unwrap(), } } } @@ -288,7 +327,11 @@ impl ToCore for webgpu::GpuBlendState { impl ToCore for webgpu::GpuBlendComponent { fn to_core(self, _table: &ResourceTable) -> wgpu_types::BlendComponent { wgpu_types::BlendComponent { - // TODO: link to spec for defaults. + // https://www.w3.org/TR/webgpu/#dictdef-gpublendcomponent + operation: self + .operation + .map(|x| x.into()) + .unwrap_or(wgpu_types::BlendOperation::Add), src_factor: self .src_factor .map(|x| x.into()) @@ -297,21 +340,25 @@ impl ToCore for webgpu::GpuBlendComponent { .dst_factor .map(|x| x.into()) .unwrap_or(wgpu_types::BlendFactor::Zero), - operation: self - .operation - .map(|x| x.into()) - .unwrap_or(wgpu_types::BlendOperation::Add), } } } impl<'a> ToCore> for webgpu::GpuVertexState { fn to_core(self, table: &ResourceTable) -> wgpu_core::pipeline::VertexState<'a> { + // https://www.w3.org/TR/webgpu/#dictdef-gpuvertexstate wgpu_core::pipeline::VertexState { stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: self.module.to_core(table), entry_point: self.entry_point.map(|e| e.into()), - constants: Default::default(), + constants: self + .constants + .map(|constants| { + // TODO: can we get rid of the clone here? + let constants = table.get(&constants).unwrap().clone(); + Cow::Owned(constants) + }) + .unwrap_or_default(), zero_initialize_workgroup_memory: true, vertex_pulling_transform: false, }, @@ -333,9 +380,13 @@ impl<'a> ToCore> for webgpu::GpuVertexState impl<'a> ToCore> for webgpu::GpuVertexBufferLayout { fn to_core(self, table: &ResourceTable) -> wgpu_core::pipeline::VertexBufferLayout<'a> { + // https://www.w3.org/TR/webgpu/#dictdef-gpuvertexbufferlayout wgpu_core::pipeline::VertexBufferLayout { array_stride: self.array_stride, - step_mode: self.step_mode.unwrap().into(), + step_mode: self + .step_mode + .map(|sm| sm.into()) + .unwrap_or(wgpu_types::VertexStepMode::Vertex), attributes: self .attributes .into_iter() @@ -362,11 +413,12 @@ impl<'a> ToCore, Vec wgpu_types::TextureDescriptor, Vec> { + // https://www.w3.org/TR/webgpu/#gputexturedescriptor wgpu_types::TextureDescriptor { label: self.label.map(|l| l.into()), size: self.size.to_core(table), - mip_level_count: self.mip_level_count.unwrap(), - sample_count: self.sample_count.unwrap(), + mip_level_count: self.mip_level_count.unwrap_or(1), + sample_count: self.sample_count.unwrap_or(1), dimension: self .dimension .unwrap_or(webgpu::GpuTextureDimension::D2) @@ -388,22 +440,40 @@ impl<'a> ToCore, Vec ToCore> for webgpu::GpuSamplerDescriptor { fn to_core(self, _table: &ResourceTable) -> wgpu_core::resource::SamplerDescriptor<'a> { + // https://www.w3.org/TR/webgpu/#GPUSamplerDescriptor wgpu_core::resource::SamplerDescriptor { label: self.label.map(|l| l.into()), address_modes: [ - self.address_mode_u.unwrap().into(), - self.address_mode_v.unwrap().into(), - self.address_mode_w.unwrap().into(), + self.address_mode_u + .map(|am| am.into()) + .unwrap_or(wgpu_types::AddressMode::ClampToEdge), + self.address_mode_v + .map(|am| am.into()) + .unwrap_or(wgpu_types::AddressMode::ClampToEdge), + self.address_mode_w + .map(|am| am.into()) + .unwrap_or(wgpu_types::AddressMode::ClampToEdge), ], - mag_filter: self.mag_filter.unwrap().into(), - min_filter: self.min_filter.unwrap().into(), - mipmap_filter: self.mipmap_filter.unwrap().into(), - lod_min_clamp: self.lod_min_clamp.unwrap(), - lod_max_clamp: self.lod_max_clamp.unwrap(), + mag_filter: self + .mag_filter + .map(|mf| mf.into()) + .unwrap_or(wgpu_types::FilterMode::Nearest), + min_filter: self + .min_filter + .map(|mf| mf.into()) + .unwrap_or(wgpu_types::FilterMode::Nearest), + mipmap_filter: self + .mipmap_filter + .map(|mf| mf.into()) + .unwrap_or(wgpu_types::FilterMode::Nearest), + lod_min_clamp: self.lod_min_clamp.unwrap_or(0.0), + lod_max_clamp: self.lod_max_clamp.unwrap_or(32.0), compare: self.compare.map(|compare| compare.into()), - // TODO: should this be coming from self.anisotropy_clamp? + // TODO: `max_anisotropy` is not available on `SamplerDescriptor` yet + // max_anisotropy: self.max_anisotropy, + // anisotropy_clamp and border_color are not present in WebGPU anisotropy_clamp: 1, - border_color: Default::default(), + border_color: None, } } } @@ -415,8 +485,9 @@ impl<'a> ToCore>> self, _table: &ResourceTable, ) -> wgpu_types::CommandBufferDescriptor> { - // TODO: - Default::default() + wgpu_types::CommandBufferDescriptor { + label: self.label.map(|l| l.into()), + } } } @@ -442,7 +513,6 @@ impl ToCore for webgpu::GpuBindGroupLayoutEntr fn to_core(self, table: &ResourceTable) -> wgpu_types::BindGroupLayoutEntry { wgpu_types::BindGroupLayoutEntry { binding: self.binding.into(), - // TODO: visibility: wgpu_types::ShaderStages::from_bits(self.visibility).unwrap(), ty: match ( self.buffer, @@ -457,17 +527,21 @@ impl ToCore for webgpu::GpuBindGroupLayoutEntr (None, None, None, None) => todo!(), _ => panic!("Can't have multiple ..."), }, - // TODO: - count: Default::default(), + // count is not present in WebGPU + count: None, } } } impl ToCore for webgpu::GpuBufferBindingLayout { fn to_core(self, _table: &ResourceTable) -> wgpu_types::BindingType { + // https://www.w3.org/TR/webgpu/#dictdef-gpubufferbindinglayout wgpu_types::BindingType::Buffer { - ty: self.type_.map(|t| t.into()).unwrap_or_default(), - has_dynamic_offset: self.has_dynamic_offset.unwrap_or_default(), + ty: self + .type_ + .map(|t| t.into()) + .unwrap_or(wgpu_types::BufferBindingType::Uniform), + has_dynamic_offset: self.has_dynamic_offset.unwrap_or(false), min_binding_size: self.min_binding_size.map(|x| x.try_into().unwrap()), } } @@ -475,19 +549,28 @@ impl ToCore for webgpu::GpuBufferBindingLayout { impl ToCore for webgpu::GpuSamplerBindingLayout { fn to_core(self, _table: &ResourceTable) -> wgpu_types::BindingType { - wgpu_types::BindingType::Sampler(self.type_.map(|t| t.into()).unwrap()) + // https://www.w3.org/TR/webgpu/#dictdef-gpusamplerbindinglayout + wgpu_types::BindingType::Sampler( + self.type_ + .map(|t| t.into()) + .unwrap_or(wgpu_types::SamplerBindingType::Filtering), + ) } } impl ToCore for webgpu::GpuTextureBindingLayout { fn to_core(self, _table: &ResourceTable) -> wgpu_types::BindingType { + // https://www.w3.org/TR/webgpu/#enumdef-gputexturesampletype wgpu_types::BindingType::Texture { - sample_type: self.sample_type.unwrap().into(), + sample_type: self + .sample_type + .map(|st| st.into()) + .unwrap_or(wgpu_types::TextureSampleType::Float { filterable: true }), view_dimension: self .view_dimension .unwrap_or(webgpu::GpuTextureViewDimension::D2) .into(), - multisampled: self.multisampled.unwrap_or_default(), + multisampled: self.multisampled.unwrap_or(false), } } } @@ -513,7 +596,6 @@ impl ToCore for webgpu::GpuStorageTextureBindingLayout // // timestamp_writes: self.timestamp_writes, // // occlusion_query_set: self.occlusion_query_set, // // TODO: self.max_draw_count not used -// ..Default::default() // } // } // } @@ -525,19 +607,20 @@ impl ToCore self, table: &ResourceTable, ) -> wgpu_core::command::RenderPassDepthStencilAttachment { + // https://www.w3.org/TR/webgpu/#dictdef-gpurenderpassdepthstencilattachment wgpu_core::command::RenderPassDepthStencilAttachment { view: self.view.to_core(table), depth: pass_channel_from_options( self.depth_load_op.map(|x| x.into()), self.depth_store_op.map(|x| x.into()), self.depth_clear_value.map(|x| x.into()), - self.depth_read_only.map(|x| x.into()), + self.depth_read_only.unwrap_or(false), ), stencil: pass_channel_from_options( self.stencil_load_op.map(|x| x.into()), self.stencil_store_op.map(|x| x.into()), self.stencil_clear_value.map(|x| x.into()), - self.stencil_read_only.map(|x| x.into()), + self.stencil_read_only.unwrap_or(false), ), } } @@ -547,29 +630,26 @@ fn pass_channel_from_options( load_op: Option, store_op: Option, clear_value: Option, - read_only: Option, + read_only: bool, ) -> wgpu_core::command::PassChannel { match (load_op, store_op, clear_value) { (Some(load_op), Some(store_op), Some(clear_value)) => wgpu_core::command::PassChannel { load_op, store_op, clear_value, - // TODO: why default to false? - read_only: read_only.unwrap_or(false), + read_only, }, (Some(load_op), Some(store_op), None) => wgpu_core::command::PassChannel { load_op, store_op, clear_value: V::default(), - // TODO: why default to false? - read_only: read_only.unwrap_or(false), + read_only, }, (None, None, None) => wgpu_core::command::PassChannel { load_op: wgpu_core::command::LoadOp::Load, store_op: wgpu_core::command::StoreOp::Store, clear_value: V::default(), - // TODO: why default to false? - read_only: read_only.unwrap_or(false), + read_only, }, _ => todo!(), } @@ -589,7 +669,7 @@ impl ToCore Some(self.store_op.into()), self.clear_value.map(|c| c.into()), // TODO: why default to false? - Some(false), + false, ), // TODO: didn't use self.depth_slice } @@ -600,11 +680,12 @@ impl<'a> ToCore>> for webgpu::GpuBufferDescriptor { fn to_core(self, _table: &ResourceTable) -> wgpu_types::BufferDescriptor> { + // https://www.w3.org/TR/webgpu/#gpubufferdescriptor wgpu_types::BufferDescriptor { label: self.label.map(|l| l.into()), size: self.size, usage: wgpu_types::BufferUsages::from_bits(self.usage).unwrap(), - mapped_at_creation: self.mapped_at_creation.unwrap_or_default(), + mapped_at_creation: self.mapped_at_creation.unwrap_or(false), } } } @@ -612,15 +693,107 @@ impl<'a> ToCore>> impl<'a> ToCore>> for webgpu::GpuDeviceDescriptor { - fn to_core(self, _table: &ResourceTable) -> wgpu_types::DeviceDescriptor> { + fn to_core(self, table: &ResourceTable) -> wgpu_types::DeviceDescriptor> { wgpu_types::DeviceDescriptor { label: self.label.map(|l| l.into()), - // TODO: Don't default - ..Default::default() + required_features: self + .required_features + .map(|f| f.to_core(table)) + .unwrap_or_default(), + // TODO: take from self.required_limits once it's a record type in wit + required_limits: Default::default(), + // TODO: use self.default_queue? + // memory_hints is not present in WebGPU + memory_hints: wgpu_types::MemoryHints::default(), } } } +impl<'a> ToCore for Vec { + fn to_core(self, _table: &ResourceTable) -> wgpu_types::Features { + self.into_iter() + .map(|feature| match feature { + webgpu::GpuFeatureName::DepthClipControl => { + wgpu_types::Features::DEPTH_CLIP_CONTROL + } + webgpu::GpuFeatureName::Depth32floatStencil8 => { + wgpu_types::Features::DEPTH32FLOAT_STENCIL8 + } + webgpu::GpuFeatureName::TextureCompressionBc => { + wgpu_types::Features::TEXTURE_COMPRESSION_BC + } + webgpu::GpuFeatureName::TextureCompressionBcSliced3d => todo!(), // wgpu_types::Features::TEXTURE_COMPRESSION_BC_SLICED_3D, + webgpu::GpuFeatureName::TextureCompressionEtc2 => { + wgpu_types::Features::TEXTURE_COMPRESSION_ETC2 + } + webgpu::GpuFeatureName::TextureCompressionAstc => { + wgpu_types::Features::TEXTURE_COMPRESSION_ASTC + } + webgpu::GpuFeatureName::TimestampQuery => wgpu_types::Features::TIMESTAMP_QUERY, + webgpu::GpuFeatureName::IndirectFirstInstance => { + wgpu_types::Features::INDIRECT_FIRST_INSTANCE + } + webgpu::GpuFeatureName::ShaderF16 => wgpu_types::Features::SHADER_F16, + webgpu::GpuFeatureName::Rg11b10ufloatRenderable => { + wgpu_types::Features::RG11B10UFLOAT_RENDERABLE + } + webgpu::GpuFeatureName::Bgra8unormStorage => { + wgpu_types::Features::BGRA8UNORM_STORAGE + } + webgpu::GpuFeatureName::Float32Filterable => { + wgpu_types::Features::FLOAT32_FILTERABLE + } + webgpu::GpuFeatureName::ClipDistances => todo!(), // wgpu_types::Features::CLIP_DISTANCES, + webgpu::GpuFeatureName::DualSourceBlending => { + wgpu_types::Features::DUAL_SOURCE_BLENDING + } + }) + .collect() + } +} + +// impl<'a> ToCore for Vec { +// fn to_core(self, _table: &ResourceTable) -> wgpu_types::Limits { +// let defaults = wgpu_types::Limits::default(); +// wgpu_types::Limits { +// max_texture_dimension_1d: (), +// max_texture_dimension_2d: (), +// max_texture_dimension_3d: (), +// max_texture_array_layers: (), +// max_bind_groups: (), +// max_bindings_per_bind_group: (), +// max_dynamic_uniform_buffers_per_pipeline_layout: (), +// max_dynamic_storage_buffers_per_pipeline_layout: (), +// max_sampled_textures_per_shader_stage: (), +// max_samplers_per_shader_stage: (), +// max_storage_buffers_per_shader_stage: (), +// max_storage_textures_per_shader_stage: (), +// max_uniform_buffers_per_shader_stage: (), +// max_uniform_buffer_binding_size: (), +// max_storage_buffer_binding_size: (), +// max_vertex_buffers: (), +// max_buffer_size: (), +// max_vertex_attributes: (), +// max_vertex_buffer_array_stride: (), +// min_uniform_buffer_offset_alignment: (), +// min_storage_buffer_offset_alignment: (), +// max_inter_stage_shader_components: (), +// max_color_attachments: (), +// max_color_attachment_bytes_per_sample: (), +// max_compute_workgroup_storage_size: (), +// max_compute_invocations_per_workgroup: (), +// max_compute_workgroup_size_x: (), +// max_compute_workgroup_size_y: (), +// max_compute_workgroup_size_z: (), +// max_compute_workgroups_per_dimension: (), +// min_subgroup_size: (), +// max_subgroup_size: (), +// max_push_constant_size: (), +// max_non_sampler_bindings: (), +// } +// } +// } + impl ToCore> for webgpu::GpuImageCopyTexture { @@ -628,29 +801,35 @@ impl ToCore> self, table: &ResourceTable, ) -> wgpu_types::ImageCopyTexture { + // https://www.w3.org/TR/webgpu/#gputexelcopytextureinfo wgpu_types::ImageCopyTexture { texture: self.texture.to_core(table), - mip_level: self.mip_level.unwrap(), - origin: self.origin.unwrap().to_core(table), - aspect: self.aspect.unwrap().into(), + mip_level: self.mip_level.unwrap_or(0), + origin: self.origin.map(|o| o.to_core(table)).unwrap_or_default(), + aspect: self + .aspect + .map(|a| a.into()) + .unwrap_or(wgpu_types::TextureAspect::All), } } } impl ToCore for webgpu::GpuOrigin3D { fn to_core(self, _table: &ResourceTable) -> wgpu_types::Origin3d { + // https://www.w3.org/TR/webgpu/#dictdef-gpuorigin3ddict wgpu_types::Origin3d { - x: self.x.unwrap(), - y: self.y.unwrap(), - z: self.z.unwrap(), + x: self.x.unwrap_or(0), + y: self.y.unwrap_or(0), + z: self.z.unwrap_or(0), } } } impl ToCore for webgpu::GpuImageDataLayout { fn to_core(self, _table: &ResourceTable) -> wgpu_types::ImageDataLayout { + // https://www.w3.org/TR/webgpu/#gputexelcopybufferlayout wgpu_types::ImageDataLayout { - offset: self.offset.unwrap(), + offset: self.offset.unwrap_or(0), bytes_per_row: self.bytes_per_row, rows_per_image: self.rows_per_image, } @@ -685,7 +864,14 @@ impl<'a> ToCore> wgpu_core::pipeline::ProgrammableStageDescriptor { module: self.module.to_core(table), entry_point: self.entry_point.map(|ep| ep.into()), - constants: Default::default(), + constants: self + .constants + .map(|constants| { + // TODO: can we get rid of the clone here? + let constants = table.get(&constants).unwrap().clone(); + Cow::Owned(constants) + }) + .unwrap_or_default(), zero_initialize_workgroup_memory: true, vertex_pulling_transform: false, } @@ -702,15 +888,26 @@ impl ToCore for webgpu::GpuComputePassT } } +impl ToCore for webgpu::GpuRenderPassTimestampWrites { + fn to_core(self, table: &ResourceTable) -> wgpu_core::command::PassTimestampWrites { + wgpu_core::command::PassTimestampWrites { + query_set: self.query_set.to_core(table), + beginning_of_pass_write_index: self.beginning_of_pass_write_index, + end_of_pass_write_index: self.end_of_pass_write_index, + } + } +} + impl ToCore> for webgpu::GpuImageCopyBuffer { fn to_core( self, table: &ResourceTable, ) -> wgpu_types::ImageCopyBuffer { + // https://www.w3.org/TR/webgpu/#gputexelcopybufferlayout wgpu_types::ImageCopyBuffer { buffer: table.get(&self.buffer).unwrap().buffer, layout: wgpu_types::ImageDataLayout { - offset: self.offset.unwrap(), + offset: self.offset.unwrap_or(0), bytes_per_row: self.bytes_per_row, rows_per_image: self.rows_per_image, },