From 0fbb75ea950e049aace6bfd60fac5e1410d2aa7d Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Tue, 14 Apr 2020 00:03:36 -0230 Subject: [PATCH] [rs] Expose more functions on the web backend --- wgpu/src/backend/native.rs | 154 ++++++++++++++++++++++++- wgpu/src/backend/web.rs | 113 ++++++++++++++++++- wgpu/src/lib.rs | 225 ++++++++++++------------------------- 3 files changed, 330 insertions(+), 162 deletions(-) diff --git a/wgpu/src/backend/native.rs b/wgpu/src/backend/native.rs index c0f757eaae..a7d7b57a39 100644 --- a/wgpu/src/backend/native.rs +++ b/wgpu/src/backend/native.rs @@ -351,6 +351,10 @@ pub(crate) fn buffer_unmap(buffer: &BufferId) { wgn::wgpu_buffer_unmap(*buffer); } +pub(crate) fn buffer_drop(buffer: &BufferId) { + wgn::wgpu_buffer_destroy(*buffer); +} + pub(crate) fn device_create_buffer(device: &DeviceId, desc: &BufferDescriptor) -> crate::Buffer { let owned_label = OwnedLabel::new(desc.label.as_deref()); crate::Buffer { @@ -445,6 +449,20 @@ pub(crate) fn command_encoder_copy_texture_to_buffer( ); } +pub(crate) fn command_encoder_copy_texture_to_texture( + command_encoder: &CommandEncoderId, + source: crate::TextureCopyView, + destination: crate::TextureCopyView, + copy_size: wgt::Extent3d, +) { + wgn::wgpu_command_encoder_copy_texture_to_texture( + *command_encoder, + &map_texture_copy_view(source), + &map_texture_copy_view(destination), + copy_size, + ); +} + pub(crate) fn begin_compute_pass(command_encoder: &CommandEncoderId) -> ComputePassId { unsafe { wgn::wgpu_command_encoder_begin_compute_pass(*command_encoder, None) } } @@ -554,10 +572,50 @@ pub(crate) fn buffer_map_read( future } +pub(crate) fn buffer_map_write( + buffer: &crate::Buffer, + start: wgt::BufferAddress, + size: wgt::BufferAddress, +) -> impl Future> { + let (future, completion) = native_gpu_future::new_gpu_future(buffer.id, size); + + extern "C" fn buffer_map_write_future_wrapper( + status: wgc::resource::BufferMapAsyncStatus, + data: *mut u8, + user_data: *mut u8, + ) { + let completion = + unsafe { native_gpu_future::GpuFutureCompletion::from_raw(user_data as _) }; + let (buffer_id, size) = completion.get_buffer_info(); + + if let wgc::resource::BufferMapAsyncStatus::Success = status { + completion.complete(Ok(crate::BufferWriteMapping { + detail: BufferWriteMappingDetail { + data, + size: size as usize, + buffer_id, + }, + })); + } else { + completion.complete(Err(crate::BufferAsyncErr)); + } + } + + wgn::wgpu_buffer_map_write_async( + buffer.id, + start, + size, + buffer_map_write_future_wrapper, + completion.to_raw() as _, + ); + + future +} + pub(crate) struct BufferReadMappingDetail { + pub(crate) buffer_id: BufferId, data: *const u8, size: usize, - pub(crate) buffer_id: BufferId, } impl BufferReadMappingDetail { @@ -566,6 +624,18 @@ impl BufferReadMappingDetail { } } +pub(crate) struct BufferWriteMappingDetail { + pub(crate) buffer_id: BufferId, + data: *mut u8, + size: usize, +} + +impl BufferWriteMappingDetail { + pub(crate) fn as_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.data as *mut u8, self.size) } + } +} + pub(crate) fn device_create_surface( window: &W, ) -> SurfaceId { @@ -633,6 +703,12 @@ pub(crate) fn render_pass_set_pipeline( } } +pub(crate) fn render_pass_set_blend_color(render_pass: &RenderPassEncoderId, color: wgt::Color) { + unsafe { + wgn::wgpu_render_pass_set_blend_color(render_pass.as_mut().unwrap(), &color); + } +} + pub(crate) fn render_pass_set_bind_group( render_pass: &RenderPassEncoderId, index: u32, @@ -684,6 +760,46 @@ pub(crate) fn render_pass_set_vertex_buffer<'a>( }; } +pub(crate) fn render_pass_set_scissor_rect( + render_pass: &RenderPassEncoderId, + x: u32, + y: u32, + width: u32, + height: u32, +) { + unsafe { + wgn::wgpu_render_pass_set_scissor_rect(render_pass.as_mut().unwrap(), x, y, width, height); + } +} + +pub(crate) fn render_pass_set_viewport( + render_pass: &RenderPassEncoderId, + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, +) { + unsafe { + wgn::wgpu_render_pass_set_viewport( + render_pass.as_mut().unwrap(), + x, + y, + width, + height, + min_depth, + max_depth, + ); + } +} + +pub(crate) fn render_pass_set_stencil_reference(render_pass: &RenderPassEncoderId, reference: u32) { + unsafe { + wgn::wgpu_render_pass_set_stencil_reference(render_pass.as_mut().unwrap(), reference); + } +} + pub(crate) fn render_pass_draw( render_pass: &RenderPassEncoderId, vertices: Range, @@ -718,6 +834,34 @@ pub(crate) fn render_pass_draw_indexed( } } +pub(crate) fn render_pass_draw_indirect<'a>( + render_pass: &RenderPassEncoderId, + indirect_buffer: &'a crate::Buffer, + indirect_offset: wgt::BufferAddress, +) { + unsafe { + wgn::wgpu_render_pass_draw_indirect( + render_pass.as_mut().unwrap(), + indirect_buffer.id, + indirect_offset, + ); + } +} + +pub(crate) fn render_pass_draw_indexed_indirect<'a>( + render_pass: &RenderPassEncoderId, + indirect_buffer: &'a crate::Buffer, + indirect_offset: wgt::BufferAddress, +) { + unsafe { + wgn::wgpu_render_pass_draw_indexed_indirect( + render_pass.as_mut().unwrap(), + indirect_buffer.id, + indirect_offset, + ); + } +} + pub(crate) fn render_pass_end_pass(render_pass: &RenderPassEncoderId) { unsafe { wgn::wgpu_render_pass_end_pass(*render_pass); @@ -731,6 +875,14 @@ pub(crate) fn texture_create_view( wgn::wgpu_texture_create_view(*texture, desc) } +pub(crate) fn texture_drop(texture: &TextureId) { + wgn::wgpu_texture_destroy(*texture); +} + +pub(crate) fn texture_view_drop(texture_view: &TextureViewId) { + wgn::wgpu_texture_view_destroy(*texture_view); +} + pub(crate) fn swap_chain_present(swap_chain: &SwapChainId) { wgn::wgpu_swap_chain_present(*swap_chain); } diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index b8018521a7..ec3b55f038 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -533,6 +533,10 @@ fn map_address_mode(mode: wgt::AddressMode) -> web_sys::GpuAddressMode { } } +fn map_color(color: wgt::Color) -> web_sys::GpuColorDict { + web_sys::GpuColorDict::new(color.a, color.b, color.g, color.r) +} + pub(crate) fn create_render_pipeline( device: &DeviceId, desc: &RenderPipelineDescriptor, @@ -665,6 +669,10 @@ pub(crate) fn buffer_unmap(buffer: &BufferId) { buffer.unmap(); } +pub(crate) fn buffer_drop(_buffer: &BufferId) { + // Buffer is dropped automatically +} + pub(crate) fn device_create_buffer(device: &DeviceId, desc: &BufferDescriptor) -> crate::Buffer { let mapped_desc = web_sys::GpuBufferDescriptor::new(desc.size as f64, desc.usage.bits()); crate::Buffer { @@ -752,6 +760,19 @@ pub(crate) fn command_encoder_copy_texture_to_buffer( ); } +pub(crate) fn command_encoder_copy_texture_to_texture( + command_encoder: &CommandEncoderId, + source: crate::TextureCopyView, + destination: crate::TextureCopyView, + copy_size: wgt::Extent3d, +) { + command_encoder.copy_texture_to_texture_with_gpu_extent_3d_dict( + &map_texture_copy_view(source), + &map_texture_copy_view(destination), + &map_extent_3d(copy_size), + ); +} + pub(crate) fn begin_compute_pass(command_encoder: &CommandEncoderId) -> ComputePassId { let mapped_desc = web_sys::GpuComputePassDescriptor::new(); command_encoder.begin_compute_pass_with_descriptor(&mapped_desc) @@ -831,6 +852,26 @@ pub(crate) async fn buffer_map_read( }) } +pub(crate) async fn buffer_map_write( + buffer: &crate::Buffer, + _start: wgt::BufferAddress, + _size: wgt::BufferAddress, +) -> Result { + let array_buffer_promise = buffer.id.map_write_async(); + let array_buffer: js_sys::ArrayBuffer = + wasm_bindgen_futures::JsFuture::from(array_buffer_promise) + .await + .expect("Unable to map buffer") + .into(); + let view = js_sys::Uint8Array::new(&array_buffer); + Ok(crate::BufferWriteMapping { + detail: BufferWriteMappingDetail { + buffer_id: buffer.id.clone(), + mapped: view.to_vec(), + }, + }) +} + pub(crate) struct BufferReadMappingDetail { pub(crate) buffer_id: BufferId, mapped: Vec, @@ -842,6 +883,17 @@ impl BufferReadMappingDetail { } } +pub(crate) struct BufferWriteMappingDetail { + pub(crate) buffer_id: BufferId, + mapped: Vec, +} + +impl BufferWriteMappingDetail { + pub(crate) fn as_slice(&mut self) -> &mut [u8] { + &mut self.mapped[..] + } +} + pub(crate) fn device_create_surface( window: &W, ) -> SurfaceId { @@ -901,12 +953,7 @@ pub(crate) fn command_encoder_begin_render_pass<'a>( let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachmentDescriptor::new( &ca.attachment.id, &match ca.load_op { - wgt::LoadOp::Clear => { - let color = ca.clear_color; - let mapped_color = - web_sys::GpuColorDict::new(color.a, color.b, color.g, color.r); - wasm_bindgen::JsValue::from(mapped_color) - } + wgt::LoadOp::Clear => wasm_bindgen::JsValue::from(map_color(ca.clear_color)), wgt::LoadOp::Load => wasm_bindgen::JsValue::from(web_sys::GpuLoadOp::Load), }, ); @@ -952,6 +999,10 @@ pub(crate) fn render_pass_set_pipeline( render_pass.set_pipeline(&pipeline); } +pub(crate) fn render_pass_set_blend_color(render_pass: &RenderPassEncoderId, color: wgt::Color) { + render_pass.set_blend_color_with_gpu_color_dict(&map_color(color)); +} + pub(crate) fn render_pass_set_bind_group( render_pass: &RenderPassEncoderId, index: u32, @@ -997,6 +1048,32 @@ pub(crate) fn render_pass_set_vertex_buffer<'a>( ); } +pub(crate) fn render_pass_set_scissor_rect( + render_pass: &RenderPassEncoderId, + x: u32, + y: u32, + width: u32, + height: u32, +) { + render_pass.set_scissor_rect(x, y, width, height); +} + +pub(crate) fn render_pass_set_viewport( + render_pass: &RenderPassEncoderId, + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, +) { + render_pass.set_viewport(x, y, width, height, min_depth, max_depth); +} + +pub(crate) fn render_pass_set_stencil_reference(render_pass: &RenderPassEncoderId, reference: u32) { + render_pass.set_stencil_reference(reference); +} + pub(crate) fn render_pass_draw( render_pass: &RenderPassEncoderId, vertices: Range, @@ -1026,6 +1103,22 @@ pub(crate) fn render_pass_draw_indexed( ); } +pub(crate) fn render_pass_draw_indirect<'a>( + render_pass: &RenderPassEncoderId, + indirect_buffer: &'a crate::Buffer, + indirect_offset: wgt::BufferAddress, +) { + render_pass.draw_indirect_with_f64(&indirect_buffer.id, indirect_offset as f64); +} + +pub(crate) fn render_pass_draw_indexed_indirect<'a>( + render_pass: &RenderPassEncoderId, + indirect_buffer: &'a crate::Buffer, + indirect_offset: wgt::BufferAddress, +) { + render_pass.draw_indexed_indirect_with_f64(&indirect_buffer.id, indirect_offset as f64); +} + pub(crate) fn render_pass_end_pass(render_pass: &RenderPassEncoderId) { render_pass.end_pass(); } @@ -1050,6 +1143,14 @@ pub(crate) fn texture_create_view( } } +pub(crate) fn texture_drop(_texture: &TextureId) { + // Texture is dropped automatically +} + +pub(crate) fn texture_view_drop(_texture_view: &TextureViewId) { + // Texture view is dropped automatically +} + pub(crate) fn swap_chain_present(_swap_chain: &SwapChainId) { // Swapchain is presented automatically } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index c18514b143..38a535d3c9 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -528,26 +528,23 @@ impl Surface { } } - /* - #[cfg(any(target_os = "ios", target_os = "macos"))] - pub fn create_surface_from_core_animation_layer(layer: *mut std::ffi::c_void) -> Self { - Surface { - id: wgn::wgpu_create_surface_from_metal_layer(layer), - } + #[cfg(any(target_os = "ios", target_os = "macos"))] + pub fn create_surface_from_core_animation_layer(layer: *mut std::ffi::c_void) -> Self { + Surface { + id: wgn::wgpu_create_surface_from_metal_layer(layer), } - */ + } } impl Adapter { - /* - /// Retrieves all available [`Adapter`]s that match the given backends. - pub fn enumerate(backends: BackendBit) -> Vec { - wgn::wgpu_enumerate_adapters(backends) - .into_iter() - .map(|id| Adapter { id }) - .collect() - } - */ + /// Retrieves all available [`Adapter`]s that match the given backends. + #[cfg(not(target_arch = "wasm32"))] + pub fn enumerate(backends: BackendBit) -> Vec { + wgn::wgpu_enumerate_adapters(backends) + .into_iter() + .map(|id| Adapter { id }) + .collect() + } /// Retrieves an [`Adapter`] which matches the given options. /// @@ -723,11 +720,8 @@ impl Drop for BufferReadMapping { } } -/* pub struct BufferWriteMapping { - data: *mut u8, - size: usize, - buffer_id: wgc::id::BufferId, + detail: backend::BufferWriteMappingDetail, } unsafe impl Send for BufferWriteMapping {} @@ -735,16 +729,15 @@ unsafe impl Sync for BufferWriteMapping {} impl BufferWriteMapping { pub fn as_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.data as *mut u8, self.size) } + self.detail.as_slice() } } impl Drop for BufferWriteMapping { fn drop(&mut self) { - wgn::wgpu_buffer_unmap(self.buffer_id); + backend::buffer_unmap(&self.detail.buffer_id); } } -*/ impl Buffer { /// Map the buffer for reading. The result is returned in a future. @@ -763,63 +756,29 @@ impl Buffer { backend::buffer_map_read(self, start, size) } - /* - /// Map the buffer for writing. The result is returned in a future. - /// - /// See the documentation of (map_read)[#method.map_read] for more information about - /// how to run this future. - pub fn map_write( - &self, - start: BufferAddress, - size: BufferAddress, - ) -> impl Future> { - let (future, completion) = native_gpu_future::new_gpu_future(self.id, size); + /// Map the buffer for writing. The result is returned in a future. + /// + /// See the documentation of (map_read)[#method.map_read] for more information about + /// how to run this future. + pub fn map_write( + &self, + start: BufferAddress, + size: BufferAddress, + ) -> impl Future> + '_ { + backend::buffer_map_write(self, start, size) + } - extern "C" fn buffer_map_write_future_wrapper( - status: wgc::resource::BufferMapAsyncStatus, - data: *mut u8, - user_data: *mut u8, - ) { - let completion = - unsafe { native_gpu_future::GpuFutureCompletion::from_raw(user_data as _) }; - let (buffer_id, size) = completion.get_buffer_info(); - - if let wgc::resource::BufferMapAsyncStatus::Success = status { - completion.complete(Ok(BufferWriteMapping { - data, - size: size as usize, - buffer_id, - })); - } else { - completion.complete(Err(BufferAsyncErr)); - } - } - - wgn::wgpu_buffer_map_write_async( - self.id, - start, - size, - buffer_map_write_future_wrapper, - completion.to_raw() as _, - ); - - future - } - - /// Flushes any pending write operations and unmaps the buffer from host memory. - pub fn unmap(&self) { - wgn::wgpu_buffer_unmap(self.id); - } - */ -} - -/* -impl Drop for Buffer { - fn drop(&mut self) { - wgn::wgpu_buffer_destroy(self.id); + /// Flushes any pending write operations and unmaps the buffer from host memory. + pub fn unmap(&self) { + backend::buffer_unmap(&self.id); + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + backend::buffer_drop(&self.id); } } -*/ impl Texture { /// Creates a view of this texture. @@ -839,11 +798,10 @@ impl Texture { } } -/* impl Drop for Texture { fn drop(&mut self) { if self.owned { - wgn::wgpu_texture_destroy(self.id); + backend::texture_drop(&self.id); } } } @@ -851,11 +809,10 @@ impl Drop for Texture { impl Drop for TextureView { fn drop(&mut self) { if self.owned { - wgn::wgpu_texture_view_destroy(self.id); + backend::texture_view_drop(&self.id); } } } -*/ impl CommandEncoder { /// Finishes recording and returns a [`CommandBuffer`] that can be submitted for execution. @@ -927,22 +884,15 @@ impl CommandEncoder { backend::command_encoder_copy_texture_to_buffer(&self.id, source, destination, copy_size); } - /* - /// Copy data from one texture to another. - pub fn copy_texture_to_texture( - &mut self, - source: TextureCopyView, - destination: TextureCopyView, - copy_size: Extent3d, - ) { - wgn::wgpu_command_encoder_copy_texture_to_texture( - self.id, - &source.into_native(), - &destination.into_native(), - copy_size, - ); - } - */ + /// Copy data from one texture to another. + pub fn copy_texture_to_texture( + &mut self, + source: TextureCopyView, + destination: TextureCopyView, + copy_size: Extent3d, + ) { + backend::command_encoder_copy_texture_to_texture(&self.id, source, destination, copy_size); + } } impl<'a> RenderPass<'a> { @@ -963,14 +913,9 @@ impl<'a> RenderPass<'a> { backend::render_pass_set_pipeline(&self.id, &pipeline.id) } - /* - pub fn set_blend_color(&mut self, color: Color) { - unsafe { - wgn::wgpu_render_pass_set_blend_color(self.id.as_mut().unwrap(), &color); - } - } - } - */ + pub fn set_blend_color(&mut self, color: Color) { + backend::render_pass_set_blend_color(&self.id, color) + } /// Sets the active index buffer. /// @@ -1011,42 +956,26 @@ impl<'a> RenderPass<'a> { backend::render_pass_set_vertex_buffer(&self.id, slot, buffer, offset, size) } - /* - /// Sets the scissor region. - /// - /// Subsequent draw calls will discard any fragments that fall outside this region. - pub fn set_scissor_rect(&mut self, x: u32, y: u32, w: u32, h: u32) { - unsafe { - wgn::wgpu_render_pass_set_scissor_rect(self.id.as_mut().unwrap(), x, y, w, h); - } - } + /// Sets the scissor region. + /// + /// Subsequent draw calls will discard any fragments that fall outside this region. + pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) { + backend::render_pass_set_scissor_rect(&self.id, x, y, width, height); + } - /// Sets the viewport region. - /// - /// Subsequent draw calls will draw any fragments in this region. - pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) { - unsafe { - wgn::wgpu_render_pass_set_viewport( - self.id.as_mut().unwrap(), - x, - y, - w, - h, - min_depth, - max_depth, - ); - } - } + /// Sets the viewport region. + /// + /// Subsequent draw calls will draw any fragments in this region. + pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) { + backend::render_pass_set_viewport(&self.id, x, y, w, h, min_depth, max_depth); + } - /// Sets the stencil reference. - /// - /// Subsequent stencil tests will test against this value. - pub fn set_stencil_reference(&mut self, reference: u32) { - unsafe { - wgn::wgpu_render_pass_set_stencil_reference(self.id.as_mut().unwrap(), reference); - } - } - */ + /// Sets the stencil reference. + /// + /// Subsequent stencil tests will test against this value. + pub fn set_stencil_reference(&mut self, reference: u32) { + backend::render_pass_set_stencil_reference(&self.id, reference); + } /// Draws primitives from the active vertex buffer(s). /// @@ -1063,7 +992,6 @@ impl<'a> RenderPass<'a> { backend::render_pass_draw_indexed(&self.id, indices, base_vertex, instances); } - /* /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. /// /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`]. @@ -1080,13 +1008,7 @@ impl<'a> RenderPass<'a> { /// } /// ``` pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - unsafe { - wgn::wgpu_render_pass_draw_indirect( - self.id.as_mut().unwrap(), - indirect_buffer.id, - indirect_offset, - ); - } + backend::render_pass_draw_indirect(&self.id, indirect_buffer, indirect_offset); } /// Draws indexed primitives using the active index buffer and the active vertex buffers, @@ -1112,15 +1034,8 @@ impl<'a> RenderPass<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - unsafe { - wgn::wgpu_render_pass_draw_indexed_indirect( - self.id.as_mut().unwrap(), - indirect_buffer.id, - indirect_offset, - ); - } + backend::render_pass_draw_indexed_indirect(&self.id, indirect_buffer, indirect_offset); } - */ } impl<'a> Drop for RenderPass<'a> {