Skip to main content

euv_engine/renderer/descriptor/
struct.rs

1use super::*;
2
3/// Describes a 2D viewport rectangle plus optional depth range, in the same
4/// pixel space as the destination render target.
5///
6/// Used by [`WebGpuRenderer::set_viewport`] (and any future caller that needs
7/// to push a `GpuViewport`-shaped JS object through `Reflect::set`). The
8/// depth-range fields are omitted from the `::new` constructor via
9/// `#[new(skip)]`; they default to zero-initialised `f32` and are typically
10/// overwritten by [`WebGpuRenderer::set_viewport`] to the WebGPU spec
11/// defaults of `0.0` / `1.0`.
12#[derive(Clone, Copy, Data, Debug, New, PartialEq)]
13pub struct ViewportDescriptor {
14    /// X coordinate of the viewport's top-left in pixels.
15    pub(crate) x: f32,
16    /// Y coordinate of the viewport's top-left in pixels.
17    pub(crate) y: f32,
18    /// Viewport width in pixels.
19    pub(crate) width: f32,
20    /// Viewport height in pixels.
21    pub(crate) height: f32,
22    /// Minimum depth, clamped to `[0, 1]`. Set to `0.0` to disable.
23    #[new(skip)]
24    pub(crate) min_depth: f32,
25    /// Maximum depth, clamped to `[0, 1]`. Set to `1.0` to disable.
26    #[new(skip)]
27    pub(crate) max_depth: f32,
28}
29
30/// A single vertex attribute within a vertex buffer layout.
31///
32/// Mirrors the fields of `GPUVertexAttribute` exactly. The shader location
33/// is the `@location(N)` qualifier in the WGSL source. The offset is in
34/// bytes from the start of the vertex, and `format` is one of the
35/// WGSL vertex format strings (e.g. `"float32x4"`, `"unorm8x4"`).
36#[derive(Clone, Copy, Debug, Eq, Getter, Hash, New, PartialEq)]
37pub struct VertexAttribute {
38    /// The shader location the attribute maps to.
39    #[get(type(copy))]
40    pub(crate) shader_location: u32,
41    /// The byte offset from the start of the vertex.
42    #[get(type(copy))]
43    pub(crate) offset: u64,
44    /// The in-memory layout of the attribute, as one of the
45    /// [`VertexAttributeFormat`] variants. Naming it turns a wrong
46    /// format string into a compile error rather than a pipeline
47    /// validation failure at creation time.
48    #[get(type(copy))]
49    pub(crate) format: VertexAttributeFormat,
50}
51
52/// The layout of a single vertex buffer, expressed as an array stride plus
53/// a list of attributes.
54///
55/// Mirrors `GPUVertexBufferLayout` from the WebGPU spec. The renderer
56/// passes the assembled descriptor straight to `createRenderPipeline` via
57/// `Reflect`.
58#[derive(Clone, Debug, Getter, New)]
59pub struct VertexBufferLayout {
60    /// The byte stride of one vertex in the buffer.
61    #[get(type(copy))]
62    pub(crate) array_stride: u64,
63    /// Whether the buffer should be advanced per-instance (`true`) or
64    /// per-vertex (`false`).
65    #[get(type(copy))]
66    pub(crate) step_mode: VertexStepMode,
67    /// The attributes that describe how to interpret the bytes of one
68    /// vertex.
69    pub(crate) attributes: Vec<VertexAttribute>,
70}
71
72/// A 2D texture descriptor for `create_texture_2d`.
73///
74/// Defaults produce a 1x1 RGBA8 texture with `TEXTURE_BINDING | COPY_DST
75/// | COPY_SRC` usage, which is the right baseline for a sampled color
76/// texture that is uploaded to via `queue.writeTexture`. Override fields
77/// after constructing to set `mip_level_count`, `sample_count`, or
78/// different `usage` flags.
79#[derive(Clone, Debug, Getter, New)]
80pub struct Texture2DDescriptor {
81    /// The texture width in pixels. Must be > 0.
82    #[get(type(copy))]
83    pub(crate) width: u32,
84    /// The texture height in pixels. Must be > 0.
85    #[get(type(copy))]
86    pub(crate) height: u32,
87    /// The texel format, as one of the [`GpuTextureFormat`] variants.
88    #[get(type(copy))]
89    pub(crate) format: GpuTextureFormat,
90    /// The number of mip levels. `0` is treated as `1`.
91    #[get(type(copy))]
92    #[new(skip)]
93    pub(crate) mip_level_count: u32,
94    /// The number of samples per texel (`1` for non-MSAA, `4` for MSAA).
95    #[get(type(copy))]
96    #[new(skip)]
97    pub(crate) sample_count: u32,
98}
99
100/// Descriptor for `GpuTexture.createView(descriptor)`.
101///
102/// Sub-selects a single cube face / mip / array slice / depth-aspect of a
103/// texture. When you need the full texture as a 2D view (the common case),
104/// just call `create_view` without a descriptor; the new method accepts an
105/// `Option<&TextureViewDescriptor>` for callers that need the full
106/// flexibility of the WebGPU spec.
107#[derive(Clone, Debug, Getter, New)]
108pub struct TextureViewDescriptor {
109    /// View format override, or `None` to use the texture's own format.
110    #[get(type(clone))]
111    #[new(value = "None")]
112    pub(crate) format: Option<&'static str>,
113    /// View dimension (`"2d"`, `"2d-array"`, `"cube"`, `"cube-array"`, ...).
114    /// `None` means the dimension is inferred from the texture.
115    #[get(type(clone))]
116    #[new(value = "None")]
117    pub(crate) dimension: Option<&'static str>,
118    /// Most significant mip level (inclusive). `None` → `0`.
119    #[get(type(copy))]
120    #[new(value = "0")]
121    pub(crate) base_mip_level: u32,
122    /// Number of mip levels in the view. `0` → all the way to the top.
123    #[get(type(copy))]
124    #[new(value = "0")]
125    pub(crate) mip_level_count: u32,
126    /// First array layer (inclusive). `None` → `0`. Only meaningful for
127    /// `2d-array` / `cube` / `cube-array` views.
128    #[get(type(copy))]
129    #[new(value = "0")]
130    pub(crate) base_array_layer: u32,
131    /// Number of array layers. `0` → all remaining layers.
132    #[get(type(copy))]
133    #[new(value = "0")]
134    pub(crate) array_layer_count: u32,
135    /// Which aspect of the texture to expose. One of:
136    /// `"all"`, `"depth-only"`, `"stencil-only"`. `None` → `"all"`.
137    #[get(type(clone))]
138    #[new(value = "None")]
139    pub(crate) aspect: Option<&'static str>,
140}
141
142/// Descriptor for `queue.writeTexture(destination, data, dataLayout, size)`.
143///
144/// WebGPU's `writeTexture` lets you upload CPU-side pixel data directly to a
145/// texture without staging through a buffer. Use it for: ImGui font atlases,
146/// procedural noise textures, sprite sheets, `ImageBitmap` pixels, etc.
147#[derive(Clone, Debug, Getter, New)]
148pub struct TextureWriteDescriptor {
149    /// The pixel data to upload. Bytes are laid out according to
150    /// `bytes_per_row` / `rows_per_image`.
151    #[get(type(clone))]
152    pub(crate) data: Vec<u8>,
153    /// Bytes per row of the source data. Must be a multiple of 256.
154    #[get(type(copy))]
155    pub(crate) bytes_per_row: u32,
156    /// Number of rows per image. `0` for 2D textures without mip chains.
157    #[get(type(copy))]
158    pub(crate) rows_per_image: u32,
159    /// Destination mip level to write into.
160    #[get(type(copy))]
161    pub(crate) mip_level: u32,
162    /// Destination texture to write into.
163    #[get(type(clone))]
164    pub(crate) texture: JsValue,
165    /// Origin within the destination texture. `None` → `(0, 0, 0)`.
166    #[get(type(clone))]
167    #[new(value = "None")]
168    pub(crate) origin: Option<JsValue>,
169    /// Whether to flip the source data vertically before writing.
170    /// `true` is essential when uploading from `<img>` / `<canvas>` whose
171    /// rows are top-to-bottom but WebGPU textures are bottom-to-top.
172    #[get(type(copy))]
173    #[new(value = "false")]
174    pub(crate) flip_y: bool,
175}
176
177/// A single entry inside a `GpuBindGroupLayoutDescriptor`.
178///
179/// Together these describe one slot of the bind group layout used by
180/// a render / compute pipeline. The `visibility` field names the
181/// shader stages that can read the binding as [`ShaderStage`] values
182/// combined with `|`; a hand-written `0x1` / `0x2` / `0x4` there
183/// silently produced a binding the shader could not see.
184#[derive(Clone, Debug)]
185pub struct BindGroupLayoutEntry {
186    /// The binding slot (matches `@binding(N)` in the shader).
187    pub binding: u32,
188    /// The shader stages that can read this binding. Combine several
189    /// with `|`, e.g. `ShaderStage::Vertex | ShaderStage::Fragment`.
190    pub visibility: ShaderStage,
191    /// The resource kind bound at this slot.
192    pub ty: BindGroupEntryType,
193}
194
195/// A strongly-typed sampler descriptor for `create_sampler`.
196///
197/// Replaces the historical `GpuSamplerDescriptor`, which spelled the
198/// filter and address modes as six independent `&'static str` fields plus
199/// a `compare: bool`. The new layout keeps the same information but as
200/// three orthogonal decisions — how to interpolate, how to blend mip
201/// levels, how to wrap — so the combinations the old fields allowed but
202/// the renderer could not express (a `Nearest` magnification filter with a
203/// `Linear` minification filter, a comparison other than the hardcoded
204/// one) are now expressible, and an invalid value is a compile error
205/// rather than a silently rejected `createSampler` call.
206#[derive(Clone, Copy, Data, Debug, New)]
207pub struct SamplerDescriptor {
208    /// How texels are interpolated within one mip level. Applied to both
209    /// the magnification and the minification filter.
210    #[get(type(copy))]
211    #[new(skip)]
212    pub(crate) filter: FilterMode,
213    /// How results from adjacent mip levels are blended together.
214    #[get(type(copy))]
215    #[new(skip)]
216    pub(crate) mipmap_filter: MipmapFilter,
217    /// What sampling does with U coordinates outside `[0, 1]`.
218    #[get(type(copy))]
219    #[new(skip)]
220    pub(crate) address_mode_u: AddressMode,
221    /// What sampling does with V coordinates outside `[0, 1]`.
222    #[get(type(copy))]
223    #[new(skip)]
224    pub(crate) address_mode_v: AddressMode,
225    /// What sampling does with W coordinates outside `[0, 1]`. Only
226    /// meaningful for 3D textures.
227    #[get(type(copy))]
228    #[new(skip)]
229    pub(crate) address_mode_w: AddressMode,
230    /// The depth comparison to apply, or `None` for a plain filtering
231    /// sampler that performs no comparison. Strictly more expressive than
232    /// the old `compare: bool`, which could only mean "compare with the
233    /// single hardcoded comparison".
234    #[get(type(copy))]
235    #[new(skip)]
236    pub(crate) compare: Option<CompareFunction>,
237}
238
239/// One color attachment of a render pass.
240///
241/// Replaces the historical `RenderPassColorAttachment`. The two `Option<&'static str>`
242/// load and store ops disappear: a [`LoadOp`] and a [`StoreOp`] say
243/// directly what the old optional strings inferred, and a clear color is
244/// the engine's own [`Color`] rather than a bare `(f64, f64, f64, f64)`
245/// tuple whose channel order had to be re-checked at every call site.
246#[derive(Clone, Debug, Getter)]
247pub struct ColorAttachment {
248    /// The texture view to draw into, or `None` to let the renderer use
249    /// the swap-chain view (or the MSAA intermediate view when
250    /// antialiasing is on).
251    pub view: Option<JsValue>,
252    /// The destination view that a multisampled attachment resolves into,
253    /// or `None` when multisampling is disabled. The renderer substitutes
254    /// the swap-chain view when this is `None` but the attachment is
255    /// multisampled.
256    pub resolve_target: Option<JsValue>,
257    /// The color to overwrite the attachment with when `load_op` is
258    /// [`LoadOp::Clear`]. `None` means no clear, so `load_op` must then be
259    /// [`LoadOp::Load`].
260    pub clear: Option<Color>,
261    /// What to do with the attachment's existing contents before drawing.
262    pub load_op: LoadOp,
263    /// What to do with the attachment's contents once the pass ends.
264    pub store_op: StoreOp,
265}
266
267/// The depth-stencil attachment of a render pass.
268///
269/// Replaces the historical `RenderPassDepthStencilAttachment`. As with
270/// [`ColorAttachment`], the optional load and store op strings are
271/// replaced by typed ops, and the clear depth is `None`-able so that
272/// "clear to 1.0" and "keep what is there" are distinguishable at the
273/// type level rather than by which fields happen to be set.
274#[derive(Clone, Debug, Getter)]
275pub struct DepthStencilAttachment {
276    /// The depth-stencil texture view to use, or `None` to let the
277    /// renderer use the default view into its own depth texture,
278    /// allocating that texture lazily if needed.
279    pub view: Option<JsValue>,
280    /// The depth to overwrite the attachment with when `depth_load_op` is
281    /// [`LoadOp::Clear`], in `0.0..=1.0`. `None` means no clear, so
282    /// `depth_load_op` must then be [`LoadOp::Load`].
283    pub depth_clear: Option<f64>,
284    /// What to do with the existing depth before drawing.
285    pub depth_load_op: LoadOp,
286    /// What to do with the depth once the pass ends.
287    pub depth_store_op: StoreOp,
288    /// Whether the pass reads depth without writing it. `true` lets the
289    /// driver skip the depth write entirely.
290    pub depth_read_only: bool,
291}
292
293/// One channel group of a [`BlendState`]: an operation plus the factors
294/// applied to the incoming and the existing value.
295#[derive(Clone, Copy, Data, Debug, Default, New, PartialEq)]
296pub struct BlendComponent {
297    /// How the two scaled terms are combined.
298    #[get(type(copy))]
299    #[new(skip)]
300    pub(crate) operation: BlendOperation,
301    /// The factor the incoming value is multiplied by.
302    #[get(type(copy))]
303    #[new(skip)]
304    pub(crate) source: BlendFactor,
305    /// The factor the existing value is multiplied by.
306    #[get(type(copy))]
307    #[new(skip)]
308    pub(crate) destination: BlendFactor,
309}
310
311/// The full blend state of a single color target.
312///
313/// Alpha blending is `BlendComponent { operation: Add, source:
314/// SourceAlpha, destination: OneMinusSourceAlpha }` on both the color and
315/// the alpha channel; replacing the source and keeping the destination is
316/// how a fade-to-black and other multiply blends are expressed.
317#[derive(Clone, Copy, Data, Debug, Default, New)]
318pub struct BlendState {
319    /// The blend applied to the RGB channels.
320    #[get(type(copy))]
321    #[new(skip)]
322    pub(crate) color: BlendComponent,
323    /// The blend applied to the alpha channel, which is frequently not
324    /// the same as the color blend.
325    #[get(type(copy))]
326    #[new(skip)]
327    pub(crate) alpha: BlendComponent,
328}
329
330/// One entry of a fragment stage's `targets` array: the format of that
331/// color attachment and how fragments write into it.
332#[derive(Clone, Copy, Data, Debug, Default, New)]
333pub struct ColorTargetState {
334    /// The format of the color attachment this target writes to. It must
335    /// match the attachment's own format.
336    #[get(type(copy))]
337    #[new(skip)]
338    pub(crate) format: GpuTextureFormat,
339    /// The blend to apply, or `None` to overwrite the target with the
340    /// fragment's color.
341    #[get(type(copy))]
342    #[new(skip)]
343    pub(crate) blend: Option<BlendState>,
344    /// Which channels the fragment stage may write, as a bitmask:
345    /// `0x1` red, `0x2` green, `0x4` blue, `0x8` alpha. All four channels
346    /// is `0xf`; `0xf` is the right value for almost every opaque
347    /// fragment.
348    #[get(type(copy))]
349    #[new(skip)]
350    pub(crate) write_mask: u32,
351}
352
353/// The pipeline's depth-stencil state: whether depth is written, and the
354/// test fragments must pass.
355#[derive(Clone, Copy, Data, Debug, Default, New)]
356pub struct DepthStencilState {
357    /// The format of the pipeline's depth-stencil attachment. It must
358    /// match the attachment's own format.
359    #[get(type(copy))]
360    #[new(skip)]
361    pub(crate) format: GpuTextureFormat,
362    /// Whether a fragment that passes the test updates the depth buffer.
363    /// `false` is correct for a pipeline that only reads depth, such as a
364    /// transparent overlay drawn after the opaque pass.
365    #[get(type(copy))]
366    #[new(skip)]
367    pub(crate) depth_write_enabled: bool,
368    /// The comparison performed between the fragment's depth and the
369    /// stored depth.
370    #[get(type(copy))]
371    #[new(skip)]
372    pub(crate) depth_compare: CompareFunction,
373}
374
375/// The pipeline's multisample state: how many samples each pixel holds and
376/// which of them are written.
377#[derive(Clone, Copy, Data, Debug, Default, New)]
378pub struct MultisampleState {
379    /// The samples per pixel: `1` disables multisampling, `4` enables 4x
380    /// MSAA. The value must match the sample count of every color
381    /// attachment the pipeline draws into.
382    #[get(type(copy))]
383    #[new(skip)]
384    pub(crate) count: u32,
385    /// Which samples are written, as a bitmask. Leave at `0xf` to write
386    /// all four samples of a 4x pipeline.
387    #[get(type(copy))]
388    #[new(skip)]
389    pub(crate) mask: u32,
390}
391
392/// The pipeline's primitive-assembly state: how vertices become
393/// triangles, and which of those triangles survive rasterization.
394#[derive(Clone, Copy, Data, Debug, Default, New)]
395pub struct PrimitiveState {
396    /// How vertices are assembled into primitives.
397    #[get(type(copy))]
398    #[new(skip)]
399    pub(crate) topology: PrimitiveTopology,
400    /// Which winding order counts as front facing.
401    #[get(type(copy))]
402    #[new(skip)]
403    pub(crate) front_face: FrontFace,
404    /// Which faces are discarded before rasterization.
405    #[get(type(copy))]
406    #[new(skip)]
407    pub(crate) cull_mode: CullMode,
408    /// The index format for a strip topology, or `None` for a
409    /// non-stripped topology where the field does not apply.
410    #[get(type(copy))]
411    #[new(skip)]
412    pub(crate) strip_index_format: Option<IndexFormat>,
413    /// Whether fragments outside the depth range of `0.0..=1.0` survive.
414    /// `false`, the default, discards them.
415    #[get(type(copy))]
416    #[new(skip)]
417    pub(crate) unclipped_depth: bool,
418}
419
420/// The pipeline's vertex stage: which shader runs, and how the vertex
421/// buffers feed it.
422#[derive(Clone, Debug, Getter, New)]
423pub struct VertexState {
424    /// The `GpuShaderModule` compiled from WGSL source.
425    #[get(type(clone))]
426    pub(crate) module: JsValue,
427    /// The `@vertex` entry point's name inside that module.
428    #[get(type(clone))]
429    pub(crate) entry_point: String,
430    /// The layouts of the vertex buffers this stage reads. The i-th entry
431    /// matches the i-th `setVertexBuffer(i, ...)` call.
432    pub(crate) buffers: Vec<VertexBufferLayout>,
433}
434
435/// The pipeline's fragment stage: which shader runs, and how it writes to
436/// the color attachments.
437#[derive(Clone, Debug, Getter, New)]
438pub struct FragmentState {
439    /// The `GpuShaderModule` compiled from WGSL source.
440    #[get(type(clone))]
441    pub(crate) module: JsValue,
442    /// The `@fragment` entry point's name inside that module.
443    #[get(type(clone))]
444    pub(crate) entry_point: String,
445    /// One entry per color attachment, in attachment order.
446    pub(crate) targets: Vec<ColorTargetState>,
447}
448
449/// The single full-control render pipeline constructor.
450///
451/// This is the one type a caller needs for any render pipeline: the
452/// renderer assembles it into a `GpuRenderPipelineDescriptor` and hands
453/// that to `device.createRenderPipeline`. Every narrower renderer method
454/// is sugar over this struct — `create_render_pipeline` is a preset with
455/// auto layout, triangle-list topology, no culling, and a single
456/// `Rgba8Unorm` target, and `create_render_pipeline_full` is the same
457/// preset with vertex buffers and a depth-stencil state added. Reach for
458/// this type when either of those presets is too narrow, and for nothing
459/// else.
460#[derive(Clone, Debug, Getter, New)]
461pub struct RenderPipelineDescriptor {
462    /// The vertex stage, and the only stage a pipeline cannot do without.
463    pub(crate) vertex: VertexState,
464    /// How vertices are assembled and which faces are discarded.
465    pub(crate) primitive: PrimitiveState,
466    /// The depth-stencil state, or `None` for a pipeline that neither
467    /// reads nor writes depth.
468    pub(crate) depth_stencil: Option<DepthStencilState>,
469    /// The multisample state, which must match the attachments.
470    pub(crate) multisample: MultisampleState,
471    /// The fragment stage, or `None` for a pipeline that writes no color
472    /// — a depth-only prepass, for instance.
473    pub(crate) fragment: Option<FragmentState>,
474}
475
476/// A compute pipeline: one shader module and one entry point.
477///
478/// The compute counterpart of [`RenderPipelineDescriptor`], and much
479/// smaller because a compute pipeline has no vertex buffers, no
480/// attachments, and no rasterization state.
481#[derive(Clone, Debug, Getter, New)]
482pub struct ComputePipelineDescriptor {
483    /// The `GpuShaderModule` compiled from WGSL source.
484    #[get(type(clone))]
485    pub(crate) module: JsValue,
486    /// The `@compute` entry point's name inside that module.
487    #[get(type(clone))]
488    pub(crate) entry_point: String,
489}
490
491/// The general texture constructor, covering 2D, 2D-array, and 3D
492/// textures.
493///
494/// [`Texture2DDescriptor`] is the narrow preset: a single layer, a
495/// format string, and a usage string, with no label. The two fields
496/// [`TextureDescriptor`] adds on top of it are what keep it general —
497/// `dimension` selects between a 2D texture, a 2D array, and a 3D
498/// texture, and `label` names the resource in the browser's GPU debug
499/// tooling, which is the only way to tell two same-sized textures apart
500/// in a capture.
501#[derive(Clone, Debug, Getter, New)]
502pub struct TextureDescriptor {
503    /// The width in texels. Must be greater than zero.
504    #[get(type(copy))]
505    pub(crate) width: u32,
506    /// The height in texels. Must be greater than zero.
507    #[get(type(copy))]
508    pub(crate) height: u32,
509    /// The number of array layers for a `2d-array` texture, or the depth
510    /// in texels for a `3d` texture. `1` for a plain 2D texture.
511    #[get(type(copy))]
512    #[new(skip)]
513    pub(crate) depth_or_layers: u32,
514    /// The texture's dimensionality. Defaults to `"2d"`; a
515    /// `"2d-array"` or `"3d"` texture needs this set explicitly.
516    #[get(type(clone))]
517    pub(crate) dimension: &'static str,
518    /// The texel format.
519    #[get(type(copy))]
520    pub(crate) format: GpuTextureFormat,
521    /// The legal uses of this texture, as a `usage` bitmask. Combine
522    /// several [`TextureUsage`] values with `|`.
523    #[get(type(copy))]
524    pub(crate) usage: u32,
525    /// The number of mip levels. Zero is treated as one.
526    #[get(type(copy))]
527    #[new(skip)]
528    pub(crate) mip_level_count: u32,
529    /// The samples per texel: `1` for an ordinary texture, `4` for a
530    /// multisampled render target.
531    #[get(type(copy))]
532    #[new(skip)]
533    pub(crate) sample_count: u32,
534    /// A debug label shown for this texture in the browser's GPU
535    /// tooling, or `None` to leave it unnamed.
536    #[get(type(clone))]
537    #[new(skip)]
538    pub(crate) label: Option<String>,
539}
540
541/// A buffer constructor, naming both the size and the legal uses of a
542/// GPU buffer.
543///
544/// Replaces the raw `usage: u32` bitmask that `create_buffer` takes
545/// today, where a caller had to know the bit values and pass `64 | 8` by
546/// hand for a uniform-or-vertex buffer. Combine several uses with `|`.
547#[derive(Clone, Debug, Getter, New)]
548pub struct BufferDescriptor {
549    /// The size in bytes. Must be greater than zero.
550    #[get(type(copy))]
551    pub(crate) size: u64,
552    /// The legal uses of this buffer, as a `usage` bitmask. Combine
553    /// several [`BufferUsage`] values with `|`.
554    #[get(type(copy))]
555    pub(crate) usage: u32,
556    /// A debug label shown for this buffer in the browser's GPU tooling,
557    /// or `None` to leave it unnamed.
558    #[get(type(clone))]
559    #[new(skip)]
560    pub(crate) label: Option<String>,
561}
562
563/// One entry in the dynamic-offset list passed to
564/// `set_bind_group_with_dynamic_offsets`.
565///
566/// A uniform buffer that a shader declares with `hasDynamicOffset: true`
567/// can hold many independent records back to back, and the bind group
568/// picks one per draw by adding an offset. Grouping the pair into a struct
569/// keeps the two values together at the call site, where writing them as
570/// two separate positional arguments is easy to transpose.
571#[derive(Clone, Copy, Data, Debug, Default, New)]
572pub struct UniformSlice {
573    /// The byte offset of this record from the start of the bound range.
574    /// The spec requires this to be a multiple of the binding's minimum
575    /// uniform buffer offset alignment, typically 256.
576    #[get(type(copy))]
577    pub(crate) offset: u64,
578    /// The size in bytes of this record. A size of zero means "from this
579    /// offset to the end of the bound range".
580    #[get(type(copy))]
581    pub(crate) size: u64,
582}
583
584/// The five arguments of an indexed draw, as one value.
585///
586/// `drawIndexed` and `drawIndexedOffset` take these as five positional
587/// arguments today, with no named parameter in between to keep them in
588/// order and no way to leave a trailing one at its default. Grouping them
589/// makes the call self-documenting and lets a caller vary one of the five
590/// without restating the other four.
591#[derive(Clone, Copy, Data, Debug, New)]
592pub struct DrawIndexedArgs {
593    /// The number of indices to read from the bound index buffer.
594    #[get(type(copy))]
595    #[new(skip)]
596    pub(crate) index_count: u32,
597    /// How many instances of the indexed geometry to draw. `1` draws a
598    /// single instance.
599    #[get(type(copy))]
600    #[new(skip)]
601    pub(crate) instance_count: u32,
602    /// The index of the first index to read, for drawing a sub-range of
603    /// the index buffer.
604    #[get(type(copy))]
605    #[new(skip)]
606    pub(crate) first_index: u32,
607    /// The value added to every index before it is used to fetch a vertex.
608    /// Lets several meshes share one vertex buffer.
609    #[get(type(copy))]
610    #[new(skip)]
611    pub(crate) base_vertex: i32,
612    /// The first instance index, for reading per-instance attributes from
613    /// an offset.
614    #[get(type(copy))]
615    #[new(skip)]
616    pub(crate) first_instance: u32,
617}
618
619/// The four arguments of a non-indexed draw, as one value.
620///
621/// The non-indexed counterpart of [`DrawIndexedArgs`], and the same
622/// argument in the same order as `draw(vertexCount, instanceCount,
623/// firstVertex, firstInstance)`.
624#[derive(Clone, Copy, Data, Debug, New)]
625pub struct DrawArgs {
626    /// The number of vertices to draw, taken from the bound vertex buffers
627    /// as a non-indexed stream.
628    #[get(type(copy))]
629    #[new(skip)]
630    pub(crate) vertex_count: u32,
631    /// How many instances of the geometry to draw. `1` draws a single
632    /// instance.
633    #[get(type(copy))]
634    #[new(skip)]
635    pub(crate) instance_count: u32,
636    /// The vertex to start from, for drawing a sub-range of the vertex
637    /// stream.
638    #[get(type(copy))]
639    #[new(skip)]
640    pub(crate) first_vertex: u32,
641    /// The first instance index, for reading per-instance attributes from
642    /// an offset.
643    #[get(type(copy))]
644    #[new(skip)]
645    pub(crate) first_instance: u32,
646}
647
648/// The three workgroup counts of a compute dispatch, as one value.
649///
650/// `dispatch(x, y, z)` today takes these as three positional numbers
651/// whose order is easy to transpose, since `x` is the fastest-varying
652/// axis and the natural reading order of a 3D problem is `z, y, x`.
653#[derive(Clone, Copy, Data, Debug, New)]
654pub struct DispatchArgs {
655    /// The workgroups dispatched along the x axis.
656    #[get(type(copy))]
657    #[new(skip)]
658    pub(crate) x: u32,
659    /// The workgroups dispatched along the y axis.
660    #[get(type(copy))]
661    #[new(skip)]
662    pub(crate) y: u32,
663    /// The workgroups dispatched along the z axis.
664    #[get(type(copy))]
665    #[new(skip)]
666    pub(crate) z: u32,
667}