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