mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Unify set push constants.
This commit is contained in:
parent
acd8cb18bb
commit
afa96af76f
@ -1315,7 +1315,7 @@ impl State {
|
||||
fn pipeline(&self) -> Result<&PipelineState, RenderBundleErrorInner> {
|
||||
self.pipeline
|
||||
.as_ref()
|
||||
.ok_or(DrawError::MissingPipeline.into())
|
||||
.ok_or(DrawError::MissingPipeline(pass::MissingPipeline).into())
|
||||
}
|
||||
|
||||
/// Mark all non-empty bind group table entries from `index` onwards as dirty.
|
||||
|
||||
@ -114,7 +114,7 @@ type ArcComputePassDescriptor<'a> = ComputePassDescriptor<'a, ArcPassTimestampWr
|
||||
#[non_exhaustive]
|
||||
pub enum DispatchError {
|
||||
#[error("Compute pipeline must be set")]
|
||||
MissingPipeline,
|
||||
MissingPipeline(pass::MissingPipeline),
|
||||
#[error(transparent)]
|
||||
IncompatibleBindGroup(#[from] Box<BinderError>),
|
||||
#[error(
|
||||
@ -176,6 +176,9 @@ pub enum ComputePassErrorInner {
|
||||
InvalidResource(#[from] InvalidResourceError),
|
||||
#[error(transparent)]
|
||||
TimestampWrites(#[from] TimestampWritesError),
|
||||
// This one is unreachable, but required for generic pass support
|
||||
#[error(transparent)]
|
||||
InvalidValuesOffset(#[from] pass::InvalidValuesOffset),
|
||||
}
|
||||
|
||||
/// Error encountered when performing a compute pass, stored for later reporting
|
||||
@ -188,6 +191,12 @@ pub struct ComputePassError {
|
||||
pub(super) inner: ComputePassErrorInner,
|
||||
}
|
||||
|
||||
impl From<pass::MissingPipeline> for ComputePassErrorInner {
|
||||
fn from(value: pass::MissingPipeline) -> Self {
|
||||
Self::Dispatch(DispatchError::MissingPipeline(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> MapPassErr<ComputePassError> for E
|
||||
where
|
||||
E: Into<ComputePassErrorInner>,
|
||||
@ -223,7 +232,7 @@ impl<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder>
|
||||
self.general.binder.check_late_buffer_bindings()?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DispatchError::MissingPipeline)
|
||||
Err(DispatchError::MissingPipeline(pass::MissingPipeline))
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,12 +609,21 @@ impl Global {
|
||||
values_offset,
|
||||
} => {
|
||||
let scope = PassErrorScope::SetPushConstant;
|
||||
set_push_constant(
|
||||
&mut state,
|
||||
pass::set_push_constant::<ComputePassErrorInner, _>(
|
||||
&mut state.general,
|
||||
&base.push_constant_data,
|
||||
wgt::ShaderStages::COMPUTE,
|
||||
offset,
|
||||
size_bytes,
|
||||
values_offset,
|
||||
Some(values_offset),
|
||||
|data_slice| {
|
||||
let offset_in_elements =
|
||||
(offset / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
let size_in_elements =
|
||||
(size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
state.push_constants[offset_in_elements..][..size_in_elements]
|
||||
.copy_from_slice(data_slice);
|
||||
},
|
||||
)
|
||||
.map_pass_err(scope)?;
|
||||
}
|
||||
@ -735,7 +753,6 @@ fn set_pipeline(
|
||||
pass::rebind_resources::<ComputePassErrorInner, _>(
|
||||
&mut state.general,
|
||||
&pipeline.layout,
|
||||
wgt::ShaderStages::COMPUTE,
|
||||
&pipeline.late_sized_buffer_groups,
|
||||
|| {
|
||||
// This only needs to be here for compute pipelines because they use push constants for
|
||||
@ -757,48 +774,6 @@ fn set_pipeline(
|
||||
)
|
||||
}
|
||||
|
||||
fn set_push_constant(
|
||||
state: &mut State,
|
||||
push_constant_data: &[u32],
|
||||
offset: u32,
|
||||
size_bytes: u32,
|
||||
values_offset: u32,
|
||||
) -> Result<(), ComputePassErrorInner> {
|
||||
let end_offset_bytes = offset + size_bytes;
|
||||
let values_end_offset = (values_offset + size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
let data_slice = &push_constant_data[(values_offset as usize)..values_end_offset];
|
||||
|
||||
let pipeline_layout = state
|
||||
.general
|
||||
.binder
|
||||
.pipeline_layout
|
||||
.as_ref()
|
||||
// TODO: don't error here, lazily update the push constants using `state.push_constants`
|
||||
.ok_or(ComputePassErrorInner::Dispatch(
|
||||
DispatchError::MissingPipeline,
|
||||
))?;
|
||||
|
||||
pipeline_layout.validate_push_constant_ranges(
|
||||
wgt::ShaderStages::COMPUTE,
|
||||
offset,
|
||||
end_offset_bytes,
|
||||
)?;
|
||||
|
||||
let offset_in_elements = (offset / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
let size_in_elements = (size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
state.push_constants[offset_in_elements..][..size_in_elements].copy_from_slice(data_slice);
|
||||
|
||||
unsafe {
|
||||
state.general.raw_encoder.set_push_constants(
|
||||
pipeline_layout.raw(),
|
||||
wgt::ShaderStages::COMPUTE,
|
||||
offset,
|
||||
data_slice,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dispatch(state: &mut State, groups: [u32; 3]) -> Result<(), ComputePassErrorInner> {
|
||||
state.is_ready()?;
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ pub enum DrawError {
|
||||
#[error("Blend constant needs to be set")]
|
||||
MissingBlendConstant,
|
||||
#[error("Render pipeline must be set")]
|
||||
MissingPipeline,
|
||||
MissingPipeline(#[from] pass::MissingPipeline),
|
||||
#[error("Currently set {pipeline} requires vertex buffer {index} to be set")]
|
||||
MissingVertexBuffer {
|
||||
pipeline: ResourceErrorIdent,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! Generic pass functions that both compute and render passes need.
|
||||
|
||||
use crate::binding_model::{BindError, BindGroup};
|
||||
use crate::binding_model::{BindError, BindGroup, PushConstantUploadError};
|
||||
use crate::command::bind::Binder;
|
||||
use crate::command::memory_init::{CommandBufferTextureMemoryActions, SurfacesInDiscardState};
|
||||
use crate::command::CommandBuffer;
|
||||
@ -26,6 +26,14 @@ pub struct BindGroupIndexOutOfRange {
|
||||
pub max: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Pipeline must be set")]
|
||||
pub struct MissingPipeline;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Setting `values_offset` to be `None` is only for internal use in render bundles")]
|
||||
pub struct InvalidValuesOffset;
|
||||
|
||||
pub(crate) struct BaseState<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder> {
|
||||
pub(crate) device: &'cmd_buf Arc<Device>,
|
||||
|
||||
@ -163,7 +171,6 @@ where
|
||||
pub(crate) fn rebind_resources<E, F: FnOnce()>(
|
||||
state: &mut BaseState,
|
||||
pipeline_layout: &Arc<binding_model::PipelineLayout>,
|
||||
stages: wgt::ShaderStages,
|
||||
late_sized_buffer_groups: &[LateSizedBufferGroup],
|
||||
f: F,
|
||||
) -> Result<(), E>
|
||||
@ -209,7 +216,7 @@ where
|
||||
super::push_constant_clear(offset, size_bytes, |clear_offset, clear_data| unsafe {
|
||||
state.raw_encoder.set_push_constants(
|
||||
pipeline_layout.raw(),
|
||||
stages,
|
||||
range.stages,
|
||||
clear_offset,
|
||||
clear_data,
|
||||
);
|
||||
@ -218,3 +225,41 @@ where
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn set_push_constant<E, F: FnOnce(&[u32])>(
|
||||
state: &mut BaseState,
|
||||
push_constant_data: &[u32],
|
||||
stages: wgt::ShaderStages,
|
||||
offset: u32,
|
||||
size_bytes: u32,
|
||||
values_offset: Option<u32>,
|
||||
f: F,
|
||||
) -> Result<(), E>
|
||||
where
|
||||
E: From<PushConstantUploadError> + From<InvalidValuesOffset> + From<MissingPipeline>,
|
||||
{
|
||||
api_log!("Pass::set_push_constants");
|
||||
|
||||
let values_offset = values_offset.ok_or(InvalidValuesOffset)?;
|
||||
|
||||
let end_offset_bytes = offset + size_bytes;
|
||||
let values_end_offset = (values_offset + size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
let data_slice = &push_constant_data[(values_offset as usize)..values_end_offset];
|
||||
|
||||
let pipeline_layout = state
|
||||
.binder
|
||||
.pipeline_layout
|
||||
.as_ref()
|
||||
.ok_or(MissingPipeline)?;
|
||||
|
||||
pipeline_layout.validate_push_constant_ranges(stages, offset, end_offset_bytes)?;
|
||||
|
||||
f(data_slice);
|
||||
|
||||
unsafe {
|
||||
state
|
||||
.raw_encoder
|
||||
.set_push_constants(pipeline_layout.raw(), stages, offset, data_slice)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ use super::{
|
||||
};
|
||||
use super::{DrawKind, Rect};
|
||||
|
||||
use crate::binding_model::BindError;
|
||||
use crate::binding_model::{BindError, PushConstantUploadError};
|
||||
pub use wgt::{LoadOp, StoreOp};
|
||||
|
||||
fn load_hal_ops<V>(load: LoadOp<V>) -> hal::AttachmentOps {
|
||||
@ -559,7 +559,7 @@ impl<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder>
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DrawError::MissingPipeline)
|
||||
Err(DrawError::MissingPipeline(pass::MissingPipeline))
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,8 +700,8 @@ pub enum RenderPassErrorInner {
|
||||
InvalidDepthOps,
|
||||
#[error("Unable to clear non-present/read-only stencil")]
|
||||
InvalidStencilOps,
|
||||
#[error("Setting `values_offset` to be `None` is only for internal use in render bundles")]
|
||||
InvalidValuesOffset,
|
||||
#[error(transparent)]
|
||||
InvalidValuesOffset(#[from] pass::InvalidValuesOffset),
|
||||
#[error(transparent)]
|
||||
MissingFeatures(#[from] MissingFeatures),
|
||||
#[error(transparent)]
|
||||
@ -789,6 +789,18 @@ impl From<pass::BindGroupIndexOutOfRange> for RenderPassErrorInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pass::MissingPipeline> for RenderPassErrorInner {
|
||||
fn from(error: pass::MissingPipeline) -> Self {
|
||||
Self::Draw(DrawError::MissingPipeline(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PushConstantUploadError> for RenderPassErrorInner {
|
||||
fn from(error: PushConstantUploadError) -> Self {
|
||||
Self::RenderCommand(error.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error encountered when performing a render pass.
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("{scope}")]
|
||||
@ -1915,13 +1927,14 @@ impl Global {
|
||||
values_offset,
|
||||
} => {
|
||||
let scope = PassErrorScope::SetPushConstant;
|
||||
set_push_constant(
|
||||
&mut state,
|
||||
pass::set_push_constant::<RenderPassErrorInner, _>(
|
||||
&mut state.general,
|
||||
&base.push_constant_data,
|
||||
stages,
|
||||
offset,
|
||||
size_bytes,
|
||||
values_offset,
|
||||
|_| {},
|
||||
)
|
||||
.map_pass_err(scope)?;
|
||||
}
|
||||
@ -2238,7 +2251,6 @@ fn set_pipeline(
|
||||
pass::rebind_resources::<RenderPassErrorInner, _>(
|
||||
&mut state.general,
|
||||
&pipeline.layout,
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
&pipeline.late_sized_buffer_groups,
|
||||
|| {},
|
||||
)?;
|
||||
@ -2438,44 +2450,6 @@ fn set_viewport(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_push_constant(
|
||||
state: &mut State,
|
||||
push_constant_data: &[u32],
|
||||
stages: ShaderStages,
|
||||
offset: u32,
|
||||
size_bytes: u32,
|
||||
values_offset: Option<u32>,
|
||||
) -> Result<(), RenderPassErrorInner> {
|
||||
api_log!("RenderPass::set_push_constants");
|
||||
|
||||
let values_offset = values_offset.ok_or(RenderPassErrorInner::InvalidValuesOffset)?;
|
||||
|
||||
let end_offset_bytes = offset + size_bytes;
|
||||
let values_end_offset = (values_offset + size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
|
||||
let data_slice = &push_constant_data[(values_offset as usize)..values_end_offset];
|
||||
|
||||
let pipeline_layout = state
|
||||
.general
|
||||
.binder
|
||||
.pipeline_layout
|
||||
.as_ref()
|
||||
.ok_or(DrawError::MissingPipeline)?;
|
||||
|
||||
pipeline_layout
|
||||
.validate_push_constant_ranges(stages, offset, end_offset_bytes)
|
||||
.map_err(RenderCommandError::from)?;
|
||||
|
||||
unsafe {
|
||||
state.general.raw_encoder.set_push_constants(
|
||||
pipeline_layout.raw(),
|
||||
stages,
|
||||
offset,
|
||||
data_slice,
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_scissor(state: &mut State, rect: Rect<u32>) -> Result<(), RenderPassErrorInner> {
|
||||
api_log!("RenderPass::set_scissor_rect {rect:?}");
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user