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