diff --git a/examples-wasi/src/entrypoint_wasi.rs b/examples-wasi/src/entrypoint_wasi.rs index 1c8b99aac9..8814da8dfb 100644 --- a/examples-wasi/src/entrypoint_wasi.rs +++ b/examples-wasi/src/entrypoint_wasi.rs @@ -55,12 +55,12 @@ const EXAMPLES: &[ExampleDesc] = &[ // webgl: false, // No canvas for WebGL // webgpu: true, // }, - // ExampleDesc { - // name: "hello_triangle", - // function: crate::hello_triangle::main, - // webgl: true, - // webgpu: true, - // }, + ExampleDesc { + name: "hello_triangle", + function: crate::hello_triangle::main, + webgl: true, + webgpu: true, + }, // ExampleDesc { // name: "hello_windows", // function: crate::hello_windows::main, diff --git a/examples-wasi/src/hello_triangle/README.md b/examples-wasi/src/hello_triangle/README.md new file mode 100644 index 0000000000..52daa8164e --- /dev/null +++ b/examples-wasi/src/hello_triangle/README.md @@ -0,0 +1,13 @@ +# hello_triangle + +This example renders a triangle to a window. + +## To Run + +``` +cargo run --bin wgpu-examples hello_triangle +``` + +## Screenshots + +![Triangle window](./screenshot.png) diff --git a/examples-wasi/src/hello_triangle/mod.rs b/examples-wasi/src/hello_triangle/mod.rs new file mode 100644 index 0000000000..0e82613098 --- /dev/null +++ b/examples-wasi/src/hello_triangle/mod.rs @@ -0,0 +1,181 @@ +use std::borrow::Cow; +use winit::{ + event::{Event, WindowEvent}, + event_loop::EventLoop, + window::Window, +}; + +async fn run(event_loop: EventLoop<()>, window: Window) { + let mut size = window.inner_size(); + size.width = size.width.max(1); + size.height = size.height.max(1); + + let instance = wgpu::Instance::default(); + + let surface = instance.create_surface(&window).unwrap(); + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + force_fallback_adapter: false, + // Request an adapter which can render to our surface + compatible_surface: Some(&surface), + }) + .await + .expect("Failed to find an appropriate adapter"); + + // Create the logical device and command queue + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain. + required_limits: wgpu::Limits::downlevel_webgl2_defaults() + .using_resolution(adapter.limits()), + }, + None, + ) + .await + .expect("Failed to create device"); + + // Load the shaders from disk + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let swapchain_capabilities = surface.get_capabilities(&adapter); + let swapchain_format = swapchain_capabilities.formats[0]; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[Some(swapchain_format.into())], + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + + let mut config = surface + .get_default_config(&adapter, size.width, size.height) + .unwrap(); + surface.configure(&device, &config); + log::info!("333333333333333333333333333333333 - 1"); + + let window = &window; + event_loop + .run(move |event, target| { + log::info!("333333333333333333333333333333333 - 2"); + // Have the closure take ownership of the resources. + // `event_loop.run` never returns, therefore we must do this to ensure + // the resources are properly cleaned up. + let _ = (&instance, &adapter, &shader, &pipeline_layout); + + if let Event::WindowEvent { + window_id: _, + event, + } = event + { + match event { + WindowEvent::Resized(new_size) => { + // Reconfigure the surface with the new size + config.width = new_size.width.max(1); + config.height = new_size.height.max(1); + surface.configure(&device, &config); + // On macos the window needs to be redrawn manually after resizing + window.request_redraw(); + } + WindowEvent::RedrawRequested => { + log::info!("333333333333333333333333333333333 - 3"); + + let frame = surface + .get_current_texture() + .expect("Failed to acquire next swap chain texture"); + let view = frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: None, + }); + { + let mut rpass = + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + rpass.set_pipeline(&render_pipeline); + rpass.draw(0..3, 0..1); + } + + queue.submit(Some(encoder.finish())); + frame.present(); + } + WindowEvent::CloseRequested => target.exit(), + _ => {} + }; + } + }) + .unwrap(); + log::info!("333333333333333333333333333333333 - 4"); +} + +pub fn main() { + crate::entrypoint_wasi::WasiLogger::init(); + let event_loop = EventLoop::<()>::new().unwrap(); + #[allow(unused_mut)] + let mut builder = winit::window::WindowBuilder::new(); + // #[cfg(target_arch = "wasm32")] + // { + // use wasm_bindgen::JsCast; + // use winit::platform::web::WindowBuilderExtWebSys; + // let canvas = web_sys::window() + // .unwrap() + // .document() + // .unwrap() + // .get_element_by_id("canvas") + // .unwrap() + // .dyn_into::() + // .unwrap(); + // builder = builder.with_canvas(Some(canvas)); + // } + let window = builder.build(&event_loop).unwrap(); + + // #[cfg(not(target_arch = "wasm32"))] + // { + // env_logger::init(); + pollster::block_on(run(event_loop, window)); + // } + // #[cfg(target_arch = "wasm32")] + // { + // std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + // console_log::init().expect("could not initialize logger"); + // wasm_bindgen_futures::spawn_local(run(event_loop, window)); + // } +} diff --git a/examples-wasi/src/hello_triangle/screenshot.png b/examples-wasi/src/hello_triangle/screenshot.png new file mode 100644 index 0000000000..ae8350b9f6 Binary files /dev/null and b/examples-wasi/src/hello_triangle/screenshot.png differ diff --git a/examples-wasi/src/hello_triangle/shader.wgsl b/examples-wasi/src/hello_triangle/shader.wgsl new file mode 100644 index 0000000000..f84ccfe94d --- /dev/null +++ b/examples-wasi/src/hello_triangle/shader.wgsl @@ -0,0 +1,11 @@ +@vertex +fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { + let x = f32(i32(in_vertex_index) - 1); + let y = f32(i32(in_vertex_index & 1u) * 2 - 1); + return vec4(x, y, 0.0, 1.0); +} + +@fragment +fn fs_main() -> @location(0) vec4 { + return vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/examples-wasi/src/lib.rs b/examples-wasi/src/lib.rs index 24705af9b0..ec1e5ea015 100644 --- a/examples-wasi/src/lib.rs +++ b/examples-wasi/src/lib.rs @@ -12,7 +12,7 @@ mod flume; // pub mod hello; pub mod hello_compute; // pub mod hello_synchronization; -// pub mod hello_triangle; +pub mod hello_triangle; // pub mod hello_windows; // pub mod hello_workgroups; // pub mod mipmap; diff --git a/wgpu/src/backend/wasi_webgpu.rs b/wgpu/src/backend/wasi_webgpu.rs index eb70a5e00b..2130f73556 100644 --- a/wgpu/src/backend/wasi_webgpu.rs +++ b/wgpu/src/backend/wasi_webgpu.rs @@ -3,9 +3,14 @@ use crate::{context::downcast_ref, SurfaceTargetUnsafe, UncapturedErrorHandler}; use std::{ future::{ready, Ready}, ops::Range, + sync::Arc, }; -use wasi::webgpu::{graphics_context::GraphicsContext, mini_canvas::MiniCanvas, webgpu}; +use wasi::webgpu::{ + graphics_context::GraphicsContext, + mini_canvas::{CreateDesc, MiniCanvas}, + webgpu, +}; wit_bindgen::generate!({ path: "../wit", @@ -62,7 +67,8 @@ impl crate::Context for ContextWasiWebgpu { // Option so that command_encoder_end_compute_pass can take ownership. type ComputePassData = Option; type RenderPassId = (); - type RenderPassData = (); // TODO: fix type + // Option so that command_encoder_end_render_pass can take ownership. + type RenderPassData = Option; type CommandBufferId = (); type CommandBufferData = webgpu::GpuCommandBuffer; type RenderBundleEncoderId = (); @@ -71,8 +77,8 @@ impl crate::Context for ContextWasiWebgpu { type RenderBundleData = webgpu::GpuRenderBundle; type SurfaceId = (); - type SurfaceData = (MiniCanvas, GraphicsContext); // TODO: fix type - type SurfaceOutputDetail = (); // TODO: fix type + type SurfaceData = (MiniCanvas, Arc); + type SurfaceOutputDetail = SurfaceOutputDetail; type SubmissionIndex = (); // TODO: fix type type SubmissionIndexData = (); // TODO: fix type @@ -98,7 +104,14 @@ impl crate::Context for ContextWasiWebgpu { &self, _target: SurfaceTargetUnsafe, ) -> Result<(Self::SurfaceId, Self::SurfaceData), crate::CreateSurfaceError> { - todo!() + let context = GraphicsContext::new(); + let canvas = MiniCanvas::new(CreateDesc { + height: 100, + width: 100, + offscreen: false, + }); + canvas.connect_graphics_context(&context); + Ok(((), (canvas, Arc::new(context)))) } fn instance_request_adapter( @@ -209,29 +222,40 @@ impl crate::Context for ContextWasiWebgpu { fn surface_configure( &self, _surface: &Self::SurfaceId, - _surface_data: &Self::SurfaceData, + surface_data: &Self::SurfaceData, _device: &Self::DeviceId, - _device_data: &Self::DeviceData, + device_data: &Self::DeviceData, _config: &crate::SurfaceConfiguration, ) { - todo!() + device_data.connect_graphics_context(&surface_data.1); } fn surface_get_current_texture( &self, _surface: &Self::SurfaceId, - _surface_data: &Self::SurfaceData, + surface_data: &Self::SurfaceData, ) -> ( Option, Option, crate::SurfaceStatus, Self::SurfaceOutputDetail, ) { - todo!() + let (_canvas, context) = surface_data; + let graphics_buffer = context.get_current_buffer(); + let texture = webgpu::GpuTexture::from_graphics_buffer(graphics_buffer); + + ( + Some(()), + Some(texture), + wgt::SurfaceStatus::Good, + SurfaceOutputDetail { + graphics_context: Arc::clone(&context), + }, + ) } - fn surface_present(&self, _texture: &Self::TextureId, _detail: &Self::SurfaceOutputDetail) { - todo!() + fn surface_present(&self, _texture: &Self::TextureId, detail: &Self::SurfaceOutputDetail) { + detail.graphics_context.present(); } fn surface_texture_discard( @@ -717,20 +741,25 @@ impl crate::Context for ContextWasiWebgpu { fn command_encoder_begin_render_pass( &self, _encoder: &Self::CommandEncoderId, - _encoder_data: &Self::CommandEncoderData, - _desc: &crate::RenderPassDescriptor<'_, '_>, + encoder_data: &Self::CommandEncoderData, + desc: &crate::RenderPassDescriptor<'_, '_>, ) -> (Self::RenderPassId, Self::RenderPassData) { - todo!() + let encoder_data = encoder_data.as_ref().unwrap(); + let render_pass = encoder_data.begin_render_pass(&desc.into()); + ((), Some(render_pass)) } fn command_encoder_end_render_pass( &self, _encoder: &Self::CommandEncoderId, - _encoder_data: &Self::CommandEncoderData, + encoder_data: &Self::CommandEncoderData, _pass: &mut Self::RenderPassId, - _pass_data: &mut Self::RenderPassData, + pass_data: &mut Self::RenderPassData, ) { - todo!() + webgpu::GpuRenderPassEncoder::end( + pass_data.take().unwrap(), + encoder_data.as_ref().unwrap(), + ); } fn command_encoder_finish( @@ -838,13 +867,19 @@ impl crate::Context for ContextWasiWebgpu { fn queue_write_buffer( &self, _queue: &Self::QueueId, - _queue_data: &Self::QueueData, + queue_data: &Self::QueueData, _buffer: &Self::BufferId, - _buffer_data: &Self::BufferData, - _offset: wgt::BufferAddress, - _data: &[u8], - ) { - todo!() + buffer_data: &Self::BufferData, + offset: wgt::BufferAddress, + data: &[u8], + ) { + queue_data.write_buffer( + &buffer_data, + offset as u64, + None, + data, + Some(data.len() as u64), + ); } fn queue_validate_write_buffer( @@ -1204,11 +1239,11 @@ impl crate::Context for ContextWasiWebgpu { fn render_pass_set_pipeline( &self, _pass: &mut Self::RenderPassId, - _pass_data: &mut Self::RenderPassData, + pass_data: &mut Self::RenderPassData, _pipeline: &Self::RenderPipelineId, - _pipeline_data: &Self::RenderPipelineData, + pipeline_data: &Self::RenderPipelineData, ) { - todo!() + pass_data.as_ref().unwrap().set_pipeline(pipeline_data); } fn render_pass_set_bind_group( @@ -1263,11 +1298,16 @@ impl crate::Context for ContextWasiWebgpu { fn render_pass_draw( &self, _pass: &mut Self::RenderPassId, - _pass_data: &mut Self::RenderPassData, - _vertices: Range, - _instances: Range, - ) { - todo!() + pass_data: &mut Self::RenderPassData, + vertices: Range, + instances: Range, + ) { + pass_data.as_ref().unwrap().draw( + vertices.end - vertices.start, + instances.end - instances.start, + vertices.start, + instances.start, + ); } fn render_pass_draw_indexed( @@ -1484,6 +1524,10 @@ impl crate::Context for ContextWasiWebgpu { } } +pub struct SurfaceOutputDetail { + pub(crate) graphics_context: Arc, +} + // inefficient, since `temporary_mapping`` needs to be copied to `actual_mapping`. // only needed becuase the `BufferMappedRange` trait methods return slices. If we change them to return `impl SliceIndex` we can get rid of this indirection. #[derive(Debug)] @@ -1851,6 +1895,198 @@ impl From for webgpu::GpuTextureFormat { } } +impl From for crate::TextureFormat { + fn from(value: webgpu::GpuTextureFormat) -> Self { + match value { + webgpu::GpuTextureFormat::R8unorm => wgt::TextureFormat::R8Unorm, + webgpu::GpuTextureFormat::R8snorm => wgt::TextureFormat::R8Snorm, + webgpu::GpuTextureFormat::R8uint => wgt::TextureFormat::R8Uint, + webgpu::GpuTextureFormat::R8sint => wgt::TextureFormat::R8Sint, + webgpu::GpuTextureFormat::R16uint => wgt::TextureFormat::R16Uint, + webgpu::GpuTextureFormat::R16sint => wgt::TextureFormat::R16Sint, + webgpu::GpuTextureFormat::R16float => wgt::TextureFormat::R16Float, + webgpu::GpuTextureFormat::Rg8unorm => wgt::TextureFormat::Rg8Unorm, + webgpu::GpuTextureFormat::Rg8snorm => wgt::TextureFormat::Rg8Snorm, + webgpu::GpuTextureFormat::Rg8uint => wgt::TextureFormat::Rg8Uint, + webgpu::GpuTextureFormat::Rg8sint => wgt::TextureFormat::Rg8Sint, + webgpu::GpuTextureFormat::R32uint => wgt::TextureFormat::R32Uint, + webgpu::GpuTextureFormat::R32sint => wgt::TextureFormat::R32Sint, + webgpu::GpuTextureFormat::R32float => wgt::TextureFormat::R32Float, + webgpu::GpuTextureFormat::Rg16uint => wgt::TextureFormat::Rg16Uint, + webgpu::GpuTextureFormat::Rg16sint => wgt::TextureFormat::Rg16Sint, + webgpu::GpuTextureFormat::Rg16float => wgt::TextureFormat::Rg16Float, + webgpu::GpuTextureFormat::Rgba8unorm => wgt::TextureFormat::Rgba8Unorm, + webgpu::GpuTextureFormat::Rgba8unormSrgb => wgt::TextureFormat::Rgba8UnormSrgb, + webgpu::GpuTextureFormat::Rgba8snorm => wgt::TextureFormat::Rgba8Snorm, + webgpu::GpuTextureFormat::Rgba8uint => wgt::TextureFormat::Rgba8Uint, + webgpu::GpuTextureFormat::Rgba8sint => wgt::TextureFormat::Rgba8Sint, + webgpu::GpuTextureFormat::Bgra8unorm => wgt::TextureFormat::Bgra8Unorm, + webgpu::GpuTextureFormat::Bgra8unormSrgb => wgt::TextureFormat::Bgra8UnormSrgb, + webgpu::GpuTextureFormat::Rgb9e5ufloat => wgt::TextureFormat::Rgb9e5Ufloat, + webgpu::GpuTextureFormat::Rgb10a2uint => wgt::TextureFormat::Rgb10a2Uint, + webgpu::GpuTextureFormat::Rgb10a2unorm => wgt::TextureFormat::Rgb10a2Unorm, + webgpu::GpuTextureFormat::Rg11b10ufloat => wgt::TextureFormat::Rg11b10Float, + webgpu::GpuTextureFormat::Rg32uint => wgt::TextureFormat::Rg32Uint, + webgpu::GpuTextureFormat::Rg32sint => wgt::TextureFormat::Rg32Sint, + webgpu::GpuTextureFormat::Rg32float => wgt::TextureFormat::Rg32Float, + webgpu::GpuTextureFormat::Rgba16uint => wgt::TextureFormat::Rgba16Uint, + webgpu::GpuTextureFormat::Rgba16sint => wgt::TextureFormat::Rgba16Sint, + webgpu::GpuTextureFormat::Rgba16float => wgt::TextureFormat::Rgba16Float, + webgpu::GpuTextureFormat::Rgba32uint => wgt::TextureFormat::Rgba32Uint, + webgpu::GpuTextureFormat::Rgba32sint => wgt::TextureFormat::Rgba32Sint, + webgpu::GpuTextureFormat::Rgba32float => wgt::TextureFormat::Rgba32Float, + webgpu::GpuTextureFormat::Stencil8 => wgt::TextureFormat::Stencil8, + webgpu::GpuTextureFormat::Depth16unorm => wgt::TextureFormat::Depth16Unorm, + webgpu::GpuTextureFormat::Depth24plus => wgt::TextureFormat::Depth24Plus, + webgpu::GpuTextureFormat::Depth24plusStencil8 => { + wgt::TextureFormat::Depth24PlusStencil8 + } + webgpu::GpuTextureFormat::Depth32float => wgt::TextureFormat::Depth32Float, + webgpu::GpuTextureFormat::Depth32floatStencil8 => { + wgt::TextureFormat::Depth32FloatStencil8 + } + webgpu::GpuTextureFormat::Bc1RgbaUnorm => wgt::TextureFormat::Bc1RgbaUnorm, + webgpu::GpuTextureFormat::Bc1RgbaUnormSrgb => wgt::TextureFormat::Bc1RgbaUnormSrgb, + webgpu::GpuTextureFormat::Bc2RgbaUnorm => wgt::TextureFormat::Bc2RgbaUnorm, + webgpu::GpuTextureFormat::Bc2RgbaUnormSrgb => wgt::TextureFormat::Bc2RgbaUnormSrgb, + webgpu::GpuTextureFormat::Bc3RgbaUnorm => wgt::TextureFormat::Bc3RgbaUnorm, + webgpu::GpuTextureFormat::Bc3RgbaUnormSrgb => wgt::TextureFormat::Bc3RgbaUnormSrgb, + webgpu::GpuTextureFormat::Bc4RUnorm => wgt::TextureFormat::Bc4RUnorm, + webgpu::GpuTextureFormat::Bc4RSnorm => wgt::TextureFormat::Bc4RSnorm, + webgpu::GpuTextureFormat::Bc5RgUnorm => wgt::TextureFormat::Bc5RgUnorm, + webgpu::GpuTextureFormat::Bc5RgSnorm => wgt::TextureFormat::Bc5RgSnorm, + webgpu::GpuTextureFormat::Bc6hRgbUfloat => wgt::TextureFormat::Bc6hRgbUfloat, + webgpu::GpuTextureFormat::Bc6hRgbFloat => wgt::TextureFormat::Bc6hRgbFloat, + webgpu::GpuTextureFormat::Bc7RgbaUnorm => wgt::TextureFormat::Bc7RgbaUnorm, + webgpu::GpuTextureFormat::Bc7RgbaUnormSrgb => wgt::TextureFormat::Bc7RgbaUnormSrgb, + webgpu::GpuTextureFormat::Etc2Rgb8unorm => wgt::TextureFormat::Etc2Rgb8Unorm, + webgpu::GpuTextureFormat::Etc2Rgb8unormSrgb => wgt::TextureFormat::Etc2Rgb8UnormSrgb, + webgpu::GpuTextureFormat::Etc2Rgb8a1unorm => wgt::TextureFormat::Etc2Rgb8A1Unorm, + webgpu::GpuTextureFormat::Etc2Rgb8a1unormSrgb => { + wgt::TextureFormat::Etc2Rgb8A1UnormSrgb + } + webgpu::GpuTextureFormat::Etc2Rgba8unorm => wgt::TextureFormat::Etc2Rgba8Unorm, + webgpu::GpuTextureFormat::Etc2Rgba8unormSrgb => wgt::TextureFormat::Etc2Rgba8UnormSrgb, + webgpu::GpuTextureFormat::EacR11unorm => wgt::TextureFormat::EacR11Unorm, + webgpu::GpuTextureFormat::EacR11snorm => wgt::TextureFormat::EacR11Snorm, + webgpu::GpuTextureFormat::EacRg11unorm => wgt::TextureFormat::EacRg11Unorm, + webgpu::GpuTextureFormat::EacRg11snorm => wgt::TextureFormat::EacRg11Snorm, + webgpu::GpuTextureFormat::Astc4x4Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B4x4, + }, + webgpu::GpuTextureFormat::Astc5x4Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B5x4, + }, + webgpu::GpuTextureFormat::Astc5x5Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B5x5, + }, + webgpu::GpuTextureFormat::Astc6x5Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B6x5, + }, + webgpu::GpuTextureFormat::Astc6x6Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B6x6, + }, + webgpu::GpuTextureFormat::Astc8x5Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B8x5, + }, + webgpu::GpuTextureFormat::Astc8x6Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B8x6, + }, + webgpu::GpuTextureFormat::Astc8x8Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B8x8, + }, + webgpu::GpuTextureFormat::Astc10x5Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B10x5, + }, + webgpu::GpuTextureFormat::Astc10x6Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B10x6, + }, + webgpu::GpuTextureFormat::Astc10x8Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B10x8, + }, + webgpu::GpuTextureFormat::Astc10x10Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B10x10, + }, + webgpu::GpuTextureFormat::Astc12x10Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B12x10, + }, + webgpu::GpuTextureFormat::Astc12x12Unorm => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::Unorm, + block: wgt::AstcBlock::B12x12, + }, + webgpu::GpuTextureFormat::Astc4x4UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B4x4, + }, + webgpu::GpuTextureFormat::Astc5x4UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B5x4, + }, + webgpu::GpuTextureFormat::Astc5x5UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B5x5, + }, + webgpu::GpuTextureFormat::Astc6x5UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B6x5, + }, + webgpu::GpuTextureFormat::Astc6x6UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B6x6, + }, + webgpu::GpuTextureFormat::Astc8x5UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B8x5, + }, + webgpu::GpuTextureFormat::Astc8x6UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B8x6, + }, + webgpu::GpuTextureFormat::Astc8x8UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B8x8, + }, + webgpu::GpuTextureFormat::Astc10x5UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B10x5, + }, + webgpu::GpuTextureFormat::Astc10x6UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B10x6, + }, + webgpu::GpuTextureFormat::Astc10x8UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B10x8, + }, + webgpu::GpuTextureFormat::Astc10x10UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B10x10, + }, + webgpu::GpuTextureFormat::Astc12x10UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B12x10, + }, + webgpu::GpuTextureFormat::Astc12x12UnormSrgb => wgt::TextureFormat::Astc { + channel: wgt::AstcChannel::UnormSrgb, + block: wgt::AstcBlock::B12x12, + }, + } + } +} + impl From for webgpu::GpuFilterMode { fn from(value: crate::FilterMode) -> Self { match value { @@ -2505,3 +2741,113 @@ impl<'a> From<&crate::BindGroupLayoutDescriptor<'a>> for webgpu::GpuBindGroupLay } } } + +impl From<&crate::Color> for webgpu::GpuColor { + fn from(value: &crate::Color) -> Self { + webgpu::GpuColor::GpuColorDict(webgpu::GpuColorDict { + r: value.r, + g: value.g, + b: value.b, + a: value.a, + }) + } +} + +impl From<&crate::LoadOp> for webgpu::GpuLoadOp { + fn from(value: &crate::LoadOp) -> Self { + match value { + crate::LoadOp::Clear(_) => webgpu::GpuLoadOp::Clear, + crate::LoadOp::Load => webgpu::GpuLoadOp::Load, + } + } +} + +impl From<&crate::StoreOp> for webgpu::GpuStoreOp { + fn from(value: &crate::StoreOp) -> Self { + match value { + crate::StoreOp::Store => webgpu::GpuStoreOp::Store, + crate::StoreOp::Discard => webgpu::GpuStoreOp::Discard, + } + } +} + +impl<'a> From<&crate::RenderPassColorAttachment<'a>> for webgpu::GpuRenderPassColorAttachment<'a> { + fn from(value: &crate::RenderPassColorAttachment<'a>) -> Self { + let clear_value = match &value.ops.load { + crate::LoadOp::Clear(color) => Some(color.into()), + crate::LoadOp::Load => None, + }; + webgpu::GpuRenderPassColorAttachment { + view: value.view.data.as_ref().downcast_ref().unwrap(), + resolve_target: value.resolve_target.map(|t| t.data.downcast_ref().unwrap()), + clear_value, + load_op: (&value.ops.load).into(), + store_op: (&value.ops.store).into(), + depth_slice: None, + } + } +} + +impl<'a> From<&crate::RenderPassDepthStencilAttachment<'a>> + for webgpu::GpuRenderPassDepthStencilAttachment<'a> +{ + fn from(value: &crate::RenderPassDepthStencilAttachment<'a>) -> Self { + let depth_clear_value = value + .depth_ops + .as_ref() + .map(|o| match o.load { + crate::LoadOp::Clear(color) => Some(color.into()), + crate::LoadOp::Load => None, + }) + .flatten(); + let stencil_clear_value = value + .stencil_ops + .as_ref() + .map(|o| match o.load { + crate::LoadOp::Clear(color) => Some(color.into()), + crate::LoadOp::Load => None, + }) + .flatten(); + webgpu::GpuRenderPassDepthStencilAttachment { + view: value.view.data.as_ref().downcast_ref().unwrap(), + depth_clear_value, + depth_load_op: value.depth_ops.as_ref().map(|o| (&o.load).into()), + depth_store_op: value.depth_ops.as_ref().map(|o| (&o.store).into()), + depth_read_only: Some(value.depth_ops.is_none()), + stencil_clear_value, + stencil_load_op: value.stencil_ops.as_ref().map(|o| (&o.load).into()), + stencil_store_op: value.stencil_ops.as_ref().map(|o| (&o.store).into()), + stencil_read_only: Some(value.stencil_ops.is_none()), + } + } +} + +impl<'a> From<&crate::RenderPassTimestampWrites<'a>> for webgpu::GpuRenderPassTimestampWrites<'a> { + fn from(value: &crate::RenderPassTimestampWrites<'a>) -> Self { + webgpu::GpuRenderPassTimestampWrites { + query_set: value.query_set.data.downcast_ref().unwrap(), + beginning_of_pass_write_index: value.beginning_of_pass_write_index, + end_of_pass_write_index: value.end_of_pass_write_index, + } + } +} + +impl<'a> From<&crate::RenderPassDescriptor<'a, 'a>> for webgpu::GpuRenderPassDescriptor<'a> { + fn from(value: &crate::RenderPassDescriptor<'a, 'a>) -> Self { + webgpu::GpuRenderPassDescriptor { + color_attachments: value + .color_attachments + .iter() + .map(|ca| ca.as_ref().expect("TODO:").into()) + .collect(), + depth_stencil_attachment: value.depth_stencil_attachment.as_ref().map(|a| a.into()), + occlusion_query_set: value + .occlusion_query_set + .as_ref() + .map(|qs| qs.data.downcast_ref().unwrap()), + timestamp_writes: value.timestamp_writes.as_ref().map(|t| t.into()), + label: value.label.map(|l| l.into()), + max_draw_count: None, + } + } +} diff --git a/wit/deps/webgpu/webgpu.wit b/wit/deps/webgpu/webgpu.wit index 6b189ffe22..ce248a1008 100644 --- a/wit/deps/webgpu/webgpu.wit +++ b/wit/deps/webgpu/webgpu.wit @@ -895,7 +895,7 @@ interface webgpu { record gpu-render-pass-descriptor { color-attachments: list, depth-stencil-attachment: option, - occlusion-query-set: option, + occlusion-query-set: option>, timestamp-writes: option, max-draw-count: option, label: option, @@ -929,14 +929,14 @@ interface webgpu { set-label: func(label: string); } record gpu-render-pass-timestamp-writes { - query-set: gpu-query-set, + query-set: borrow, beginning-of-pass-write-index: option, end-of-pass-write-index: option, } record gpu-render-pass-color-attachment { - view: gpu-texture-view, + view: borrow, depth-slice: option, - resolve-target: option, + resolve-target: option>, clear-value: option, load-op: gpu-load-op, store-op: gpu-store-op,