Separate renderpass arc resolve & renderpass consume on end (#5794)

This commit is contained in:
Andreas Reich 2024-06-25 09:37:29 +02:00 committed by GitHub
parent 29e3b984a4
commit b4c7987aa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1559 additions and 669 deletions

View File

@ -9,6 +9,7 @@ use deno_core::ResourceId;
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use wgpu_core::global::Global;
use super::error::WebGpuResult; use super::error::WebGpuResult;
@ -41,7 +42,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_commands::wgpu_render_pass_set_viewport( state.borrow::<Global>().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,
@ -49,7 +50,7 @@ pub fn op_webgpu_render_pass_set_viewport(
args.height, args.height,
args.min_depth, args.min_depth,
args.max_depth, args.max_depth,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -68,13 +69,13 @@ 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_commands::wgpu_render_pass_set_scissor_rect( state.borrow::<Global>().render_pass_set_scissor_rect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
x, x,
y, y,
width, width,
height, height,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -90,10 +91,9 @@ 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_commands::wgpu_render_pass_set_blend_constant( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
&color, .render_pass_set_blend_constant(&mut render_pass_resource.0.borrow_mut(), &color)?;
);
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -109,10 +109,9 @@ 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_commands::wgpu_render_pass_set_stencil_reference( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
reference, .render_pass_set_stencil_reference(&mut render_pass_resource.0.borrow_mut(), reference)?;
);
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -128,10 +127,9 @@ 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_commands::wgpu_render_pass_begin_occlusion_query( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
query_index, .render_pass_begin_occlusion_query(&mut render_pass_resource.0.borrow_mut(), query_index)?;
);
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -146,9 +144,9 @@ 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_commands::wgpu_render_pass_end_occlusion_query( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
); .render_pass_end_occlusion_query(&mut render_pass_resource.0.borrow_mut())?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -174,10 +172,9 @@ pub fn op_webgpu_render_pass_execute_bundles(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_commands::wgpu_render_pass_execute_bundles( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
&bundles, .render_pass_execute_bundles(&mut render_pass_resource.0.borrow_mut(), &bundles)?;
);
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -191,11 +188,15 @@ pub fn op_webgpu_render_pass_end(
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.take::<WebGpuRenderPass>(render_pass_rid)?; .take::<WebGpuRenderPass>(render_pass_rid)?;
let render_pass = &render_pass_resource.0.borrow();
let command_encoder = render_pass.parent_id();
let instance = state.borrow::<super::Instance>();
gfx_ok!(command_encoder => instance.render_pass_end(render_pass)) // TODO: Just like parent_id ComputePass, there's going to be DynComputePass soon which will eliminate the need of doing gfx_select here.
let instance = state.borrow::<Global>();
let parent_id = render_pass_resource.0.borrow().parent_id();
gfx_select!(parent_id => instance.render_pass_end(
&mut render_pass_resource.0.borrow_mut()
))?;
Ok(WebGpuResult::empty())
} }
#[op2] #[op2]
@ -225,12 +226,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];
wgpu_core::command::render_commands::wgpu_render_pass_set_bind_group( state.borrow::<Global>().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, dynamic_offsets_data,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -246,11 +247,11 @@ pub fn op_webgpu_render_pass_push_debug_group(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_commands::wgpu_render_pass_push_debug_group( state.borrow::<Global>().render_pass_push_debug_group(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
group_label, group_label,
0, // wgpu#975 0, // wgpu#975
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -265,9 +266,9 @@ 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_commands::wgpu_render_pass_pop_debug_group( state
&mut render_pass_resource.0.borrow_mut(), .borrow::<Global>()
); .render_pass_pop_debug_group(&mut render_pass_resource.0.borrow_mut())?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -283,11 +284,11 @@ pub fn op_webgpu_render_pass_insert_debug_marker(
.resource_table .resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_commands::wgpu_render_pass_insert_debug_marker( state.borrow::<Global>().render_pass_insert_debug_marker(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
marker_label, marker_label,
0, // wgpu#975 0, // wgpu#975
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -306,10 +307,10 @@ 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_commands::wgpu_render_pass_set_pipeline( state.borrow::<Global>().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,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -340,12 +341,13 @@ pub fn op_webgpu_render_pass_set_index_buffer(
None None
}; };
render_pass_resource.0.borrow_mut().set_index_buffer( state.borrow::<Global>().render_pass_set_index_buffer(
&mut render_pass_resource.0.borrow_mut(),
buffer_resource.1, buffer_resource.1,
index_format, index_format,
offset, offset,
size, size,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -376,13 +378,13 @@ pub fn op_webgpu_render_pass_set_vertex_buffer(
None None
}; };
wgpu_core::command::render_commands::wgpu_render_pass_set_vertex_buffer( state.borrow::<Global>().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,
offset, offset,
size, size,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -401,13 +403,13 @@ 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_commands::wgpu_render_pass_draw( state.borrow::<Global>().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,
first_vertex, first_vertex,
first_instance, first_instance,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -427,14 +429,14 @@ 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_commands::wgpu_render_pass_draw_indexed( state.borrow::<Global>().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,
first_index, first_index,
base_vertex, base_vertex,
first_instance, first_instance,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -454,11 +456,11 @@ 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_commands::wgpu_render_pass_draw_indirect( state.borrow::<Global>().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,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -478,11 +480,11 @@ 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_commands::wgpu_render_pass_draw_indexed_indirect( state.borrow::<Global>().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,
); )?;
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }

View File

@ -113,9 +113,9 @@ impl GlobalPlay for wgc::global::Global {
timestamp_writes, timestamp_writes,
occlusion_query_set_id, occlusion_query_set_id,
} => { } => {
self.render_pass_end_impl::<A>( self.render_pass_end_with_unresolved_commands::<A>(
encoder, encoder,
base.as_ref(), base,
&target_colors, &target_colors,
target_depth_stencil.as_ref(), target_depth_stencil.as_ref(),
timestamp_writes.as_ref(), timestamp_writes.as_ref(),

View File

@ -48,7 +48,7 @@ To create a render bundle:
3) Call [`Global::render_bundle_encoder_finish`][Grbef], which analyzes and cleans up 3) Call [`Global::render_bundle_encoder_finish`][Grbef], which analyzes and cleans up
the command stream and returns a `RenderBundleId`. the command stream and returns a `RenderBundleId`.
4) Then, any number of times, call [`wgpu_render_pass_execute_bundles`][wrpeb] to 4) Then, any number of times, call [`render_pass_execute_bundles`][wrpeb] to
execute the bundle as part of some render pass. execute the bundle as part of some render pass.
## Implementation ## Implementation
@ -73,7 +73,7 @@ index format changes.
[Gdcrbe]: crate::global::Global::device_create_render_bundle_encoder [Gdcrbe]: crate::global::Global::device_create_render_bundle_encoder
[Grbef]: crate::global::Global::render_bundle_encoder_finish [Grbef]: crate::global::Global::render_bundle_encoder_finish
[wrpeb]: crate::command::render::render_commands::wgpu_render_pass_execute_bundles [wrpeb]: crate::global::Global::render_pass_execute_bundles
!*/ !*/
#![allow(clippy::reversed_empty_ranges)] #![allow(clippy::reversed_empty_ranges)]
@ -84,7 +84,7 @@ use crate::{
binding_model::{buffer_binding_type_alignment, BindGroup, BindGroupLayout, PipelineLayout}, binding_model::{buffer_binding_type_alignment, BindGroup, BindGroupLayout, PipelineLayout},
command::{ command::{
BasePass, BindGroupStateChange, ColorAttachmentError, DrawError, MapPassErr, BasePass, BindGroupStateChange, ColorAttachmentError, DrawError, MapPassErr,
PassErrorScope, RenderCommand, RenderCommandError, StateChange, PassErrorScope, RenderCommandError, StateChange,
}, },
conv, conv,
device::{ device::{
@ -112,7 +112,10 @@ use thiserror::Error;
use hal::CommandEncoder as _; use hal::CommandEncoder as _;
use super::ArcRenderCommand; use super::{
render_command::{ArcRenderCommand, RenderCommand},
DrawKind,
};
/// <https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw> /// <https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw>
fn validate_draw<A: HalApi>( fn validate_draw<A: HalApi>(
@ -327,7 +330,7 @@ impl RenderBundleEncoder {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
pub(crate) fn to_base_pass(&self) -> BasePass<RenderCommand> { pub(crate) fn to_base_pass(&self) -> BasePass<RenderCommand> {
BasePass::from_ref(self.base.as_ref()) self.base.clone()
} }
pub fn parent(&self) -> id::DeviceId { pub fn parent(&self) -> id::DeviceId {
@ -398,10 +401,11 @@ impl RenderBundleEncoder {
let mut buffer_memory_init_actions = Vec::new(); let mut buffer_memory_init_actions = Vec::new();
let mut texture_memory_init_actions = Vec::new(); let mut texture_memory_init_actions = Vec::new();
let base = self.base.as_ref();
let mut next_dynamic_offset = 0; let mut next_dynamic_offset = 0;
for &command in base.commands { let base = &self.base;
for &command in &base.commands {
match command { match command {
RenderCommand::SetBindGroup { RenderCommand::SetBindGroup {
index, index,
@ -621,8 +625,8 @@ impl RenderBundleEncoder {
first_instance, first_instance,
} => { } => {
let scope = PassErrorScope::Draw { let scope = PassErrorScope::Draw {
kind: DrawKind::Draw,
indexed: false, indexed: false,
indirect: false,
pipeline: state.pipeline_id(), pipeline: state.pipeline_id(),
}; };
let pipeline = state.pipeline(scope)?; let pipeline = state.pipeline(scope)?;
@ -639,7 +643,7 @@ impl RenderBundleEncoder {
if instance_count > 0 && vertex_count > 0 { if instance_count > 0 && vertex_count > 0 {
commands.extend(state.flush_vertices()); commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets)); commands.extend(state.flush_binds(used_bind_groups, &base.dynamic_offsets));
commands.push(ArcRenderCommand::Draw { commands.push(ArcRenderCommand::Draw {
vertex_count, vertex_count,
instance_count, instance_count,
@ -656,8 +660,8 @@ impl RenderBundleEncoder {
first_instance, first_instance,
} => { } => {
let scope = PassErrorScope::Draw { let scope = PassErrorScope::Draw {
kind: DrawKind::Draw,
indexed: true, indexed: true,
indirect: false,
pipeline: state.pipeline_id(), pipeline: state.pipeline_id(),
}; };
let pipeline = state.pipeline(scope)?; let pipeline = state.pipeline(scope)?;
@ -680,7 +684,7 @@ impl RenderBundleEncoder {
if instance_count > 0 && index_count > 0 { if instance_count > 0 && index_count > 0 {
commands.extend(state.flush_index()); commands.extend(state.flush_index());
commands.extend(state.flush_vertices()); commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets)); commands.extend(state.flush_binds(used_bind_groups, &base.dynamic_offsets));
commands.push(ArcRenderCommand::DrawIndexed { index_count, instance_count, first_index, base_vertex, first_instance }); commands.push(ArcRenderCommand::DrawIndexed { index_count, instance_count, first_index, base_vertex, first_instance });
} }
} }
@ -691,8 +695,8 @@ impl RenderBundleEncoder {
indexed: false, indexed: false,
} => { } => {
let scope = PassErrorScope::Draw { let scope = PassErrorScope::Draw {
kind: DrawKind::DrawIndirect,
indexed: false, indexed: false,
indirect: true,
pipeline: state.pipeline_id(), pipeline: state.pipeline_id(),
}; };
device device
@ -724,7 +728,7 @@ impl RenderBundleEncoder {
)); ));
commands.extend(state.flush_vertices()); commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets)); commands.extend(state.flush_binds(used_bind_groups, &base.dynamic_offsets));
commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: false }); commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: false });
} }
RenderCommand::MultiDrawIndirect { RenderCommand::MultiDrawIndirect {
@ -734,8 +738,8 @@ impl RenderBundleEncoder {
indexed: true, indexed: true,
} => { } => {
let scope = PassErrorScope::Draw { let scope = PassErrorScope::Draw {
kind: DrawKind::DrawIndirect,
indexed: true, indexed: true,
indirect: true,
pipeline: state.pipeline_id(), pipeline: state.pipeline_id(),
}; };
device device
@ -773,7 +777,7 @@ impl RenderBundleEncoder {
commands.extend(index.flush()); commands.extend(index.flush());
commands.extend(state.flush_vertices()); commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets)); commands.extend(state.flush_binds(used_bind_groups, &base.dynamic_offsets));
commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: true }); commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: true });
} }
RenderCommand::MultiDrawIndirect { .. } RenderCommand::MultiDrawIndirect { .. }

View File

@ -72,7 +72,7 @@ pub enum ComputeCommand {
impl ComputeCommand { impl ComputeCommand {
/// Resolves all ids in a list of commands into the corresponding resource Arc. /// Resolves all ids in a list of commands into the corresponding resource Arc.
/// //
// TODO: Once resolving is done on-the-fly during recording, this function should be only needed with the replay feature: // TODO: Once resolving is done on-the-fly during recording, this function should be only needed with the replay feature:
// #[cfg(feature = "replay")] // #[cfg(feature = "replay")]
pub fn resolve_compute_command_ids<A: HalApi>( pub fn resolve_compute_command_ids<A: HalApi>(

View File

@ -1,24 +1,14 @@
/*! Draw structures - shared between render passes and bundles.
!*/
use crate::{ use crate::{
binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PushConstantUploadError}, binding_model::{LateMinBufferBindingSizeMismatch, PushConstantUploadError},
error::ErrorFormatter, error::ErrorFormatter,
hal_api::HalApi,
id, id,
pipeline::RenderPipeline, resource::{DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError},
resource::{
Buffer, DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError, QuerySet,
},
track::ResourceUsageCompatibilityError, track::ResourceUsageCompatibilityError,
}; };
use wgt::{BufferAddress, BufferSize, Color, VertexStepMode}; use wgt::VertexStepMode;
use std::{num::NonZeroU32, sync::Arc};
use thiserror::Error; use thiserror::Error;
use super::RenderBundle;
/// Error validating a draw call. /// Error validating a draw call.
#[derive(Clone, Debug, Error, Eq, PartialEq)] #[derive(Clone, Debug, Error, Eq, PartialEq)]
#[non_exhaustive] #[non_exhaustive]
@ -134,226 +124,3 @@ pub struct Rect<T> {
pub w: T, pub w: T,
pub h: T, pub h: T,
} }
#[doc(hidden)]
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RenderCommand {
SetBindGroup {
index: u32,
num_dynamic_offsets: usize,
bind_group_id: id::BindGroupId,
},
SetPipeline(id::RenderPipelineId),
SetIndexBuffer {
buffer_id: id::BufferId,
index_format: wgt::IndexFormat,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetVertexBuffer {
slot: u32,
buffer_id: id::BufferId,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetBlendConstant(Color),
SetStencilReference(u32),
SetViewport {
rect: Rect<f32>,
//TODO: use half-float to reduce the size?
depth_min: f32,
depth_max: f32,
},
SetScissor(Rect<u32>),
/// Set a range of push constants to values stored in [`BasePass::push_constant_data`].
///
/// See [`wgpu::RenderPass::set_push_constants`] for a detailed explanation
/// of the restrictions these commands must satisfy.
SetPushConstant {
/// Which stages we are setting push constant values for.
stages: wgt::ShaderStages,
/// The byte offset within the push constant storage to write to. This
/// must be a multiple of four.
offset: u32,
/// The number of bytes to write. This must be a multiple of four.
size_bytes: u32,
/// Index in [`BasePass::push_constant_data`] of the start of the data
/// to be written.
///
/// Note: this is not a byte offset like `offset`. Rather, it is the
/// index of the first `u32` element in `push_constant_data` to read.
///
/// `None` means zeros should be written to the destination range, and
/// there is no corresponding data in `push_constant_data`. This is used
/// by render bundles, which explicitly clear out any state that
/// post-bundle code might see.
values_offset: Option<u32>,
},
Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},
DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
base_vertex: i32,
first_instance: u32,
},
MultiDrawIndirect {
buffer_id: id::BufferId,
offset: BufferAddress,
/// Count of `None` represents a non-multi call.
count: Option<NonZeroU32>,
indexed: bool,
},
MultiDrawIndirectCount {
buffer_id: id::BufferId,
offset: BufferAddress,
count_buffer_id: id::BufferId,
count_buffer_offset: BufferAddress,
max_count: u32,
indexed: bool,
},
PushDebugGroup {
color: u32,
len: usize,
},
PopDebugGroup,
InsertDebugMarker {
color: u32,
len: usize,
},
WriteTimestamp {
query_set_id: id::QuerySetId,
query_index: u32,
},
BeginOcclusionQuery {
query_index: u32,
},
EndOcclusionQuery,
BeginPipelineStatisticsQuery {
query_set_id: id::QuerySetId,
query_index: u32,
},
EndPipelineStatisticsQuery,
ExecuteBundle(id::RenderBundleId),
}
/// Equivalent to `RenderCommand` with the Ids resolved into resource Arcs.
#[doc(hidden)]
#[derive(Clone, Debug)]
pub enum ArcRenderCommand<A: HalApi> {
SetBindGroup {
index: u32,
num_dynamic_offsets: usize,
bind_group: Arc<BindGroup<A>>,
},
SetPipeline(Arc<RenderPipeline<A>>),
SetIndexBuffer {
buffer: Arc<Buffer<A>>,
index_format: wgt::IndexFormat,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetVertexBuffer {
slot: u32,
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetBlendConstant(Color),
SetStencilReference(u32),
SetViewport {
rect: Rect<f32>,
depth_min: f32,
depth_max: f32,
},
SetScissor(Rect<u32>),
/// Set a range of push constants to values stored in [`BasePass::push_constant_data`].
///
/// See [`wgpu::RenderPass::set_push_constants`] for a detailed explanation
/// of the restrictions these commands must satisfy.
SetPushConstant {
/// Which stages we are setting push constant values for.
stages: wgt::ShaderStages,
/// The byte offset within the push constant storage to write to. This
/// must be a multiple of four.
offset: u32,
/// The number of bytes to write. This must be a multiple of four.
size_bytes: u32,
/// Index in [`BasePass::push_constant_data`] of the start of the data
/// to be written.
///
/// Note: this is not a byte offset like `offset`. Rather, it is the
/// index of the first `u32` element in `push_constant_data` to read.
///
/// `None` means zeros should be written to the destination range, and
/// there is no corresponding data in `push_constant_data`. This is used
/// by render bundles, which explicitly clear out any state that
/// post-bundle code might see.
values_offset: Option<u32>,
},
Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},
DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
base_vertex: i32,
first_instance: u32,
},
MultiDrawIndirect {
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
/// Count of `None` represents a non-multi call.
count: Option<NonZeroU32>,
indexed: bool,
},
MultiDrawIndirectCount {
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
count_buffer: Arc<Buffer<A>>,
count_buffer_offset: BufferAddress,
max_count: u32,
indexed: bool,
},
PushDebugGroup {
color: u32,
len: usize,
},
PopDebugGroup,
InsertDebugMarker {
color: u32,
len: usize,
},
WriteTimestamp {
query_set: Arc<QuerySet<A>>,
query_index: u32,
},
BeginOcclusionQuery {
query_index: u32,
},
EndOcclusionQuery,
BeginPipelineStatisticsQuery {
query_set: Arc<QuerySet<A>>,
query_index: u32,
},
EndPipelineStatisticsQuery,
ExecuteBundle(Arc<RenderBundle<A>>),
}

View File

@ -9,6 +9,7 @@ mod dyn_compute_pass;
mod memory_init; mod memory_init;
mod query; mod query;
mod render; mod render;
mod render_command;
mod transfer; mod transfer;
use std::sync::Arc; use std::sync::Arc;
@ -16,7 +17,8 @@ use std::sync::Arc;
pub(crate) use self::clear::clear_texture; pub(crate) use self::clear::clear_texture;
pub use self::{ pub use self::{
bundle::*, clear::ClearError, compute::*, compute_command::ComputeCommand, draw::*, bundle::*, clear::ClearError, compute::*, compute_command::ComputeCommand, draw::*,
dyn_compute_pass::DynComputePass, query::*, render::*, transfer::*, dyn_compute_pass::DynComputePass, query::*, render::*, render_command::RenderCommand,
transfer::*,
}; };
pub(crate) use allocator::CommandAllocator; pub(crate) use allocator::CommandAllocator;
@ -544,15 +546,6 @@ impl<A: HalApi> ParentDevice<A> for CommandBuffer<A> {
} }
} }
#[derive(Copy, Clone, Debug)]
pub struct BasePassRef<'a, C> {
pub label: Option<&'a str>,
pub commands: &'a [C],
pub dynamic_offsets: &'a [wgt::DynamicOffset],
pub string_data: &'a [u8],
pub push_constant_data: &'a [u32],
}
/// A stream of commands for a render pass or compute pass. /// A stream of commands for a render pass or compute pass.
/// ///
/// This also contains side tables referred to by certain commands, /// This also contains side tables referred to by certain commands,
@ -565,7 +558,7 @@ pub struct BasePassRef<'a, C> {
/// [`SetBindGroup`]: RenderCommand::SetBindGroup /// [`SetBindGroup`]: RenderCommand::SetBindGroup
/// [`InsertDebugMarker`]: RenderCommand::InsertDebugMarker /// [`InsertDebugMarker`]: RenderCommand::InsertDebugMarker
#[doc(hidden)] #[doc(hidden)]
#[derive(Debug)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BasePass<C> { pub struct BasePass<C> {
pub label: Option<String>, pub label: Option<String>,
@ -602,27 +595,6 @@ impl<C: Clone> BasePass<C> {
push_constant_data: Vec::new(), push_constant_data: Vec::new(),
} }
} }
#[cfg(feature = "trace")]
fn from_ref(base: BasePassRef<C>) -> Self {
Self {
label: base.label.map(str::to_string),
commands: base.commands.to_vec(),
dynamic_offsets: base.dynamic_offsets.to_vec(),
string_data: base.string_data.to_vec(),
push_constant_data: base.push_constant_data.to_vec(),
}
}
pub fn as_ref(&self) -> BasePassRef<C> {
BasePassRef {
label: self.label.as_deref(),
commands: &self.commands,
dynamic_offsets: &self.dynamic_offsets,
string_data: &self.string_data,
push_constant_data: &self.push_constant_data,
}
}
} }
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
@ -879,6 +851,14 @@ trait MapPassErr<T, O> {
fn map_pass_err(self, scope: PassErrorScope) -> Result<T, O>; fn map_pass_err(self, scope: PassErrorScope) -> Result<T, O>;
} }
#[derive(Clone, Copy, Debug)]
pub enum DrawKind {
Draw,
DrawIndirect,
MultiDrawIndirect,
MultiDrawIndirectCount,
}
#[derive(Clone, Copy, Debug, Error)] #[derive(Clone, Copy, Debug, Error)]
pub enum PassErrorScope { pub enum PassErrorScope {
#[error("In a bundle parameter")] #[error("In a bundle parameter")]
@ -902,14 +882,18 @@ pub enum PassErrorScope {
SetVertexBuffer(id::BufferId), SetVertexBuffer(id::BufferId),
#[error("In a set_index_buffer command")] #[error("In a set_index_buffer command")]
SetIndexBuffer(id::BufferId), SetIndexBuffer(id::BufferId),
#[error("In a set_blend_constant command")]
SetBlendConstant,
#[error("In a set_stencil_reference command")]
SetStencilReference,
#[error("In a set_viewport command")] #[error("In a set_viewport command")]
SetViewport, SetViewport,
#[error("In a set_scissor_rect command")] #[error("In a set_scissor_rect command")]
SetScissorRect, SetScissorRect,
#[error("In a draw command, indexed:{indexed} indirect:{indirect}")] #[error("In a draw command, kind: {kind:?}")]
Draw { Draw {
kind: DrawKind,
indexed: bool, indexed: bool,
indirect: bool,
pipeline: Option<id::RenderPipelineId>, pipeline: Option<id::RenderPipelineId>,
}, },
#[error("While resetting queries after the renderpass was ran")] #[error("While resetting queries after the renderpass was ran")]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,668 @@
use crate::{
binding_model::BindGroup,
hal_api::HalApi,
id,
pipeline::RenderPipeline,
resource::{Buffer, QuerySet},
};
use wgt::{BufferAddress, BufferSize, Color};
use std::{num::NonZeroU32, sync::Arc};
use super::{
DrawKind, PassErrorScope, Rect, RenderBundle, RenderCommandError, RenderPassError,
RenderPassErrorInner,
};
#[doc(hidden)]
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RenderCommand {
SetBindGroup {
index: u32,
num_dynamic_offsets: usize,
bind_group_id: id::BindGroupId,
},
SetPipeline(id::RenderPipelineId),
SetIndexBuffer {
buffer_id: id::BufferId,
index_format: wgt::IndexFormat,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetVertexBuffer {
slot: u32,
buffer_id: id::BufferId,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetBlendConstant(Color),
SetStencilReference(u32),
SetViewport {
rect: Rect<f32>,
//TODO: use half-float to reduce the size?
depth_min: f32,
depth_max: f32,
},
SetScissor(Rect<u32>),
/// Set a range of push constants to values stored in [`BasePass::push_constant_data`].
///
/// See [`wgpu::RenderPass::set_push_constants`] for a detailed explanation
/// of the restrictions these commands must satisfy.
SetPushConstant {
/// Which stages we are setting push constant values for.
stages: wgt::ShaderStages,
/// The byte offset within the push constant storage to write to. This
/// must be a multiple of four.
offset: u32,
/// The number of bytes to write. This must be a multiple of four.
size_bytes: u32,
/// Index in [`BasePass::push_constant_data`] of the start of the data
/// to be written.
///
/// Note: this is not a byte offset like `offset`. Rather, it is the
/// index of the first `u32` element in `push_constant_data` to read.
///
/// `None` means zeros should be written to the destination range, and
/// there is no corresponding data in `push_constant_data`. This is used
/// by render bundles, which explicitly clear out any state that
/// post-bundle code might see.
values_offset: Option<u32>,
},
Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},
DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
base_vertex: i32,
first_instance: u32,
},
MultiDrawIndirect {
buffer_id: id::BufferId,
offset: BufferAddress,
/// Count of `None` represents a non-multi call.
count: Option<NonZeroU32>,
indexed: bool,
},
MultiDrawIndirectCount {
buffer_id: id::BufferId,
offset: BufferAddress,
count_buffer_id: id::BufferId,
count_buffer_offset: BufferAddress,
max_count: u32,
indexed: bool,
},
PushDebugGroup {
color: u32,
len: usize,
},
PopDebugGroup,
InsertDebugMarker {
color: u32,
len: usize,
},
WriteTimestamp {
query_set_id: id::QuerySetId,
query_index: u32,
},
BeginOcclusionQuery {
query_index: u32,
},
EndOcclusionQuery,
BeginPipelineStatisticsQuery {
query_set_id: id::QuerySetId,
query_index: u32,
},
EndPipelineStatisticsQuery,
ExecuteBundle(id::RenderBundleId),
}
impl RenderCommand {
/// Resolves all ids in a list of commands into the corresponding resource Arc.
//
// TODO: Once resolving is done on-the-fly during recording, this function should be only needed with the replay feature:
// #[cfg(feature = "replay")]
pub fn resolve_render_command_ids<A: HalApi>(
hub: &crate::hub::Hub<A>,
commands: &[RenderCommand],
) -> Result<Vec<ArcRenderCommand<A>>, RenderPassError> {
let buffers_guard = hub.buffers.read();
let bind_group_guard = hub.bind_groups.read();
let query_set_guard = hub.query_sets.read();
let pipelines_guard = hub.render_pipelines.read();
let resolved_commands: Vec<ArcRenderCommand<A>> = commands
.iter()
.map(|c| -> Result<ArcRenderCommand<A>, RenderPassError> {
Ok(match *c {
RenderCommand::SetBindGroup {
index,
num_dynamic_offsets,
bind_group_id,
} => ArcRenderCommand::SetBindGroup {
index,
num_dynamic_offsets,
bind_group: bind_group_guard.get_owned(bind_group_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::SetBindGroup(bind_group_id),
inner: RenderPassErrorInner::InvalidBindGroup(index),
}
})?,
},
RenderCommand::SetPipeline(pipeline_id) => ArcRenderCommand::SetPipeline(
pipelines_guard
.get_owned(pipeline_id)
.map_err(|_| RenderPassError {
scope: PassErrorScope::SetPipelineRender(pipeline_id),
inner: RenderCommandError::InvalidPipeline(pipeline_id).into(),
})?,
),
RenderCommand::SetPushConstant {
offset,
size_bytes,
values_offset,
stages,
} => ArcRenderCommand::SetPushConstant {
offset,
size_bytes,
values_offset,
stages,
},
RenderCommand::PushDebugGroup { color, len } => {
ArcRenderCommand::PushDebugGroup { color, len }
}
RenderCommand::PopDebugGroup => ArcRenderCommand::PopDebugGroup,
RenderCommand::InsertDebugMarker { color, len } => {
ArcRenderCommand::InsertDebugMarker { color, len }
}
RenderCommand::WriteTimestamp {
query_set_id,
query_index,
} => ArcRenderCommand::WriteTimestamp {
query_set: query_set_guard.get_owned(query_set_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::WriteTimestamp,
inner: RenderPassErrorInner::InvalidQuerySet(query_set_id),
}
})?,
query_index,
},
RenderCommand::BeginPipelineStatisticsQuery {
query_set_id,
query_index,
} => ArcRenderCommand::BeginPipelineStatisticsQuery {
query_set: query_set_guard.get_owned(query_set_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::BeginPipelineStatisticsQuery,
inner: RenderPassErrorInner::InvalidQuerySet(query_set_id),
}
})?,
query_index,
},
RenderCommand::EndPipelineStatisticsQuery => {
ArcRenderCommand::EndPipelineStatisticsQuery
}
RenderCommand::SetIndexBuffer {
buffer_id,
index_format,
offset,
size,
} => ArcRenderCommand::SetIndexBuffer {
buffer: buffers_guard.get_owned(buffer_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::SetIndexBuffer(buffer_id),
inner: RenderCommandError::InvalidBufferId(buffer_id).into(),
}
})?,
index_format,
offset,
size,
},
RenderCommand::SetVertexBuffer {
slot,
buffer_id,
offset,
size,
} => ArcRenderCommand::SetVertexBuffer {
slot,
buffer: buffers_guard.get_owned(buffer_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::SetVertexBuffer(buffer_id),
inner: RenderCommandError::InvalidBufferId(buffer_id).into(),
}
})?,
offset,
size,
},
RenderCommand::SetBlendConstant(color) => {
ArcRenderCommand::SetBlendConstant(color)
}
RenderCommand::SetStencilReference(reference) => {
ArcRenderCommand::SetStencilReference(reference)
}
RenderCommand::SetViewport {
rect,
depth_min,
depth_max,
} => ArcRenderCommand::SetViewport {
rect,
depth_min,
depth_max,
},
RenderCommand::SetScissor(scissor) => ArcRenderCommand::SetScissor(scissor),
RenderCommand::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
} => ArcRenderCommand::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
},
RenderCommand::DrawIndexed {
index_count,
instance_count,
first_index,
base_vertex,
first_instance,
} => ArcRenderCommand::DrawIndexed {
index_count,
instance_count,
first_index,
base_vertex,
first_instance,
},
RenderCommand::MultiDrawIndirect {
buffer_id,
offset,
count,
indexed,
} => ArcRenderCommand::MultiDrawIndirect {
buffer: buffers_guard.get_owned(buffer_id).map_err(|_| {
RenderPassError {
scope: PassErrorScope::Draw {
kind: if count.is_some() {
DrawKind::MultiDrawIndirect
} else {
DrawKind::DrawIndirect
},
indexed,
pipeline: None,
},
inner: RenderCommandError::InvalidBufferId(buffer_id).into(),
}
})?,
offset,
count,
indexed,
},
RenderCommand::MultiDrawIndirectCount {
buffer_id,
offset,
count_buffer_id,
count_buffer_offset,
max_count,
indexed,
} => {
let scope = PassErrorScope::Draw {
kind: DrawKind::MultiDrawIndirectCount,
indexed,
pipeline: None,
};
ArcRenderCommand::MultiDrawIndirectCount {
buffer: buffers_guard.get_owned(buffer_id).map_err(|_| {
RenderPassError {
scope,
inner: RenderCommandError::InvalidBufferId(buffer_id).into(),
}
})?,
offset,
count_buffer: buffers_guard.get_owned(count_buffer_id).map_err(
|_| RenderPassError {
scope,
inner: RenderCommandError::InvalidBufferId(count_buffer_id)
.into(),
},
)?,
count_buffer_offset,
max_count,
indexed,
}
}
RenderCommand::BeginOcclusionQuery { query_index } => {
ArcRenderCommand::BeginOcclusionQuery { query_index }
}
RenderCommand::EndOcclusionQuery => ArcRenderCommand::EndOcclusionQuery,
RenderCommand::ExecuteBundle(bundle) => ArcRenderCommand::ExecuteBundle(
hub.render_bundles.read().get_owned(bundle).map_err(|_| {
RenderPassError {
scope: PassErrorScope::ExecuteBundle,
inner: RenderCommandError::InvalidRenderBundle(bundle).into(),
}
})?,
),
})
})
.collect::<Result<Vec<_>, RenderPassError>>()?;
Ok(resolved_commands)
}
}
/// Equivalent to `RenderCommand` with the Ids resolved into resource Arcs.
#[doc(hidden)]
#[derive(Clone, Debug)]
pub enum ArcRenderCommand<A: HalApi> {
SetBindGroup {
index: u32,
num_dynamic_offsets: usize,
bind_group: Arc<BindGroup<A>>,
},
SetPipeline(Arc<RenderPipeline<A>>),
SetIndexBuffer {
buffer: Arc<Buffer<A>>,
index_format: wgt::IndexFormat,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetVertexBuffer {
slot: u32,
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
size: Option<BufferSize>,
},
SetBlendConstant(Color),
SetStencilReference(u32),
SetViewport {
rect: Rect<f32>,
depth_min: f32,
depth_max: f32,
},
SetScissor(Rect<u32>),
/// Set a range of push constants to values stored in [`BasePass::push_constant_data`].
///
/// See [`wgpu::RenderPass::set_push_constants`] for a detailed explanation
/// of the restrictions these commands must satisfy.
SetPushConstant {
/// Which stages we are setting push constant values for.
stages: wgt::ShaderStages,
/// The byte offset within the push constant storage to write to. This
/// must be a multiple of four.
offset: u32,
/// The number of bytes to write. This must be a multiple of four.
size_bytes: u32,
/// Index in [`BasePass::push_constant_data`] of the start of the data
/// to be written.
///
/// Note: this is not a byte offset like `offset`. Rather, it is the
/// index of the first `u32` element in `push_constant_data` to read.
///
/// `None` means zeros should be written to the destination range, and
/// there is no corresponding data in `push_constant_data`. This is used
/// by render bundles, which explicitly clear out any state that
/// post-bundle code might see.
values_offset: Option<u32>,
},
Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},
DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
base_vertex: i32,
first_instance: u32,
},
MultiDrawIndirect {
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
/// Count of `None` represents a non-multi call.
count: Option<NonZeroU32>,
indexed: bool,
},
MultiDrawIndirectCount {
buffer: Arc<Buffer<A>>,
offset: BufferAddress,
count_buffer: Arc<Buffer<A>>,
count_buffer_offset: BufferAddress,
max_count: u32,
indexed: bool,
},
PushDebugGroup {
color: u32,
len: usize,
},
PopDebugGroup,
InsertDebugMarker {
color: u32,
len: usize,
},
WriteTimestamp {
query_set: Arc<QuerySet<A>>,
query_index: u32,
},
BeginOcclusionQuery {
query_index: u32,
},
EndOcclusionQuery,
BeginPipelineStatisticsQuery {
query_set: Arc<QuerySet<A>>,
query_index: u32,
},
EndPipelineStatisticsQuery,
ExecuteBundle(Arc<RenderBundle<A>>),
}
#[cfg(feature = "trace")]
impl<A: HalApi> From<&ArcRenderCommand<A>> for RenderCommand {
fn from(value: &ArcRenderCommand<A>) -> Self {
use crate::resource::Resource as _;
match value {
ArcRenderCommand::SetBindGroup {
index,
num_dynamic_offsets,
bind_group,
} => RenderCommand::SetBindGroup {
index: *index,
num_dynamic_offsets: *num_dynamic_offsets,
bind_group_id: bind_group.as_info().id(),
},
ArcRenderCommand::SetPipeline(pipeline) => {
RenderCommand::SetPipeline(pipeline.as_info().id())
}
ArcRenderCommand::SetPushConstant {
offset,
size_bytes,
values_offset,
stages,
} => RenderCommand::SetPushConstant {
offset: *offset,
size_bytes: *size_bytes,
values_offset: *values_offset,
stages: *stages,
},
ArcRenderCommand::PushDebugGroup { color, len } => RenderCommand::PushDebugGroup {
color: *color,
len: *len,
},
ArcRenderCommand::PopDebugGroup => RenderCommand::PopDebugGroup,
ArcRenderCommand::InsertDebugMarker { color, len } => {
RenderCommand::InsertDebugMarker {
color: *color,
len: *len,
}
}
ArcRenderCommand::WriteTimestamp {
query_set,
query_index,
} => RenderCommand::WriteTimestamp {
query_set_id: query_set.as_info().id(),
query_index: *query_index,
},
ArcRenderCommand::BeginPipelineStatisticsQuery {
query_set,
query_index,
} => RenderCommand::BeginPipelineStatisticsQuery {
query_set_id: query_set.as_info().id(),
query_index: *query_index,
},
ArcRenderCommand::EndPipelineStatisticsQuery => {
RenderCommand::EndPipelineStatisticsQuery
}
ArcRenderCommand::SetIndexBuffer {
buffer,
index_format,
offset,
size,
} => RenderCommand::SetIndexBuffer {
buffer_id: buffer.as_info().id(),
index_format: *index_format,
offset: *offset,
size: *size,
},
ArcRenderCommand::SetVertexBuffer {
slot,
buffer,
offset,
size,
} => RenderCommand::SetVertexBuffer {
slot: *slot,
buffer_id: buffer.as_info().id(),
offset: *offset,
size: *size,
},
ArcRenderCommand::SetBlendConstant(color) => RenderCommand::SetBlendConstant(*color),
ArcRenderCommand::SetStencilReference(reference) => {
RenderCommand::SetStencilReference(*reference)
}
ArcRenderCommand::SetViewport {
rect,
depth_min,
depth_max,
} => RenderCommand::SetViewport {
rect: *rect,
depth_min: *depth_min,
depth_max: *depth_max,
},
ArcRenderCommand::SetScissor(scissor) => RenderCommand::SetScissor(*scissor),
ArcRenderCommand::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
} => RenderCommand::Draw {
vertex_count: *vertex_count,
instance_count: *instance_count,
first_vertex: *first_vertex,
first_instance: *first_instance,
},
ArcRenderCommand::DrawIndexed {
index_count,
instance_count,
first_index,
base_vertex,
first_instance,
} => RenderCommand::DrawIndexed {
index_count: *index_count,
instance_count: *instance_count,
first_index: *first_index,
base_vertex: *base_vertex,
first_instance: *first_instance,
},
ArcRenderCommand::MultiDrawIndirect {
buffer,
offset,
count,
indexed,
} => RenderCommand::MultiDrawIndirect {
buffer_id: buffer.as_info().id(),
offset: *offset,
count: *count,
indexed: *indexed,
},
ArcRenderCommand::MultiDrawIndirectCount {
buffer,
offset,
count_buffer,
count_buffer_offset,
max_count,
indexed,
} => RenderCommand::MultiDrawIndirectCount {
buffer_id: buffer.as_info().id(),
offset: *offset,
count_buffer_id: count_buffer.as_info().id(),
count_buffer_offset: *count_buffer_offset,
max_count: *max_count,
indexed: *indexed,
},
ArcRenderCommand::BeginOcclusionQuery { query_index } => {
RenderCommand::BeginOcclusionQuery {
query_index: *query_index,
}
}
ArcRenderCommand::EndOcclusionQuery => RenderCommand::EndOcclusionQuery,
ArcRenderCommand::ExecuteBundle(bundle) => {
RenderCommand::ExecuteBundle(bundle.as_info().id())
}
}
}
}

