wgpu_core/command/
draw.rs

1use alloc::boxed::Box;
2
3use thiserror::Error;
4
5use wgt::error::{ErrorType, WebGpuError};
6
7use super::bind::BinderError;
8use crate::command::pass;
9use crate::resource::InvalidResourceError;
10use crate::validation::InvalidWorkgroupSizeError;
11use crate::{
12    binding_model::{BindingError, ImmediateUploadError, LateMinBufferBindingSizeMismatch},
13    resource::{
14        DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError,
15        ResourceErrorIdent,
16    },
17    track::ResourceUsageCompatibilityError,
18};
19
20/// Error validating a draw call.
21#[derive(Clone, Debug, Error)]
22#[non_exhaustive]
23pub enum DrawError {
24    #[error("Blend constant needs to be set")]
25    MissingBlendConstant,
26    #[error("Render pipeline must be set")]
27    MissingPipeline(#[from] pass::MissingPipeline),
28    #[error("Currently set {pipeline} requires vertex buffer {index} to be set")]
29    MissingVertexBuffer {
30        pipeline: ResourceErrorIdent,
31        index: usize,
32    },
33    #[error("Index buffer must be set")]
34    MissingIndexBuffer,
35    #[error(transparent)]
36    IncompatibleBindGroup(#[from] Box<BinderError>),
37    #[error("Vertex {last_vertex} extends beyond limit {vertex_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Vertex` step-rate vertex buffer?")]
38    VertexBeyondLimit {
39        last_vertex: u64,
40        vertex_limit: u64,
41        slot: u32,
42    },
43    #[error("Instance {last_instance} extends beyond limit {instance_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Instance` step-rate vertex buffer?")]
44    InstanceBeyondLimit {
45        last_instance: u64,
46        instance_limit: u64,
47        slot: u32,
48    },
49    #[error("Index {last_index} extends beyond limit {index_limit}. Did you bind the correct index buffer?")]
50    IndexBeyondLimit { last_index: u64, index_limit: u64 },
51    #[error("For indexed drawing with strip topology, {pipeline}'s strip index format {strip_index_format:?} must match index buffer format {buffer_format:?}")]
52    UnmatchedStripIndexFormat {
53        pipeline: ResourceErrorIdent,
54        strip_index_format: Option<wgt::IndexFormat>,
55        buffer_format: wgt::IndexFormat,
56    },
57    #[error(transparent)]
58    BindingSizeTooSmall(#[from] LateMinBufferBindingSizeMismatch),
59    #[error(
60        "Wrong pipeline type for this draw command. Attempted to call {} draw command on {} pipeline",
61        if *wanted_mesh_pipeline {"mesh shader"} else {"standard"},
62        if *wanted_mesh_pipeline {"standard"} else {"mesh shader"},
63    )]
64    WrongPipelineType { wanted_mesh_pipeline: bool },
65    #[error(transparent)]
66    InvalidGroupSize(#[from] InvalidWorkgroupSizeError),
67    #[error(
68        "Mesh shader calls in multiview render passes require enabling the `EXPERIMENTAL_MESH_SHADER_MULTIVIEW` feature, and the highest bit ({highest_view_index}) in the multiview mask must be <= `Limits::max_multiview_view_count` ({max_multiviews})"
69    )]
70    MeshPipelineMultiviewLimitsViolated {
71        highest_view_index: u32,
72        max_multiviews: u32,
73    },
74    #[error("Not all immediate data required by the pipeline has been set via set_immediates (missing byte ranges: {missing})")]
75    MissingImmediateData {
76        missing: naga::valid::ImmediateSlots,
77    },
78    #[error("The number of bind groups + vertex buffers {given} exceeds the limit {limit}")]
79    TooManyBindGroupsPlusVertexBuffers { given: u32, limit: u32 },
80}
81
82impl WebGpuError for DrawError {
83    fn webgpu_error_type(&self) -> ErrorType {
84        ErrorType::Validation
85    }
86}
87
88/// Error encountered when encoding a render command.
89/// This is the shared error set between render bundles and passes.
90#[derive(Clone, Debug, Error)]
91#[non_exhaustive]
92pub enum RenderCommandError {
93    #[error(transparent)]
94    BindGroupIndexOutOfRange(#[from] pass::BindGroupIndexOutOfRange),
95    #[error("Vertex buffer index {index} is greater than the device's requested `max_vertex_buffers` limit {max}")]
96    VertexBufferIndexOutOfRange { index: u32, max: u32 },
97    #[error(
98        "Offset {offset} for vertex buffer in slot {slot} is not a multiple of `VERTEX_ALIGNMENT`"
99    )]
100    UnalignedVertexBuffer { slot: u32, offset: u64 },
101    #[error("Offset {offset} for index buffer is not a multiple of {alignment}")]
102    UnalignedIndexBuffer { offset: u64, alignment: usize },
103    #[error("Render pipeline targets are incompatible with render pass")]
104    IncompatiblePipelineTargets(#[from] crate::device::RenderPassCompatibilityError),
105    #[error("{0} writes to depth, while the pass has read-only depth access")]
106    IncompatibleDepthAccess(ResourceErrorIdent),
107    #[error("{0} writes to stencil, while the pass has read-only stencil access")]
108    IncompatibleStencilAccess(ResourceErrorIdent),
109    #[error(transparent)]
110    ResourceUsageCompatibility(#[from] ResourceUsageCompatibilityError),
111    #[error(transparent)]
112    DestroyedResource(#[from] DestroyedResourceError),
113    #[error(transparent)]
114    InvalidResource(#[from] InvalidResourceError),
115    #[error(transparent)]
116    MissingBufferUsage(#[from] MissingBufferUsageError),
117    #[error(transparent)]
118    MissingTextureUsage(#[from] MissingTextureUsageError),
119    #[error(transparent)]
120    ImmediateData(#[from] ImmediateUploadError),
121    #[error(transparent)]
122    BindingError(#[from] BindingError),
123    #[error("Viewport size {{ w: {w}, h: {h} }} greater than device's requested `max_texture_dimension_2d` limit {max}, or less than zero")]
124    InvalidViewportRectSize { w: f32, h: f32, max: u32 },
125    #[error("Viewport has invalid rect {rect:?} for device's requested `max_texture_dimension_2d` limit; Origin less than -2 * `max_texture_dimension_2d` ({min}), or rect extends past 2 * `max_texture_dimension_2d` - 1 ({max})")]
126    InvalidViewportRectPosition { rect: Rect<f32>, min: f32, max: f32 },
127    #[error("Viewport minDepth {0} and/or maxDepth {1} are not in [0, 1]")]
128    InvalidViewportDepth(f32, f32),
129    #[error("Scissor {0:?} is not contained in the render target {1:?}")]
130    InvalidScissorRect(Rect<u32>, wgt::Extent3d),
131    #[error("Indirect buffer offset {0:?} is not a multiple of 4")]
132    UnalignedIndirectBufferOffset(wgt::BufferAddress),
133    #[error("Indirect draw arguments of {args_size} bytes (count = {count}) starting at {offset} would overrun buffer size of {buffer_size}")]
134    IndirectBufferOverrun {
135        count: u32,
136        offset: u64,
137        args_size: u64,
138        buffer_size: u64,
139    },
140    #[error("Support for {0} is not implemented yet")]
141    Unimplemented(&'static str),
142}
143
144impl WebGpuError for RenderCommandError {
145    fn webgpu_error_type(&self) -> ErrorType {
146        match self {
147            Self::IncompatiblePipelineTargets(e) => e.webgpu_error_type(),
148            Self::ResourceUsageCompatibility(e) => e.webgpu_error_type(),
149            Self::DestroyedResource(e) => e.webgpu_error_type(),
150            Self::InvalidResource(e) => e.webgpu_error_type(),
151            Self::MissingBufferUsage(e) => e.webgpu_error_type(),
152            Self::MissingTextureUsage(e) => e.webgpu_error_type(),
153            Self::ImmediateData(e) => e.webgpu_error_type(),
154            Self::BindingError(e) => e.webgpu_error_type(),
155
156            Self::BindGroupIndexOutOfRange { .. }
157            | Self::VertexBufferIndexOutOfRange { .. }
158            | Self::UnalignedIndexBuffer { .. }
159            | Self::UnalignedVertexBuffer { .. }
160            | Self::IncompatibleDepthAccess(..)
161            | Self::IncompatibleStencilAccess(..)
162            | Self::InvalidViewportRectSize { .. }
163            | Self::InvalidViewportRectPosition { .. }
164            | Self::InvalidViewportDepth(..)
165            | Self::InvalidScissorRect(..)
166            | Self::UnalignedIndirectBufferOffset(..)
167            | Self::IndirectBufferOverrun { .. }
168            | Self::Unimplemented(..) => ErrorType::Validation,
169        }
170    }
171}
172
173#[derive(Clone, Copy, Debug, Default)]
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175pub struct Rect<T> {
176    pub x: T,
177    pub y: T,
178    pub w: T,
179    pub h: T,
180}