From ef3b1414065f91b81a9d5980b6c954640515d206 Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Fri, 26 Jun 2020 13:20:29 +0530 Subject: [PATCH] address review comments --- components/script/dom/bindings/trace.rs | 3 +- components/script/dom/gpubuffer.rs | 58 +- components/script/dom/gpudevice.rs | 6 +- components/webgpu/lib.rs | 1165 ++++++++++++----------- 4 files changed, 632 insertions(+), 600 deletions(-) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 9c536ff0994..d6216cdad48 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -135,7 +135,7 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell, UnsafeCell}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::hash::{BuildHasher, Hash}; -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, Range}; use std::path::PathBuf; use std::rc::Rc; use std::sync::atomic::{AtomicBool, AtomicUsize}; @@ -586,6 +586,7 @@ unsafe_no_jsmanaged_fields!(Option); unsafe_no_jsmanaged_fields!(Option); unsafe_no_jsmanaged_fields!(GPUBufferState); unsafe_no_jsmanaged_fields!(GPUCommandEncoderState); +unsafe_no_jsmanaged_fields!(Range); unsafe_no_jsmanaged_fields!(WebXRSwapChainId); unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!( diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index 016f5d8bd1d..8b1b80e6365 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferMethods; +use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{GPUBufferMethods, GPUSize64}; use crate::dom::bindings::codegen::Bindings::GPUMapModeBinding::GPUMapModeConstants; use crate::dom::bindings::error::Error; use crate::dom::bindings::reflector::DomObject; @@ -22,6 +22,7 @@ use js::rust::jsapi_wrapped::{DetachArrayBuffer, IsPromiseObject, RejectPromise} use js::rust::MutableHandle; use js::typedarray::{ArrayBuffer, CreateWith}; use std::cell::Cell; +use std::ops::Range; use std::ptr; use std::rc::Rc; use webgpu::{ @@ -50,8 +51,8 @@ pub struct GPUBuffer { valid: Cell, #[ignore_malloc_size_of = "defined in mozjs"] mapping: RootedTraceableBox>, - mapping_range: (u64, u64), - size: u64, + mapping_range: DomRefCell>, + size: GPUSize64, map_mode: Cell>, } @@ -61,10 +62,10 @@ impl GPUBuffer { buffer: WebGPUBuffer, device: WebGPUDevice, state: GPUBufferState, - size: u64, + size: GPUSize64, valid: bool, mapping: RootedTraceableBox>, - mapping_range: (u64, u64), + mapping_range: Range, ) -> Self { Self { reflector_: Reflector::new(), @@ -76,7 +77,7 @@ impl GPUBuffer { buffer, mapping, size, - mapping_range, + mapping_range: DomRefCell::new(mapping_range), map_mode: Cell::new(None), } } @@ -88,10 +89,10 @@ impl GPUBuffer { buffer: WebGPUBuffer, device: WebGPUDevice, state: GPUBufferState, - size: u64, + size: GPUSize64, valid: bool, mapping: RootedTraceableBox>, - mapping_range: (u64, u64), + mapping_range: Range, ) -> DomRoot { reflect_dom_object( Box::new(GPUBuffer::new_inherited( @@ -186,6 +187,7 @@ impl GPUBufferMethods for GPUBuffer { // Step 4 self.state.set(GPUBufferState::Unmapped); self.map_mode.set(None); + *self.mapping_range.borrow_mut() = 0..0; } /// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy @@ -217,17 +219,16 @@ impl GPUBufferMethods for GPUBuffer { let map_range = if size == 0 { offset..self.size } else { - offset..size + if offset + size > self.size { + warn!("Requested mapping size is greated than buffer size"); + promise.reject_error(Error::Abort); + return promise; + } + offset..offset + size }; let host_map = match mode { - GPUMapModeConstants::READ => { - self.map_mode.set(Some(mode)); - HostMap::Read - }, - GPUMapModeConstants::WRITE => { - self.map_mode.set(Some(mode)); - HostMap::Write - }, + GPUMapModeConstants::READ => HostMap::Read, + GPUMapModeConstants::WRITE => HostMap::Write, _ => { promise.reject_error(Error::Abort); return promise; @@ -238,15 +239,13 @@ impl GPUBufferMethods for GPUBuffer { return promise; } self.mapping.set(*promise.promise_obj()); - self.state.set(GPUBufferState::MappingPending); let sender = response_async(&promise, self); - if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { sender, buffer_id: self.buffer.0, host_map, - map_range, + map_range: map_range.clone(), }) { warn!( "Failed to send BufferMapAsync ({:?}) ({})", @@ -256,6 +255,9 @@ impl GPUBufferMethods for GPUBuffer { return promise; } + self.state.set(GPUBufferState::MappingPending); + self.map_mode.set(Some(mode)); + *self.mapping_range.borrow_mut() = map_range; promise } @@ -275,19 +277,23 @@ impl AsyncWGPUListener for GPUBuffer { fn handle_response(&self, response: WebGPUResponse, promise: &Rc) { match response { WebGPUResponse::BufferMapAsync(bytes) => { - if unsafe { + match unsafe { ArrayBuffer::create( *self.global().get_cx(), CreateWith::Slice(&bytes), MutableHandle::from_raw(self.mapping.handle_mut()), ) - } - .is_err() - { - promise.reject_error(Error::Operation); + } { + Ok(_) => promise.resolve_native(&()), + Err(()) => { + warn!( + "Failed to create ArrayBuffer for buffer({:?})", + self.buffer.0 + ); + promise.reject_error(Error::Operation); + }, } self.state.set(GPUBufferState::Mapped); - promise.resolve_native(&()); }, _ => { warn!("Wrong WebGPUResponse received"); diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index f522cd17d33..08bc4f05744 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -191,10 +191,10 @@ impl GPUDeviceMethods for GPUDevice { .is_ok()); } state = GPUBufferState::MappedAtCreation; - mapping_range = (0, descriptor.size); + mapping_range = 0..descriptor.size; } else { state = GPUBufferState::Unmapped; - mapping_range = (0, 0); + mapping_range = 0..0; } GPUBuffer::new( @@ -364,7 +364,7 @@ impl GPUDeviceMethods for GPUDevice { WebGPUBindings::Buffer(BufferBinding { buffer_id: b.buffer.id().0, offset: b.offset, - size: wgt::BufferSize::new(b.size.unwrap_or(0)), + size: b.size.and_then(wgt::BufferSize::new), }) }, }, diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 4b342e117f3..6eeb0824286 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -20,9 +20,10 @@ use servo_config::pref; use smallvec::SmallVec; use std::collections::HashMap; use std::ffi::CString; -use std::ptr; +use std::ptr::{self, NonNull}; use std::slice; use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; use webrender_traits::{ WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageHandlerType, WebrenderImageSource, @@ -36,6 +37,8 @@ use wgpu::{ resource::{BufferMapAsyncStatus, BufferMapOperation}, }; +const DEVICE_POLL_INTERVAL: u64 = 100; + #[derive(Debug, Deserialize, Serialize)] pub enum WebGPUResponse { RequestAdapter { @@ -295,6 +298,7 @@ struct WGPU<'a> { webrender_document: webrender_api::DocumentId, external_images: Arc>, wgpu_image_map: Arc>>, + last_poll: Instant, } impl<'a> WGPU<'a> { @@ -323,612 +327,633 @@ impl<'a> WGPU<'a> { webrender_document, external_images, wgpu_image_map, + last_poll: Instant::now(), } } fn run(&'a mut self) { - while let Ok(msg) = self.receiver.recv() { - self.devices.iter().for_each(|device| { - let global = &self.global; - let device_id = device.0; - gfx_select!(device_id => global.device_poll(device_id, false)); - }); - match msg { - WebGPURequest::BufferMapAsync { - sender, - buffer_id, - host_map, - map_range, - } => { - let map_info = BufferMapInfo { - buffer_id, + loop { + if self.last_poll.elapsed() >= Duration::from_millis(DEVICE_POLL_INTERVAL) { + self.global.poll_all_devices(false); + self.last_poll = Instant::now(); + } + if let Ok(msg) = self.receiver.try_recv() { + match msg { + WebGPURequest::BufferMapAsync { sender, - global: &self.global, - size: (map_range.end - map_range.start) as usize, - }; - self.buffer_maps.insert(buffer_id, map_info); + buffer_id, + host_map, + map_range, + } => { + let map_info = BufferMapInfo { + buffer_id, + sender, + global: &self.global, + size: (map_range.end - map_range.start) as usize, + }; + self.buffer_maps.insert(buffer_id, map_info); - unsafe extern "C" fn callback(status: BufferMapAsyncStatus, userdata: *mut u8) { - let info = (userdata as *mut BufferMapInfo).as_ref().unwrap(); - match status { - BufferMapAsyncStatus::Success => { - let global = info.global; - let data_pt = gfx_select!(info.buffer_id => - global.buffer_get_mapped_range(info.buffer_id, 0, None)); - let data = slice::from_raw_parts(data_pt, info.size).to_vec(); - if let Err(e) = - info.sender.send(Ok(WebGPUResponse::BufferMapAsync(data))) - { - warn!("Could not send BufferMapAsync Response ({})", e); - } - }, - _ => warn!("Could not map buffer({:?})", info.buffer_id), + unsafe extern "C" fn callback( + status: BufferMapAsyncStatus, + userdata: *mut u8, + ) { + let nonnull_info = + NonNull::new(userdata as *mut BufferMapInfo).unwrap(); + let info = nonnull_info.as_ref(); + match status { + BufferMapAsyncStatus::Success => { + let global = &info.global; + let data_pt = gfx_select!(info.buffer_id => + global.buffer_get_mapped_range(info.buffer_id, 0, None)); + let data = slice::from_raw_parts(data_pt, info.size).to_vec(); + if let Err(e) = + info.sender.send(Ok(WebGPUResponse::BufferMapAsync(data))) + { + warn!("Could not send BufferMapAsync Response ({})", e); + } + }, + _ => error!("Could not map buffer({:?})", info.buffer_id), + } } - } - let operation = BufferMapOperation { - host: host_map, - callback, - user_data: convert_to_pointer(self.buffer_maps.get(&buffer_id).unwrap()), - }; - let global = &self.global; - gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); - }, - WebGPURequest::BufferMapComplete(buffer_id) => { - self.buffer_maps.remove(&buffer_id); - }, - WebGPURequest::CommandEncoderFinish { command_encoder_id } => { - let global = &self.global; - let _ = gfx_select!(command_encoder_id => global.command_encoder_finish( - command_encoder_id, - &wgt::CommandBufferDescriptor::default() - )); - }, - WebGPURequest::CopyBufferToBuffer { - command_encoder_id, - source_id, - source_offset, - destination_id, - destination_offset, - size, - } => { - let global = &self.global; - let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_buffer( + let operation = BufferMapOperation { + host: host_map, + callback, + user_data: convert_to_pointer( + self.buffer_maps.get(&buffer_id).unwrap(), + ), + }; + let global = &self.global; + gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); + }, + WebGPURequest::BufferMapComplete(buffer_id) => { + self.buffer_maps.remove(&buffer_id); + }, + WebGPURequest::CommandEncoderFinish { command_encoder_id } => { + let global = &self.global; + let _ = gfx_select!(command_encoder_id => global.command_encoder_finish( + command_encoder_id, + &wgt::CommandBufferDescriptor::default() + )); + }, + WebGPURequest::CopyBufferToBuffer { command_encoder_id, source_id, source_offset, destination_id, destination_offset, - size - )); - }, - WebGPURequest::CreateBindGroup { - device_id, - bind_group_id, - bind_group_layout_id, - mut entries, - } => { - let global = &self.global; - let bindings = entries - .drain(..) - .map(|(bind, res)| { - let resource = match res { - WebGPUBindings::Sampler(s) => BindingResource::Sampler(s), - WebGPUBindings::TextureView(t) => BindingResource::TextureView(t), - WebGPUBindings::Buffer(b) => BindingResource::Buffer(b), - }; - BindGroupEntry { - binding: bind, - resource, - } - }) - .collect::>(); - let descriptor = BindGroupDescriptor { - label: None, - layout: bind_group_layout_id, - bindings: bindings.as_slice(), - }; - let _ = gfx_select!(bind_group_id => - global.device_create_bind_group(device_id, &descriptor, bind_group_id)); - }, - WebGPURequest::CreateBindGroupLayout { - device_id, - bind_group_layout_id, - entries, - } => { - let global = &self.global; - let descriptor = wgt::BindGroupLayoutDescriptor { - bindings: entries.as_slice(), - label: None, - }; - let _ = gfx_select!(bind_group_layout_id => - global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); - }, - WebGPURequest::CreateBuffer { - device_id, - buffer_id, - descriptor, - } => { - let global = &self.global; - let st = CString::new(descriptor.label.as_bytes()).unwrap(); - let _ = gfx_select!(buffer_id => - global.device_create_buffer(device_id, &descriptor.map_label(|_| st.as_ptr()), buffer_id)); - }, - WebGPURequest::CreateCommandEncoder { - device_id, - command_encoder_id, - } => { - let global = &self.global; - let desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; - let _ = gfx_select!(command_encoder_id => - global.device_create_command_encoder(device_id, &desc, command_encoder_id)); - }, - WebGPURequest::CreateComputePipeline { - device_id, - compute_pipeline_id, - pipeline_layout_id, - program_id, - entry_point, - } => { - let global = &self.global; - let entry_point = std::ffi::CString::new(entry_point).unwrap(); - let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor { - layout: pipeline_layout_id, - compute_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: program_id, - entry_point: entry_point.as_ptr(), - }, - }; - let _ = gfx_select!(compute_pipeline_id => - global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); - }, - WebGPURequest::CreateContext(sender) => { - let id = self - .external_images - .lock() - .expect("Lock poisoned?") - .next_id(WebrenderImageHandlerType::WebGPU); - if let Err(e) = sender.send(id) { - warn!("Failed to send ExternalImageId to new context ({})", e); - }; - }, - WebGPURequest::CreatePipelineLayout { - device_id, - pipeline_layout_id, - bind_group_layouts, - } => { - let global = &self.global; - let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor { - bind_group_layouts: bind_group_layouts.as_ptr(), - bind_group_layouts_length: bind_group_layouts.len(), - }; - let _ = gfx_select!(pipeline_layout_id => - global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)); - }, - //TODO: consider https://github.com/gfx-rs/wgpu/issues/684 - WebGPURequest::CreateRenderPipeline { - device_id, - render_pipeline_id, - pipeline_layout_id, - vertex_module, - vertex_entry_point, - fragment_module, - fragment_entry_point, - primitive_topology, - rasterization_state, - color_states, - depth_stencil_state, - vertex_state, - sample_count, - sample_mask, - alpha_to_coverage_enabled, - } => { - let global = &self.global; - let vertex_ep = std::ffi::CString::new(vertex_entry_point).unwrap(); - let frag_ep; - let frag_stage = match fragment_module { - Some(frag) => { - frag_ep = - std::ffi::CString::new(fragment_entry_point.unwrap()).unwrap(); - let frag_module = wgpu_core::pipeline::ProgrammableStageDescriptor { - module: frag, - entry_point: frag_ep.as_ptr(), - }; - Some(frag_module) - }, - None => None, - }; - let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor { - layout: pipeline_layout_id, - vertex_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: vertex_module, - entry_point: vertex_ep.as_ptr(), - }, - fragment_stage: frag_stage - .as_ref() - .map_or(ptr::null(), |fs| fs as *const _), + size, + } => { + let global = &self.global; + let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_buffer( + command_encoder_id, + source_id, + source_offset, + destination_id, + destination_offset, + size + )); + }, + WebGPURequest::CreateBindGroup { + device_id, + bind_group_id, + bind_group_layout_id, + mut entries, + } => { + let global = &self.global; + let bindings = entries + .drain(..) + .map(|(bind, res)| { + let resource = match res { + WebGPUBindings::Sampler(s) => BindingResource::Sampler(s), + WebGPUBindings::TextureView(t) => { + BindingResource::TextureView(t) + }, + WebGPUBindings::Buffer(b) => BindingResource::Buffer(b), + }; + BindGroupEntry { + binding: bind, + resource, + } + }) + .collect::>(); + let descriptor = BindGroupDescriptor { + label: None, + layout: bind_group_layout_id, + bindings: bindings.as_slice(), + }; + let _ = gfx_select!(bind_group_id => + global.device_create_bind_group(device_id, &descriptor, bind_group_id)); + }, + WebGPURequest::CreateBindGroupLayout { + device_id, + bind_group_layout_id, + entries, + } => { + let global = &self.global; + let descriptor = wgt::BindGroupLayoutDescriptor { + bindings: entries.as_slice(), + label: None, + }; + let _ = gfx_select!(bind_group_layout_id => + global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); + }, + WebGPURequest::CreateBuffer { + device_id, + buffer_id, + descriptor, + } => { + let global = &self.global; + let st = CString::new(descriptor.label.as_bytes()).unwrap(); + let _ = gfx_select!(buffer_id => + global.device_create_buffer(device_id, &descriptor.map_label(|_| st.as_ptr()), buffer_id)); + }, + WebGPURequest::CreateCommandEncoder { + device_id, + command_encoder_id, + } => { + let global = &self.global; + let desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; + let _ = gfx_select!(command_encoder_id => + global.device_create_command_encoder(device_id, &desc, command_encoder_id)); + }, + WebGPURequest::CreateComputePipeline { + device_id, + compute_pipeline_id, + pipeline_layout_id, + program_id, + entry_point, + } => { + let global = &self.global; + let entry_point = std::ffi::CString::new(entry_point).unwrap(); + let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor { + layout: pipeline_layout_id, + compute_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { + module: program_id, + entry_point: entry_point.as_ptr(), + }, + }; + let _ = gfx_select!(compute_pipeline_id => + global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); + }, + WebGPURequest::CreateContext(sender) => { + let id = self + .external_images + .lock() + .expect("Lock poisoned?") + .next_id(WebrenderImageHandlerType::WebGPU); + if let Err(e) = sender.send(id) { + warn!("Failed to send ExternalImageId to new context ({})", e); + }; + }, + WebGPURequest::CreatePipelineLayout { + device_id, + pipeline_layout_id, + bind_group_layouts, + } => { + let global = &self.global; + let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor { + bind_group_layouts: bind_group_layouts.as_ptr(), + bind_group_layouts_length: bind_group_layouts.len(), + }; + let _ = gfx_select!(pipeline_layout_id => + global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)); + }, + //TODO: consider https://github.com/gfx-rs/wgpu/issues/684 + WebGPURequest::CreateRenderPipeline { + device_id, + render_pipeline_id, + pipeline_layout_id, + vertex_module, + vertex_entry_point, + fragment_module, + fragment_entry_point, primitive_topology, - rasterization_state: &rasterization_state as *const _, - color_states: color_states.as_ptr(), - color_states_length: color_states.len(), - depth_stencil_state: depth_stencil_state - .as_ref() - .map_or(ptr::null(), |dss| dss as *const _), - vertex_state: wgpu_core::pipeline::VertexStateDescriptor { - index_format: vertex_state.0, - vertex_buffers_length: vertex_state.1.len(), - vertex_buffers: vertex_state - .1 - .iter() - .map(|buffer| wgpu_core::pipeline::VertexBufferLayoutDescriptor { - array_stride: buffer.0, - step_mode: buffer.1, - attributes_length: buffer.2.len(), - attributes: buffer.2.as_ptr(), - }) - .collect::>() - .as_ptr(), - }, + rasterization_state, + color_states, + depth_stencil_state, + vertex_state, sample_count, sample_mask, alpha_to_coverage_enabled, - }; + } => { + let global = &self.global; + let vertex_ep = std::ffi::CString::new(vertex_entry_point).unwrap(); + let frag_ep; + let frag_stage = match fragment_module { + Some(frag) => { + frag_ep = + std::ffi::CString::new(fragment_entry_point.unwrap()).unwrap(); + let frag_module = + wgpu_core::pipeline::ProgrammableStageDescriptor { + module: frag, + entry_point: frag_ep.as_ptr(), + }; + Some(frag_module) + }, + None => None, + }; + let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor { + layout: pipeline_layout_id, + vertex_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { + module: vertex_module, + entry_point: vertex_ep.as_ptr(), + }, + fragment_stage: frag_stage + .as_ref() + .map_or(ptr::null(), |fs| fs as *const _), + primitive_topology, + rasterization_state: &rasterization_state as *const _, + color_states: color_states.as_ptr(), + color_states_length: color_states.len(), + depth_stencil_state: depth_stencil_state + .as_ref() + .map_or(ptr::null(), |dss| dss as *const _), + vertex_state: wgpu_core::pipeline::VertexStateDescriptor { + index_format: vertex_state.0, + vertex_buffers_length: vertex_state.1.len(), + vertex_buffers: vertex_state + .1 + .iter() + .map(|buffer| { + wgpu_core::pipeline::VertexBufferLayoutDescriptor { + array_stride: buffer.0, + step_mode: buffer.1, + attributes_length: buffer.2.len(), + attributes: buffer.2.as_ptr(), + } + }) + .collect::>() + .as_ptr(), + }, + sample_count, + sample_mask, + alpha_to_coverage_enabled, + }; - let _ = gfx_select!(render_pipeline_id => - global.device_create_render_pipeline(device_id, &descriptor, render_pipeline_id)); - }, - WebGPURequest::CreateSampler { - device_id, - sampler_id, - descriptor, - } => { - let global = &self.global; - let st = CString::new(descriptor.label.as_bytes()).unwrap(); - let _ = gfx_select!(sampler_id => - global.device_create_sampler(device_id, &descriptor.map_label(|_| st.as_ptr()), sampler_id)); - }, - WebGPURequest::CreateShaderModule { - device_id, - program_id, - program, - } => { - let global = &self.global; - let source = wgpu_core::pipeline::ShaderModuleSource::SpirV(&program); - let _ = gfx_select!(program_id => - global.device_create_shader_module(device_id, source, program_id)); - }, - WebGPURequest::CreateSwapChain { - device_id, - buffer_id, - external_id, - sender, - image_desc, - image_data, - } => { - let height = image_desc.size.height; - let width = image_desc.size.width; - let buffer_stride = - ((width * 4) as u32 | (wgt::COPY_BYTES_PER_ROW_ALIGNMENT - 1)) + 1; - let _ = self.wgpu_image_map.lock().unwrap().insert( - external_id, - PresentationData { - device_id, - queue_id: device_id, - data: vec![255; (buffer_stride * height as u32) as usize], - size: Size2D::new(width, height), - buffer_id, - buffer_stride, - image_desc, - image_data: image_data.clone(), - }, - ); - let buffer_size = (buffer_stride * height as u32) as wgt::BufferAddress; - let global = &self.global; - let buffer_desc = wgt::BufferDescriptor { - label: ptr::null(), - size: buffer_size, - usage: wgt::BufferUsage::MAP_READ | wgt::BufferUsage::COPY_DST, - mapped_at_creation: false, - }; - let _ = gfx_select!(buffer_id => global.device_create_buffer( + let _ = gfx_select!(render_pipeline_id => + global.device_create_render_pipeline(device_id, &descriptor, render_pipeline_id)); + }, + WebGPURequest::CreateSampler { device_id, - &buffer_desc, - buffer_id - )); + sampler_id, + descriptor, + } => { + let global = &self.global; + let st = CString::new(descriptor.label.as_bytes()).unwrap(); + let _ = gfx_select!(sampler_id => global.device_create_sampler( + device_id, + &descriptor.map_label(|_| st.as_ptr()), + sampler_id + )); + }, + WebGPURequest::CreateShaderModule { + device_id, + program_id, + program, + } => { + let global = &self.global; + let source = wgpu_core::pipeline::ShaderModuleSource::SpirV(&program); + let _ = gfx_select!(program_id => + global.device_create_shader_module(device_id, source, program_id)); + }, + WebGPURequest::CreateSwapChain { + device_id, + buffer_id, + external_id, + sender, + image_desc, + image_data, + } => { + let height = image_desc.size.height; + let width = image_desc.size.width; + let buffer_stride = + ((width * 4) as u32 | (wgt::COPY_BYTES_PER_ROW_ALIGNMENT - 1)) + 1; + let _ = self.wgpu_image_map.lock().unwrap().insert( + external_id, + PresentationData { + device_id, + queue_id: device_id, + data: vec![255; (buffer_stride * height as u32) as usize], + size: Size2D::new(width, height), + buffer_id, + buffer_stride, + image_desc, + image_data: image_data.clone(), + }, + ); + let buffer_size = (buffer_stride * height as u32) as wgt::BufferAddress; + let global = &self.global; + let buffer_desc = wgt::BufferDescriptor { + label: ptr::null(), + size: buffer_size, + usage: wgt::BufferUsage::MAP_READ | wgt::BufferUsage::COPY_DST, + mapped_at_creation: false, + }; + let _ = gfx_select!(buffer_id => global.device_create_buffer( + device_id, + &buffer_desc, + buffer_id + )); - let image_key = self.webrender_api.generate_image_key(); - if let Err(e) = sender.send(image_key) { - warn!("Failed to send ImageKey ({})", e); - } + let image_key = self.webrender_api.generate_image_key(); + if let Err(e) = sender.send(image_key) { + warn!("Failed to send ImageKey ({})", e); + } - let mut txn = webrender_api::Transaction::new(); - txn.add_image(image_key, image_desc, image_data, None); - self.webrender_api - .send_transaction(self.webrender_document, txn); - }, - WebGPURequest::CreateTexture { - device_id, - texture_id, - descriptor, - } => { - let global = &self.global; - let st = CString::new(descriptor.label.as_bytes()).unwrap(); - let _ = gfx_select!(texture_id => - global.device_create_texture(device_id, &descriptor.map_label(|_| st.as_ptr()), texture_id)); - }, - WebGPURequest::CreateTextureView { - texture_id, - texture_view_id, - descriptor, - } => { - let global = &self.global; - let st = CString::new(descriptor.label.as_bytes()).unwrap(); - let _ = gfx_select!(texture_view_id => global.texture_create_view( + let mut txn = webrender_api::Transaction::new(); + txn.add_image(image_key, image_desc, image_data, None); + self.webrender_api + .send_transaction(self.webrender_document, txn); + }, + WebGPURequest::CreateTexture { + device_id, texture_id, - Some(&descriptor.map_label(|_| st.as_ptr())), - texture_view_id - )); - }, - WebGPURequest::DestroyBuffer(buffer) => { - let global = &self.global; - gfx_select!(buffer => global.buffer_destroy(buffer)); - }, - WebGPURequest::DestroySwapChain { - external_id, - image_key, - } => { - let data = self - .wgpu_image_map - .lock() - .unwrap() - .remove(&external_id) - .unwrap(); - let global = &self.global; - gfx_select!(data.buffer_id => global.buffer_destroy(data.buffer_id)); - let mut txn = webrender_api::Transaction::new(); - txn.delete_image(image_key); - self.webrender_api - .send_transaction(self.webrender_document, txn); - }, - WebGPURequest::DestroyTexture(texture) => { - let global = &self.global; - gfx_select!(texture => global.texture_destroy(texture)); - }, - WebGPURequest::Exit(sender) => { - if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) { - warn!("Failed to send WebGPUMsg::Exit to script ({})", e); - } - if let Err(e) = sender.send(()) { - warn!("Failed to send response to WebGPURequest::Exit ({})", e) - } - return; - }, - WebGPURequest::RequestAdapter { - sender, - options, - ids, - } => { - let adapter_id = match self.global.pick_adapter( - &options, - wgt::UnsafeExtensions::disallow(), - wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), - ) { - Some(id) => id, - None => { - if let Err(e) = - sender.send(Err("Failed to get webgpu adapter".to_string())) - { - warn!( + descriptor, + } => { + let global = &self.global; + let st = CString::new(descriptor.label.as_bytes()).unwrap(); + let _ = gfx_select!(texture_id => global.device_create_texture( + device_id, + &descriptor.map_label(|_| st.as_ptr()), + texture_id + )); + }, + WebGPURequest::CreateTextureView { + texture_id, + texture_view_id, + descriptor, + } => { + let global = &self.global; + let st = CString::new(descriptor.label.as_bytes()).unwrap(); + let _ = gfx_select!(texture_view_id => global.texture_create_view( + texture_id, + Some(&descriptor.map_label(|_| st.as_ptr())), + texture_view_id + )); + }, + WebGPURequest::DestroyBuffer(buffer) => { + let global = &self.global; + gfx_select!(buffer => global.buffer_destroy(buffer)); + }, + WebGPURequest::DestroySwapChain { + external_id, + image_key, + } => { + let data = self + .wgpu_image_map + .lock() + .unwrap() + .remove(&external_id) + .unwrap(); + let global = &self.global; + gfx_select!(data.buffer_id => global.buffer_destroy(data.buffer_id)); + let mut txn = webrender_api::Transaction::new(); + txn.delete_image(image_key); + self.webrender_api + .send_transaction(self.webrender_document, txn); + }, + WebGPURequest::DestroyTexture(texture) => { + let global = &self.global; + gfx_select!(texture => global.texture_destroy(texture)); + }, + WebGPURequest::Exit(sender) => { + if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) { + warn!("Failed to send WebGPUMsg::Exit to script ({})", e); + } + if let Err(e) = sender.send(()) { + warn!("Failed to send response to WebGPURequest::Exit ({})", e) + } + return; + }, + WebGPURequest::RequestAdapter { + sender, + options, + ids, + } => { + let adapter_id = match self.global.pick_adapter( + &options, + wgt::UnsafeExtensions::disallow(), + wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), + ) { + Some(id) => id, + None => { + if let Err(e) = + sender.send(Err("Failed to get webgpu adapter".to_string())) + { + warn!( "Failed to send response to WebGPURequest::RequestAdapter ({})", e ) - } - return; - }, - }; - let adapter = WebGPUAdapter(adapter_id); - self.adapters.push(adapter); - let global = &self.global; - let info = gfx_select!(adapter_id => global.adapter_get_info(adapter_id)); - if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter { - adapter_name: info.name, - adapter_id: adapter, - channel: WebGPU(self.sender.clone()), - })) { - warn!( - "Failed to send response to WebGPURequest::RequestAdapter ({})", - e - ) - } - }, - WebGPURequest::RequestDevice { - sender, - adapter_id, - descriptor, - device_id, - } => { - let global = &self.global; - let id = gfx_select!(device_id => global.adapter_request_device( - adapter_id.0, - &descriptor, - None, - device_id - )); + } + return; + }, + }; + let adapter = WebGPUAdapter(adapter_id); + self.adapters.push(adapter); + let global = &self.global; + let info = gfx_select!(adapter_id => global.adapter_get_info(adapter_id)); + if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter { + adapter_name: info.name, + adapter_id: adapter, + channel: WebGPU(self.sender.clone()), + })) { + warn!( + "Failed to send response to WebGPURequest::RequestAdapter ({})", + e + ) + } + }, + WebGPURequest::RequestDevice { + sender, + adapter_id, + descriptor, + device_id, + } => { + let global = &self.global; + let id = gfx_select!(device_id => global.adapter_request_device( + adapter_id.0, + &descriptor, + None, + device_id + )); - let device = WebGPUDevice(id); - // Note: (zakorgy) Note sure if sending the queue is needed at all, - // since wgpu-core uses the same id for the device and the queue - let queue = WebGPUQueue(id); - self.devices.push(device); - if let Err(e) = sender.send(Ok(WebGPUResponse::RequestDevice { - device_id: device, - queue_id: queue, - _descriptor: descriptor, - })) { - warn!( - "Failed to send response to WebGPURequest::RequestDevice ({})", - e - ) - } - }, - WebGPURequest::RunComputePass { - command_encoder_id, - compute_pass, - } => { - let global = &self.global; - gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass( + let device = WebGPUDevice(id); + // Note: (zakorgy) Note sure if sending the queue is needed at all, + // since wgpu-core uses the same id for the device and the queue + let queue = WebGPUQueue(id); + self.devices.push(device); + if let Err(e) = sender.send(Ok(WebGPUResponse::RequestDevice { + device_id: device, + queue_id: queue, + _descriptor: descriptor, + })) { + warn!( + "Failed to send response to WebGPURequest::RequestDevice ({})", + e + ) + } + }, + WebGPURequest::RunComputePass { command_encoder_id, - &compute_pass - )); - }, - WebGPURequest::RunRenderPass { - command_encoder_id, - render_pass, - } => { - let global = &self.global; - gfx_select!(command_encoder_id => global.command_encoder_run_render_pass( + compute_pass, + } => { + let global = &self.global; + gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass( + command_encoder_id, + &compute_pass + )); + }, + WebGPURequest::RunRenderPass { command_encoder_id, - &render_pass - )); - }, - WebGPURequest::Submit { - queue_id, - command_buffers, - } => { - let global = &self.global; - let _ = gfx_select!(queue_id => global.queue_submit( + render_pass, + } => { + let global = &self.global; + gfx_select!(command_encoder_id => global.command_encoder_run_render_pass( + command_encoder_id, + &render_pass + )); + }, + WebGPURequest::Submit { queue_id, - &command_buffers - )); - }, - WebGPURequest::SwapChainPresent { - external_id, - texture_id, - encoder_id, - image_key, - } => { - let global = &self.global; - let device_id; - let queue_id; - let size; - let buffer_id; - let buffer_stride; - { + command_buffers, + } => { + let global = &self.global; + let _ = gfx_select!(queue_id => global.queue_submit( + queue_id, + &command_buffers + )); + }, + WebGPURequest::SwapChainPresent { + external_id, + texture_id, + encoder_id, + image_key, + } => { + let global = &self.global; + let device_id; + let queue_id; + let size; + let buffer_id; + let buffer_stride; + { + if let Some(present_data) = + self.wgpu_image_map.lock().unwrap().get_mut(&external_id) + { + size = present_data.size; + device_id = present_data.device_id; + queue_id = present_data.queue_id; + buffer_id = present_data.buffer_id; + buffer_stride = present_data.buffer_stride; + } else { + warn!("Data not found for ExternalImageId({:?})", external_id); + continue; + } + } + + let buffer_size = + (size.height as u32 * buffer_stride) as wgt::BufferAddress; + let comm_desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; + let _ = gfx_select!(encoder_id => global.device_create_command_encoder( + device_id, + &comm_desc, + encoder_id + )); + + let buffer_cv = BufferCopyView { + buffer: buffer_id, + layout: wgt::TextureDataLayout { + offset: 0, + bytes_per_row: buffer_stride, + rows_per_image: 0, + }, + }; + let texture_cv = TextureCopyView { + texture: texture_id, + mip_level: 0, + origin: wgt::Origin3d::ZERO, + }; + let copy_size = wgt::Extent3d { + width: size.width as u32, + height: size.height as u32, + depth: 1, + }; + gfx_select!(encoder_id => global.command_encoder_copy_texture_to_buffer( + encoder_id, + &texture_cv, + &buffer_cv, + ©_size + )); + let _ = gfx_select!(encoder_id => global.command_encoder_finish( + encoder_id, + &wgt::CommandBufferDescriptor::default() + )); + gfx_select!(queue_id => global.queue_submit( + queue_id, + &[encoder_id] + )); + extern "C" fn callback(status: BufferMapAsyncStatus, _user_data: *mut u8) { + match status { + BufferMapAsyncStatus::Success => { + debug!("Buffer Mapped"); + }, + _ => warn!("Could not map buffer"), + } + } + let map_op = BufferMapOperation { + host: HostMap::Read, + callback, + user_data: ptr::null_mut(), + }; + gfx_select!(buffer_id => global.buffer_map_async(buffer_id, 0..buffer_size, map_op)); + // TODO: Remove the blocking behaviour + gfx_select!(device_id => global.device_poll(device_id, true)); + let buf_data = gfx_select!(buffer_id => + global.buffer_get_mapped_range(buffer_id, 0, None)); if let Some(present_data) = self.wgpu_image_map.lock().unwrap().get_mut(&external_id) { - size = present_data.size; - device_id = present_data.device_id; - queue_id = present_data.queue_id; - buffer_id = present_data.buffer_id; - buffer_stride = present_data.buffer_stride; + present_data.data = unsafe { + slice::from_raw_parts(buf_data, buffer_size as usize).to_vec() + }; + let mut txn = webrender_api::Transaction::new(); + txn.update_image( + image_key, + present_data.image_desc, + present_data.image_data.clone(), + &webrender_api::DirtyRect::All, + ); + self.webrender_api + .send_transaction(self.webrender_document, txn); } else { warn!("Data not found for ExternalImageId({:?})", external_id); - continue; } - } - - let buffer_size = (size.height as u32 * buffer_stride) as wgt::BufferAddress; - let comm_desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; - let _ = gfx_select!(encoder_id => global.device_create_command_encoder( + gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); + }, + WebGPURequest::UnmapBuffer { device_id, - &comm_desc, - encoder_id - )); - - let buffer_cv = BufferCopyView { - buffer: buffer_id, - layout: wgt::TextureDataLayout { - offset: 0, - bytes_per_row: buffer_stride, - rows_per_image: 0, - }, - }; - let texture_cv = TextureCopyView { - texture: texture_id, - mip_level: 0, - origin: wgt::Origin3d::ZERO, - }; - let copy_size = wgt::Extent3d { - width: size.width as u32, - height: size.height as u32, - depth: 1, - }; - gfx_select!(encoder_id => global.command_encoder_copy_texture_to_buffer( - encoder_id, - &texture_cv, - &buffer_cv, - ©_size - )); - let _ = gfx_select!(encoder_id => global.command_encoder_finish( - encoder_id, - &wgt::CommandBufferDescriptor::default() - )); - gfx_select!(queue_id => global.queue_submit( - queue_id, - &[encoder_id] - )); - extern "C" fn callback(status: BufferMapAsyncStatus, _user_data: *mut u8) { - match status { - BufferMapAsyncStatus::Success => { - debug!("Buffer Mapped"); - }, - _ => warn!("Could not map buffer"), + buffer_id, + array_buffer, + mapped_at_creation, + } => { + let global = &self.global; + if mapped_at_creation { + gfx_select!(device_id => global.queue_write_buffer( + device_id, + buffer_id, + 0, + array_buffer.as_slice() + )); + } else { + gfx_select!(buffer_id => global.device_set_buffer_sub_data( + device_id, + buffer_id, + 0, + array_buffer.as_slice() + )); } - } - let map_op = BufferMapOperation { - host: HostMap::Read, - callback, - user_data: ptr::null_mut(), - }; - gfx_select!(buffer_id => global.buffer_map_async(buffer_id, 0..buffer_size, map_op)); - // TODO: Remove the blocking behaviour - gfx_select!(device_id => global.device_poll(device_id, true)); - let buf_data = gfx_select!(buffer_id => - global.buffer_get_mapped_range(buffer_id, 0, None)); - if let Some(present_data) = - self.wgpu_image_map.lock().unwrap().get_mut(&external_id) - { - present_data.data = unsafe { - slice::from_raw_parts(buf_data, buffer_size as usize).to_vec() - }; - let mut txn = webrender_api::Transaction::new(); - txn.update_image( - image_key, - present_data.image_desc, - present_data.image_data.clone(), - &webrender_api::DirtyRect::All, - ); - self.webrender_api - .send_transaction(self.webrender_document, txn); - } else { - warn!("Data not found for ExternalImageId({:?})", external_id); - } - gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); - }, - WebGPURequest::UnmapBuffer { - device_id, - buffer_id, - array_buffer, - mapped_at_creation, - } => { - let global = &self.global; - if mapped_at_creation { - gfx_select!(device_id => global.queue_write_buffer( - device_id, - buffer_id, - 0, - array_buffer.as_slice() - )); - } else { - gfx_select!(buffer_id => global.device_set_buffer_sub_data( - device_id, - buffer_id, - 0, - array_buffer.as_slice() - )); - } - }, + }, + } } } }