Skip to main content

wgpu_types/
binding.rs

1//! Bind groups and the bindings in them.
2
3use core::num::NonZeroU32;
4
5#[cfg(any(feature = "serde", test))]
6use serde::{Deserialize, Serialize};
7
8use crate::{link_to_wgpu_docs, link_to_wgpu_item, BufferSize};
9
10#[cfg(doc)]
11use crate::Features;
12
13/// Type of a binding in a [bind group layout][`BindGroupLayoutEntry`].
14///
15/// For each binding in a layout, a [`BindGroup`] must provide a [`BindingResource`] of the
16/// corresponding type.
17///
18/// Corresponds to WebGPU's mutually exclusive fields within [`GPUBindGroupLayoutEntry`](
19/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
20///
21#[doc = link_to_wgpu_item!(enum BindingResource)]
22#[doc = link_to_wgpu_item!(struct BindGroup)]
23#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub enum BindingType {
26    /// A buffer binding.
27    ///
28    /// Corresponds to [WebGPU `GPUBufferBindingLayout`](
29    /// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout).
30    Buffer {
31        /// Sub-type of the buffer binding.
32        ty: BufferBindingType,
33
34        /// Indicates that the binding has a dynamic offset.
35        ///
36        /// One offset must be passed to [`RenderPass::set_bind_group`][RPsbg]
37        /// for each dynamic binding in increasing order of binding number.
38        ///
39        #[doc = link_to_wgpu_docs!(["RPsbg"]: "struct.RenderPass.html#method.set_bind_group")]
40        #[cfg_attr(feature = "serde", serde(default))]
41        has_dynamic_offset: bool,
42
43        /// The minimum size for a [`BufferBinding`] matching this entry, in bytes.
44        ///
45        /// If this is `Some(size)`:
46        ///
47        /// - When calling [`create_bind_group`], the resource at this bind point
48        ///   must be a [`BindingResource::Buffer`] whose effective size is at
49        ///   least `size`.
50        ///
51        /// - When calling [`create_render_pipeline`] or [`create_compute_pipeline`],
52        ///   `size` must be at least the [minimum buffer binding size] for the
53        ///   shader module global at this bind point: large enough to hold the
54        ///   global's value, along with one element of a trailing runtime-sized
55        ///   array, if present.
56        ///
57        /// If this is `None`:
58        ///
59        /// - Each draw or dispatch command checks that the buffer range at this
60        ///   bind point satisfies the [minimum buffer binding size].
61        ///
62        #[doc = link_to_wgpu_item!(struct BufferBinding)]
63        #[doc = link_to_wgpu_docs!(["`create_bind_group`"]: "struct.Device.html#method.create_bind_group")]
64        #[doc = link_to_wgpu_docs!(["`BindingResource::Buffer`"]: "enum.BindingResource.html#variant.Buffer")]
65        /// [minimum buffer binding size]: https://www.w3.org/TR/webgpu/#minimum-buffer-binding-size
66        #[doc = link_to_wgpu_docs!(["`create_render_pipeline`"]: "struct.Device.html#method.create_render_pipeline")]
67        #[doc = link_to_wgpu_docs!(["`create_compute_pipeline`"]: "struct.Device.html#method.create_compute_pipeline")]
68        #[cfg_attr(feature = "serde", serde(default))]
69        min_binding_size: Option<BufferSize>,
70    },
71    /// A sampler that can be used to sample a texture.
72    ///
73    /// Example WGSL syntax:
74    /// ```rust,ignore
75    /// @group(0) @binding(0)
76    /// var s: sampler;
77    /// ```
78    ///
79    /// Example GLSL syntax:
80    /// ```cpp,ignore
81    /// layout(binding = 0)
82    /// uniform sampler s;
83    /// ```
84    ///
85    /// Corresponds to [WebGPU `GPUSamplerBindingLayout`](
86    /// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout).
87    Sampler(SamplerBindingType),
88    /// A texture binding.
89    ///
90    /// Example WGSL syntax:
91    /// ```rust,ignore
92    /// @group(0) @binding(0)
93    /// var t: texture_2d<f32>;
94    /// ```
95    ///
96    /// Example GLSL syntax:
97    /// ```cpp,ignore
98    /// layout(binding = 0)
99    /// uniform texture2D t;
100    /// ```
101    ///
102    /// Corresponds to [WebGPU `GPUTextureBindingLayout`](
103    /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout).
104    Texture {
105        /// Sample type of the texture binding.
106        sample_type: crate::TextureSampleType,
107        /// Dimension of the texture view that is going to be sampled.
108        view_dimension: crate::TextureViewDimension,
109        /// True if the texture has a sample count greater than 1. If this is true,
110        /// the texture must be declared as `texture_multisampled_2d` or
111        /// `texture_depth_multisampled_2d` in the shader, and read using `textureLoad`.
112        multisampled: bool,
113    },
114    /// A storage texture.
115    ///
116    /// Example WGSL syntax:
117    /// ```rust,ignore
118    /// @group(0) @binding(0)
119    /// var my_storage_image: texture_storage_2d<r32float, write>;
120    /// ```
121    ///
122    /// Example GLSL syntax:
123    /// ```cpp,ignore
124    /// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
125    /// ```
126    /// Note that the texture format must be specified in the shader, along with the
127    /// access mode. For WGSL, the format must be one of the enumerants in the list
128    /// of [storage texel formats](https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats).
129    ///
130    /// Corresponds to [WebGPU `GPUStorageTextureBindingLayout`](
131    /// https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout).
132    StorageTexture {
133        /// Allowed access to this texture.
134        access: crate::StorageTextureAccess,
135        /// Format of the texture.
136        format: crate::TextureFormat,
137        /// Dimension of the texture view that is going to be sampled.
138        view_dimension: crate::TextureViewDimension,
139    },
140
141    /// A ray-tracing acceleration structure binding.
142    ///
143    /// Example WGSL syntax:
144    /// ```rust,ignore
145    /// @group(0) @binding(0)
146    /// var as: acceleration_structure;
147    /// ```
148    ///
149    /// or with vertex return enabled
150    /// ```rust,ignore
151    /// @group(0) @binding(0)
152    /// var as: acceleration_structure<vertex_return>;
153    /// ```
154    ///
155    /// Example GLSL syntax:
156    /// ```cpp,ignore
157    /// layout(binding = 0)
158    /// uniform accelerationStructureEXT as;
159    /// ```
160    AccelerationStructure {
161        /// Whether this acceleration structure can be used to
162        /// create a ray query that has flag vertex return in the shader
163        ///
164        /// If enabled requires [`Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN`]
165        vertex_return: bool,
166    },
167
168    /// An external texture binding.
169    ///
170    /// Example WGSL syntax:
171    /// ```rust,ignore
172    /// @group(0) @binding(0)
173    /// var t: texture_external;
174    /// ```
175    ///
176    /// Corresponds to [WebGPU `GPUExternalTextureBindingLayout`](
177    /// https://gpuweb.github.io/gpuweb/#dictdef-gpuexternaltexturebindinglayout).
178    ///
179    /// Requires [`Features::EXTERNAL_TEXTURE`]
180    ExternalTexture,
181}
182
183impl BindingType {
184    /// Returns true for buffer bindings with dynamic offset enabled.
185    #[must_use]
186    pub fn has_dynamic_offset(&self) -> bool {
187        match *self {
188            Self::Buffer {
189                has_dynamic_offset, ..
190            } => has_dynamic_offset,
191            _ => false,
192        }
193    }
194}
195
196crate::bitflags_array! {
197    /// Describes the shader stages that a binding will be visible from.
198    ///
199    /// These can be combined so something that is visible from both vertex and fragment shaders can be defined as:
200    ///
201    /// `ShaderStages::VERTEX | ShaderStages::FRAGMENT`
202    ///
203    /// Corresponds to [WebGPU `GPUShaderStageFlags`](
204    /// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags).
205    #[repr(C)]
206    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
207    pub struct (ShaderStages, ShaderStagesBits): [u32; 2];
208
209    /// Shader stages that are defined in the WebGPU specification.
210    /// For all usages, see [`ShaderStages`].
211    ///
212    /// Corresponds to [WebGPU `GPUShaderStageFlags`](
213    /// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags).
214    #[repr(transparent)]
215    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
216    #[cfg_attr(feature = "serde", serde(transparent))]
217    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
218    pub struct ShaderStagesWebGPU features_webgpu {
219        /// Binding is not visible from any shader stage.
220        const NONE = 0;
221        /// Binding is visible from the vertex shader of a render pipeline.
222        const VERTEX = 1 << 0;
223        /// Binding is visible from the fragment shader of a render pipeline.
224        const FRAGMENT = 1 << 1;
225        /// Binding is visible from the compute shader of a compute pipeline.
226        const COMPUTE = 1 << 2;
227        /// Binding is visible from the vertex and fragment shaders of a render pipeline.
228        const VERTEX_FRAGMENT = ShaderStagesWebGPU::VERTEX.bits() | ShaderStagesWebGPU::FRAGMENT.bits();
229    }
230
231    /// Shader stages that are available in WGPU only when targeting native.
232    /// For all usages, see [`ShaderStages`].
233    #[repr(transparent)]
234    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
235    #[cfg_attr(feature = "serde", serde(transparent))]
236    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
237    pub struct ShaderStagesWGPU features_wgpu {
238        /// Binding is visible from the task shader of a mesh pipeline.
239        const TASK = 1 << 0;
240        /// Binding is visible from the mesh shader of a mesh pipeline.
241        const MESH = 1 << 1;
242        /// Binding is visible from the ray generation shader of a ray tracing pipeline.
243        const RAY_GENERATION = 1 << 2;
244        /// Binding is visible from the ray any hit shader of a ray tracing pipeline.
245        const ANY_HIT = 1 << 3;
246        /// Binding is visible from the ray closest hit shader of a ray tracing pipeline.
247        const CLOSEST_HIT = 1 << 4;
248        /// Binding is visible from the ray miss shader of a ray tracing pipeline.
249        const MISS = 1 << 5;
250    }
251}
252
253/// Specific type of a buffer binding.
254///
255/// Corresponds to [WebGPU `GPUBufferBindingType`](
256/// https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype).
257#[repr(C)]
258#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
260pub enum BufferBindingType {
261    /// A buffer for uniform values.
262    ///
263    /// Example WGSL syntax:
264    /// ```rust,ignore
265    /// struct Globals {
266    ///     a_uniform: vec2<f32>,
267    ///     another_uniform: vec2<f32>,
268    /// }
269    /// @group(0) @binding(0)
270    /// var<uniform> globals: Globals;
271    /// ```
272    ///
273    /// Example GLSL syntax:
274    /// ```cpp,ignore
275    /// layout(std140, binding = 0)
276    /// uniform Globals {
277    ///     vec2 aUniform;
278    ///     vec2 anotherUniform;
279    /// };
280    /// ```
281    #[default]
282    Uniform,
283    /// A storage buffer.
284    ///
285    /// Example WGSL syntax:
286    /// ```rust,ignore
287    /// @group(0) @binding(0)
288    /// var<storage, read_write> my_element: array<vec4<f32>>;
289    /// ```
290    ///
291    /// Example GLSL syntax:
292    /// ```cpp,ignore
293    /// layout (set=0, binding=0) buffer myStorageBuffer {
294    ///     vec4 myElement[];
295    /// };
296    /// ```
297    Storage {
298        /// If `true`, the buffer can only be read in the shader,
299        /// and it:
300        /// - may or may not be annotated with `read` (WGSL).
301        /// - must be annotated with `readonly` (GLSL).
302        ///
303        /// Example WGSL syntax:
304        /// ```rust,ignore
305        /// @group(0) @binding(0)
306        /// var<storage, read> my_element: array<vec4<f32>>;
307        /// ```
308        ///
309        /// Example GLSL syntax:
310        /// ```cpp,ignore
311        /// layout (set=0, binding=0) readonly buffer myStorageBuffer {
312        ///     vec4 myElement[];
313        /// };
314        /// ```
315        read_only: bool,
316    },
317}
318
319/// Specific type of a sampler binding.
320///
321/// For use in [`BindingType::Sampler`].
322///
323/// Corresponds to [WebGPU `GPUSamplerBindingType`](
324/// https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype).
325#[repr(C)]
326#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
329pub enum SamplerBindingType {
330    /// The sampling result is produced based on more than a single color sample from a texture,
331    /// e.g. when bilinear interpolation is enabled.
332    Filtering,
333    /// The sampling result is produced based on a single color sample from a texture.
334    NonFiltering,
335    /// Use as a comparison sampler instead of a normal sampler.
336    /// For more info take a look at the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode>.
337    Comparison,
338}
339
340/// Describes a single binding inside a bind group.
341///
342/// Corresponds to [WebGPU `GPUBindGroupLayoutEntry`](
343/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
344#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
346pub struct BindGroupLayoutEntry {
347    /// Binding index. Must match shader index and be unique inside a `BindGroupLayout`. A binding
348    /// of index 1, would be described as `@group(0) @binding(1)` in shaders.
349    pub binding: u32,
350    /// Which shader stages can see this binding.
351    pub visibility: ShaderStages,
352    /// The type of the binding
353    pub ty: BindingType,
354    /// If the binding is an array of multiple resources. Corresponds to `binding_array<T>` in the shader.
355    ///
356    /// When this is `Some` the following validation applies:
357    /// - Count must be of value 1 or greater, this corresponds to the length of the array of resources that will be bound.
358    /// - When `ty == BindingType::Texture`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
359    /// - When `ty == BindingType::Sampler`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
360    /// - When `ty == BindingType::Buffer`, [`Features::BUFFER_BINDING_ARRAY`] must be supported.
361    /// - When `ty == BindingType::Buffer` and `ty.ty == BufferBindingType::Storage`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
362    /// - When `ty == BindingType::StorageTexture`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
363    /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `has_dynamic_offset == true`
364    /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `ty.ty == BufferBindingType::Uniform`.
365    /// - If [`Features::PARTIALLY_BOUND_BINDING_ARRAY`] is enabled, the specified count becomes the upper bound instead.
366    ///
367    #[cfg_attr(feature = "serde", serde(default))]
368    pub count: Option<NonZeroU32>,
369}