wgpu_naga_bridge/
lib.rs

1//! Conversions between [`naga`] and [`wgpu_types`].
2
3#![no_std]
4
5use naga::valid::Capabilities as Caps;
6use wgpu_types as wgt;
7
8/// Map [`wgt::Features`] and [`wgt::DownlevelFlags`] to [`naga::valid::Capabilities`].
9pub fn features_to_naga_capabilities(
10    features: wgt::Features,
11    downlevel: wgt::DownlevelFlags,
12) -> Caps {
13    let mut caps = Caps::empty();
14    caps.set(
15        Caps::IMMEDIATES,
16        features.contains(wgt::Features::IMMEDIATES),
17    );
18    caps.set(Caps::FLOAT64, features.contains(wgt::Features::SHADER_F64));
19    caps.set(
20        Caps::SHADER_FLOAT16,
21        features.contains(wgt::Features::SHADER_F16),
22    );
23    caps.set(
24        Caps::SHADER_FLOAT16_IN_FLOAT32,
25        downlevel.contains(wgt::DownlevelFlags::SHADER_F16_IN_F32),
26    );
27    caps.set(
28        Caps::SHADER_INT16,
29        features.contains(wgt::Features::SHADER_I16),
30    );
31    caps.set(
32        Caps::PRIMITIVE_INDEX,
33        features.contains(wgt::Features::PRIMITIVE_INDEX),
34    );
35    caps.set(
36        Caps::TEXTURE_AND_SAMPLER_BINDING_ARRAY,
37        features.contains(wgt::Features::TEXTURE_BINDING_ARRAY),
38    );
39    caps.set(
40        Caps::BUFFER_BINDING_ARRAY,
41        features.contains(wgt::Features::BUFFER_BINDING_ARRAY),
42    );
43    caps.set(
44        Caps::STORAGE_TEXTURE_BINDING_ARRAY,
45        features.contains(wgt::Features::TEXTURE_BINDING_ARRAY)
46            && features.contains(wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY),
47    );
48    caps.set(
49        Caps::STORAGE_BUFFER_BINDING_ARRAY,
50        features.contains(wgt::Features::BUFFER_BINDING_ARRAY)
51            && features.contains(wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY),
52    );
53    caps.set(
54        Caps::TEXTURE_AND_SAMPLER_BINDING_ARRAY_NON_UNIFORM_INDEXING,
55        features
56            .contains(wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING),
57    );
58    caps.set(
59        Caps::BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING,
60        features.contains(wgt::Features::UNIFORM_BUFFER_BINDING_ARRAYS),
61    );
62    caps.set(
63        Caps::STORAGE_TEXTURE_BINDING_ARRAY_NON_UNIFORM_INDEXING,
64        features.contains(wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING),
65    );
66    caps.set(
67        Caps::STORAGE_BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING,
68        features
69            .contains(wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING),
70    );
71    caps.set(
72        Caps::ACCELERATION_STRUCTURE_BINDING_ARRAY,
73        features.contains(wgt::Features::ACCELERATION_STRUCTURE_BINDING_ARRAY),
74    );
75    caps.set(
76        Caps::STORAGE_TEXTURE_16BIT_NORM_FORMATS,
77        features.contains(wgt::Features::TEXTURE_FORMAT_16BIT_NORM),
78    );
79    caps.set(Caps::MULTIVIEW, features.contains(wgt::Features::MULTIVIEW));
80    caps.set(
81        Caps::EARLY_DEPTH_TEST,
82        features.contains(wgt::Features::SHADER_EARLY_DEPTH_TEST),
83    );
84    caps.set(
85        Caps::SHADER_INT64,
86        features.contains(wgt::Features::SHADER_INT64),
87    );
88    caps.set(
89        Caps::SHADER_INT64_ATOMIC_MIN_MAX,
90        features.intersects(
91            wgt::Features::SHADER_INT64_ATOMIC_MIN_MAX | wgt::Features::SHADER_INT64_ATOMIC_ALL_OPS,
92        ),
93    );
94    caps.set(
95        Caps::SHADER_INT64_ATOMIC_ALL_OPS,
96        features.contains(wgt::Features::SHADER_INT64_ATOMIC_ALL_OPS),
97    );
98    caps.set(
99        Caps::TEXTURE_ATOMIC,
100        features.contains(wgt::Features::TEXTURE_ATOMIC),
101    );
102    caps.set(
103        Caps::TEXTURE_INT64_ATOMIC,
104        features.contains(wgt::Features::TEXTURE_INT64_ATOMIC),
105    );
106    caps.set(
107        Caps::SHADER_FLOAT32_ATOMIC,
108        features.contains(wgt::Features::SHADER_FLOAT32_ATOMIC),
109    );
110    caps.set(
111        Caps::MULTISAMPLED_SHADING,
112        downlevel.contains(wgt::DownlevelFlags::MULTISAMPLED_SHADING),
113    );
114    caps.set(
115        Caps::DUAL_SOURCE_BLENDING,
116        features.contains(wgt::Features::DUAL_SOURCE_BLENDING),
117    );
118    caps.set(
119        Caps::CLIP_DISTANCES,
120        features.contains(wgt::Features::CLIP_DISTANCES),
121    );
122    caps.set(
123        Caps::CUBE_ARRAY_TEXTURES,
124        downlevel.contains(wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES),
125    );
126    caps.set(
127        Caps::SUBGROUP,
128        features.intersects(wgt::Features::SUBGROUP | wgt::Features::SUBGROUP_VERTEX),
129    );
130    caps.set(
131        Caps::SUBGROUP_BARRIER,
132        features.intersects(wgt::Features::SUBGROUP_BARRIER),
133    );
134    caps.set(
135        Caps::RAY_QUERY,
136        features.intersects(wgt::Features::EXPERIMENTAL_RAY_QUERY),
137    );
138    caps.set(
139        Caps::SUBGROUP_VERTEX_STAGE,
140        features.contains(wgt::Features::SUBGROUP_VERTEX),
141    );
142    caps.set(
143        Caps::RAY_HIT_VERTEX_POSITION,
144        features.intersects(wgt::Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN),
145    );
146    caps.set(
147        Caps::TEXTURE_EXTERNAL,
148        features.intersects(wgt::Features::EXTERNAL_TEXTURE),
149    );
150    caps.set(
151        Caps::SHADER_BARYCENTRICS,
152        features.intersects(wgt::Features::SHADER_BARYCENTRICS),
153    );
154    caps.set(
155        Caps::MESH_SHADER,
156        features.intersects(wgt::Features::EXPERIMENTAL_MESH_SHADER),
157    );
158    caps.set(
159        Caps::MESH_SHADER_POINT_TOPOLOGY,
160        features.intersects(wgt::Features::EXPERIMENTAL_MESH_SHADER_POINTS),
161    );
162    caps.set(
163        Caps::COOPERATIVE_MATRIX,
164        features.intersects(wgt::Features::EXPERIMENTAL_COOPERATIVE_MATRIX),
165    );
166    caps.set(
167        Caps::PER_VERTEX,
168        features.intersects(wgt::Features::SHADER_PER_VERTEX),
169    );
170    caps.set(
171        Caps::DRAW_INDEX,
172        features.intersects(wgt::Features::SHADER_DRAW_INDEX),
173    );
174    caps.set(
175        Caps::MEMORY_DECORATION_COHERENT,
176        features.contains(wgt::Features::MEMORY_DECORATION_COHERENT),
177    );
178    caps.set(
179        Caps::MEMORY_DECORATION_VOLATILE,
180        features.contains(wgt::Features::MEMORY_DECORATION_VOLATILE),
181    );
182    caps
183}
184
185/// Create a [`naga::valid::Validator`] configured for the given feature set.
186pub fn create_validator(
187    features: wgt::Features,
188    downlevel: wgt::DownlevelFlags,
189    flags: naga::valid::ValidationFlags,
190) -> naga::valid::Validator {
191    let caps = features_to_naga_capabilities(features, downlevel);
192    naga::valid::Validator::new(flags, caps)
193}
194
195/// Map a [`wgt::TextureFormat`] to the corresponding [`naga::StorageFormat`], if any.
196pub fn map_storage_format_to_naga(format: wgt::TextureFormat) -> Option<naga::StorageFormat> {
197    use naga::StorageFormat as Sf;
198    use wgt::TextureFormat as Tf;
199
200    Some(match format {
201        Tf::R8Unorm => Sf::R8Unorm,
202        Tf::R8Snorm => Sf::R8Snorm,
203        Tf::R8Uint => Sf::R8Uint,
204        Tf::R8Sint => Sf::R8Sint,
205
206        Tf::R16Uint => Sf::R16Uint,
207        Tf::R16Sint => Sf::R16Sint,
208        Tf::R16Float => Sf::R16Float,
209        Tf::Rg8Unorm => Sf::Rg8Unorm,
210        Tf::Rg8Snorm => Sf::Rg8Snorm,
211        Tf::Rg8Uint => Sf::Rg8Uint,
212        Tf::Rg8Sint => Sf::Rg8Sint,
213
214        Tf::R32Uint => Sf::R32Uint,
215        Tf::R32Sint => Sf::R32Sint,
216        Tf::R32Float => Sf::R32Float,
217        Tf::Rg16Uint => Sf::Rg16Uint,
218        Tf::Rg16Sint => Sf::Rg16Sint,
219        Tf::Rg16Float => Sf::Rg16Float,
220        Tf::Rgba8Unorm => Sf::Rgba8Unorm,
221        Tf::Rgba8Snorm => Sf::Rgba8Snorm,
222        Tf::Rgba8Uint => Sf::Rgba8Uint,
223        Tf::Rgba8Sint => Sf::Rgba8Sint,
224        Tf::Bgra8Unorm => Sf::Bgra8Unorm,
225
226        Tf::Rgb10a2Uint => Sf::Rgb10a2Uint,
227        Tf::Rgb10a2Unorm => Sf::Rgb10a2Unorm,
228        Tf::Rg11b10Ufloat => Sf::Rg11b10Ufloat,
229
230        Tf::R64Uint => Sf::R64Uint,
231        Tf::Rg32Uint => Sf::Rg32Uint,
232        Tf::Rg32Sint => Sf::Rg32Sint,
233        Tf::Rg32Float => Sf::Rg32Float,
234        Tf::Rgba16Uint => Sf::Rgba16Uint,
235        Tf::Rgba16Sint => Sf::Rgba16Sint,
236        Tf::Rgba16Float => Sf::Rgba16Float,
237
238        Tf::Rgba32Uint => Sf::Rgba32Uint,
239        Tf::Rgba32Sint => Sf::Rgba32Sint,
240        Tf::Rgba32Float => Sf::Rgba32Float,
241
242        Tf::R16Unorm => Sf::R16Unorm,
243        Tf::R16Snorm => Sf::R16Snorm,
244        Tf::Rg16Unorm => Sf::Rg16Unorm,
245        Tf::Rg16Snorm => Sf::Rg16Snorm,
246        Tf::Rgba16Unorm => Sf::Rgba16Unorm,
247        Tf::Rgba16Snorm => Sf::Rgba16Snorm,
248
249        _ => return None,
250    })
251}
252
253/// Map a [`naga::StorageFormat`] to the corresponding [`wgt::TextureFormat`].
254pub fn map_storage_format_from_naga(format: naga::StorageFormat) -> wgt::TextureFormat {
255    use naga::StorageFormat as Sf;
256    use wgt::TextureFormat as Tf;
257
258    match format {
259        Sf::R8Unorm => Tf::R8Unorm,
260        Sf::R8Snorm => Tf::R8Snorm,
261        Sf::R8Uint => Tf::R8Uint,
262        Sf::R8Sint => Tf::R8Sint,
263
264        Sf::R16Uint => Tf::R16Uint,
265        Sf::R16Sint => Tf::R16Sint,
266        Sf::R16Float => Tf::R16Float,
267        Sf::Rg8Unorm => Tf::Rg8Unorm,
268        Sf::Rg8Snorm => Tf::Rg8Snorm,
269        Sf::Rg8Uint => Tf::Rg8Uint,
270        Sf::Rg8Sint => Tf::Rg8Sint,
271
272        Sf::R32Uint => Tf::R32Uint,
273        Sf::R32Sint => Tf::R32Sint,
274        Sf::R32Float => Tf::R32Float,
275        Sf::Rg16Uint => Tf::Rg16Uint,
276        Sf::Rg16Sint => Tf::Rg16Sint,
277        Sf::Rg16Float => Tf::Rg16Float,
278        Sf::Rgba8Unorm => Tf::Rgba8Unorm,
279        Sf::Rgba8Snorm => Tf::Rgba8Snorm,
280        Sf::Rgba8Uint => Tf::Rgba8Uint,
281        Sf::Rgba8Sint => Tf::Rgba8Sint,
282        Sf::Bgra8Unorm => Tf::Bgra8Unorm,
283
284        Sf::Rgb10a2Uint => Tf::Rgb10a2Uint,
285        Sf::Rgb10a2Unorm => Tf::Rgb10a2Unorm,
286        Sf::Rg11b10Ufloat => Tf::Rg11b10Ufloat,
287
288        Sf::R64Uint => Tf::R64Uint,
289        Sf::Rg32Uint => Tf::Rg32Uint,
290        Sf::Rg32Sint => Tf::Rg32Sint,
291        Sf::Rg32Float => Tf::Rg32Float,
292        Sf::Rgba16Uint => Tf::Rgba16Uint,
293        Sf::Rgba16Sint => Tf::Rgba16Sint,
294        Sf::Rgba16Float => Tf::Rgba16Float,
295
296        Sf::Rgba32Uint => Tf::Rgba32Uint,
297        Sf::Rgba32Sint => Tf::Rgba32Sint,
298        Sf::Rgba32Float => Tf::Rgba32Float,
299
300        Sf::R16Unorm => Tf::R16Unorm,
301        Sf::R16Snorm => Tf::R16Snorm,
302        Sf::Rg16Unorm => Tf::Rg16Unorm,
303        Sf::Rg16Snorm => Tf::Rg16Snorm,
304        Sf::Rgba16Unorm => Tf::Rgba16Unorm,
305        Sf::Rgba16Snorm => Tf::Rgba16Snorm,
306    }
307}
308
309/// Map a [`naga::ShaderStage`] to the corresponding [`wgt::ShaderStages`] flag.
310pub fn map_naga_stage(stage: naga::ShaderStage) -> wgt::ShaderStages {
311    match stage {
312        naga::ShaderStage::Vertex => wgt::ShaderStages::VERTEX,
313        naga::ShaderStage::Fragment => wgt::ShaderStages::FRAGMENT,
314        naga::ShaderStage::Compute => wgt::ShaderStages::COMPUTE,
315        naga::ShaderStage::Task => wgt::ShaderStages::TASK,
316        naga::ShaderStage::Mesh => wgt::ShaderStages::MESH,
317        naga::ShaderStage::RayGeneration => wgt::ShaderStages::RAY_GENERATION,
318        naga::ShaderStage::AnyHit => wgt::ShaderStages::ANY_HIT,
319        naga::ShaderStage::ClosestHit => wgt::ShaderStages::CLOSEST_HIT,
320        naga::ShaderStage::Miss => wgt::ShaderStages::MISS,
321    }
322}