View File

@ -24,12 +24,8 @@ use std::{
sync::Arc, sync::Arc,
}; };
use wgc::{ use wgc::{
command::{bundle_ffi::*, render_commands::*}, command::bundle_ffi::*, device::DeviceLostClosure, gfx_select, id::CommandEncoderId,
device::DeviceLostClosure, id::TextureViewId, pipeline::CreateShaderModuleError,
gfx_select,
id::CommandEncoderId,
id::TextureViewId,
pipeline::CreateShaderModuleError,
}; };
use wgt::WasmNotSendSync; use wgt::WasmNotSendSync;
@ -2814,7 +2810,18 @@ impl crate::Context for ContextWgpuCore {
pipeline: &Self::RenderPipelineId, pipeline: &Self::RenderPipelineId,
_pipeline_data: &Self::RenderPipelineData, _pipeline_data: &Self::RenderPipelineData,
) { ) {
wgpu_render_pass_set_pipeline(&mut pass_data.pass, *pipeline) if let Err(cause) = self
.0
.render_pass_set_pipeline(&mut pass_data.pass, *pipeline)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_pipeline",
);
}
} }
fn render_pass_set_bind_group( fn render_pass_set_bind_group(
@ -2826,7 +2833,18 @@ impl crate::Context for ContextWgpuCore {
_bind_group_data: &Self::BindGroupData, _bind_group_data: &Self::BindGroupData,
offsets: &[wgt::DynamicOffset], offsets: &[wgt::DynamicOffset],
) { ) {
wgpu_render_pass_set_bind_group(&mut pass_data.pass, index, *bind_group, offsets) if let Err(cause) =
self.0
.render_pass_set_bind_group(&mut pass_data.pass, index, *bind_group, offsets)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_bind_group",
);
}
} }
fn render_pass_set_index_buffer( fn render_pass_set_index_buffer(
@ -2839,9 +2857,21 @@ impl crate::Context for ContextWgpuCore {
offset: wgt::BufferAddress, offset: wgt::BufferAddress,
size: Option<wgt::BufferSize>, size: Option<wgt::BufferSize>,
) { ) {
pass_data if let Err(cause) = self.0.render_pass_set_index_buffer(
.pass &mut pass_data.pass,
.set_index_buffer(*buffer, index_format, offset, size) *buffer,
index_format,
offset,
size,
) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_index_buffer",
);
}
} }
fn render_pass_set_vertex_buffer( fn render_pass_set_vertex_buffer(
@ -2854,7 +2884,18 @@ impl crate::Context for ContextWgpuCore {
offset: wgt::BufferAddress, offset: wgt::BufferAddress,
size: Option<wgt::BufferSize>, size: Option<wgt::BufferSize>,
) { ) {
wgpu_render_pass_set_vertex_buffer(&mut pass_data.pass, slot, *buffer, offset, size) if let Err(cause) =
self.0
.render_pass_set_vertex_buffer(&mut pass_data.pass, slot, *buffer, offset, size)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_vertex_buffer",
);
}
} }
fn render_pass_set_push_constants( fn render_pass_set_push_constants(
@ -2865,7 +2906,18 @@ impl crate::Context for ContextWgpuCore {
offset: u32, offset: u32,
data: &[u8], data: &[u8],
) { ) {
wgpu_render_pass_set_push_constants(&mut pass_data.pass, stages, offset, data) if let Err(cause) =
self.0
.render_pass_set_push_constants(&mut pass_data.pass, stages, offset, data)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_push_constants",
);
}
} }
fn render_pass_draw( fn render_pass_draw(
@ -2875,13 +2927,21 @@ impl crate::Context for ContextWgpuCore {
vertices: Range<u32>, vertices: Range<u32>,
instances: Range<u32>, instances: Range<u32>,
) { ) {
wgpu_render_pass_draw( if let Err(cause) = self.0.render_pass_draw(
&mut pass_data.pass, &mut pass_data.pass,
vertices.end - vertices.start, vertices.end - vertices.start,
instances.end - instances.start, instances.end - instances.start,
vertices.start, vertices.start,
instances.start, instances.start,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::draw",
);
}
} }
fn render_pass_draw_indexed( fn render_pass_draw_indexed(
@ -2892,14 +2952,22 @@ impl crate::Context for ContextWgpuCore {
base_vertex: i32, base_vertex: i32,
instances: Range<u32>, instances: Range<u32>,
) { ) {
wgpu_render_pass_draw_indexed( if let Err(cause) = self.0.render_pass_draw_indexed(
&mut pass_data.pass, &mut pass_data.pass,
indices.end - indices.start, indices.end - indices.start,
instances.end - instances.start, instances.end - instances.start,
indices.start, indices.start,
base_vertex, base_vertex,
instances.start, instances.start,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::draw_indexed",
);
}
} }
fn render_pass_draw_indirect( fn render_pass_draw_indirect(
@ -2910,7 +2978,18 @@ impl crate::Context for ContextWgpuCore {
_indirect_buffer_data: &Self::BufferData, _indirect_buffer_data: &Self::BufferData,
indirect_offset: wgt::BufferAddress, indirect_offset: wgt::BufferAddress,
) { ) {
wgpu_render_pass_draw_indirect(&mut pass_data.pass, *indirect_buffer, indirect_offset) if let Err(cause) =
self.0
.render_pass_draw_indirect(&mut pass_data.pass, *indirect_buffer, indirect_offset)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::draw_indirect",
);
}
} }
fn render_pass_draw_indexed_indirect( fn render_pass_draw_indexed_indirect(
@ -2921,11 +3000,19 @@ impl crate::Context for ContextWgpuCore {
_indirect_buffer_data: &Self::BufferData, _indirect_buffer_data: &Self::BufferData,
indirect_offset: wgt::BufferAddress, indirect_offset: wgt::BufferAddress,
) { ) {
wgpu_render_pass_draw_indexed_indirect( if let Err(cause) = self.0.render_pass_draw_indexed_indirect(
&mut pass_data.pass, &mut pass_data.pass,
*indirect_buffer, *indirect_buffer,
indirect_offset, indirect_offset,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::draw_indexed_indirect",
);
}
} }
fn render_pass_multi_draw_indirect( fn render_pass_multi_draw_indirect(
@ -2937,12 +3024,20 @@ impl crate::Context for ContextWgpuCore {
indirect_offset: wgt::BufferAddress, indirect_offset: wgt::BufferAddress,
count: u32, count: u32,
) { ) {
wgpu_render_pass_multi_draw_indirect( if let Err(cause) = self.0.render_pass_multi_draw_indirect(
&mut pass_data.pass, &mut pass_data.pass,
*indirect_buffer, *indirect_buffer,
indirect_offset, indirect_offset,
count, count,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::multi_draw_indirect",
);
}
} }
fn render_pass_multi_draw_indexed_indirect( fn render_pass_multi_draw_indexed_indirect(
@ -2954,12 +3049,20 @@ impl crate::Context for ContextWgpuCore {
indirect_offset: wgt::BufferAddress, indirect_offset: wgt::BufferAddress,
count: u32, count: u32,
) { ) {
wgpu_render_pass_multi_draw_indexed_indirect( if let Err(cause) = self.0.render_pass_multi_draw_indexed_indirect(
&mut pass_data.pass, &mut pass_data.pass,
*indirect_buffer, *indirect_buffer,
indirect_offset, indirect_offset,
count, count,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::multi_draw_indexed_indirect",
);
}
} }
fn render_pass_multi_draw_indirect_count( fn render_pass_multi_draw_indirect_count(
@ -2974,14 +3077,22 @@ impl crate::Context for ContextWgpuCore {
count_buffer_offset: wgt::BufferAddress, count_buffer_offset: wgt::BufferAddress,
max_count: u32, max_count: u32,
) { ) {
wgpu_render_pass_multi_draw_indirect_count( if let Err(cause) = self.0.render_pass_multi_draw_indirect_count(
&mut pass_data.pass, &mut pass_data.pass,
*indirect_buffer, *indirect_buffer,
indirect_offset, indirect_offset,
*count_buffer, *count_buffer,
count_buffer_offset, count_buffer_offset,
max_count, max_count,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::multi_draw_indirect_count",
);
}
} }
fn render_pass_multi_draw_indexed_indirect_count( fn render_pass_multi_draw_indexed_indirect_count(
@ -2996,14 +3107,22 @@ impl crate::Context for ContextWgpuCore {
count_buffer_offset: wgt::BufferAddress, count_buffer_offset: wgt::BufferAddress,
max_count: u32, max_count: u32,
) { ) {
wgpu_render_pass_multi_draw_indexed_indirect_count( if let Err(cause) = self.0.render_pass_multi_draw_indexed_indirect_count(
&mut pass_data.pass, &mut pass_data.pass,
*indirect_buffer, *indirect_buffer,
indirect_offset, indirect_offset,
*count_buffer, *count_buffer,
count_buffer_offset, count_buffer_offset,
max_count, max_count,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::multi_draw_indexed_indirect_count",
);
}
} }
fn render_pass_set_blend_constant( fn render_pass_set_blend_constant(
@ -3012,7 +3131,18 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
color: wgt::Color, color: wgt::Color,
) { ) {
wgpu_render_pass_set_blend_constant(&mut pass_data.pass, &color) if let Err(cause) = self
.0
.render_pass_set_blend_constant(&mut pass_data.pass, &color)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_blend_constant",
);
}
} }
fn render_pass_set_scissor_rect( fn render_pass_set_scissor_rect(
@ -3024,7 +3154,18 @@ impl crate::Context for ContextWgpuCore {
width: u32, width: u32,
height: u32, height: u32,
) { ) {
wgpu_render_pass_set_scissor_rect(&mut pass_data.pass, x, y, width, height) if let Err(cause) =
self.0
.render_pass_set_scissor_rect(&mut pass_data.pass, x, y, width, height)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_scissor_rect",
);
}
} }
fn render_pass_set_viewport( fn render_pass_set_viewport(
@ -3038,7 +3179,7 @@ impl crate::Context for ContextWgpuCore {
min_depth: f32, min_depth: f32,
max_depth: f32, max_depth: f32,
) { ) {
wgpu_render_pass_set_viewport( if let Err(cause) = self.0.render_pass_set_viewport(
&mut pass_data.pass, &mut pass_data.pass,
x, x,
y, y,
@ -3046,7 +3187,15 @@ impl crate::Context for ContextWgpuCore {
height, height,
min_depth, min_depth,
max_depth, max_depth,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_viewport",
);
}
} }
fn render_pass_set_stencil_reference( fn render_pass_set_stencil_reference(
@ -3055,7 +3204,18 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
reference: u32, reference: u32,
) { ) {
wgpu_render_pass_set_stencil_reference(&mut pass_data.pass, reference) if let Err(cause) = self
.0
.render_pass_set_stencil_reference(&mut pass_data.pass, reference)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::set_stencil_reference",
);
}
} }
fn render_pass_insert_debug_marker( fn render_pass_insert_debug_marker(
@ -3064,7 +3224,18 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
label: &str, label: &str,
) { ) {
wgpu_render_pass_insert_debug_marker(&mut pass_data.pass, label, 0); if let Err(cause) = self
.0
.render_pass_insert_debug_marker(&mut pass_data.pass, label, 0)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::insert_debug_marker",
);
}
} }
fn render_pass_push_debug_group( fn render_pass_push_debug_group(
@ -3073,7 +3244,18 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
group_label: &str, group_label: &str,
) { ) {
wgpu_render_pass_push_debug_group(&mut pass_data.pass, group_label, 0); if let Err(cause) = self
.0
.render_pass_push_debug_group(&mut pass_data.pass, group_label, 0)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::push_debug_group",
);
}
} }
fn render_pass_pop_debug_group( fn render_pass_pop_debug_group(
@ -3081,7 +3263,15 @@ impl crate::Context for ContextWgpuCore {
_pass: &mut Self::RenderPassId, _pass: &mut Self::RenderPassId,
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
) { ) {
wgpu_render_pass_pop_debug_group(&mut pass_data.pass); if let Err(cause) = self.0.render_pass_pop_debug_group(&mut pass_data.pass) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::pop_debug_group",
);
}
} }
fn render_pass_write_timestamp( fn render_pass_write_timestamp(
@ -3092,7 +3282,18 @@ impl crate::Context for ContextWgpuCore {
_query_set_data: &Self::QuerySetData, _query_set_data: &Self::QuerySetData,
query_index: u32, query_index: u32,
) { ) {
wgpu_render_pass_write_timestamp(&mut pass_data.pass, *query_set, query_index) if let Err(cause) =
self.0
.render_pass_write_timestamp(&mut pass_data.pass, *query_set, query_index)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::write_timestamp",
);
}
} }
fn render_pass_begin_occlusion_query( fn render_pass_begin_occlusion_query(
@ -3101,7 +3302,18 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
query_index: u32, query_index: u32,
) { ) {
wgpu_render_pass_begin_occlusion_query(&mut pass_data.pass, query_index) if let Err(cause) = self
.0
.render_pass_begin_occlusion_query(&mut pass_data.pass, query_index)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::begin_occlusion_query",
);
}
} }
fn render_pass_end_occlusion_query( fn render_pass_end_occlusion_query(
@ -3109,7 +3321,15 @@ impl crate::Context for ContextWgpuCore {
_pass: &mut Self::RenderPassId, _pass: &mut Self::RenderPassId,
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
) { ) {
wgpu_render_pass_end_occlusion_query(&mut pass_data.pass) if let Err(cause) = self.0.render_pass_end_occlusion_query(&mut pass_data.pass) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::end_occlusion_query",
);
}
} }
fn render_pass_begin_pipeline_statistics_query( fn render_pass_begin_pipeline_statistics_query(
@ -3120,11 +3340,19 @@ impl crate::Context for ContextWgpuCore {
_query_set_data: &Self::QuerySetData, _query_set_data: &Self::QuerySetData,
query_index: u32, query_index: u32,
) { ) {
wgpu_render_pass_begin_pipeline_statistics_query( if let Err(cause) = self.0.render_pass_begin_pipeline_statistics_query(
&mut pass_data.pass, &mut pass_data.pass,
*query_set, *query_set,
query_index, query_index,
) ) {
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::begin_pipeline_statistics_query",
);
}
} }
fn render_pass_end_pipeline_statistics_query( fn render_pass_end_pipeline_statistics_query(
@ -3132,7 +3360,18 @@ impl crate::Context for ContextWgpuCore {
_pass: &mut Self::RenderPassId, _pass: &mut Self::RenderPassId,
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
) { ) {
wgpu_render_pass_end_pipeline_statistics_query(&mut pass_data.pass) if let Err(cause) = self
.0
.render_pass_end_pipeline_statistics_query(&mut pass_data.pass)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::end_pipeline_statistics_query",
);
}
} }
fn render_pass_execute_bundles( fn render_pass_execute_bundles(
@ -3142,7 +3381,18 @@ 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]>>();
wgpu_render_pass_execute_bundles(&mut pass_data.pass, &temp_render_bundles) if let Err(cause) = self
.0
.render_pass_execute_bundles(&mut pass_data.pass, &temp_render_bundles)
{
self.handle_error(
&pass_data.error_sink,
cause,
LABEL,
pass_data.pass.label(),
"RenderPass::execute_bundles",
);
}
} }
fn render_pass_end( fn render_pass_end(
@ -3151,7 +3401,8 @@ impl crate::Context for ContextWgpuCore {
pass_data: &mut Self::RenderPassData, pass_data: &mut Self::RenderPassData,
) { ) {
let encoder = pass_data.pass.parent_id(); let encoder = pass_data.pass.parent_id();
if let Err(cause) = wgc::gfx_select!(encoder => self.0.render_pass_end(&pass_data.pass)) { if let Err(cause) = wgc::gfx_select!(encoder => self.0.render_pass_end(&mut pass_data.pass))
{
self.handle_error( self.handle_error(
&pass_data.error_sink, &pass_data.error_sink,
cause, cause,