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
196bitflags::bitflags! {
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(transparent)]
206 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
207 #[cfg_attr(feature = "serde", serde(transparent))]
208 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
209 pub struct ShaderStages: u32 {
210 /// Binding is not visible from any shader stage.
211 const NONE = 0;
212 /// Binding is visible from the vertex shader of a render pipeline.
213 const VERTEX = 1 << 0;
214 /// Binding is visible from the fragment shader of a render pipeline.
215 const FRAGMENT = 1 << 1;
216 /// Binding is visible from the compute shader of a compute pipeline.
217 const COMPUTE = 1 << 2;
218 /// Binding is visible from the vertex and fragment shaders of a render pipeline.
219 const VERTEX_FRAGMENT = Self::VERTEX.bits() | Self::FRAGMENT.bits();
220 /// Binding is visible from the task shader of a mesh pipeline.
221 const TASK = 1 << 3;
222 /// Binding is visible from the mesh shader of a mesh pipeline.
223 const MESH = 1 << 4;
224 }
225}
226
227/// Specific type of a buffer binding.
228///
229/// Corresponds to [WebGPU `GPUBufferBindingType`](
230/// https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype).
231#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
233pub enum BufferBindingType {
234 /// A buffer for uniform values.
235 ///
236 /// Example WGSL syntax:
237 /// ```rust,ignore
238 /// struct Globals {
239 /// a_uniform: vec2<f32>,
240 /// another_uniform: vec2<f32>,
241 /// }
242 /// @group(0) @binding(0)
243 /// var<uniform> globals: Globals;
244 /// ```
245 ///
246 /// Example GLSL syntax:
247 /// ```cpp,ignore
248 /// layout(std140, binding = 0)
249 /// uniform Globals {
250 /// vec2 aUniform;
251 /// vec2 anotherUniform;
252 /// };
253 /// ```
254 #[default]
255 Uniform,
256 /// A storage buffer.
257 ///
258 /// Example WGSL syntax:
259 /// ```rust,ignore
260 /// @group(0) @binding(0)
261 /// var<storage, read_write> my_element: array<vec4<f32>>;
262 /// ```
263 ///
264 /// Example GLSL syntax:
265 /// ```cpp,ignore
266 /// layout (set=0, binding=0) buffer myStorageBuffer {
267 /// vec4 myElement[];
268 /// };
269 /// ```
270 Storage {
271 /// If `true`, the buffer can only be read in the shader,
272 /// and it:
273 /// - may or may not be annotated with `read` (WGSL).
274 /// - must be annotated with `readonly` (GLSL).
275 ///
276 /// Example WGSL syntax:
277 /// ```rust,ignore
278 /// @group(0) @binding(0)
279 /// var<storage, read> my_element: array<vec4<f32>>;
280 /// ```
281 ///
282 /// Example GLSL syntax:
283 /// ```cpp,ignore
284 /// layout (set=0, binding=0) readonly buffer myStorageBuffer {
285 /// vec4 myElement[];
286 /// };
287 /// ```
288 read_only: bool,
289 },
290}
291
292/// Specific type of a sampler binding.
293///
294/// For use in [`BindingType::Sampler`].
295///
296/// Corresponds to [WebGPU `GPUSamplerBindingType`](
297/// https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype).
298#[repr(C)]
299#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
301#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
302pub enum SamplerBindingType {
303 /// The sampling result is produced based on more than a single color sample from a texture,
304 /// e.g. when bilinear interpolation is enabled.
305 Filtering,
306 /// The sampling result is produced based on a single color sample from a texture.
307 NonFiltering,
308 /// Use as a comparison sampler instead of a normal sampler.
309 /// For more info take a look at the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode>.
310 Comparison,
311}
312
313/// Describes a single binding inside a bind group.
314///
315/// Corresponds to [WebGPU `GPUBindGroupLayoutEntry`](
316/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
317#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
318#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
319pub struct BindGroupLayoutEntry {
320 /// Binding index. Must match shader index and be unique inside a `BindGroupLayout`. A binding
321 /// of index 1, would be described as `@group(0) @binding(1)` in shaders.
322 pub binding: u32,
323 /// Which shader stages can see this binding.
324 pub visibility: ShaderStages,
325 /// The type of the binding
326 pub ty: BindingType,
327 /// If the binding is an array of multiple resources. Corresponds to `binding_array<T>` in the shader.
328 ///
329 /// When this is `Some` the following validation applies:
330 /// - Size must be of value 1 or greater.
331 /// - When `ty == BindingType::Texture`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
332 /// - When `ty == BindingType::Sampler`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
333 /// - When `ty == BindingType::Buffer`, [`Features::BUFFER_BINDING_ARRAY`] must be supported.
334 /// - When `ty == BindingType::Buffer` and `ty.ty == BufferBindingType::Storage`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
335 /// - When `ty == BindingType::StorageTexture`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
336 /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `has_dynamic_offset == true`
337 /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `ty.ty == BufferBindingType::Uniform`.
338 ///
339 #[cfg_attr(feature = "serde", serde(default))]
340 pub count: Option<NonZeroU32>,
341}