Remove exposed C symbols from renderpass/computepass recording (#5409)

Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
Andreas Reich 2024-04-17 22:48:45 +02:00 committed by GitHub
parent c1291bd131
commit ad6774f7bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 148 additions and 343 deletions

View File

@ -154,6 +154,7 @@ Bottom level categories:
- Failing to set the device lost closure will call the closure before returning. By @bradwerth in [#5358](https://github.com/gfx-rs/wgpu/pull/5358). - Failing to set the device lost closure will call the closure before returning. By @bradwerth in [#5358](https://github.com/gfx-rs/wgpu/pull/5358).
- Use memory pooling for UsageScopes to avoid frequent large allocations. by @robtfm in [#5414](https://github.com/gfx-rs/wgpu/pull/5414) - Use memory pooling for UsageScopes to avoid frequent large allocations. by @robtfm in [#5414](https://github.com/gfx-rs/wgpu/pull/5414)
- Fix deadlocks caused by recursive read-write lock acquisitions [#5426](https://github.com/gfx-rs/wgpu/pull/5426). - Fix deadlocks caused by recursive read-write lock acquisitions [#5426](https://github.com/gfx-rs/wgpu/pull/5426).
- Remove exposed C symbols (`extern "C"` + [no_mangle]) from RenderPass & ComputePass recording. By @wumpf in [#5409](https://github.com/gfx-rs/wgpu/pull/5409).
- Fix surfaces being only compatible with first backend enabled on an instance, causing failures when manually specifying an adapter. By @Wumpf in [#5535](https://github.com/gfx-rs/wgpu/pull/5535). - Fix surfaces being only compatible with first backend enabled on an instance, causing failures when manually specifying an adapter. By @Wumpf in [#5535](https://github.com/gfx-rs/wgpu/pull/5535).
#### Naga #### Naga

View File

@ -31,7 +31,7 @@ pub fn op_webgpu_compute_pass_set_pipeline(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_set_pipeline( wgpu_core::command::compute_commands::wgpu_compute_pass_set_pipeline(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
compute_pipeline_resource.1, compute_pipeline_resource.1,
); );
@ -52,7 +52,7 @@ pub fn op_webgpu_compute_pass_dispatch_workgroups(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups( wgpu_core::command::compute_commands::wgpu_compute_pass_dispatch_workgroups(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
x, x,
y, y,
@ -77,7 +77,7 @@ pub fn op_webgpu_compute_pass_dispatch_workgroups_indirect(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups_indirect( wgpu_core::command::compute_commands::wgpu_compute_pass_dispatch_workgroups_indirect(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
buffer_resource.1, buffer_resource.1,
indirect_offset, indirect_offset,
@ -137,17 +137,12 @@ pub fn op_webgpu_compute_pass_set_bind_group(
let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len]; 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 wgpu_core::command::compute_commands::wgpu_compute_pass_set_bind_group(
// lives longer than the below function invocation.
unsafe {
wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
index, index,
bind_group_resource.1, bind_group_resource.1,
dynamic_offsets_data.as_ptr(), dynamic_offsets_data,
dynamic_offsets_data.len(),
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -163,16 +158,11 @@ pub fn op_webgpu_compute_pass_push_debug_group(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
let label = std::ffi::CString::new(group_label).unwrap(); wgpu_core::command::compute_commands::wgpu_compute_pass_push_debug_group(
// SAFETY: the string the raw pointer points to lives longer than the below
// function invocation.
unsafe {
wgpu_core::command::compute_ffi::wgpu_compute_pass_push_debug_group(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
label.as_ptr(), group_label,
0, // wgpu#975 0, // wgpu#975
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -187,7 +177,7 @@ pub fn op_webgpu_compute_pass_pop_debug_group(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_pop_debug_group( wgpu_core::command::compute_commands::wgpu_compute_pass_pop_debug_group(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
); );
@ -205,16 +195,11 @@ pub fn op_webgpu_compute_pass_insert_debug_marker(
.resource_table .resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
let label = std::ffi::CString::new(marker_label).unwrap(); wgpu_core::command::compute_commands::wgpu_compute_pass_insert_debug_marker(
// SAFETY: the string the raw pointer points to lives longer than the below
// function invocation.
unsafe {
wgpu_core::command::compute_ffi::wgpu_compute_pass_insert_debug_marker(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
label.as_ptr(), marker_label,
0, // wgpu#975 0, // wgpu#975
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }

View File

@ -41,7 +41,7 @@ pub fn op_webgpu_render_pass_set_viewport(
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(args.render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_viewport( wgpu_core::command::render_commands::wgpu_render_pass_set_viewport(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.x, args.x,
args.y, args.y,
@ -68,7 +68,7 @@ pub fn op_webgpu_render_pass_set_scissor_rect(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_scissor_rect( wgpu_core::command::render_commands::wgpu_render_pass_set_scissor_rect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
x, x,
y, y,
@ -90,7 +90,7 @@ pub fn op_webgpu_render_pass_set_blend_constant(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant( wgpu_core::command::render_commands::wgpu_render_pass_set_blend_constant(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
&color, &color,
); );
@ -109,7 +109,7 @@ pub fn op_webgpu_render_pass_set_stencil_reference(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_stencil_reference( wgpu_core::command::render_commands::wgpu_render_pass_set_stencil_reference(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
reference, reference,
); );
@ -128,7 +128,7 @@ pub fn op_webgpu_render_pass_begin_occlusion_query(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_begin_occlusion_query( wgpu_core::command::render_commands::wgpu_render_pass_begin_occlusion_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
query_index, query_index,
); );
@ -146,7 +146,7 @@ pub fn op_webgpu_render_pass_end_occlusion_query(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_end_occlusion_query( wgpu_core::command::render_commands::wgpu_render_pass_end_occlusion_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
); );
@ -174,15 +174,10 @@ pub fn op_webgpu_render_pass_execute_bundles(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
// SAFETY: the raw pointer and length are of the same slice, and that slice wgpu_core::command::render_commands::wgpu_render_pass_execute_bundles(
// 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(), &mut render_pass_resource.0.borrow_mut(),
bundles.as_ptr(), &bundles,
bundles.len(),
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -235,17 +230,12 @@ pub fn op_webgpu_render_pass_set_bind_group(
let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len]; 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 wgpu_core::command::render_commands::wgpu_render_pass_set_bind_group(
// 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(), &mut render_pass_resource.0.borrow_mut(),
index, index,
bind_group_resource.1, bind_group_resource.1,
dynamic_offsets_data.as_ptr(), dynamic_offsets_data,
dynamic_offsets_data.len(),
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -261,16 +251,11 @@ pub fn op_webgpu_render_pass_push_debug_group(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let label = std::ffi::CString::new(group_label).unwrap(); wgpu_core::command::render_commands::wgpu_render_pass_push_debug_group(
// SAFETY: the string the raw pointer points to lives longer than the below
// function invocation.
unsafe {
wgpu_core::command::render_ffi::wgpu_render_pass_push_debug_group(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
label.as_ptr(), group_label,
0, // wgpu#975 0, // wgpu#975
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -285,7 +270,7 @@ pub fn op_webgpu_render_pass_pop_debug_group(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_pop_debug_group( wgpu_core::command::render_commands::wgpu_render_pass_pop_debug_group(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
); );
@ -303,16 +288,11 @@ pub fn op_webgpu_render_pass_insert_debug_marker(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let label = std::ffi::CString::new(marker_label).unwrap(); wgpu_core::command::render_commands::wgpu_render_pass_insert_debug_marker(
// SAFETY: the string the raw pointer points to lives longer than the below
// function invocation.
unsafe {
wgpu_core::command::render_ffi::wgpu_render_pass_insert_debug_marker(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
label.as_ptr(), marker_label,
0, // wgpu#975 0, // wgpu#975
); );
}
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -331,7 +311,7 @@ pub fn op_webgpu_render_pass_set_pipeline(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_pipeline( wgpu_core::command::render_commands::wgpu_render_pass_set_pipeline(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
render_pipeline_resource.1, render_pipeline_resource.1,
); );
@ -401,7 +381,7 @@ pub fn op_webgpu_render_pass_set_vertex_buffer(
None None
}; };
wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer( wgpu_core::command::render_commands::wgpu_render_pass_set_vertex_buffer(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
slot, slot,
buffer_resource.1, buffer_resource.1,
@ -426,7 +406,7 @@ pub fn op_webgpu_render_pass_draw(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw( wgpu_core::command::render_commands::wgpu_render_pass_draw(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
vertex_count, vertex_count,
instance_count, instance_count,
@ -452,7 +432,7 @@ pub fn op_webgpu_render_pass_draw_indexed(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed( wgpu_core::command::render_commands::wgpu_render_pass_draw_indexed(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
index_count, index_count,
instance_count, instance_count,
@ -479,7 +459,7 @@ pub fn op_webgpu_render_pass_draw_indirect(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indirect( wgpu_core::command::render_commands::wgpu_render_pass_draw_indirect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
buffer_resource.1, buffer_resource.1,
indirect_offset, indirect_offset,
@ -503,7 +483,7 @@ pub fn op_webgpu_render_pass_draw_indexed_indirect(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed_indirect( wgpu_core::command::render_commands::wgpu_render_pass_draw_indexed_indirect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
buffer_resource.1, buffer_resource.1,
indirect_offset, indirect_offset,

View File

@ -1548,15 +1548,14 @@ pub mod bundle_ffi {
offsets: *const DynamicOffset, offsets: *const DynamicOffset,
offset_length: usize, offset_length: usize,
) { ) {
let redundant = unsafe { let offsets = unsafe { slice::from_raw_parts(offsets, offset_length) };
bundle.current_bind_groups.set_and_check_redundant(
let redundant = bundle.current_bind_groups.set_and_check_redundant(
bind_group_id, bind_group_id,
index, index,
&mut bundle.base.dynamic_offsets, &mut bundle.base.dynamic_offsets,
offsets, offsets,
offset_length, );
)
};
if redundant { if redundant {
return; return;

View File

@ -885,33 +885,24 @@ impl Global {
} }
} }
pub mod compute_ffi { pub mod compute_commands {
use super::{ComputeCommand, ComputePass}; use super::{ComputeCommand, ComputePass};
use crate::{id, RawString}; use crate::id;
use std::{convert::TryInto, ffi, slice}; use std::convert::TryInto;
use wgt::{BufferAddress, DynamicOffset}; use wgt::{BufferAddress, DynamicOffset};
/// # Safety pub fn wgpu_compute_pass_set_bind_group(
///
/// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `offset_length` elements.
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_set_bind_group(
pass: &mut ComputePass, pass: &mut ComputePass,
index: u32, index: u32,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
offsets: *const DynamicOffset, offsets: &[DynamicOffset],
offset_length: usize,
) { ) {
let redundant = unsafe { let redundant = pass.current_bind_groups.set_and_check_redundant(
pass.current_bind_groups.set_and_check_redundant(
bind_group_id, bind_group_id,
index, index,
&mut pass.base.dynamic_offsets, &mut pass.base.dynamic_offsets,
offsets, offsets,
offset_length, );
)
};
if redundant { if redundant {
return; return;
@ -919,13 +910,12 @@ pub mod compute_ffi {
pass.base.commands.push(ComputeCommand::SetBindGroup { pass.base.commands.push(ComputeCommand::SetBindGroup {
index, index,
num_dynamic_offsets: offset_length, num_dynamic_offsets: offsets.len(),
bind_group_id, bind_group_id,
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_set_pipeline(
pub extern "C" fn wgpu_compute_pass_set_pipeline(
pass: &mut ComputePass, pass: &mut ComputePass,
pipeline_id: id::ComputePipelineId, pipeline_id: id::ComputePipelineId,
) { ) {
@ -938,47 +928,34 @@ pub mod compute_ffi {
.push(ComputeCommand::SetPipeline(pipeline_id)); .push(ComputeCommand::SetPipeline(pipeline_id));
} }
/// # Safety pub fn wgpu_compute_pass_set_push_constant(pass: &mut ComputePass, offset: u32, data: &[u8]) {
///
/// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `size_bytes` bytes.
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_set_push_constant(
pass: &mut ComputePass,
offset: u32,
size_bytes: u32,
data: *const u8,
) {
assert_eq!( assert_eq!(
offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1), offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0, 0,
"Push constant offset must be aligned to 4 bytes." "Push constant offset must be aligned to 4 bytes."
); );
assert_eq!( assert_eq!(
size_bytes & (wgt::PUSH_CONSTANT_ALIGNMENT - 1), data.len() as u32 & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0, 0,
"Push constant size must be aligned to 4 bytes." "Push constant size must be aligned to 4 bytes."
); );
let data_slice = unsafe { slice::from_raw_parts(data, size_bytes as usize) };
let value_offset = pass.base.push_constant_data.len().try_into().expect( let value_offset = pass.base.push_constant_data.len().try_into().expect(
"Ran out of push constant space. Don't set 4gb of push constants per ComputePass.", "Ran out of push constant space. Don't set 4gb of push constants per ComputePass.",
); );
pass.base.push_constant_data.extend( pass.base.push_constant_data.extend(
data_slice data.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])), .map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])),
); );
pass.base.commands.push(ComputeCommand::SetPushConstant { pass.base.commands.push(ComputeCommand::SetPushConstant {
offset, offset,
size_bytes, size_bytes: data.len() as u32,
values_offset: value_offset, values_offset: value_offset,
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_dispatch_workgroups(
pub extern "C" fn wgpu_compute_pass_dispatch_workgroups(
pass: &mut ComputePass, pass: &mut ComputePass,
groups_x: u32, groups_x: u32,
groups_y: u32, groups_y: u32,
@ -989,8 +966,7 @@ pub mod compute_ffi {
.push(ComputeCommand::Dispatch([groups_x, groups_y, groups_z])); .push(ComputeCommand::Dispatch([groups_x, groups_y, groups_z]));
} }
#[no_mangle] pub fn wgpu_compute_pass_dispatch_workgroups_indirect(
pub extern "C" fn wgpu_compute_pass_dispatch_workgroups_indirect(
pass: &mut ComputePass, pass: &mut ComputePass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -1000,17 +976,8 @@ pub mod compute_ffi {
.push(ComputeCommand::DispatchIndirect { buffer_id, offset }); .push(ComputeCommand::DispatchIndirect { buffer_id, offset });
} }
/// # Safety pub fn wgpu_compute_pass_push_debug_group(pass: &mut ComputePass, label: &str, color: u32) {
/// let bytes = label.as_bytes();
/// This function is unsafe as there is no guarantee that the given `label`
/// is a valid null-terminated string.
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_push_debug_group(
pass: &mut ComputePass,
label: RawString,
color: u32,
) {
let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
pass.base.string_data.extend_from_slice(bytes); pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(ComputeCommand::PushDebugGroup { pass.base.commands.push(ComputeCommand::PushDebugGroup {
@ -1019,22 +986,12 @@ pub mod compute_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_pop_debug_group(pass: &mut ComputePass) {
pub extern "C" fn wgpu_compute_pass_pop_debug_group(pass: &mut ComputePass) {
pass.base.commands.push(ComputeCommand::PopDebugGroup); pass.base.commands.push(ComputeCommand::PopDebugGroup);
} }
/// # Safety pub fn wgpu_compute_pass_insert_debug_marker(pass: &mut ComputePass, label: &str, color: u32) {
/// let bytes = label.as_bytes();
/// This function is unsafe as there is no guarantee that the given `label`
/// is a valid null-terminated string.
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_insert_debug_marker(
pass: &mut ComputePass,
label: RawString,
color: u32,
) {
let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
pass.base.string_data.extend_from_slice(bytes); pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(ComputeCommand::InsertDebugMarker { pass.base.commands.push(ComputeCommand::InsertDebugMarker {
@ -1043,8 +1000,7 @@ pub mod compute_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_write_timestamp(
pub extern "C" fn wgpu_compute_pass_write_timestamp(
pass: &mut ComputePass, pass: &mut ComputePass,
query_set_id: id::QuerySetId, query_set_id: id::QuerySetId,
query_index: u32, query_index: u32,
@ -1055,8 +1011,7 @@ pub mod compute_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_begin_pipeline_statistics_query(
pub extern "C" fn wgpu_compute_pass_begin_pipeline_statistics_query(
pass: &mut ComputePass, pass: &mut ComputePass,
query_set_id: id::QuerySetId, query_set_id: id::QuerySetId,
query_index: u32, query_index: u32,
@ -1069,8 +1024,7 @@ pub mod compute_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_compute_pass_end_pipeline_statistics_query(pass: &mut ComputePass) {
pub extern "C" fn wgpu_compute_pass_end_pipeline_statistics_query(pass: &mut ComputePass) {
pass.base pass.base
.commands .commands
.push(ComputeCommand::EndPipelineStatisticsQuery); .push(ComputeCommand::EndPipelineStatisticsQuery);

View File

@ -9,7 +9,6 @@ mod query;
mod render; mod render;
mod transfer; mod transfer;
use std::slice;
use std::sync::Arc; use std::sync::Arc;
pub(crate) use self::clear::clear_texture; pub(crate) use self::clear::clear_texture;
@ -757,16 +756,15 @@ impl BindGroupStateChange {
} }
} }
unsafe fn set_and_check_redundant( fn set_and_check_redundant(
&mut self, &mut self,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
index: u32, index: u32,
dynamic_offsets: &mut Vec<u32>, dynamic_offsets: &mut Vec<u32>,
offsets: *const wgt::DynamicOffset, offsets: &[wgt::DynamicOffset],
offset_length: usize,
) -> bool { ) -> bool {
// For now never deduplicate bind groups with dynamic offsets. // For now never deduplicate bind groups with dynamic offsets.
if offset_length == 0 { if offsets.is_empty() {
// If this get returns None, that means we're well over the limit, // If this get returns None, that means we're well over the limit,
// so let the call through to get a proper error // so let the call through to get a proper error
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) { if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
@ -782,8 +780,7 @@ impl BindGroupStateChange {
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) { if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
current_bind_group.reset(); current_bind_group.reset();
} }
dynamic_offsets dynamic_offsets.extend_from_slice(offsets);
.extend_from_slice(unsafe { slice::from_raw_parts(offsets, offset_length) });
} }
false false
} }

View File

@ -2459,36 +2459,31 @@ impl Global {
} }
} }
pub mod render_ffi { pub mod render_commands {
use super::{ use super::{
super::{Rect, RenderCommand}, super::{Rect, RenderCommand},
RenderPass, RenderPass,
}; };
use crate::{id, RawString}; use crate::id;
use std::{convert::TryInto, ffi, num::NonZeroU32, slice}; use std::{convert::TryInto, num::NonZeroU32};
use wgt::{BufferAddress, BufferSize, Color, DynamicOffset, IndexFormat}; use wgt::{BufferAddress, BufferSize, Color, DynamicOffset, IndexFormat};
/// # Safety /// # Safety
/// ///
/// This function is unsafe as there is no guarantee that the given pointer is /// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `offset_length` elements. /// valid for `offset_length` elements.
#[no_mangle] pub fn wgpu_render_pass_set_bind_group(
pub unsafe extern "C" fn wgpu_render_pass_set_bind_group(
pass: &mut RenderPass, pass: &mut RenderPass,
index: u32, index: u32,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
offsets: *const DynamicOffset, offsets: &[DynamicOffset],
offset_length: usize,
) { ) {
let redundant = unsafe { let redundant = pass.current_bind_groups.set_and_check_redundant(
pass.current_bind_groups.set_and_check_redundant(
bind_group_id, bind_group_id,
index, index,
&mut pass.base.dynamic_offsets, &mut pass.base.dynamic_offsets,
offsets, offsets,
offset_length, );
)
};
if redundant { if redundant {
return; return;
@ -2496,16 +2491,12 @@ pub mod render_ffi {
pass.base.commands.push(RenderCommand::SetBindGroup { pass.base.commands.push(RenderCommand::SetBindGroup {
index, index,
num_dynamic_offsets: offset_length, num_dynamic_offsets: offsets.len(),
bind_group_id, bind_group_id,
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_set_pipeline(pass: &mut RenderPass, pipeline_id: id::RenderPipelineId) {
pub extern "C" fn wgpu_render_pass_set_pipeline(
pass: &mut RenderPass,
pipeline_id: id::RenderPipelineId,
) {
if pass.current_pipeline.set_and_check_redundant(pipeline_id) { if pass.current_pipeline.set_and_check_redundant(pipeline_id) {
return; return;
} }
@ -2515,8 +2506,7 @@ pub mod render_ffi {
.push(RenderCommand::SetPipeline(pipeline_id)); .push(RenderCommand::SetPipeline(pipeline_id));
} }
#[no_mangle] pub fn wgpu_render_pass_set_vertex_buffer(
pub extern "C" fn wgpu_render_pass_set_vertex_buffer(
pass: &mut RenderPass, pass: &mut RenderPass,
slot: u32, slot: u32,
buffer_id: id::BufferId, buffer_id: id::BufferId,
@ -2531,8 +2521,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_set_index_buffer(
pub extern "C" fn wgpu_render_pass_set_index_buffer(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer: id::BufferId, buffer: id::BufferId,
index_format: IndexFormat, index_format: IndexFormat,
@ -2542,22 +2531,19 @@ pub mod render_ffi {
pass.set_index_buffer(buffer, index_format, offset, size); pass.set_index_buffer(buffer, index_format, offset, size);
} }
#[no_mangle] pub fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
pub extern "C" fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
pass.base pass.base
.commands .commands
.push(RenderCommand::SetBlendConstant(*color)); .push(RenderCommand::SetBlendConstant(*color));
} }
#[no_mangle] pub fn wgpu_render_pass_set_stencil_reference(pass: &mut RenderPass, value: u32) {
pub extern "C" fn wgpu_render_pass_set_stencil_reference(pass: &mut RenderPass, value: u32) {
pass.base pass.base
.commands .commands
.push(RenderCommand::SetStencilReference(value)); .push(RenderCommand::SetStencilReference(value));
} }
#[no_mangle] pub fn wgpu_render_pass_set_viewport(
pub extern "C" fn wgpu_render_pass_set_viewport(
pass: &mut RenderPass, pass: &mut RenderPass,
x: f32, x: f32,
y: f32, y: f32,
@ -2573,8 +2559,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_set_scissor_rect(
pub extern "C" fn wgpu_render_pass_set_scissor_rect(
pass: &mut RenderPass, pass: &mut RenderPass,
x: u32, x: u32,
y: u32, y: u32,
@ -2590,13 +2575,11 @@ pub mod render_ffi {
/// ///
/// This function is unsafe as there is no guarantee that the given pointer is /// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `size_bytes` bytes. /// valid for `size_bytes` bytes.
#[no_mangle] pub fn wgpu_render_pass_set_push_constants(
pub unsafe extern "C" fn wgpu_render_pass_set_push_constants(
pass: &mut RenderPass, pass: &mut RenderPass,
stages: wgt::ShaderStages, stages: wgt::ShaderStages,
offset: u32, offset: u32,
size_bytes: u32, data: &[u8],
data: *const u8,
) { ) {
assert_eq!( assert_eq!(
offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1), offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
@ -2604,31 +2587,28 @@ pub mod render_ffi {
"Push constant offset must be aligned to 4 bytes." "Push constant offset must be aligned to 4 bytes."
); );
assert_eq!( assert_eq!(
size_bytes & (wgt::PUSH_CONSTANT_ALIGNMENT - 1), data.len() as u32 & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0, 0,
"Push constant size must be aligned to 4 bytes." "Push constant size must be aligned to 4 bytes."
); );
let data_slice = unsafe { slice::from_raw_parts(data, size_bytes as usize) };
let value_offset = pass.base.push_constant_data.len().try_into().expect( let value_offset = pass.base.push_constant_data.len().try_into().expect(
"Ran out of push constant space. Don't set 4gb of push constants per RenderPass.", "Ran out of push constant space. Don't set 4gb of push constants per RenderPass.",
); );
pass.base.push_constant_data.extend( pass.base.push_constant_data.extend(
data_slice data.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])), .map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])),
); );
pass.base.commands.push(RenderCommand::SetPushConstant { pass.base.commands.push(RenderCommand::SetPushConstant {
stages, stages,
offset, offset,
size_bytes, size_bytes: data.len() as u32,
values_offset: Some(value_offset), values_offset: Some(value_offset),
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_draw(
pub extern "C" fn wgpu_render_pass_draw(
pass: &mut RenderPass, pass: &mut RenderPass,
vertex_count: u32, vertex_count: u32,
instance_count: u32, instance_count: u32,
@ -2643,8 +2623,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_draw_indexed(
pub extern "C" fn wgpu_render_pass_draw_indexed(
pass: &mut RenderPass, pass: &mut RenderPass,
index_count: u32, index_count: u32,
instance_count: u32, instance_count: u32,
@ -2661,8 +2640,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_draw_indirect(
pub extern "C" fn wgpu_render_pass_draw_indirect(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2675,8 +2653,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_draw_indexed_indirect(
pub extern "C" fn wgpu_render_pass_draw_indexed_indirect(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2689,8 +2666,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_multi_draw_indirect(
pub extern "C" fn wgpu_render_pass_multi_draw_indirect(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2704,8 +2680,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_multi_draw_indexed_indirect(
pub extern "C" fn wgpu_render_pass_multi_draw_indexed_indirect(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2719,8 +2694,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_multi_draw_indirect_count(
pub extern "C" fn wgpu_render_pass_multi_draw_indirect_count(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2740,8 +2714,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_multi_draw_indexed_indirect_count(
pub extern "C" fn wgpu_render_pass_multi_draw_indexed_indirect_count(
pass: &mut RenderPass, pass: &mut RenderPass,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
@ -2761,17 +2734,8 @@ pub mod render_ffi {
}); });
} }
/// # Safety pub fn wgpu_render_pass_push_debug_group(pass: &mut RenderPass, label: &str, color: u32) {
/// let bytes = label.as_bytes();
/// This function is unsafe as there is no guarantee that the given `label`
/// is a valid null-terminated string.
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_push_debug_group(
pass: &mut RenderPass,
label: RawString,
color: u32,
) {
let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
pass.base.string_data.extend_from_slice(bytes); pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(RenderCommand::PushDebugGroup { pass.base.commands.push(RenderCommand::PushDebugGroup {
@ -2780,22 +2744,12 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_pop_debug_group(pass: &mut RenderPass) {
pub extern "C" fn wgpu_render_pass_pop_debug_group(pass: &mut RenderPass) {
pass.base.commands.push(RenderCommand::PopDebugGroup); pass.base.commands.push(RenderCommand::PopDebugGroup);
} }
/// # Safety pub fn wgpu_render_pass_insert_debug_marker(pass: &mut RenderPass, label: &str, color: u32) {
/// let bytes = label.as_bytes();
/// This function is unsafe as there is no guarantee that the given `label`
/// is a valid null-terminated string.
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_insert_debug_marker(
pass: &mut RenderPass,
label: RawString,
color: u32,
) {
let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
pass.base.string_data.extend_from_slice(bytes); pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(RenderCommand::InsertDebugMarker { pass.base.commands.push(RenderCommand::InsertDebugMarker {
@ -2804,8 +2758,7 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_write_timestamp(
pub extern "C" fn wgpu_render_pass_write_timestamp(
pass: &mut RenderPass, pass: &mut RenderPass,
query_set_id: id::QuerySetId, query_set_id: id::QuerySetId,
query_index: u32, query_index: u32,
@ -2816,23 +2769,17 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_begin_occlusion_query(pass: &mut RenderPass, query_index: u32) {
pub extern "C" fn wgpu_render_pass_begin_occlusion_query(
pass: &mut RenderPass,
query_index: u32,
) {
pass.base pass.base
.commands .commands
.push(RenderCommand::BeginOcclusionQuery { query_index }); .push(RenderCommand::BeginOcclusionQuery { query_index });
} }
#[no_mangle] pub fn wgpu_render_pass_end_occlusion_query(pass: &mut RenderPass) {
pub extern "C" fn wgpu_render_pass_end_occlusion_query(pass: &mut RenderPass) {
pass.base.commands.push(RenderCommand::EndOcclusionQuery); pass.base.commands.push(RenderCommand::EndOcclusionQuery);
} }
#[no_mangle] pub fn wgpu_render_pass_begin_pipeline_statistics_query(
pub extern "C" fn wgpu_render_pass_begin_pipeline_statistics_query(
pass: &mut RenderPass, pass: &mut RenderPass,
query_set_id: id::QuerySetId, query_set_id: id::QuerySetId,
query_index: u32, query_index: u32,
@ -2845,26 +2792,17 @@ pub mod render_ffi {
}); });
} }
#[no_mangle] pub fn wgpu_render_pass_end_pipeline_statistics_query(pass: &mut RenderPass) {
pub extern "C" fn wgpu_render_pass_end_pipeline_statistics_query(pass: &mut RenderPass) {
pass.base pass.base
.commands .commands
.push(RenderCommand::EndPipelineStatisticsQuery); .push(RenderCommand::EndPipelineStatisticsQuery);
} }
/// # Safety pub fn wgpu_render_pass_execute_bundles(
///
/// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `render_bundle_ids_length` elements.
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_execute_bundles(
pass: &mut RenderPass, pass: &mut RenderPass,
render_bundle_ids: *const id::RenderBundleId, render_bundle_ids: &[id::RenderBundleId],
render_bundle_ids_length: usize,
) { ) {
for &bundle_id in for &bundle_id in render_bundle_ids {
unsafe { slice::from_raw_parts(render_bundle_ids, render_bundle_ids_length) }
{
pass.base pass.base
.commands .commands
.push(RenderCommand::ExecuteBundle(bundle_id)); .push(RenderCommand::ExecuteBundle(bundle_id));

View File

@ -23,7 +23,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
use wgc::{ use wgc::{
command::{bundle_ffi::*, compute_ffi::*, render_ffi::*}, command::{bundle_ffi::*, compute_commands::*, render_commands::*},
device::DeviceLostClosure, device::DeviceLostClosure,
id::{CommandEncoderId, TextureViewId}, id::{CommandEncoderId, TextureViewId},
}; };
@ -2323,15 +2323,7 @@ impl crate::Context for ContextWgpuCore {
_bind_group_data: &Self::BindGroupData, _bind_group_data: &Self::BindGroupData,
offsets: &[wgt::DynamicOffset], offsets: &[wgt::DynamicOffset],
) { ) {
unsafe { wgpu_compute_pass_set_bind_group(pass_data, index, *bind_group, offsets);
wgpu_compute_pass_set_bind_group(
pass_data,
index,
*bind_group,
offsets.as_ptr(),
offsets.len(),
)
}
} }
fn compute_pass_set_push_constants( fn compute_pass_set_push_constants(
@ -2341,14 +2333,7 @@ impl crate::Context for ContextWgpuCore {
offset: u32, offset: u32,
data: &[u8], data: &[u8],
) { ) {
unsafe { wgpu_compute_pass_set_push_constant(pass_data, offset, data);
wgpu_compute_pass_set_push_constant(
pass_data,
offset,
data.len().try_into().unwrap(),
data.as_ptr(),
)
}
} }
fn compute_pass_insert_debug_marker( fn compute_pass_insert_debug_marker(
@ -2357,10 +2342,7 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::ComputePassData, pass_data: &mut Self::ComputePassData,
label: &str, label: &str,
) { ) {
unsafe { wgpu_compute_pass_insert_debug_marker(pass_data, label, 0);
let label = std::ffi::CString::new(label).unwrap();
wgpu_compute_pass_insert_debug_marker(pass_data, label.as_ptr(), 0);
}
} }
fn compute_pass_push_debug_group( fn compute_pass_push_debug_group(
@ -2369,10 +2351,7 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::ComputePassData, pass_data: &mut Self::ComputePassData,
group_label: &str, group_label: &str,
) { ) {
unsafe { wgpu_compute_pass_push_debug_group(pass_data, group_label, 0);
let label = std::ffi::CString::new(group_label).unwrap();
wgpu_compute_pass_push_debug_group(pass_data, label.as_ptr(), 0);
}
} }
fn compute_pass_pop_debug_group( fn compute_pass_pop_debug_group(
@ -2639,15 +2618,7 @@ impl crate::Context for ContextWgpuCore {
_bind_group_data: &Self::BindGroupData, _bind_group_data: &Self::BindGroupData,
offsets: &[wgt::DynamicOffset], offsets: &[wgt::DynamicOffset],
) { ) {
unsafe { wgpu_render_pass_set_bind_group(pass_data, index, *bind_group, offsets)
wgpu_render_pass_set_bind_group(
pass_data,
index,
*bind_group,
offsets.as_ptr(),
offsets.len(),
)
}
} }
fn render_pass_set_index_buffer( fn render_pass_set_index_buffer(
@ -2684,15 +2655,7 @@ impl crate::Context for ContextWgpuCore {
offset: u32, offset: u32,
data: &[u8], data: &[u8],
) { ) {
unsafe { wgpu_render_pass_set_push_constants(pass_data, stages, offset, data)
wgpu_render_pass_set_push_constants(
pass_data,
stages,
offset,
data.len().try_into().unwrap(),
data.as_ptr(),
)
}
} }
fn render_pass_draw( fn render_pass_draw(
@ -2874,10 +2837,7 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
label: &str, label: &str,
) { ) {
unsafe { wgpu_render_pass_insert_debug_marker(pass_data, label, 0);
let label = std::ffi::CString::new(label).unwrap();
wgpu_render_pass_insert_debug_marker(pass_data, label.as_ptr(), 0);
}
} }
fn render_pass_push_debug_group( fn render_pass_push_debug_group(
@ -2886,10 +2846,7 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
group_label: &str, group_label: &str,
) { ) {
unsafe { wgpu_render_pass_push_debug_group(pass_data, group_label, 0);
let label = std::ffi::CString::new(group_label).unwrap();
wgpu_render_pass_push_debug_group(pass_data, label.as_ptr(), 0);
}
} }
fn render_pass_pop_debug_group( fn render_pass_pop_debug_group(
@ -2954,13 +2911,7 @@ impl crate::Context for ContextWgpuCore {
render_bundles: &mut dyn Iterator<Item = (Self::RenderBundleId, &Self::RenderBundleData)>, render_bundles: &mut dyn Iterator<Item = (Self::RenderBundleId, &Self::RenderBundleData)>,
) { ) {
let temp_render_bundles = render_bundles.map(|(i, _)| i).collect::<SmallVec<[_; 4]>>(); let temp_render_bundles = render_bundles.map(|(i, _)| i).collect::<SmallVec<[_; 4]>>();
unsafe { wgpu_render_pass_execute_bundles(pass_data, &temp_render_bundles)
wgpu_render_pass_execute_bundles(
pass_data,
temp_render_bundles.as_ptr(),
temp_render_bundles.len(),
)
}
} }
} }