summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/command
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
commitfbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 (patch)
tree4c1ccaf5486d4f2009f9a338a98a83e886e29c97 /third_party/rust/wgpu-core/src/command
parentReleasing progress-linux version 124.0.1-1~progress7.99u1. (diff)
downloadfirefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.tar.xz
firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wgpu-core/src/command')
-rw-r--r--third_party/rust/wgpu-core/src/command/bundle.rs294
-rw-r--r--third_party/rust/wgpu-core/src/command/clear.rs45
-rw-r--r--third_party/rust/wgpu-core/src/command/compute.rs35
-rw-r--r--third_party/rust/wgpu-core/src/command/draw.rs120
-rw-r--r--third_party/rust/wgpu-core/src/command/mod.rs5
-rw-r--r--third_party/rust/wgpu-core/src/command/query.rs9
-rw-r--r--third_party/rust/wgpu-core/src/command/render.rs54
7 files changed, 359 insertions, 203 deletions
diff --git a/third_party/rust/wgpu-core/src/command/bundle.rs b/third_party/rust/wgpu-core/src/command/bundle.rs
index 9d80c62f85..ab2d18bc59 100644
--- a/third_party/rust/wgpu-core/src/command/bundle.rs
+++ b/third_party/rust/wgpu-core/src/command/bundle.rs
@@ -97,7 +97,7 @@ use crate::{
id,
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
pipeline::{PipelineFlags, RenderPipeline, VertexStep},
- resource::{Resource, ResourceInfo, ResourceType},
+ resource::{Buffer, Resource, ResourceInfo, ResourceType},
resource_log,
track::RenderBundleScope,
validation::check_buffer_usage,
@@ -110,9 +110,11 @@ use thiserror::Error;
use hal::CommandEncoder as _;
+use super::ArcRenderCommand;
+
/// https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw
-fn validate_draw(
- vertex: &[Option<VertexState>],
+fn validate_draw<A: HalApi>(
+ vertex: &[Option<VertexState<A>>],
step: &[VertexStep],
first_vertex: u32,
vertex_count: u32,
@@ -152,10 +154,10 @@ fn validate_draw(
}
// See https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-drawindexed
-fn validate_indexed_draw(
- vertex: &[Option<VertexState>],
+fn validate_indexed_draw<A: HalApi>(
+ vertex: &[Option<VertexState<A>>],
step: &[VertexStep],
- index_state: &IndexState,
+ index_state: &IndexState<A>,
first_index: u32,
index_count: u32,
first_instance: u32,
@@ -260,6 +262,9 @@ impl RenderBundleEncoder {
None => (true, true),
};
+ // TODO: should be device.limits.max_color_attachments
+ let max_color_attachments = hal::MAX_COLOR_ATTACHMENTS;
+
//TODO: validate that attachment formats are renderable,
// have expected aspects, support multisampling.
Ok(Self {
@@ -267,11 +272,11 @@ impl RenderBundleEncoder {
parent_id,
context: RenderPassContext {
attachments: AttachmentData {
- colors: if desc.color_formats.len() > hal::MAX_COLOR_ATTACHMENTS {
+ colors: if desc.color_formats.len() > max_color_attachments {
return Err(CreateRenderBundleError::ColorAttachment(
ColorAttachmentError::TooMany {
given: desc.color_formats.len(),
- limit: hal::MAX_COLOR_ATTACHMENTS,
+ limit: max_color_attachments,
},
));
} else {
@@ -345,24 +350,44 @@ impl RenderBundleEncoder {
) -> Result<RenderBundle<A>, RenderBundleError> {
let bind_group_guard = hub.bind_groups.read();
let pipeline_guard = hub.render_pipelines.read();
- let query_set_guard = hub.query_sets.read();
let buffer_guard = hub.buffers.read();
- let texture_guard = hub.textures.read();
let mut state = State {
- trackers: RenderBundleScope::new(
- &*buffer_guard,
- &*texture_guard,
- &*bind_group_guard,
- &*pipeline_guard,
- &*query_set_guard,
- ),
+ trackers: RenderBundleScope::new(),
pipeline: None,
bind: (0..hal::MAX_BIND_GROUPS).map(|_| None).collect(),
vertex: (0..hal::MAX_VERTEX_BUFFERS).map(|_| None).collect(),
index: None,
flat_dynamic_offsets: Vec::new(),
};
+
+ let indices = &device.tracker_indices;
+ state
+ .trackers
+ .buffers
+ .write()
+ .set_size(indices.buffers.size());
+ state
+ .trackers
+ .textures
+ .write()
+ .set_size(indices.textures.size());
+ state
+ .trackers
+ .bind_groups
+ .write()
+ .set_size(indices.bind_groups.size());
+ state
+ .trackers
+ .render_pipelines
+ .write()
+ .set_size(indices.render_pipelines.size());
+ state
+ .trackers
+ .query_sets
+ .write()
+ .set_size(indices.query_sets.size());
+
let mut commands = Vec::new();
let mut buffer_memory_init_actions = Vec::new();
let mut texture_memory_init_actions = Vec::new();
@@ -399,7 +424,6 @@ impl RenderBundleEncoder {
}
// Identify the next `num_dynamic_offsets` entries from `base.dynamic_offsets`.
- let num_dynamic_offsets = num_dynamic_offsets;
let offsets_range =
next_dynamic_offset..next_dynamic_offset + num_dynamic_offsets;
next_dynamic_offset = offsets_range.end;
@@ -471,7 +495,7 @@ impl RenderBundleEncoder {
let pipeline_state = PipelineState::new(pipeline);
- commands.push(command);
+ commands.push(ArcRenderCommand::SetPipeline(pipeline.clone()));
// If this pipeline uses push constants, zero out their values.
if let Some(iter) = pipeline_state.zero_push_constants() {
@@ -496,7 +520,7 @@ impl RenderBundleEncoder {
.map_pass_err(scope)?;
self.check_valid_to_use(buffer.device.info.id())
.map_pass_err(scope)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::INDEX)
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::INDEX)
.map_pass_err(scope)?;
let end = match size {
@@ -508,7 +532,7 @@ impl RenderBundleEncoder {
offset..end,
MemoryInitKind::NeedsInitializedMemory,
));
- state.set_index_buffer(buffer_id, index_format, offset..end);
+ state.set_index_buffer(buffer.clone(), index_format, offset..end);
}
RenderCommand::SetVertexBuffer {
slot,
@@ -535,7 +559,7 @@ impl RenderBundleEncoder {
.map_pass_err(scope)?;
self.check_valid_to_use(buffer.device.info.id())
.map_pass_err(scope)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::VERTEX)
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::VERTEX)
.map_pass_err(scope)?;
let end = match size {
@@ -547,13 +571,13 @@ impl RenderBundleEncoder {
offset..end,
MemoryInitKind::NeedsInitializedMemory,
));
- state.vertex[slot as usize] = Some(VertexState::new(buffer_id, offset..end));
+ state.vertex[slot as usize] = Some(VertexState::new(buffer.clone(), offset..end));
}
RenderCommand::SetPushConstant {
stages,
offset,
size_bytes,
- values_offset: _,
+ values_offset,
} => {
let scope = PassErrorScope::SetPushConstant;
let end_offset = offset + size_bytes;
@@ -564,7 +588,7 @@ impl RenderBundleEncoder {
.validate_push_constant_ranges(stages, offset, end_offset)
.map_pass_err(scope)?;
- commands.push(command);
+ commands.push(ArcRenderCommand::SetPushConstant { stages, offset, size_bytes, values_offset });
}
RenderCommand::Draw {
vertex_count,
@@ -592,14 +616,19 @@ impl RenderBundleEncoder {
if instance_count > 0 && vertex_count > 0 {
commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets));
- commands.push(command);
+ commands.push(ArcRenderCommand::Draw {
+ vertex_count,
+ instance_count,
+ first_vertex,
+ first_instance,
+ });
}
}
RenderCommand::DrawIndexed {
index_count,
instance_count,
first_index,
- base_vertex: _,
+ base_vertex,
first_instance,
} => {
let scope = PassErrorScope::Draw {
@@ -628,7 +657,7 @@ impl RenderBundleEncoder {
commands.extend(state.flush_index());
commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets));
- commands.push(command);
+ commands.push(ArcRenderCommand::DrawIndexed { index_count, instance_count, first_index, base_vertex, first_instance });
}
}
RenderCommand::MultiDrawIndirect {
@@ -657,7 +686,7 @@ impl RenderBundleEncoder {
.map_pass_err(scope)?;
self.check_valid_to_use(buffer.device.info.id())
.map_pass_err(scope)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::INDIRECT)
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::INDIRECT)
.map_pass_err(scope)?;
buffer_memory_init_actions.extend(buffer.initialization_status.read().create_action(
@@ -668,7 +697,7 @@ impl RenderBundleEncoder {
commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets));
- commands.push(command);
+ commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: false });
}
RenderCommand::MultiDrawIndirect {
buffer_id,
@@ -696,7 +725,7 @@ impl RenderBundleEncoder {
.map_pass_err(scope)?;
self.check_valid_to_use(buffer.device.info.id())
.map_pass_err(scope)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::INDIRECT)
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::INDIRECT)
.map_pass_err(scope)?;
buffer_memory_init_actions.extend(buffer.initialization_status.read().create_action(
@@ -713,7 +742,7 @@ impl RenderBundleEncoder {
commands.extend(index.flush());
commands.extend(state.flush_vertices());
commands.extend(state.flush_binds(used_bind_groups, base.dynamic_offsets));
- commands.push(command);
+ commands.push(ArcRenderCommand::MultiDrawIndirect { buffer: buffer.clone(), offset, count: None, indexed: true });
}
RenderCommand::MultiDrawIndirect { .. }
| RenderCommand::MultiDrawIndirectCount { .. } => unimplemented!(),
@@ -748,7 +777,10 @@ impl RenderBundleEncoder {
buffer_memory_init_actions,
texture_memory_init_actions,
context: self.context,
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(device.tracker_indices.bundles.clone()),
+ ),
discard_hal_labels: device
.instance_flags
.contains(wgt::InstanceFlags::DISCARD_HAL_LABELS),
@@ -824,7 +856,7 @@ pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
pub struct RenderBundle<A: HalApi> {
// Normalized command stream. It can be executed verbatim,
// without re-binding anything on the pipeline change.
- base: BasePass<RenderCommand>,
+ base: BasePass<ArcRenderCommand<A>>,
pub(super) is_depth_read_only: bool,
pub(super) is_stencil_read_only: bool,
pub(crate) device: Arc<Device<A>>,
@@ -863,7 +895,6 @@ impl<A: HalApi> RenderBundle<A> {
/// All the validation has already been done by this point.
/// The only failure condition is if some of the used buffers are destroyed.
pub(super) unsafe fn execute(&self, raw: &mut A::CommandEncoder) -> Result<(), ExecutionError> {
- let trackers = &self.used;
let mut offsets = self.base.dynamic_offsets.as_slice();
let mut pipeline_layout = None::<Arc<PipelineLayout<A>>>;
if !self.discard_hal_labels {
@@ -874,74 +905,65 @@ impl<A: HalApi> RenderBundle<A> {
let snatch_guard = self.device.snatchable_lock.read();
+ use ArcRenderCommand as Cmd;
for command in self.base.commands.iter() {
- match *command {
- RenderCommand::SetBindGroup {
+ match command {
+ Cmd::SetBindGroup {
index,
num_dynamic_offsets,
- bind_group_id,
+ bind_group,
} => {
- let bind_groups = trackers.bind_groups.read();
- let bind_group = bind_groups.get(bind_group_id).unwrap();
let raw_bg = bind_group
.raw(&snatch_guard)
- .ok_or(ExecutionError::InvalidBindGroup(bind_group_id))?;
+ .ok_or(ExecutionError::InvalidBindGroup(bind_group.info.id()))?;
unsafe {
raw.set_bind_group(
pipeline_layout.as_ref().unwrap().raw(),
- index,
+ *index,
raw_bg,
- &offsets[..num_dynamic_offsets],
+ &offsets[..*num_dynamic_offsets],
)
};
- offsets = &offsets[num_dynamic_offsets..];
+ offsets = &offsets[*num_dynamic_offsets..];
}
- RenderCommand::SetPipeline(pipeline_id) => {
- let render_pipelines = trackers.render_pipelines.read();
- let pipeline = render_pipelines.get(pipeline_id).unwrap();
+ Cmd::SetPipeline(pipeline) => {
unsafe { raw.set_render_pipeline(pipeline.raw()) };
pipeline_layout = Some(pipeline.layout.clone());
}
- RenderCommand::SetIndexBuffer {
- buffer_id,
+ Cmd::SetIndexBuffer {
+ buffer,
index_format,
offset,
size,
} => {
- let buffers = trackers.buffers.read();
- let buffer: &A::Buffer = buffers
- .get(buffer_id)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?
+ let buffer: &A::Buffer = buffer
.raw(&snatch_guard)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?;
+ .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
let bb = hal::BufferBinding {
buffer,
- offset,
- size,
+ offset: *offset,
+ size: *size,
};
- unsafe { raw.set_index_buffer(bb, index_format) };
+ unsafe { raw.set_index_buffer(bb, *index_format) };
}
- RenderCommand::SetVertexBuffer {
+ Cmd::SetVertexBuffer {
slot,
- buffer_id,
+ buffer,
offset,
size,
} => {
- let buffers = trackers.buffers.read();
- let buffer = buffers
- .get(buffer_id)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?
+ let buffer = buffer
.raw(&snatch_guard)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?;
+ .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
let bb = hal::BufferBinding {
buffer,
- offset,
- size,
+ offset: *offset,
+ size: *size,
};
- unsafe { raw.set_vertex_buffer(slot, bb) };
+ unsafe { raw.set_vertex_buffer(*slot, bb) };
}
- RenderCommand::SetPushConstant {
+ Cmd::SetPushConstant {
stages,
offset,
size_bytes,
@@ -949,7 +971,7 @@ impl<A: HalApi> RenderBundle<A> {
} => {
let pipeline_layout = pipeline_layout.as_ref().unwrap();
- if let Some(values_offset) = values_offset {
+ if let Some(values_offset) = *values_offset {
let values_end_offset =
(values_offset + size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
let data_slice = &self.base.push_constant_data
@@ -958,20 +980,20 @@ impl<A: HalApi> RenderBundle<A> {
unsafe {
raw.set_push_constants(
pipeline_layout.raw(),
- stages,
- offset,
+ *stages,
+ *offset,
data_slice,
)
}
} else {
super::push_constant_clear(
- offset,
- size_bytes,
+ *offset,
+ *size_bytes,
|clear_offset, clear_data| {
unsafe {
raw.set_push_constants(
pipeline_layout.raw(),
- stages,
+ *stages,
clear_offset,
clear_data,
)
@@ -980,15 +1002,22 @@ impl<A: HalApi> RenderBundle<A> {
);
}
}
- RenderCommand::Draw {
+ Cmd::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
} => {
- unsafe { raw.draw(first_vertex, vertex_count, first_instance, instance_count) };
+ unsafe {
+ raw.draw(
+ *first_vertex,
+ *vertex_count,
+ *first_instance,
+ *instance_count,
+ )
+ };
}
- RenderCommand::DrawIndexed {
+ Cmd::DrawIndexed {
index_count,
instance_count,
first_index,
@@ -997,63 +1026,54 @@ impl<A: HalApi> RenderBundle<A> {
} => {
unsafe {
raw.draw_indexed(
- first_index,
- index_count,
- base_vertex,
- first_instance,
- instance_count,
+ *first_index,
+ *index_count,
+ *base_vertex,
+ *first_instance,
+ *instance_count,
)
};
}
- RenderCommand::MultiDrawIndirect {
- buffer_id,
+ Cmd::MultiDrawIndirect {
+ buffer,
offset,
count: None,
indexed: false,
} => {
- let buffers = trackers.buffers.read();
- let buffer = buffers
- .get(buffer_id)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?
+ let buffer = buffer
.raw(&snatch_guard)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?;
- unsafe { raw.draw_indirect(buffer, offset, 1) };
+ .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
+ unsafe { raw.draw_indirect(buffer, *offset, 1) };
}
- RenderCommand::MultiDrawIndirect {
- buffer_id,
+ Cmd::MultiDrawIndirect {
+ buffer,
offset,
count: None,
indexed: true,
} => {
- let buffers = trackers.buffers.read();
- let buffer = buffers
- .get(buffer_id)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?
+ let buffer = buffer
.raw(&snatch_guard)
- .ok_or(ExecutionError::DestroyedBuffer(buffer_id))?;
- unsafe { raw.draw_indexed_indirect(buffer, offset, 1) };
+ .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
+ unsafe { raw.draw_indexed_indirect(buffer, *offset, 1) };
}
- RenderCommand::MultiDrawIndirect { .. }
- | RenderCommand::MultiDrawIndirectCount { .. } => {
+ Cmd::MultiDrawIndirect { .. } | Cmd::MultiDrawIndirectCount { .. } => {
return Err(ExecutionError::Unimplemented("multi-draw-indirect"))
}
- RenderCommand::PushDebugGroup { .. }
- | RenderCommand::InsertDebugMarker { .. }
- | RenderCommand::PopDebugGroup => {
+ Cmd::PushDebugGroup { .. } | Cmd::InsertDebugMarker { .. } | Cmd::PopDebugGroup => {
return Err(ExecutionError::Unimplemented("debug-markers"))
}
- RenderCommand::WriteTimestamp { .. }
- | RenderCommand::BeginOcclusionQuery { .. }
- | RenderCommand::EndOcclusionQuery
- | RenderCommand::BeginPipelineStatisticsQuery { .. }
- | RenderCommand::EndPipelineStatisticsQuery => {
+ Cmd::WriteTimestamp { .. }
+ | Cmd::BeginOcclusionQuery { .. }
+ | Cmd::EndOcclusionQuery
+ | Cmd::BeginPipelineStatisticsQuery { .. }
+ | Cmd::EndPipelineStatisticsQuery => {
return Err(ExecutionError::Unimplemented("queries"))
}
- RenderCommand::ExecuteBundle(_)
- | RenderCommand::SetBlendConstant(_)
- | RenderCommand::SetStencilReference(_)
- | RenderCommand::SetViewport { .. }
- | RenderCommand::SetScissor(_) => unreachable!(),
+ Cmd::ExecuteBundle(_)
+ | Cmd::SetBlendConstant(_)
+ | Cmd::SetStencilReference(_)
+ | Cmd::SetViewport { .. }
+ | Cmd::SetScissor(_) => unreachable!(),
}
}
@@ -1087,14 +1107,14 @@ impl<A: HalApi> Resource for RenderBundle<A> {
/// and calls [`State::flush_index`] before any indexed draw command to produce
/// a `SetIndexBuffer` command if one is necessary.
#[derive(Debug)]
-struct IndexState {
- buffer: id::BufferId,
+struct IndexState<A: HalApi> {
+ buffer: Arc<Buffer<A>>,
format: wgt::IndexFormat,
range: Range<wgt::BufferAddress>,
is_dirty: bool,
}
-impl IndexState {
+impl<A: HalApi> IndexState<A> {
/// Return the number of entries in the current index buffer.
///
/// Panic if no index buffer has been set.
@@ -1109,11 +1129,11 @@ impl IndexState {
/// Generate a `SetIndexBuffer` command to prepare for an indexed draw
/// command, if needed.
- fn flush(&mut self) -> Option<RenderCommand> {
+ fn flush(&mut self) -> Option<ArcRenderCommand<A>> {
if self.is_dirty {
self.is_dirty = false;
- Some(RenderCommand::SetIndexBuffer {
- buffer_id: self.buffer,
+ Some(ArcRenderCommand::SetIndexBuffer {
+ buffer: self.buffer.clone(),
index_format: self.format,
offset: self.range.start,
size: wgt::BufferSize::new(self.range.end - self.range.start),
@@ -1134,14 +1154,14 @@ impl IndexState {
///
/// [`flush`]: IndexState::flush
#[derive(Debug)]
-struct VertexState {
- buffer: id::BufferId,
+struct VertexState<A: HalApi> {
+ buffer: Arc<Buffer<A>>,
range: Range<wgt::BufferAddress>,
is_dirty: bool,
}
-impl VertexState {
- fn new(buffer: id::BufferId, range: Range<wgt::BufferAddress>) -> Self {
+impl<A: HalApi> VertexState<A> {
+ fn new(buffer: Arc<Buffer<A>>, range: Range<wgt::BufferAddress>) -> Self {
Self {
buffer,
range,
@@ -1152,12 +1172,12 @@ impl VertexState {
/// Generate a `SetVertexBuffer` command for this slot, if necessary.
///
/// `slot` is the index of the vertex buffer slot that `self` tracks.
- fn flush(&mut self, slot: u32) -> Option<RenderCommand> {
+ fn flush(&mut self, slot: u32) -> Option<ArcRenderCommand<A>> {
if self.is_dirty {
self.is_dirty = false;
- Some(RenderCommand::SetVertexBuffer {
+ Some(ArcRenderCommand::SetVertexBuffer {
slot,
- buffer_id: self.buffer,
+ buffer: self.buffer.clone(),
offset: self.range.start,
size: wgt::BufferSize::new(self.range.end - self.range.start),
})
@@ -1219,7 +1239,7 @@ impl<A: HalApi> PipelineState<A> {
/// Return a sequence of commands to zero the push constant ranges this
/// pipeline uses. If no initialization is necessary, return `None`.
- fn zero_push_constants(&self) -> Option<impl Iterator<Item = RenderCommand>> {
+ fn zero_push_constants(&self) -> Option<impl Iterator<Item = ArcRenderCommand<A>>> {
if !self.push_constant_ranges.is_empty() {
let nonoverlapping_ranges =
super::bind::compute_nonoverlapping_ranges(&self.push_constant_ranges);
@@ -1227,7 +1247,7 @@ impl<A: HalApi> PipelineState<A> {
Some(
nonoverlapping_ranges
.into_iter()
- .map(|range| RenderCommand::SetPushConstant {
+ .map(|range| ArcRenderCommand::SetPushConstant {
stages: range.stages,
offset: range.range.start,
size_bytes: range.range.end - range.range.start,
@@ -1261,11 +1281,11 @@ struct State<A: HalApi> {
bind: ArrayVec<Option<BindState<A>>, { hal::MAX_BIND_GROUPS }>,
/// The state of each vertex buffer slot.
- vertex: ArrayVec<Option<VertexState>, { hal::MAX_VERTEX_BUFFERS }>,
+ vertex: ArrayVec<Option<VertexState<A>>, { hal::MAX_VERTEX_BUFFERS }>,
/// The current index buffer, if one has been set. We flush this state
/// before indexed draw commands.
- index: Option<IndexState>,
+ index: Option<IndexState<A>>,
/// Dynamic offset values used by the cleaned-up command sequence.
///
@@ -1375,13 +1395,13 @@ impl<A: HalApi> State<A> {
/// Set the bundle's current index buffer and its associated parameters.
fn set_index_buffer(
&mut self,
- buffer: id::BufferId,
+ buffer: Arc<Buffer<A>>,
format: wgt::IndexFormat,
range: Range<wgt::BufferAddress>,
) {
match self.index {
Some(ref current)
- if current.buffer == buffer
+ if Arc::ptr_eq(&current.buffer, &buffer)
&& current.format == format
&& current.range == range =>
{
@@ -1400,11 +1420,11 @@ impl<A: HalApi> State<A> {
/// Generate a `SetIndexBuffer` command to prepare for an indexed draw
/// command, if needed.
- fn flush_index(&mut self) -> Option<RenderCommand> {
+ fn flush_index(&mut self) -> Option<ArcRenderCommand<A>> {
self.index.as_mut().and_then(|index| index.flush())
}
- fn flush_vertices(&mut self) -> impl Iterator<Item = RenderCommand> + '_ {
+ fn flush_vertices(&mut self) -> impl Iterator<Item = ArcRenderCommand<A>> + '_ {
self.vertex
.iter_mut()
.enumerate()
@@ -1416,7 +1436,7 @@ impl<A: HalApi> State<A> {
&mut self,
used_bind_groups: usize,
dynamic_offsets: &[wgt::DynamicOffset],
- ) -> impl Iterator<Item = RenderCommand> + '_ {
+ ) -> impl Iterator<Item = ArcRenderCommand<A>> + '_ {
// Append each dirty bind group's dynamic offsets to `flat_dynamic_offsets`.
for contents in self.bind[..used_bind_groups].iter().flatten() {
if contents.is_dirty {
@@ -1435,9 +1455,9 @@ impl<A: HalApi> State<A> {
if contents.is_dirty {
contents.is_dirty = false;
let offsets = &contents.dynamic_offsets;
- return Some(RenderCommand::SetBindGroup {
+ return Some(ArcRenderCommand::SetBindGroup {
index: i.try_into().unwrap(),
- bind_group_id: contents.bind_group.as_info().id(),
+ bind_group: contents.bind_group.clone(),
num_dynamic_offsets: offsets.end - offsets.start,
});
}
diff --git a/third_party/rust/wgpu-core/src/command/clear.rs b/third_party/rust/wgpu-core/src/command/clear.rs
index 2569fea1a4..e404fabb14 100644
--- a/third_party/rust/wgpu-core/src/command/clear.rs
+++ b/third_party/rust/wgpu-core/src/command/clear.rs
@@ -39,6 +39,11 @@ pub enum ClearError {
UnalignedFillSize(BufferAddress),
#[error("Buffer offset {0:?} is not a multiple of `COPY_BUFFER_ALIGNMENT`")]
UnalignedBufferOffset(BufferAddress),
+ #[error("Clear starts at offset {start_offset} with size of {requested_size}, but these added together exceed `u64::MAX`")]
+ OffsetPlusSizeExceeds64BitBounds {
+ start_offset: BufferAddress,
+ requested_size: BufferAddress,
+ },
#[error("Clear of {start_offset}..{end_offset} would end up overrunning the bounds of the buffer of size {buffer_size}")]
BufferOverrun {
start_offset: BufferAddress,
@@ -117,25 +122,27 @@ impl Global {
if offset % wgt::COPY_BUFFER_ALIGNMENT != 0 {
return Err(ClearError::UnalignedBufferOffset(offset));
}
- if let Some(size) = size {
- if size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
- return Err(ClearError::UnalignedFillSize(size));
- }
- let destination_end_offset = offset + size;
- if destination_end_offset > dst_buffer.size {
- return Err(ClearError::BufferOverrun {
+
+ let size = size.unwrap_or(dst_buffer.size.saturating_sub(offset));
+ if size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
+ return Err(ClearError::UnalignedFillSize(size));
+ }
+ let end_offset =
+ offset
+ .checked_add(size)
+ .ok_or(ClearError::OffsetPlusSizeExceeds64BitBounds {
start_offset: offset,
- end_offset: destination_end_offset,
- buffer_size: dst_buffer.size,
- });
- }
+ requested_size: size,
+ })?;
+ if end_offset > dst_buffer.size {
+ return Err(ClearError::BufferOverrun {
+ start_offset: offset,
+ end_offset,
+ buffer_size: dst_buffer.size,
+ });
}
- let end = match size {
- Some(size) => offset + size,
- None => dst_buffer.size,
- };
- if offset == end {
+ if offset == end_offset {
log::trace!("Ignoring fill_buffer of size 0");
return Ok(());
}
@@ -144,7 +151,7 @@ impl Global {
cmd_buf_data.buffer_memory_init_actions.extend(
dst_buffer.initialization_status.read().create_action(
&dst_buffer,
- offset..end,
+ offset..end_offset,
MemoryInitKind::ImplicitlyInitialized,
),
);
@@ -154,7 +161,7 @@ impl Global {
let cmd_buf_raw = cmd_buf_data.encoder.open()?;
unsafe {
cmd_buf_raw.transition_buffers(dst_barrier.into_iter());
- cmd_buf_raw.clear_buffer(dst_raw, offset..end);
+ cmd_buf_raw.clear_buffer(dst_raw, offset..end_offset);
}
Ok(())
}
@@ -366,7 +373,7 @@ fn clear_texture_via_buffer_copies<A: HalApi>(
assert!(
max_rows_per_copy > 0,
"Zero buffer size is too small to fill a single row \
- of a texture with format {:?} and desc {:?}",
+ of a texture with format {:?} and desc {:?}",
texture_desc.format,
texture_desc.size
);
diff --git a/third_party/rust/wgpu-core/src/command/compute.rs b/third_party/rust/wgpu-core/src/command/compute.rs
index 804186a01e..c2fd3ab397 100644
--- a/third_party/rust/wgpu-core/src/command/compute.rs
+++ b/third_party/rust/wgpu-core/src/command/compute.rs
@@ -1,6 +1,7 @@
use crate::device::DeviceError;
use crate::resource::Resource;
use crate::snatch::SnatchGuard;
+use crate::track::TrackerIndex;
use crate::{
binding_model::{
BindError, BindGroup, LateMinBufferBindingSizeMismatch, PushConstantUploadError,
@@ -305,7 +306,7 @@ impl<A: HalApi> State<A> {
raw_encoder: &mut A::CommandEncoder,
base_trackers: &mut Tracker<A>,
bind_group_guard: &Storage<BindGroup<A>>,
- indirect_buffer: Option<id::BufferId>,
+ indirect_buffer: Option<TrackerIndex>,
snatch_guard: &SnatchGuard,
) -> Result<(), UsageConflict> {
for id in self.binder.list_active() {
@@ -402,12 +403,11 @@ impl Global {
let pipeline_guard = hub.compute_pipelines.read();
let query_set_guard = hub.query_sets.read();
let buffer_guard = hub.buffers.read();
- let texture_guard = hub.textures.read();
let mut state = State {
binder: Binder::new(),
pipeline: None,
- scope: UsageScope::new(&*buffer_guard, &*texture_guard),
+ scope: UsageScope::new(&device.tracker_indices),
debug_scope_depth: 0,
};
let mut temp_offsets = Vec::new();
@@ -452,17 +452,14 @@ impl Global {
let snatch_guard = device.snatchable_lock.read();
- tracker.set_size(
- Some(&*buffer_guard),
- Some(&*texture_guard),
- None,
- None,
- Some(&*bind_group_guard),
- Some(&*pipeline_guard),
- None,
- None,
- Some(&*query_set_guard),
- );
+ let indices = &device.tracker_indices;
+ tracker.buffers.set_size(indices.buffers.size());
+ tracker.textures.set_size(indices.textures.size());
+ tracker.bind_groups.set_size(indices.bind_groups.size());
+ tracker
+ .compute_pipelines
+ .set_size(indices.compute_pipelines.size());
+ tracker.query_sets.set_size(indices.query_sets.size());
let discard_hal_labels = self
.instance
@@ -719,8 +716,12 @@ impl Global {
.buffers
.merge_single(&*buffer_guard, buffer_id, hal::BufferUses::INDIRECT)
.map_pass_err(scope)?;
- check_buffer_usage(indirect_buffer.usage, wgt::BufferUsages::INDIRECT)
- .map_pass_err(scope)?;
+ check_buffer_usage(
+ buffer_id,
+ indirect_buffer.usage,
+ wgt::BufferUsages::INDIRECT,
+ )
+ .map_pass_err(scope)?;
let end_offset = offset + mem::size_of::<wgt::DispatchIndirectArgs>() as u64;
if end_offset > indirect_buffer.size {
@@ -753,7 +754,7 @@ impl Global {
raw,
&mut intermediate_trackers,
&*bind_group_guard,
- Some(buffer_id),
+ Some(indirect_buffer.as_info().tracker_index()),
&snatch_guard,
)
.map_pass_err(scope)?;
diff --git a/third_party/rust/wgpu-core/src/command/draw.rs b/third_party/rust/wgpu-core/src/command/draw.rs
index e03a78ee93..98aa689b78 100644
--- a/third_party/rust/wgpu-core/src/command/draw.rs
+++ b/third_party/rust/wgpu-core/src/command/draw.rs
@@ -2,17 +2,22 @@
!*/
use crate::{
- binding_model::{LateMinBufferBindingSizeMismatch, PushConstantUploadError},
+ binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PushConstantUploadError},
error::ErrorFormatter,
+ hal_api::HalApi,
id,
+ pipeline::RenderPipeline,
+ resource::{Buffer, QuerySet},
track::UsageConflict,
validation::{MissingBufferUsageError, MissingTextureUsageError},
};
use wgt::{BufferAddress, BufferSize, Color, VertexStepMode};
-use std::num::NonZeroU32;
+use std::{num::NonZeroU32, sync::Arc};
use thiserror::Error;
+use super::RenderBundle;
+
/// Error validating a draw call.
#[derive(Clone, Debug, Error, Eq, PartialEq)]
#[non_exhaustive]
@@ -245,3 +250,114 @@ pub enum RenderCommand {
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>>),
+}
diff --git a/third_party/rust/wgpu-core/src/command/mod.rs b/third_party/rust/wgpu-core/src/command/mod.rs
index 2d5fca200a..febed4fc97 100644
--- a/third_party/rust/wgpu-core/src/command/mod.rs
+++ b/third_party/rust/wgpu-core/src/command/mod.rs
@@ -75,7 +75,7 @@ impl<A: HalApi> CommandEncoder<A> {
Ok(())
}
- fn discard(&mut self) {
+ pub(crate) fn discard(&mut self) {
if self.is_open {
self.is_open = false;
unsafe { self.raw.discard_encoding() };
@@ -112,7 +112,7 @@ pub(crate) struct DestroyedBufferError(pub id::BufferId);
pub(crate) struct DestroyedTextureError(pub id::TextureId);
pub struct CommandBufferMutable<A: HalApi> {
- encoder: CommandEncoder<A>,
+ pub(crate) encoder: CommandEncoder<A>,
status: CommandEncoderStatus,
pub(crate) trackers: Tracker<A>,
buffer_memory_init_actions: Vec<BufferInitTrackerAction<A>>,
@@ -174,6 +174,7 @@ impl<A: HalApi> CommandBuffer<A> {
.as_ref()
.unwrap_or(&String::from("<CommandBuffer>"))
.as_str(),
+ None,
),
data: Mutex::new(Some(CommandBufferMutable {
encoder: CommandEncoder {
diff --git a/third_party/rust/wgpu-core/src/command/query.rs b/third_party/rust/wgpu-core/src/command/query.rs
index 39d7a9cc93..89cba6fbf3 100644
--- a/third_party/rust/wgpu-core/src/command/query.rs
+++ b/third_party/rust/wgpu-core/src/command/query.rs
@@ -4,7 +4,7 @@ use hal::CommandEncoder as _;
use crate::device::trace::Command as TraceCommand;
use crate::{
command::{CommandBuffer, CommandEncoderError},
- device::DeviceError,
+ device::{DeviceError, MissingFeatures},
global::Global,
hal_api::HalApi,
id::{self, Id},
@@ -108,6 +108,8 @@ pub enum QueryError {
Device(#[from] DeviceError),
#[error(transparent)]
Encoder(#[from] CommandEncoderError),
+ #[error(transparent)]
+ MissingFeature(#[from] MissingFeatures),
#[error("Error encountered while trying to use queries")]
Use(#[from] QueryUseError),
#[error("Error encountered while trying to resolve a query")]
@@ -355,6 +357,11 @@ impl Global {
let hub = A::hub(self);
let cmd_buf = CommandBuffer::get_encoder(hub, command_encoder_id)?;
+
+ cmd_buf
+ .device
+ .require_features(wgt::Features::TIMESTAMP_QUERY_INSIDE_ENCODERS)?;
+
let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
diff --git a/third_party/rust/wgpu-core/src/command/render.rs b/third_party/rust/wgpu-core/src/command/render.rs
index d3de3e26e1..9141ddb021 100644
--- a/third_party/rust/wgpu-core/src/command/render.rs
+++ b/third_party/rust/wgpu-core/src/command/render.rs
@@ -22,7 +22,7 @@ use crate::{
hal_label, id,
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
pipeline::{self, PipelineFlags},
- resource::{Buffer, QuerySet, Texture, TextureView, TextureViewNotRenderableReason},
+ resource::{QuerySet, Texture, TextureView, TextureViewNotRenderableReason},
storage::Storage,
track::{TextureSelector, Tracker, UsageConflict, UsageScope},
validation::{
@@ -531,6 +531,8 @@ pub enum ColorAttachmentError {
InvalidFormat(wgt::TextureFormat),
#[error("The number of color attachments {given} exceeds the limit {limit}")]
TooMany { given: usize, limit: usize },
+ #[error("The total number of bytes per sample in color attachments {total} exceeds the limit {limit}")]
+ TooManyBytesPerSample { total: u32, limit: u32 },
}
/// Error encountered when performing a render pass.
@@ -799,8 +801,6 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
texture_memory_actions: &mut CommandBufferTextureMemoryActions<A>,
pending_query_resets: &mut QueryResetMap<A>,
view_guard: &'a Storage<TextureView<A>>,
- buffer_guard: &'a Storage<Buffer<A>>,
- texture_guard: &'a Storage<Texture<A>>,
query_set_guard: &'a Storage<QuerySet<A>>,
snatch_guard: &SnatchGuard<'a>,
) -> Result<Self, RenderPassErrorInner> {
@@ -1214,7 +1214,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
Ok(Self {
context,
- usage_scope: UsageScope::new(buffer_guard, texture_guard),
+ usage_scope: UsageScope::new(&device.tracker_indices),
render_attachments,
is_depth_read_only,
is_stencil_read_only,
@@ -1386,7 +1386,6 @@ impl Global {
let render_pipeline_guard = hub.render_pipelines.read();
let query_set_guard = hub.query_sets.read();
let buffer_guard = hub.buffers.read();
- let texture_guard = hub.textures.read();
let view_guard = hub.texture_views.read();
log::trace!(
@@ -1406,24 +1405,21 @@ impl Global {
texture_memory_actions,
pending_query_resets,
&*view_guard,
- &*buffer_guard,
- &*texture_guard,
&*query_set_guard,
&snatch_guard,
)
.map_pass_err(pass_scope)?;
- tracker.set_size(
- Some(&*buffer_guard),
- Some(&*texture_guard),
- Some(&*view_guard),
- None,
- Some(&*bind_group_guard),
- None,
- Some(&*render_pipeline_guard),
- Some(&*bundle_guard),
- Some(&*query_set_guard),
- );
+ let indices = &device.tracker_indices;
+ tracker.buffers.set_size(indices.buffers.size());
+ tracker.textures.set_size(indices.textures.size());
+ tracker.views.set_size(indices.texture_views.size());
+ tracker.bind_groups.set_size(indices.bind_groups.size());
+ tracker
+ .render_pipelines
+ .set_size(indices.render_pipelines.size());
+ tracker.bundles.set_size(indices.bundles.size());
+ tracker.query_sets.set_size(indices.query_sets.size());
let raw = &mut encoder.raw;
@@ -1675,7 +1671,7 @@ impl Global {
return Err(DeviceError::WrongDevice).map_pass_err(scope);
}
- check_buffer_usage(buffer.usage, BufferUsages::INDEX)
+ check_buffer_usage(buffer_id, buffer.usage, BufferUsages::INDEX)
.map_pass_err(scope)?;
let buf_raw = buffer
.raw
@@ -1737,7 +1733,7 @@ impl Global {
.map_pass_err(scope);
}
- check_buffer_usage(buffer.usage, BufferUsages::VERTEX)
+ check_buffer_usage(buffer_id, buffer.usage, BufferUsages::VERTEX)
.map_pass_err(scope)?;
let buf_raw = buffer
.raw
@@ -2034,8 +2030,12 @@ impl Global {
.buffers
.merge_single(&*buffer_guard, buffer_id, hal::BufferUses::INDIRECT)
.map_pass_err(scope)?;
- check_buffer_usage(indirect_buffer.usage, BufferUsages::INDIRECT)
- .map_pass_err(scope)?;
+ check_buffer_usage(
+ buffer_id,
+ indirect_buffer.usage,
+ BufferUsages::INDIRECT,
+ )
+ .map_pass_err(scope)?;
let indirect_raw = indirect_buffer
.raw
.get(&snatch_guard)
@@ -2106,8 +2106,12 @@ impl Global {
.buffers
.merge_single(&*buffer_guard, buffer_id, hal::BufferUses::INDIRECT)
.map_pass_err(scope)?;
- check_buffer_usage(indirect_buffer.usage, BufferUsages::INDIRECT)
- .map_pass_err(scope)?;
+ check_buffer_usage(
+ buffer_id,
+ indirect_buffer.usage,
+ BufferUsages::INDIRECT,
+ )
+ .map_pass_err(scope)?;
let indirect_raw = indirect_buffer
.raw
.get(&snatch_guard)
@@ -2123,7 +2127,7 @@ impl Global {
hal::BufferUses::INDIRECT,
)
.map_pass_err(scope)?;
- check_buffer_usage(count_buffer.usage, BufferUsages::INDIRECT)
+ check_buffer_usage(buffer_id, count_buffer.usage, BufferUsages::INDIRECT)
.map_pass_err(scope)?;
let count_raw = count_buffer
.raw