1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use crate::{
6     command::{LoadOp, PassChannel, StoreOp},
7     pipeline::ColorStateError,
8     resource, PrivateFeatures,
9 };
10 
11 use std::convert::TryInto;
12 
map_adapter_info( info: hal::adapter::AdapterInfo, backend: wgt::Backend, ) -> wgt::AdapterInfo13 pub fn map_adapter_info(
14     info: hal::adapter::AdapterInfo,
15     backend: wgt::Backend,
16 ) -> wgt::AdapterInfo {
17     use hal::adapter::DeviceType as Dt;
18 
19     wgt::AdapterInfo {
20         name: info.name,
21         vendor: info.vendor,
22         device: info.device,
23         device_type: match info.device_type {
24             Dt::Other => wgt::DeviceType::Other,
25             Dt::IntegratedGpu => wgt::DeviceType::IntegratedGpu,
26             Dt::DiscreteGpu => wgt::DeviceType::DiscreteGpu,
27             Dt::VirtualGpu => wgt::DeviceType::VirtualGpu,
28             Dt::Cpu => wgt::DeviceType::Cpu,
29         },
30         backend,
31     }
32 }
33 
map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties)34 pub fn map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties) {
35     use hal::buffer::Usage as U;
36     use hal::memory::Properties as P;
37     use wgt::BufferUsage as W;
38 
39     let mut hal_memory = P::empty();
40     if usage.contains(W::MAP_READ) {
41         hal_memory |= P::CPU_VISIBLE | P::CPU_CACHED;
42     }
43     if usage.contains(W::MAP_WRITE) {
44         hal_memory |= P::CPU_VISIBLE;
45     }
46 
47     let mut hal_usage = U::empty();
48     if usage.contains(W::COPY_SRC) {
49         hal_usage |= U::TRANSFER_SRC;
50     }
51     if usage.contains(W::COPY_DST) {
52         hal_usage |= U::TRANSFER_DST;
53     }
54     if usage.contains(W::INDEX) {
55         hal_usage |= U::INDEX;
56     }
57     if usage.contains(W::VERTEX) {
58         hal_usage |= U::VERTEX;
59     }
60     if usage.contains(W::UNIFORM) {
61         hal_usage |= U::UNIFORM;
62     }
63     if usage.contains(W::STORAGE) {
64         hal_usage |= U::STORAGE;
65     }
66     if usage.contains(W::INDIRECT) {
67         hal_usage |= U::INDIRECT;
68     }
69 
70     (hal_usage, hal_memory)
71 }
72 
map_texture_usage( usage: wgt::TextureUsage, aspects: hal::format::Aspects, ) -> hal::image::Usage73 pub fn map_texture_usage(
74     usage: wgt::TextureUsage,
75     aspects: hal::format::Aspects,
76 ) -> hal::image::Usage {
77     use hal::image::Usage as U;
78     use wgt::TextureUsage as W;
79 
80     let mut value = U::empty();
81     if usage.contains(W::COPY_SRC) {
82         value |= U::TRANSFER_SRC;
83     }
84     if usage.contains(W::COPY_DST) {
85         value |= U::TRANSFER_DST;
86     }
87     if usage.contains(W::SAMPLED) {
88         value |= U::SAMPLED;
89     }
90     if usage.contains(W::STORAGE) {
91         value |= U::STORAGE;
92     }
93     if usage.contains(W::RENDER_ATTACHMENT) {
94         if aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
95             value |= U::DEPTH_STENCIL_ATTACHMENT;
96         } else {
97             value |= U::COLOR_ATTACHMENT;
98         }
99     }
100     // Note: TextureUsage::Present does not need to be handled explicitly
101     // TODO: HAL Transient Attachment, HAL Input Attachment
102     value
103 }
104 
map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType105 pub fn map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType {
106     use hal::pso;
107     use wgt::BindingType as Bt;
108     match binding.ty {
109         Bt::Buffer {
110             ty,
111             has_dynamic_offset,
112             min_binding_size: _,
113         } => pso::DescriptorType::Buffer {
114             ty: match ty {
115                 wgt::BufferBindingType::Uniform => pso::BufferDescriptorType::Uniform,
116                 wgt::BufferBindingType::Storage { read_only } => {
117                     pso::BufferDescriptorType::Storage { read_only }
118                 }
119             },
120             format: pso::BufferDescriptorFormat::Structured {
121                 dynamic_offset: has_dynamic_offset,
122             },
123         },
124         Bt::Sampler { .. } => pso::DescriptorType::Sampler,
125         Bt::Texture { .. } => pso::DescriptorType::Image {
126             ty: pso::ImageDescriptorType::Sampled {
127                 with_sampler: false,
128             },
129         },
130         Bt::StorageTexture { access, .. } => pso::DescriptorType::Image {
131             ty: pso::ImageDescriptorType::Storage {
132                 read_only: match access {
133                     wgt::StorageTextureAccess::ReadOnly => true,
134                     _ => false,
135                 },
136             },
137         },
138     }
139 }
140 
map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags141 pub fn map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags {
142     use hal::pso::ShaderStageFlags as H;
143     use wgt::ShaderStage as Ss;
144 
145     let mut value = H::empty();
146     if shader_stage_flags.contains(Ss::VERTEX) {
147         value |= H::VERTEX;
148     }
149     if shader_stage_flags.contains(Ss::FRAGMENT) {
150         value |= H::FRAGMENT;
151     }
152     if shader_stage_flags.contains(Ss::COMPUTE) {
153         value |= H::COMPUTE;
154     }
155     value
156 }
157 
map_hal_flags_to_shader_stage( shader_stage_flags: hal::pso::ShaderStageFlags, ) -> wgt::ShaderStage158 pub fn map_hal_flags_to_shader_stage(
159     shader_stage_flags: hal::pso::ShaderStageFlags,
160 ) -> wgt::ShaderStage {
161     use hal::pso::ShaderStageFlags as H;
162     use wgt::ShaderStage as Ss;
163 
164     let mut value = Ss::empty();
165     if shader_stage_flags.contains(H::VERTEX) {
166         value |= Ss::VERTEX;
167     }
168     if shader_stage_flags.contains(H::FRAGMENT) {
169         value |= Ss::FRAGMENT;
170     }
171     if shader_stage_flags.contains(H::COMPUTE) {
172         value |= Ss::COMPUTE;
173     }
174     value
175 }
176 
map_extent(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> hal::image::Extent177 pub fn map_extent(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> hal::image::Extent {
178     hal::image::Extent {
179         width: extent.width,
180         height: extent.height,
181         depth: match dim {
182             wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1,
183             wgt::TextureDimension::D3 => extent.depth_or_array_layers,
184         },
185     }
186 }
187 
map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal::pso::Primitive188 pub fn map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal::pso::Primitive {
189     use hal::pso::Primitive as H;
190     use wgt::PrimitiveTopology as Pt;
191     match primitive_topology {
192         Pt::PointList => H::PointList,
193         Pt::LineList => H::LineList,
194         Pt::LineStrip => H::LineStrip,
195         Pt::TriangleList => H::TriangleList,
196         Pt::TriangleStrip => H::TriangleStrip,
197     }
198 }
199 
map_color_target_state( desc: &wgt::ColorTargetState, ) -> Result<hal::pso::ColorBlendDesc, ColorStateError>200 pub fn map_color_target_state(
201     desc: &wgt::ColorTargetState,
202 ) -> Result<hal::pso::ColorBlendDesc, ColorStateError> {
203     let color_mask = desc.write_mask;
204     let blend = desc
205         .blend
206         .as_ref()
207         .map(|bs| {
208             Ok(hal::pso::BlendState {
209                 color: map_blend_component(&bs.color)?,
210                 alpha: map_blend_component(&bs.alpha)?,
211             })
212         })
213         .transpose()?;
214     Ok(hal::pso::ColorBlendDesc {
215         mask: map_color_write_flags(color_mask),
216         blend,
217     })
218 }
219 
map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask220 fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask {
221     use hal::pso::ColorMask as H;
222     use wgt::ColorWrite as Cw;
223 
224     let mut value = H::empty();
225     if flags.contains(Cw::RED) {
226         value |= H::RED;
227     }
228     if flags.contains(Cw::GREEN) {
229         value |= H::GREEN;
230     }
231     if flags.contains(Cw::BLUE) {
232         value |= H::BLUE;
233     }
234     if flags.contains(Cw::ALPHA) {
235         value |= H::ALPHA;
236     }
237     value
238 }
239 
map_blend_component( component: &wgt::BlendComponent, ) -> Result<hal::pso::BlendOp, ColorStateError>240 fn map_blend_component(
241     component: &wgt::BlendComponent,
242 ) -> Result<hal::pso::BlendOp, ColorStateError> {
243     use hal::pso::BlendOp as H;
244     use wgt::BlendOperation as Bo;
245     Ok(match *component {
246         wgt::BlendComponent {
247             operation: Bo::Add,
248             src_factor,
249             dst_factor,
250         } => H::Add {
251             src: map_blend_factor(src_factor),
252             dst: map_blend_factor(dst_factor),
253         },
254         wgt::BlendComponent {
255             operation: Bo::Subtract,
256             src_factor,
257             dst_factor,
258         } => H::Sub {
259             src: map_blend_factor(src_factor),
260             dst: map_blend_factor(dst_factor),
261         },
262         wgt::BlendComponent {
263             operation: Bo::ReverseSubtract,
264             src_factor,
265             dst_factor,
266         } => H::RevSub {
267             src: map_blend_factor(src_factor),
268             dst: map_blend_factor(dst_factor),
269         },
270         wgt::BlendComponent {
271             operation: Bo::Min,
272             src_factor: wgt::BlendFactor::One,
273             dst_factor: wgt::BlendFactor::One,
274         } => H::Min,
275         wgt::BlendComponent {
276             operation: Bo::Max,
277             src_factor: wgt::BlendFactor::One,
278             dst_factor: wgt::BlendFactor::One,
279         } => H::Max,
280         _ => return Err(ColorStateError::InvalidMinMaxBlendFactors(*component)),
281     })
282 }
283 
map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor284 fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor {
285     use hal::pso::Factor as H;
286     use wgt::BlendFactor as Bf;
287     match blend_factor {
288         Bf::Zero => H::Zero,
289         Bf::One => H::One,
290         Bf::Src => H::SrcColor,
291         Bf::OneMinusSrc => H::OneMinusSrcColor,
292         Bf::SrcAlpha => H::SrcAlpha,
293         Bf::OneMinusSrcAlpha => H::OneMinusSrcAlpha,
294         Bf::Dst => H::DstColor,
295         Bf::OneMinusDst => H::OneMinusDstColor,
296         Bf::DstAlpha => H::DstAlpha,
297         Bf::OneMinusDstAlpha => H::OneMinusDstAlpha,
298         Bf::SrcAlphaSaturated => H::SrcAlphaSaturate,
299         Bf::Constant => H::ConstColor,
300         Bf::OneMinusConstant => H::OneMinusConstColor,
301     }
302 }
303 
map_depth_stencil_state(desc: &wgt::DepthStencilState) -> hal::pso::DepthStencilDesc304 pub fn map_depth_stencil_state(desc: &wgt::DepthStencilState) -> hal::pso::DepthStencilDesc {
305     hal::pso::DepthStencilDesc {
306         depth: if desc.is_depth_enabled() {
307             Some(hal::pso::DepthTest {
308                 fun: map_compare_function(desc.depth_compare),
309                 write: desc.depth_write_enabled,
310             })
311         } else {
312             None
313         },
314         depth_bounds: false, // TODO
315         stencil: if desc.stencil.is_enabled() {
316             let s = &desc.stencil;
317             Some(hal::pso::StencilTest {
318                 faces: hal::pso::Sided {
319                     front: map_stencil_face(&s.front),
320                     back: map_stencil_face(&s.back),
321                 },
322                 read_masks: hal::pso::State::Static(hal::pso::Sided::new(s.read_mask)),
323                 write_masks: hal::pso::State::Static(hal::pso::Sided::new(s.write_mask)),
324                 reference_values: if s.needs_ref_value() {
325                     hal::pso::State::Dynamic
326                 } else {
327                     hal::pso::State::Static(hal::pso::Sided::new(0))
328                 },
329             })
330         } else {
331             None
332         },
333     }
334 }
335 
map_stencil_face(stencil_state_face_desc: &wgt::StencilFaceState) -> hal::pso::StencilFace336 fn map_stencil_face(stencil_state_face_desc: &wgt::StencilFaceState) -> hal::pso::StencilFace {
337     hal::pso::StencilFace {
338         fun: map_compare_function(stencil_state_face_desc.compare),
339         op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
340         op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op),
341         op_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
342     }
343 }
344 
map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison345 pub fn map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison {
346     use hal::pso::Comparison as H;
347     use wgt::CompareFunction as Cf;
348     match compare_function {
349         Cf::Never => H::Never,
350         Cf::Less => H::Less,
351         Cf::Equal => H::Equal,
352         Cf::LessEqual => H::LessEqual,
353         Cf::Greater => H::Greater,
354         Cf::NotEqual => H::NotEqual,
355         Cf::GreaterEqual => H::GreaterEqual,
356         Cf::Always => H::Always,
357     }
358 }
359 
map_stencil_operation(stencil_operation: wgt::StencilOperation) -> hal::pso::StencilOp360 fn map_stencil_operation(stencil_operation: wgt::StencilOperation) -> hal::pso::StencilOp {
361     use hal::pso::StencilOp as H;
362     use wgt::StencilOperation as So;
363     match stencil_operation {
364         So::Keep => H::Keep,
365         So::Zero => H::Zero,
366         So::Replace => H::Replace,
367         So::Invert => H::Invert,
368         So::IncrementClamp => H::IncrementClamp,
369         So::DecrementClamp => H::DecrementClamp,
370         So::IncrementWrap => H::IncrementWrap,
371         So::DecrementWrap => H::DecrementWrap,
372     }
373 }
374 
map_texture_format( texture_format: wgt::TextureFormat, private_features: PrivateFeatures, ) -> hal::format::Format375 pub(crate) fn map_texture_format(
376     texture_format: wgt::TextureFormat,
377     private_features: PrivateFeatures,
378 ) -> hal::format::Format {
379     use hal::format::Format as H;
380     use wgt::TextureFormat as Tf;
381     match texture_format {
382         // Normal 8 bit formats
383         Tf::R8Unorm => H::R8Unorm,
384         Tf::R8Snorm => H::R8Snorm,
385         Tf::R8Uint => H::R8Uint,
386         Tf::R8Sint => H::R8Sint,
387 
388         // Normal 16 bit formats
389         Tf::R16Uint => H::R16Uint,
390         Tf::R16Sint => H::R16Sint,
391         Tf::R16Float => H::R16Sfloat,
392         Tf::Rg8Unorm => H::Rg8Unorm,
393         Tf::Rg8Snorm => H::Rg8Snorm,
394         Tf::Rg8Uint => H::Rg8Uint,
395         Tf::Rg8Sint => H::Rg8Sint,
396 
397         // Normal 32 bit formats
398         Tf::R32Uint => H::R32Uint,
399         Tf::R32Sint => H::R32Sint,
400         Tf::R32Float => H::R32Sfloat,
401         Tf::Rg16Uint => H::Rg16Uint,
402         Tf::Rg16Sint => H::Rg16Sint,
403         Tf::Rg16Float => H::Rg16Sfloat,
404         Tf::Rgba8Unorm => H::Rgba8Unorm,
405         Tf::Rgba8UnormSrgb => H::Rgba8Srgb,
406         Tf::Rgba8Snorm => H::Rgba8Snorm,
407         Tf::Rgba8Uint => H::Rgba8Uint,
408         Tf::Rgba8Sint => H::Rgba8Sint,
409         Tf::Bgra8Unorm => H::Bgra8Unorm,
410         Tf::Bgra8UnormSrgb => H::Bgra8Srgb,
411 
412         // Packed 32 bit formats
413         Tf::Rgb10a2Unorm => H::A2r10g10b10Unorm,
414         Tf::Rg11b10Float => H::B10g11r11Ufloat,
415 
416         // Normal 64 bit formats
417         Tf::Rg32Uint => H::Rg32Uint,
418         Tf::Rg32Sint => H::Rg32Sint,
419         Tf::Rg32Float => H::Rg32Sfloat,
420         Tf::Rgba16Uint => H::Rgba16Uint,
421         Tf::Rgba16Sint => H::Rgba16Sint,
422         Tf::Rgba16Float => H::Rgba16Sfloat,
423 
424         // Normal 128 bit formats
425         Tf::Rgba32Uint => H::Rgba32Uint,
426         Tf::Rgba32Sint => H::Rgba32Sint,
427         Tf::Rgba32Float => H::Rgba32Sfloat,
428 
429         // Depth and stencil formats
430         Tf::Depth32Float => H::D32Sfloat,
431         Tf::Depth24Plus => {
432             if private_features.texture_d24 {
433                 H::X8D24Unorm
434             } else {
435                 H::D32Sfloat
436             }
437         }
438         Tf::Depth24PlusStencil8 => {
439             if private_features.texture_d24_s8 {
440                 H::D24UnormS8Uint
441             } else {
442                 H::D32SfloatS8Uint
443             }
444         }
445 
446         // BCn compressed formats
447         Tf::Bc1RgbaUnorm => H::Bc1RgbaUnorm,
448         Tf::Bc1RgbaUnormSrgb => H::Bc1RgbaSrgb,
449         Tf::Bc2RgbaUnorm => H::Bc2Unorm,
450         Tf::Bc2RgbaUnormSrgb => H::Bc2Srgb,
451         Tf::Bc3RgbaUnorm => H::Bc3Unorm,
452         Tf::Bc3RgbaUnormSrgb => H::Bc3Srgb,
453         Tf::Bc4RUnorm => H::Bc4Unorm,
454         Tf::Bc4RSnorm => H::Bc4Snorm,
455         Tf::Bc5RgUnorm => H::Bc5Unorm,
456         Tf::Bc5RgSnorm => H::Bc5Snorm,
457         Tf::Bc6hRgbSfloat => H::Bc6hSfloat,
458         Tf::Bc6hRgbUfloat => H::Bc6hUfloat,
459         Tf::Bc7RgbaUnorm => H::Bc7Unorm,
460         Tf::Bc7RgbaUnormSrgb => H::Bc7Srgb,
461 
462         // ETC compressed formats
463         Tf::Etc2RgbUnorm => H::Etc2R8g8b8Unorm,
464         Tf::Etc2RgbUnormSrgb => H::Etc2R8g8b8Srgb,
465         Tf::Etc2RgbA1Unorm => H::Etc2R8g8b8a1Unorm,
466         Tf::Etc2RgbA1UnormSrgb => H::Etc2R8g8b8a1Srgb,
467         Tf::Etc2RgbA8Unorm => H::Etc2R8g8b8a8Unorm,
468         Tf::Etc2RgbA8UnormSrgb => H::Etc2R8g8b8a8Unorm,
469         Tf::EacRUnorm => H::EacR11Unorm,
470         Tf::EacRSnorm => H::EacR11Snorm,
471         Tf::EtcRgUnorm => H::EacR11g11Unorm,
472         Tf::EtcRgSnorm => H::EacR11g11Snorm,
473 
474         // ASTC compressed formats
475         Tf::Astc4x4RgbaUnorm => H::Astc4x4Srgb,
476         Tf::Astc4x4RgbaUnormSrgb => H::Astc4x4Srgb,
477         Tf::Astc5x4RgbaUnorm => H::Astc5x4Unorm,
478         Tf::Astc5x4RgbaUnormSrgb => H::Astc5x4Srgb,
479         Tf::Astc5x5RgbaUnorm => H::Astc5x5Unorm,
480         Tf::Astc5x5RgbaUnormSrgb => H::Astc5x5Srgb,
481         Tf::Astc6x5RgbaUnorm => H::Astc6x5Unorm,
482         Tf::Astc6x5RgbaUnormSrgb => H::Astc6x5Srgb,
483         Tf::Astc6x6RgbaUnorm => H::Astc6x6Unorm,
484         Tf::Astc6x6RgbaUnormSrgb => H::Astc6x6Srgb,
485         Tf::Astc8x5RgbaUnorm => H::Astc8x5Unorm,
486         Tf::Astc8x5RgbaUnormSrgb => H::Astc8x5Srgb,
487         Tf::Astc8x6RgbaUnorm => H::Astc8x6Unorm,
488         Tf::Astc8x6RgbaUnormSrgb => H::Astc8x6Srgb,
489         Tf::Astc10x5RgbaUnorm => H::Astc10x5Unorm,
490         Tf::Astc10x5RgbaUnormSrgb => H::Astc10x5Srgb,
491         Tf::Astc10x6RgbaUnorm => H::Astc10x6Unorm,
492         Tf::Astc10x6RgbaUnormSrgb => H::Astc10x6Srgb,
493         Tf::Astc8x8RgbaUnorm => H::Astc8x8Unorm,
494         Tf::Astc8x8RgbaUnormSrgb => H::Astc8x8Srgb,
495         Tf::Astc10x8RgbaUnorm => H::Astc10x8Unorm,
496         Tf::Astc10x8RgbaUnormSrgb => H::Astc10x8Srgb,
497         Tf::Astc10x10RgbaUnorm => H::Astc10x10Unorm,
498         Tf::Astc10x10RgbaUnormSrgb => H::Astc10x10Srgb,
499         Tf::Astc12x10RgbaUnorm => H::Astc12x10Unorm,
500         Tf::Astc12x10RgbaUnormSrgb => H::Astc12x10Srgb,
501         Tf::Astc12x12RgbaUnorm => H::Astc12x12Unorm,
502         Tf::Astc12x12RgbaUnormSrgb => H::Astc12x12Srgb,
503     }
504 }
505 
map_vertex_format(vertex_format: wgt::VertexFormat) -> hal::format::Format506 pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> hal::format::Format {
507     use hal::format::Format as H;
508     use wgt::VertexFormat as Vf;
509     match vertex_format {
510         Vf::Uint8x2 => H::Rg8Uint,
511         Vf::Uint8x4 => H::Rgba8Uint,
512         Vf::Sint8x2 => H::Rg8Sint,
513         Vf::Sint8x4 => H::Rgba8Sint,
514         Vf::Unorm8x2 => H::Rg8Unorm,
515         Vf::Unorm8x4 => H::Rgba8Unorm,
516         Vf::Snorm8x2 => H::Rg8Snorm,
517         Vf::Snorm8x4 => H::Rgba8Snorm,
518         Vf::Uint16x2 => H::Rg16Uint,
519         Vf::Uint16x4 => H::Rgba16Uint,
520         Vf::Sint16x2 => H::Rg16Sint,
521         Vf::Sint16x4 => H::Rgba16Sint,
522         Vf::Unorm16x2 => H::Rg16Unorm,
523         Vf::Unorm16x4 => H::Rgba16Unorm,
524         Vf::Snorm16x2 => H::Rg16Snorm,
525         Vf::Snorm16x4 => H::Rgba16Snorm,
526         Vf::Float16x2 => H::Rg16Sfloat,
527         Vf::Float16x4 => H::Rgba16Sfloat,
528         Vf::Float32 => H::R32Sfloat,
529         Vf::Float32x2 => H::Rg32Sfloat,
530         Vf::Float32x3 => H::Rgb32Sfloat,
531         Vf::Float32x4 => H::Rgba32Sfloat,
532         Vf::Uint32 => H::R32Uint,
533         Vf::Uint32x2 => H::Rg32Uint,
534         Vf::Uint32x3 => H::Rgb32Uint,
535         Vf::Uint32x4 => H::Rgba32Uint,
536         Vf::Sint32 => H::R32Sint,
537         Vf::Sint32x2 => H::Rg32Sint,
538         Vf::Sint32x3 => H::Rgb32Sint,
539         Vf::Sint32x4 => H::Rgba32Sint,
540         Vf::Float64 => H::R64Sfloat,
541         Vf::Float64x2 => H::Rg64Sfloat,
542         Vf::Float64x3 => H::Rgb64Sfloat,
543         Vf::Float64x4 => H::Rgba64Sfloat,
544     }
545 }
546 
is_power_of_two(val: u32) -> bool547 pub fn is_power_of_two(val: u32) -> bool {
548     val != 0 && (val & (val - 1)) == 0
549 }
550 
is_valid_copy_src_texture_format(format: wgt::TextureFormat) -> bool551 pub fn is_valid_copy_src_texture_format(format: wgt::TextureFormat) -> bool {
552     use wgt::TextureFormat as Tf;
553     match format {
554         Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false,
555         _ => true,
556     }
557 }
558 
is_valid_copy_dst_texture_format(format: wgt::TextureFormat) -> bool559 pub fn is_valid_copy_dst_texture_format(format: wgt::TextureFormat) -> bool {
560     use wgt::TextureFormat as Tf;
561     match format {
562         Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false,
563         _ => true,
564     }
565 }
566 
567 pub fn map_texture_dimension_size(
568     dimension: wgt::TextureDimension,
569     wgt::Extent3d {
570         width,
571         height,
572         depth_or_array_layers,
573     }: wgt::Extent3d,
574     sample_size: u32,
575     limits: &wgt::Limits,
576 ) -> Result<hal::image::Kind, resource::TextureDimensionError> {
577     use hal::image::Kind as H;
578     use resource::{TextureDimensionError as Tde, TextureErrorDimension as Ted};
579     use wgt::TextureDimension::*;
580 
581     let layers = depth_or_array_layers.try_into().unwrap_or(!0);
582     let (kind, extent_limits, sample_limit) = match dimension {
583         D1 => (
584             H::D1(width, layers),
585             [
586                 limits.max_texture_dimension_1d,
587                 1,
588                 limits.max_texture_array_layers,
589             ],
590             1,
591         ),
592         D2 => (
593             H::D2(width, height, layers, sample_size as u8),
594             [
595                 limits.max_texture_dimension_2d,
596                 limits.max_texture_dimension_2d,
597                 limits.max_texture_array_layers,
598             ],
599             32,
600         ),
601         D3 => (
602             H::D3(width, height, depth_or_array_layers),
603             [
604                 limits.max_texture_dimension_3d,
605                 limits.max_texture_dimension_3d,
606                 limits.max_texture_dimension_3d,
607             ],
608             1,
609         ),
610     };
611 
612     for (&dim, (&given, &limit)) in [Ted::X, Ted::Y, Ted::Z].iter().zip(
613         [width, height, depth_or_array_layers]
614             .iter()
615             .zip(extent_limits.iter()),
616     ) {
617         if given == 0 {
618             return Err(Tde::Zero(dim));
619         }
620         if given > limit {
621             return Err(Tde::LimitExceeded { dim, given, limit });
622         }
623     }
624     if sample_size == 0 || sample_size > sample_limit || !is_power_of_two(sample_size) {
625         return Err(Tde::InvalidSampleCount(sample_size));
626     }
627 
628     Ok(kind)
629 }
630 
map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind631 pub fn map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind {
632     use hal::image::ViewKind as H;
633     use wgt::TextureViewDimension::*;
634     match dimension {
635         D1 => H::D1,
636         D2 => H::D2,
637         D2Array => H::D2Array,
638         Cube => H::Cube,
639         CubeArray => H::CubeArray,
640         D3 => H::D3,
641     }
642 }
643 
map_buffer_state(usage: resource::BufferUse) -> hal::buffer::State644 pub(crate) fn map_buffer_state(usage: resource::BufferUse) -> hal::buffer::State {
645     use crate::resource::BufferUse as W;
646     use hal::buffer::Access as A;
647 
648     let mut access = A::empty();
649     if usage.contains(W::MAP_READ) {
650         access |= A::HOST_READ;
651     }
652     if usage.contains(W::MAP_WRITE) {
653         access |= A::HOST_WRITE;
654     }
655     if usage.contains(W::COPY_SRC) {
656         access |= A::TRANSFER_READ;
657     }
658     if usage.contains(W::COPY_DST) {
659         access |= A::TRANSFER_WRITE;
660     }
661     if usage.contains(W::INDEX) {
662         access |= A::INDEX_BUFFER_READ;
663     }
664     if usage.contains(W::VERTEX) {
665         access |= A::VERTEX_BUFFER_READ;
666     }
667     if usage.contains(W::UNIFORM) {
668         access |= A::UNIFORM_READ | A::SHADER_READ;
669     }
670     if usage.contains(W::STORAGE_LOAD) {
671         access |= A::SHADER_READ;
672     }
673     if usage.contains(W::STORAGE_STORE) {
674         access |= A::SHADER_READ | A::SHADER_WRITE;
675     }
676     if usage.contains(W::INDIRECT) {
677         access |= A::INDIRECT_COMMAND_READ;
678     }
679 
680     access
681 }
682 
map_texture_state( usage: resource::TextureUse, aspects: hal::format::Aspects, ) -> hal::image::State683 pub(crate) fn map_texture_state(
684     usage: resource::TextureUse,
685     aspects: hal::format::Aspects,
686 ) -> hal::image::State {
687     use crate::resource::TextureUse as W;
688     use hal::image::{Access as A, Layout as L};
689 
690     let is_color = aspects.contains(hal::format::Aspects::COLOR);
691     let layout = match usage {
692         W::UNINITIALIZED => return (A::empty(), L::Undefined),
693         W::COPY_SRC => L::TransferSrcOptimal,
694         W::COPY_DST => L::TransferDstOptimal,
695         W::SAMPLED if is_color => L::ShaderReadOnlyOptimal,
696         W::ATTACHMENT_READ | W::ATTACHMENT_WRITE if is_color => L::ColorAttachmentOptimal,
697         _ if is_color => L::General,
698         W::ATTACHMENT_WRITE => L::DepthStencilAttachmentOptimal,
699         _ => L::DepthStencilReadOnlyOptimal,
700     };
701 
702     let mut access = A::empty();
703     if usage.contains(W::COPY_SRC) {
704         access |= A::TRANSFER_READ;
705     }
706     if usage.contains(W::COPY_DST) {
707         access |= A::TRANSFER_WRITE;
708     }
709     if usage.contains(W::SAMPLED) {
710         access |= A::SHADER_READ;
711     }
712     if usage.contains(W::ATTACHMENT_READ) {
713         access |= if is_color {
714             A::COLOR_ATTACHMENT_READ
715         } else {
716             A::DEPTH_STENCIL_ATTACHMENT_READ
717         };
718     }
719     if usage.contains(W::ATTACHMENT_WRITE) {
720         access |= if is_color {
721             A::COLOR_ATTACHMENT_WRITE
722         } else {
723             A::DEPTH_STENCIL_ATTACHMENT_WRITE
724         };
725     }
726     if usage.contains(W::STORAGE_LOAD) {
727         access |= A::SHADER_READ;
728     }
729     if usage.contains(W::STORAGE_STORE) {
730         access |= A::SHADER_WRITE;
731     }
732 
733     (access, layout)
734 }
735 
map_query_type(ty: &wgt::QueryType) -> (hal::query::Type, u32)736 pub fn map_query_type(ty: &wgt::QueryType) -> (hal::query::Type, u32) {
737     match *ty {
738         wgt::QueryType::PipelineStatistics(pipeline_statistics) => {
739             let mut ps = hal::query::PipelineStatistic::empty();
740             ps.set(
741                 hal::query::PipelineStatistic::VERTEX_SHADER_INVOCATIONS,
742                 pipeline_statistics
743                     .contains(wgt::PipelineStatisticsTypes::VERTEX_SHADER_INVOCATIONS),
744             );
745             ps.set(
746                 hal::query::PipelineStatistic::CLIPPING_INVOCATIONS,
747                 pipeline_statistics.contains(wgt::PipelineStatisticsTypes::CLIPPER_INVOCATIONS),
748             );
749             ps.set(
750                 hal::query::PipelineStatistic::CLIPPING_PRIMITIVES,
751                 pipeline_statistics.contains(wgt::PipelineStatisticsTypes::CLIPPER_PRIMITIVES_OUT),
752             );
753             ps.set(
754                 hal::query::PipelineStatistic::FRAGMENT_SHADER_INVOCATIONS,
755                 pipeline_statistics
756                     .contains(wgt::PipelineStatisticsTypes::FRAGMENT_SHADER_INVOCATIONS),
757             );
758             ps.set(
759                 hal::query::PipelineStatistic::COMPUTE_SHADER_INVOCATIONS,
760                 pipeline_statistics
761                     .contains(wgt::PipelineStatisticsTypes::COMPUTE_SHADER_INVOCATIONS),
762             );
763 
764             (
765                 hal::query::Type::PipelineStatistics(ps),
766                 pipeline_statistics.bits().count_ones(),
767             )
768         }
769         wgt::QueryType::Timestamp => (hal::query::Type::Timestamp, 1),
770     }
771 }
772 
map_load_store_ops<V>(channel: &PassChannel<V>) -> hal::pass::AttachmentOps773 pub fn map_load_store_ops<V>(channel: &PassChannel<V>) -> hal::pass::AttachmentOps {
774     hal::pass::AttachmentOps {
775         load: match channel.load_op {
776             LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear,
777             LoadOp::Load => hal::pass::AttachmentLoadOp::Load,
778         },
779         store: match channel.store_op {
780             StoreOp::Clear => hal::pass::AttachmentStoreOp::DontCare, //TODO!
781             StoreOp::Store => hal::pass::AttachmentStoreOp::Store,
782         },
783     }
784 }
785 
map_color_f32(color: &wgt::Color) -> hal::pso::ColorValue786 pub fn map_color_f32(color: &wgt::Color) -> hal::pso::ColorValue {
787     [
788         color.r as f32,
789         color.g as f32,
790         color.b as f32,
791         color.a as f32,
792     ]
793 }
map_color_i32(color: &wgt::Color) -> [i32; 4]794 pub fn map_color_i32(color: &wgt::Color) -> [i32; 4] {
795     [
796         color.r as i32,
797         color.g as i32,
798         color.b as i32,
799         color.a as i32,
800     ]
801 }
map_color_u32(color: &wgt::Color) -> [u32; 4]802 pub fn map_color_u32(color: &wgt::Color) -> [u32; 4] {
803     [
804         color.r as u32,
805         color.g as u32,
806         color.b as u32,
807         color.a as u32,
808     ]
809 }
810 
map_filter(filter: wgt::FilterMode) -> hal::image::Filter811 pub fn map_filter(filter: wgt::FilterMode) -> hal::image::Filter {
812     match filter {
813         wgt::FilterMode::Nearest => hal::image::Filter::Nearest,
814         wgt::FilterMode::Linear => hal::image::Filter::Linear,
815     }
816 }
817 
map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode818 pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
819     use hal::image::WrapMode as W;
820     use wgt::AddressMode as Am;
821     match address {
822         Am::ClampToEdge => W::Clamp,
823         Am::Repeat => W::Tile,
824         Am::MirrorRepeat => W::Mirror,
825         Am::ClampToBorder => W::Border,
826     }
827 }
828 
map_primitive_state_to_input_assembler( desc: &wgt::PrimitiveState, ) -> hal::pso::InputAssemblerDesc829 pub fn map_primitive_state_to_input_assembler(
830     desc: &wgt::PrimitiveState,
831 ) -> hal::pso::InputAssemblerDesc {
832     hal::pso::InputAssemblerDesc {
833         primitive: map_primitive_topology(desc.topology),
834         with_adjacency: false,
835         restart_index: desc.strip_index_format.map(map_index_format),
836     }
837 }
838 
map_primitive_state_to_rasterizer( desc: &wgt::PrimitiveState, depth_stencil: Option<&wgt::DepthStencilState>, ) -> hal::pso::Rasterizer839 pub fn map_primitive_state_to_rasterizer(
840     desc: &wgt::PrimitiveState,
841     depth_stencil: Option<&wgt::DepthStencilState>,
842 ) -> hal::pso::Rasterizer {
843     use hal::pso;
844     let depth_bias = match depth_stencil {
845         Some(dsd) if dsd.bias.is_enabled() => Some(pso::State::Static(pso::DepthBias {
846             const_factor: dsd.bias.constant as f32,
847             slope_factor: dsd.bias.slope_scale,
848             clamp: dsd.bias.clamp,
849         })),
850         _ => None,
851     };
852     pso::Rasterizer {
853         depth_clamping: desc.clamp_depth,
854         polygon_mode: match desc.polygon_mode {
855             wgt::PolygonMode::Fill => pso::PolygonMode::Fill,
856             wgt::PolygonMode::Line => pso::PolygonMode::Line,
857             wgt::PolygonMode::Point => pso::PolygonMode::Point,
858         },
859         cull_face: match desc.cull_mode {
860             None => pso::Face::empty(),
861             Some(wgt::Face::Front) => pso::Face::FRONT,
862             Some(wgt::Face::Back) => pso::Face::BACK,
863         },
864         front_face: match desc.front_face {
865             wgt::FrontFace::Ccw => pso::FrontFace::CounterClockwise,
866             wgt::FrontFace::Cw => pso::FrontFace::Clockwise,
867         },
868         depth_bias,
869         conservative: desc.conservative,
870         line_width: pso::State::Static(1.0),
871     }
872 }
873 
map_multisample_state(desc: &wgt::MultisampleState) -> hal::pso::Multisampling874 pub fn map_multisample_state(desc: &wgt::MultisampleState) -> hal::pso::Multisampling {
875     hal::pso::Multisampling {
876         rasterization_samples: desc.count as _,
877         sample_shading: None,
878         sample_mask: desc.mask,
879         alpha_coverage: desc.alpha_to_coverage_enabled,
880         alpha_to_one: false,
881     }
882 }
883 
map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType884 pub fn map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType {
885     match index_format {
886         wgt::IndexFormat::Uint16 => hal::IndexType::U16,
887         wgt::IndexFormat::Uint32 => hal::IndexType::U32,
888     }
889 }
890 
891 /// Take `value` and round it up to the nearest alignment `alignment`.
892 ///
893 /// ```text
894 /// (0, 3) -> 0
895 /// (1, 3) -> 3
896 /// (2, 3) -> 3
897 /// (3, 3) -> 3
898 /// (4, 3) -> 6
899 /// ...
align_up(value: u32, alignment: u32) -> u32900 pub fn align_up(value: u32, alignment: u32) -> u32 {
901     ((value + alignment - 1) / alignment) * alignment
902 }
903