diff options
Diffstat (limited to 'ext/webgpu/render_pass.rs')
-rw-r--r-- | ext/webgpu/render_pass.rs | 83 |
1 files changed, 44 insertions, 39 deletions
diff --git a/ext/webgpu/render_pass.rs b/ext/webgpu/render_pass.rs index e01a6d478..125579b52 100644 --- a/ext/webgpu/render_pass.rs +++ b/ext/webgpu/render_pass.rs @@ -1,6 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::error::null_opbuf; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::ResourceId; @@ -10,6 +9,8 @@ use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; +use crate::pipeline::GpuIndexFormat; + use super::error::WebGpuResult; pub(crate) struct WebGpuRenderPass( @@ -253,11 +254,13 @@ pub fn op_webgpu_render_pass_execute_bundles( .resource_table .get::<WebGpuRenderPass>(args.render_pass_rid)?; + // SAFETY: the raw pointer and length are of the same slice, and that slice + // lives longer than the below function invocation. unsafe { wgpu_core::command::render_ffi::wgpu_render_pass_execute_bundles( &mut render_pass_resource.0.borrow_mut(), render_bundle_ids.as_ptr(), - args.bundles.len(), + render_bundle_ids.len(), ); } @@ -297,7 +300,7 @@ pub struct RenderPassSetBindGroupArgs { render_pass_rid: ResourceId, index: u32, bind_group: u32, - dynamic_offsets_data: Option<Vec<u32>>, + dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data_start: usize, dynamic_offsets_data_length: usize, } @@ -305,7 +308,7 @@ pub struct RenderPassSetBindGroupArgs { pub fn op_webgpu_render_pass_set_bind_group( state: &mut OpState, args: RenderPassSetBindGroupArgs, - zero_copy: Option<ZeroCopyBuf>, + _: (), ) -> Result<WebGpuResult, AnyError> { let bind_group_resource = state @@ -315,37 +318,35 @@ pub fn op_webgpu_render_pass_set_bind_group( .resource_table .get::<WebGpuRenderPass>(args.render_pass_rid)?; - // I know this might look like it can be easily deduplicated, but it can not - // be due to the lifetime of the args.dynamic_offsets_data slice. Because we - // need to use a raw pointer here the slice can be freed before the pointer - // is used in wgpu_render_pass_set_bind_group. See - // https://matrix.to/#/!XFRnMvAfptAHthwBCx:matrix.org/$HgrlhD-Me1DwsGb8UdMu2Hqubgks8s7ILwWRwigOUAg - match args.dynamic_offsets_data { - Some(data) => unsafe { - wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( - &mut render_pass_resource.0.borrow_mut(), - args.index, - bind_group_resource.0, - data.as_slice().as_ptr(), - args.dynamic_offsets_data_length, - ); - }, - None => { - let zero_copy = zero_copy.ok_or_else(null_opbuf)?; - let (prefix, data, suffix) = unsafe { zero_copy.align_to::<u32>() }; - assert!(prefix.is_empty()); - assert!(suffix.is_empty()); - unsafe { - wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( - &mut render_pass_resource.0.borrow_mut(), - args.index, - bind_group_resource.0, - data[args.dynamic_offsets_data_start..].as_ptr(), - args.dynamic_offsets_data_length, - ); - } - } - }; + // Align the data + assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0); + // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a + // multiple of 4. + let (prefix, dynamic_offsets_data, suffix) = + unsafe { args.dynamic_offsets_data.align_to::<u32>() }; + assert!(prefix.is_empty()); + assert!(suffix.is_empty()); + + let start = args.dynamic_offsets_data_start; + let len = args.dynamic_offsets_data_length; + + // Assert that length and start are both in bounds + assert!(start <= dynamic_offsets_data.len()); + assert!(len <= dynamic_offsets_data.len() - start); + + let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len]; + + // SAFETY: the raw pointer and length are of the same slice, and that slice + // lives longer than the below function invocation. + unsafe { + wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( + &mut render_pass_resource.0.borrow_mut(), + args.index, + bind_group_resource.0, + dynamic_offsets_data.as_ptr(), + dynamic_offsets_data.len(), + ); + } Ok(WebGpuResult::empty()) } @@ -366,8 +367,10 @@ pub fn op_webgpu_render_pass_push_debug_group( .resource_table .get::<WebGpuRenderPass>(args.render_pass_rid)?; + let label = std::ffi::CString::new(args.group_label).unwrap(); + // SAFETY: the string the raw pointer points to lives longer than the below + // function invocation. unsafe { - let label = std::ffi::CString::new(args.group_label).unwrap(); wgpu_core::command::render_ffi::wgpu_render_pass_push_debug_group( &mut render_pass_resource.0.borrow_mut(), label.as_ptr(), @@ -416,8 +419,10 @@ pub fn op_webgpu_render_pass_insert_debug_marker( .resource_table .get::<WebGpuRenderPass>(args.render_pass_rid)?; + let label = std::ffi::CString::new(args.marker_label).unwrap(); + // SAFETY: the string the raw pointer points to lives longer than the below + // function invocation. unsafe { - let label = std::ffi::CString::new(args.marker_label).unwrap(); wgpu_core::command::render_ffi::wgpu_render_pass_insert_debug_marker( &mut render_pass_resource.0.borrow_mut(), label.as_ptr(), @@ -461,7 +466,7 @@ pub fn op_webgpu_render_pass_set_pipeline( pub struct RenderPassSetIndexBufferArgs { render_pass_rid: ResourceId, buffer: u32, - index_format: String, + index_format: GpuIndexFormat, offset: u64, size: Option<u64>, } @@ -489,7 +494,7 @@ pub fn op_webgpu_render_pass_set_index_buffer( render_pass_resource.0.borrow_mut().set_index_buffer( buffer_resource.0, - super::pipeline::serialize_index_format(args.index_format), + args.index_format.into(), args.offset, size, ); |