1 use hal;
2 
3 use crate::PrivateCapabilities;
4 
5 use hal::{
6     format::{Format, Properties, Swizzle},
7     image, pass, pso,
8     pso::{Comparison, StencilOp},
9     IndexType,
10 };
11 use metal::*;
12 use std::num::NonZeroU32;
13 
14 impl PrivateCapabilities {
map_format(&self, format: Format) -> Option<MTLPixelFormat>15     pub fn map_format(&self, format: Format) -> Option<MTLPixelFormat> {
16         use self::hal::format::Format as f;
17         use metal::MTLPixelFormat::*;
18         Some(match format {
19             f::R5g6b5Unorm if self.format_b5 => B5G6R5Unorm,
20             f::R5g5b5a1Unorm if self.format_b5 => A1BGR5Unorm,
21             f::A1r5g5b5Unorm if self.format_b5 => BGR5A1Unorm,
22             f::Rgba4Unorm if self.format_b5 => ABGR4Unorm,
23             f::R8Srgb if self.format_min_srgb_channels <= 1 => R8Unorm_sRGB,
24             f::Rg8Srgb if self.format_min_srgb_channels <= 2 => RG8Unorm_sRGB,
25             f::Rgba8Srgb if self.format_min_srgb_channels <= 4 => RGBA8Unorm_sRGB,
26             f::Bgra8Srgb if self.format_min_srgb_channels <= 4 => BGRA8Unorm_sRGB,
27             f::D16Unorm if self.format_depth16unorm => Depth16Unorm,
28             f::D24UnormS8Uint if self.format_depth24_stencil8 => Depth24Unorm_Stencil8,
29             f::D32Sfloat => Depth32Float,
30             f::D32SfloatS8Uint => Depth32Float_Stencil8,
31             f::R8Unorm => R8Unorm,
32             f::R8Snorm => R8Snorm,
33             f::R8Uint => R8Uint,
34             f::R8Sint => R8Sint,
35             f::Rg8Unorm => RG8Unorm,
36             f::Rg8Snorm => RG8Snorm,
37             f::Rg8Uint => RG8Uint,
38             f::Rg8Sint => RG8Sint,
39             f::Rgba8Unorm => RGBA8Unorm,
40             f::Rgba8Snorm => RGBA8Snorm,
41             f::Rgba8Uint => RGBA8Uint,
42             f::Rgba8Sint => RGBA8Sint,
43             f::Bgra8Unorm => BGRA8Unorm,
44             f::R16Unorm => R16Unorm,
45             f::R16Snorm => R16Snorm,
46             f::R16Uint => R16Uint,
47             f::R16Sint => R16Sint,
48             f::R16Sfloat => R16Float,
49             f::Rg16Unorm => RG16Unorm,
50             f::Rg16Snorm => RG16Snorm,
51             f::Rg16Uint => RG16Uint,
52             f::Rg16Sint => RG16Sint,
53             f::Rg16Sfloat => RG16Float,
54             f::Rgba16Unorm => RGBA16Unorm,
55             f::Rgba16Snorm => RGBA16Snorm,
56             f::Rgba16Uint => RGBA16Uint,
57             f::Rgba16Sint => RGBA16Sint,
58             f::Rgba16Sfloat => RGBA16Float,
59             f::A2r10g10b10Unorm => BGR10A2Unorm,
60             f::A2b10g10r10Unorm => RGB10A2Unorm,
61             f::B10g11r11Ufloat => RG11B10Float,
62             f::E5b9g9r9Ufloat => RGB9E5Float,
63             f::R32Uint => R32Uint,
64             f::R32Sint => R32Sint,
65             f::R32Sfloat => R32Float,
66             f::Rg32Uint => RG32Uint,
67             f::Rg32Sint => RG32Sint,
68             f::Rg32Sfloat => RG32Float,
69             f::Rgba32Uint => RGBA32Uint,
70             f::Rgba32Sint => RGBA32Sint,
71             f::Rgba32Sfloat => RGBA32Float,
72             f::Bc1RgbaUnorm if self.format_bc => BC1_RGBA,
73             f::Bc1RgbaSrgb if self.format_bc => BC1_RGBA_sRGB,
74             f::Bc1RgbUnorm if self.format_bc => BC1_RGBA, //TODO?
75             f::Bc1RgbSrgb if self.format_bc => BC1_RGBA_sRGB, //TODO?
76             f::Bc2Unorm if self.format_bc => BC2_RGBA,
77             f::Bc2Srgb if self.format_bc => BC2_RGBA_sRGB,
78             f::Bc3Unorm if self.format_bc => BC3_RGBA,
79             f::Bc3Srgb if self.format_bc => BC3_RGBA_sRGB,
80             f::Bc4Unorm if self.format_bc => BC4_RUnorm,
81             f::Bc4Snorm if self.format_bc => BC4_RSnorm,
82             f::Bc5Unorm if self.format_bc => BC5_RGUnorm,
83             f::Bc5Snorm if self.format_bc => BC5_RGSnorm,
84             f::Bc6hUfloat if self.format_bc => BC6H_RGBUfloat,
85             f::Bc6hSfloat if self.format_bc => BC6H_RGBFloat,
86             f::Bc7Unorm if self.format_bc => BC7_RGBAUnorm,
87             f::Bc7Srgb if self.format_bc => BC7_RGBAUnorm_sRGB,
88             f::EacR11Unorm if self.format_eac_etc => EAC_R11Unorm,
89             f::EacR11Snorm if self.format_eac_etc => EAC_R11Snorm,
90             f::EacR11g11Unorm if self.format_eac_etc => EAC_RG11Unorm,
91             f::EacR11g11Snorm if self.format_eac_etc => EAC_RG11Snorm,
92             f::Etc2R8g8b8Unorm if self.format_eac_etc => ETC2_RGB8,
93             f::Etc2R8g8b8Srgb if self.format_eac_etc => ETC2_RGB8_sRGB,
94             f::Etc2R8g8b8a1Unorm if self.format_eac_etc => ETC2_RGB8A1,
95             f::Etc2R8g8b8a1Srgb if self.format_eac_etc => ETC2_RGB8A1_sRGB,
96             f::Astc4x4Unorm if self.format_astc => ASTC_4x4_LDR,
97             f::Astc4x4Srgb if self.format_astc => ASTC_4x4_sRGB,
98             f::Astc5x4Unorm if self.format_astc => ASTC_5x4_LDR,
99             f::Astc5x4Srgb if self.format_astc => ASTC_5x4_sRGB,
100             f::Astc5x5Unorm if self.format_astc => ASTC_5x5_LDR,
101             f::Astc5x5Srgb if self.format_astc => ASTC_5x5_sRGB,
102             f::Astc6x5Unorm if self.format_astc => ASTC_6x5_LDR,
103             f::Astc6x5Srgb if self.format_astc => ASTC_6x5_sRGB,
104             f::Astc6x6Unorm if self.format_astc => ASTC_6x6_LDR,
105             f::Astc6x6Srgb if self.format_astc => ASTC_6x6_sRGB,
106             f::Astc8x5Unorm if self.format_astc => ASTC_8x5_LDR,
107             f::Astc8x5Srgb if self.format_astc => ASTC_8x5_sRGB,
108             f::Astc8x6Unorm if self.format_astc => ASTC_8x6_LDR,
109             f::Astc8x6Srgb if self.format_astc => ASTC_8x6_sRGB,
110             f::Astc8x8Unorm if self.format_astc => ASTC_8x8_LDR,
111             f::Astc8x8Srgb if self.format_astc => ASTC_8x8_sRGB,
112             f::Astc10x5Unorm if self.format_astc => ASTC_10x5_LDR,
113             f::Astc10x5Srgb if self.format_astc => ASTC_10x5_sRGB,
114             f::Astc10x6Unorm if self.format_astc => ASTC_10x6_LDR,
115             f::Astc10x6Srgb if self.format_astc => ASTC_10x6_sRGB,
116             f::Astc10x8Unorm if self.format_astc => ASTC_10x8_LDR,
117             f::Astc10x8Srgb if self.format_astc => ASTC_10x8_sRGB,
118             f::Astc10x10Unorm if self.format_astc => ASTC_10x10_LDR,
119             f::Astc10x10Srgb if self.format_astc => ASTC_10x10_sRGB,
120             f::Astc12x10Unorm if self.format_astc => ASTC_12x10_LDR,
121             f::Astc12x10Srgb if self.format_astc => ASTC_12x10_sRGB,
122             f::Astc12x12Unorm if self.format_astc => ASTC_12x12_LDR,
123             f::Astc12x12Srgb if self.format_astc => ASTC_12x12_sRGB,
124             // Not supported:
125             // a8Unorm
126             // agbr4Unorm
127             // pvrtc_rgb_2bpp
128             // pvrtc_rgb_2bpp_srgb
129             // pvrtc_rgb_4bpp
130             // pvrtc_rgb_4bpp_srgb
131             // pvrtc_rgba_2bpp
132             // pvrtc_rgba_2bpp_srgb
133             // pvrtc_rgba_4bpp
134             // pvrtc_rgba_4bpp_srgb
135             // eac_rgba8
136             // eac_rgba8_srgb
137             // gbgr422
138             // bgrg422
139             // stencil8 (float-version)
140             // x32_stencil8 (float-version)
141             // x24_stencil8 (float-version)
142             // bgra10_xr
143             // bgra10_xr_srgb
144             // bgr10_xr
145             // bgr10_xr_srgb
146             _ => return None,
147         })
148     }
149 
map_format_with_swizzle( &self, format: Format, swizzle: Swizzle, ) -> Option<MTLPixelFormat>150     pub fn map_format_with_swizzle(
151         &self,
152         format: Format,
153         swizzle: Swizzle,
154     ) -> Option<MTLPixelFormat> {
155         use self::hal::format::{Component::*, Format::*};
156         use metal::MTLPixelFormat as Pf;
157         match (format, swizzle) {
158             (R8Unorm, Swizzle(Zero, Zero, Zero, R)) => Some(Pf::A8Unorm),
159             (Rgba8Unorm, Swizzle(B, G, R, A)) => Some(Pf::BGRA8Unorm),
160             (Bgra8Unorm, Swizzle(B, G, R, A)) => Some(Pf::RGBA8Unorm),
161             (Bgra8Srgb, Swizzle(B, G, R, A)) => Some(Pf::RGBA8Unorm_sRGB),
162             (B5g6r5Unorm, Swizzle(B, G, R, A)) if self.format_b5 => Some(Pf::B5G6R5Unorm),
163             _ => {
164                 let bits = format.base_format().0.describe_bits();
165                 if swizzle != Swizzle::NO && !(bits.alpha == 0 && swizzle == Swizzle(R, G, B, One))
166                 {
167                     error!("Unsupported swizzle {:?} for format {:?}", swizzle, format);
168                 }
169                 self.map_format(format)
170             }
171         }
172     }
173 
map_format_properties(&self, format: Format) -> Properties174     pub fn map_format_properties(&self, format: Format) -> Properties {
175         use self::hal::format::{BufferFeature as Bf, ImageFeature as If};
176         use metal::MTLPixelFormat::*;
177 
178         // Affected formats documented at:
179         // https://developer.apple.com/documentation/metal/mtlreadwritetexturetier/mtlreadwritetexturetier1?language=objc
180         // https://developer.apple.com/documentation/metal/mtlreadwritetexturetier/mtlreadwritetexturetier2?language=objc
181         let (read_write_tier1_if, read_write_tier2_if) = match self.read_write_texture_tier {
182             MTLReadWriteTextureTier::TierNone => (If::empty(), If::empty()),
183             MTLReadWriteTextureTier::Tier1 => (If::STORAGE_READ_WRITE, If::empty()),
184             MTLReadWriteTextureTier::Tier2 => (If::STORAGE_READ_WRITE, If::STORAGE_READ_WRITE),
185         };
186 
187         let mtl_format = match self.map_format(format) {
188             Some(mtl_format) => mtl_format,
189             None => {
190                 return Properties {
191                     buffer_features: if map_vertex_format(format).is_some() {
192                         Bf::VERTEX
193                     } else {
194                         Bf::empty()
195                     },
196                     optimal_tiling: If::empty(),
197                     linear_tiling: If::empty(),
198                 }
199             }
200         };
201         let extra_optimal = match mtl_format {
202             A8Unorm => If::SAMPLED_LINEAR,
203             R8Unorm => {
204                 read_write_tier2_if
205                     | If::SAMPLED_LINEAR
206                     | If::STORAGE
207                     | If::COLOR_ATTACHMENT
208                     | If::COLOR_ATTACHMENT_BLEND
209             }
210             R8Unorm_sRGB if self.format_any8_unorm_srgb_all => {
211                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
212             }
213             R8Unorm_sRGB if self.format_any8_unorm_srgb_no_write => {
214                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
215             }
216             R8Snorm if self.format_any8_snorm_all => {
217                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
218             }
219             R8Uint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
220             R8Sint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
221             R16Unorm if self.format_r16_norm_all => {
222                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
223             }
224             R16Snorm if self.format_r16_norm_all => {
225                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
226             }
227             R16Uint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
228             R16Sint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
229             R16Float => {
230                 read_write_tier2_if
231                     | If::SAMPLED_LINEAR
232                     | If::STORAGE
233                     | If::COLOR_ATTACHMENT
234                     | If::COLOR_ATTACHMENT_BLEND
235             }
236             RG8Unorm => {
237                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
238             }
239             RG8Unorm_sRGB if self.format_any8_unorm_srgb_all => {
240                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
241             }
242             RG8Unorm_sRGB if self.format_any8_unorm_srgb_no_write => {
243                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
244             }
245             RG8Snorm if self.format_any8_snorm_all => {
246                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
247             }
248             RG8Uint => If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT,
249             RG8Sint => If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT,
250             B5G6R5Unorm if self.format_b5 => {
251                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
252             }
253             A1BGR5Unorm if self.format_b5 => {
254                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
255             }
256             ABGR4Unorm if self.format_b5 => {
257                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
258             }
259             BGR5A1Unorm if self.format_b5 => {
260                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
261             }
262             R32Uint if self.format_r32_all => {
263                 read_write_tier1_if | If::STORAGE | If::COLOR_ATTACHMENT
264             }
265             R32Uint if self.format_r32_no_write => If::COLOR_ATTACHMENT,
266             R32Sint if self.format_r32_all => {
267                 read_write_tier1_if | If::STORAGE | If::COLOR_ATTACHMENT
268             }
269             R32Sint if self.format_r32_no_write => If::COLOR_ATTACHMENT,
270             R32Float if self.format_r32float_no_write_no_filter => {
271                 If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
272             }
273             R32Float if self.format_r32float_no_filter => {
274                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
275             }
276             R32Float if self.format_r32float_all => {
277                 read_write_tier1_if
278                     | If::SAMPLED_LINEAR
279                     | If::STORAGE
280                     | If::COLOR_ATTACHMENT
281                     | If::COLOR_ATTACHMENT_BLEND
282             }
283             RG16Unorm => {
284                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
285             }
286             RG16Snorm => {
287                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
288             }
289             RG16Float => {
290                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
291             }
292             RGBA8Unorm => {
293                 read_write_tier2_if
294                     | If::SAMPLED_LINEAR
295                     | If::STORAGE
296                     | If::COLOR_ATTACHMENT
297                     | If::COLOR_ATTACHMENT_BLEND
298             }
299             RGBA8Unorm_sRGB if self.format_rgba8_srgb_no_write => {
300                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
301             }
302             RGBA8Unorm_sRGB if self.format_rgba8_srgb_all => {
303                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
304             }
305             RGBA8Snorm => {
306                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
307             }
308             RGBA8Uint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
309             RGBA8Sint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
310             BGRA8Unorm => {
311                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
312             }
313             BGRA8Unorm_sRGB if self.format_rgba8_srgb_no_write => {
314                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
315             }
316             BGRA8Unorm_sRGB if self.format_rgba8_srgb_all => {
317                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
318             }
319             RGB10A2Unorm if self.format_rgb10a2_unorm_all => {
320                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
321             }
322             RGB10A2Unorm if self.format_rgb10a2_unorm_no_write => {
323                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
324             }
325             RGB10A2Uint if self.format_rgb10a2_uint_color => If::COLOR_ATTACHMENT,
326             RGB10A2Uint if self.format_rgb10a2_uint_color_write => {
327                 If::STORAGE | If::COLOR_ATTACHMENT
328             }
329             RG11B10Float if self.format_rg11b10_all => {
330                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
331             }
332             RG11B10Float if self.format_rg11b10_no_write => {
333                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
334             }
335             RGB9E5Float if self.format_rgb9e5_all => {
336                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
337             }
338             RGB9E5Float if self.format_rgb9e5_filter_only => If::SAMPLED_LINEAR,
339             RGB9E5Float if self.format_rgb9e5_no_write => {
340                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
341             }
342             RG32Uint if self.format_rg32_color => If::COLOR_ATTACHMENT,
343             RG32Sint if self.format_rg32_color => If::COLOR_ATTACHMENT,
344             RG32Uint if self.format_rg32_color_write => If::COLOR_ATTACHMENT | If::STORAGE,
345             RG32Sint if self.format_rg32_color_write => If::COLOR_ATTACHMENT | If::STORAGE,
346             RG32Float if self.format_rg32float_all => {
347                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
348             }
349             RG32Float if self.format_rg32float_color_blend => {
350                 If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
351             }
352             RG32Float if self.format_rg32float_no_filter => {
353                 If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
354             }
355             RGBA16Unorm => {
356                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
357             }
358             RGBA16Snorm => {
359                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
360             }
361             RGBA16Uint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
362             RGBA16Sint => read_write_tier2_if | If::STORAGE | If::COLOR_ATTACHMENT,
363             RGBA16Float => {
364                 read_write_tier2_if
365                     | If::SAMPLED_LINEAR
366                     | If::STORAGE
367                     | If::COLOR_ATTACHMENT
368                     | If::COLOR_ATTACHMENT_BLEND
369             }
370             RGBA32Uint if self.format_rgba32int_color => If::COLOR_ATTACHMENT,
371             RGBA32Uint if self.format_rgba32int_color_write => {
372                 read_write_tier2_if | If::COLOR_ATTACHMENT | If::STORAGE
373             }
374             RGBA32Sint if self.format_rgba32int_color => If::COLOR_ATTACHMENT,
375             RGBA32Sint if self.format_rgba32int_color_write => {
376                 read_write_tier2_if | If::COLOR_ATTACHMENT | If::STORAGE
377             }
378             RGBA32Float if self.format_rgba32float_all => {
379                 read_write_tier2_if
380                     | If::SAMPLED_LINEAR
381                     | If::STORAGE
382                     | If::COLOR_ATTACHMENT
383                     | If::COLOR_ATTACHMENT_BLEND
384             }
385             RGBA32Float if self.format_rgba32float_color => If::COLOR_ATTACHMENT,
386             RGBA32Float if self.format_rgba32float_color_write => {
387                 read_write_tier2_if | If::COLOR_ATTACHMENT | If::STORAGE
388             }
389             EAC_R11Unorm if self.format_eac_etc => If::SAMPLED_LINEAR,
390             EAC_R11Snorm if self.format_eac_etc => If::SAMPLED_LINEAR,
391             EAC_RG11Unorm if self.format_eac_etc => If::SAMPLED_LINEAR,
392             EAC_RG11Snorm if self.format_eac_etc => If::SAMPLED_LINEAR,
393             ETC2_RGB8 if self.format_eac_etc => If::SAMPLED_LINEAR,
394             ETC2_RGB8_sRGB if self.format_eac_etc => If::SAMPLED_LINEAR,
395             ETC2_RGB8A1 if self.format_eac_etc => If::SAMPLED_LINEAR,
396             ETC2_RGB8A1_sRGB if self.format_eac_etc => If::SAMPLED_LINEAR,
397             ASTC_4x4_LDR if self.format_astc => If::SAMPLED_LINEAR,
398             ASTC_4x4_sRGB if self.format_astc => If::SAMPLED_LINEAR,
399             ASTC_5x4_LDR if self.format_astc => If::SAMPLED_LINEAR,
400             ASTC_5x4_sRGB if self.format_astc => If::SAMPLED_LINEAR,
401             ASTC_5x5_LDR if self.format_astc => If::SAMPLED_LINEAR,
402             ASTC_5x5_sRGB if self.format_astc => If::SAMPLED_LINEAR,
403             ASTC_6x5_LDR if self.format_astc => If::SAMPLED_LINEAR,
404             ASTC_6x5_sRGB if self.format_astc => If::SAMPLED_LINEAR,
405             ASTC_6x6_LDR if self.format_astc => If::SAMPLED_LINEAR,
406             ASTC_6x6_sRGB if self.format_astc => If::SAMPLED_LINEAR,
407             ASTC_8x5_LDR if self.format_astc => If::SAMPLED_LINEAR,
408             ASTC_8x5_sRGB if self.format_astc => If::SAMPLED_LINEAR,
409             ASTC_8x6_LDR if self.format_astc => If::SAMPLED_LINEAR,
410             ASTC_8x6_sRGB if self.format_astc => If::SAMPLED_LINEAR,
411             ASTC_8x8_LDR if self.format_astc => If::SAMPLED_LINEAR,
412             ASTC_8x8_sRGB if self.format_astc => If::SAMPLED_LINEAR,
413             ASTC_10x5_LDR if self.format_astc => If::SAMPLED_LINEAR,
414             ASTC_10x5_sRGB if self.format_astc => If::SAMPLED_LINEAR,
415             ASTC_10x6_LDR if self.format_astc => If::SAMPLED_LINEAR,
416             ASTC_10x6_sRGB if self.format_astc => If::SAMPLED_LINEAR,
417             ASTC_10x8_LDR if self.format_astc => If::SAMPLED_LINEAR,
418             ASTC_10x8_sRGB if self.format_astc => If::SAMPLED_LINEAR,
419             ASTC_10x10_LDR if self.format_astc => If::SAMPLED_LINEAR,
420             ASTC_10x10_sRGB if self.format_astc => If::SAMPLED_LINEAR,
421             ASTC_12x10_LDR if self.format_astc => If::SAMPLED_LINEAR,
422             ASTC_12x10_sRGB if self.format_astc => If::SAMPLED_LINEAR,
423             ASTC_12x12_LDR if self.format_astc => If::SAMPLED_LINEAR,
424             ASTC_12x12_sRGB if self.format_astc => If::SAMPLED_LINEAR,
425             BC1_RGBA if self.format_bc => If::SAMPLED_LINEAR,
426             BC1_RGBA_sRGB if self.format_bc => If::SAMPLED_LINEAR,
427             BC2_RGBA if self.format_bc => If::SAMPLED_LINEAR,
428             BC2_RGBA_sRGB if self.format_bc => If::SAMPLED_LINEAR,
429             BC3_RGBA if self.format_bc => If::SAMPLED_LINEAR,
430             BC3_RGBA_sRGB if self.format_bc => If::SAMPLED_LINEAR,
431             BC4_RUnorm if self.format_bc => If::SAMPLED_LINEAR,
432             BC4_RSnorm if self.format_bc => If::SAMPLED_LINEAR,
433             BC5_RGUnorm if self.format_bc => If::SAMPLED_LINEAR,
434             BC5_RGSnorm if self.format_bc => If::SAMPLED_LINEAR,
435             BC6H_RGBUfloat if self.format_bc => If::SAMPLED_LINEAR,
436             BC6H_RGBFloat if self.format_bc => If::SAMPLED_LINEAR,
437             BC7_RGBAUnorm if self.format_bc => If::SAMPLED_LINEAR,
438             BC7_RGBAUnorm_sRGB if self.format_bc => If::SAMPLED_LINEAR,
439             Depth16Unorm if self.format_depth16unorm => {
440                 If::DEPTH_STENCIL_ATTACHMENT | If::SAMPLED_LINEAR
441             }
442             Depth32Float if self.format_depth32float_filter => {
443                 If::DEPTH_STENCIL_ATTACHMENT | If::SAMPLED_LINEAR
444             }
445             Depth32Float if self.format_depth32float_none => If::DEPTH_STENCIL_ATTACHMENT,
446             Stencil8 => If::empty(),
447             Depth24Unorm_Stencil8 if self.format_depth24_stencil8 => If::DEPTH_STENCIL_ATTACHMENT,
448             Depth32Float_Stencil8 if self.format_depth32_stencil8_filter => {
449                 If::DEPTH_STENCIL_ATTACHMENT | If::SAMPLED_LINEAR
450             }
451             Depth32Float_Stencil8 if self.format_depth32_stencil8_none => {
452                 If::DEPTH_STENCIL_ATTACHMENT
453             }
454             BGR10A2Unorm if self.format_bgr10a2_all => {
455                 If::SAMPLED_LINEAR | If::STORAGE | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
456             }
457             BGR10A2Unorm if self.format_bgr10a2_no_write => {
458                 If::SAMPLED_LINEAR | If::COLOR_ATTACHMENT | If::COLOR_ATTACHMENT_BLEND
459             }
460             _ => If::empty(),
461         };
462 
463         Properties {
464             linear_tiling: If::TRANSFER_SRC | If::TRANSFER_DST,
465             optimal_tiling: If::SAMPLED
466                 | If::BLIT_SRC
467                 | If::BLIT_DST
468                 | If::TRANSFER_SRC
469                 | If::TRANSFER_DST
470                 | extra_optimal,
471             buffer_features: Bf::all(),
472         }
473     }
474 }
475 
map_load_operation(operation: pass::AttachmentLoadOp) -> MTLLoadAction476 pub fn map_load_operation(operation: pass::AttachmentLoadOp) -> MTLLoadAction {
477     use self::pass::AttachmentLoadOp::*;
478 
479     match operation {
480         Load => MTLLoadAction::Load,
481         Clear => MTLLoadAction::Clear,
482         DontCare => MTLLoadAction::DontCare,
483     }
484 }
485 
map_store_operation(operation: pass::AttachmentStoreOp) -> MTLStoreAction486 pub fn map_store_operation(operation: pass::AttachmentStoreOp) -> MTLStoreAction {
487     use self::pass::AttachmentStoreOp::*;
488 
489     match operation {
490         Store => MTLStoreAction::Store,
491         DontCare => MTLStoreAction::DontCare,
492     }
493 }
494 
map_resolved_store_operation(operation: pass::AttachmentStoreOp) -> MTLStoreAction495 pub fn map_resolved_store_operation(operation: pass::AttachmentStoreOp) -> MTLStoreAction {
496     use self::pass::AttachmentStoreOp::*;
497 
498     match operation {
499         Store => MTLStoreAction::StoreAndMultisampleResolve,
500         DontCare => MTLStoreAction::MultisampleResolve,
501     }
502 }
503 
map_write_mask(mask: pso::ColorMask) -> MTLColorWriteMask504 pub fn map_write_mask(mask: pso::ColorMask) -> MTLColorWriteMask {
505     let mut mtl_mask = MTLColorWriteMask::empty();
506 
507     if mask.contains(pso::ColorMask::RED) {
508         mtl_mask |= MTLColorWriteMask::Red;
509     }
510     if mask.contains(pso::ColorMask::GREEN) {
511         mtl_mask |= MTLColorWriteMask::Green;
512     }
513     if mask.contains(pso::ColorMask::BLUE) {
514         mtl_mask |= MTLColorWriteMask::Blue;
515     }
516     if mask.contains(pso::ColorMask::ALPHA) {
517         mtl_mask |= MTLColorWriteMask::Alpha;
518     }
519 
520     mtl_mask
521 }
522 
map_factor(factor: pso::Factor) -> MTLBlendFactor523 fn map_factor(factor: pso::Factor) -> MTLBlendFactor {
524     use self::hal::pso::Factor::*;
525 
526     match factor {
527         Zero => MTLBlendFactor::Zero,
528         One => MTLBlendFactor::One,
529         SrcColor => MTLBlendFactor::SourceColor,
530         OneMinusSrcColor => MTLBlendFactor::OneMinusSourceColor,
531         DstColor => MTLBlendFactor::DestinationColor,
532         OneMinusDstColor => MTLBlendFactor::OneMinusDestinationColor,
533         SrcAlpha => MTLBlendFactor::SourceAlpha,
534         OneMinusSrcAlpha => MTLBlendFactor::OneMinusSourceAlpha,
535         DstAlpha => MTLBlendFactor::DestinationAlpha,
536         OneMinusDstAlpha => MTLBlendFactor::OneMinusDestinationAlpha,
537         ConstColor => MTLBlendFactor::BlendColor,
538         OneMinusConstColor => MTLBlendFactor::OneMinusBlendColor,
539         ConstAlpha => MTLBlendFactor::BlendAlpha,
540         OneMinusConstAlpha => MTLBlendFactor::OneMinusBlendAlpha,
541         SrcAlphaSaturate => MTLBlendFactor::SourceAlphaSaturated,
542         Src1Color => MTLBlendFactor::Source1Color,
543         OneMinusSrc1Color => MTLBlendFactor::OneMinusSource1Color,
544         Src1Alpha => MTLBlendFactor::Source1Alpha,
545         OneMinusSrc1Alpha => MTLBlendFactor::OneMinusSource1Alpha,
546     }
547 }
548 
map_blend_op( operation: pso::BlendOp, ) -> (MTLBlendOperation, MTLBlendFactor, MTLBlendFactor)549 pub fn map_blend_op(
550     operation: pso::BlendOp,
551 ) -> (MTLBlendOperation, MTLBlendFactor, MTLBlendFactor) {
552     use self::hal::pso::BlendOp::*;
553 
554     match operation {
555         Add { src, dst } => (MTLBlendOperation::Add, map_factor(src), map_factor(dst)),
556         Sub { src, dst } => (
557             MTLBlendOperation::Subtract,
558             map_factor(src),
559             map_factor(dst),
560         ),
561         RevSub { src, dst } => (
562             MTLBlendOperation::ReverseSubtract,
563             map_factor(src),
564             map_factor(dst),
565         ),
566         Min => (
567             MTLBlendOperation::Min,
568             MTLBlendFactor::Zero,
569             MTLBlendFactor::Zero,
570         ),
571         Max => (
572             MTLBlendOperation::Max,
573             MTLBlendFactor::Zero,
574             MTLBlendFactor::Zero,
575         ),
576     }
577 }
578 
map_vertex_format(format: Format) -> Option<MTLVertexFormat>579 pub fn map_vertex_format(format: Format) -> Option<MTLVertexFormat> {
580     use self::hal::format::Format as f;
581     use metal::MTLVertexFormat::*;
582     Some(match format {
583         f::R8Unorm => UCharNormalized,
584         f::R8Snorm => CharNormalized,
585         f::R8Uint => UChar,
586         f::R8Sint => Char,
587         f::Rg8Unorm => UChar2Normalized,
588         f::Rg8Snorm => Char2Normalized,
589         f::Rg8Uint => UChar2,
590         f::Rg8Sint => Char2,
591         f::Rgb8Unorm => UChar3Normalized,
592         f::Rgb8Snorm => Char3Normalized,
593         f::Rgb8Uint => UChar3,
594         f::Rgb8Sint => Char3,
595         f::Rgba8Unorm => UChar4Normalized,
596         f::Rgba8Snorm => Char4Normalized,
597         f::Rgba8Uint => UChar4,
598         f::Rgba8Sint => Char4,
599         f::Bgra8Unorm => UChar4Normalized_BGRA,
600         f::R16Unorm => UShortNormalized,
601         f::R16Snorm => ShortNormalized,
602         f::R16Uint => UShort,
603         f::R16Sint => Short,
604         f::R16Sfloat => Half,
605         f::Rg16Unorm => UShort2Normalized,
606         f::Rg16Snorm => Short2Normalized,
607         f::Rg16Uint => UShort2,
608         f::Rg16Sint => Short2,
609         f::Rg16Sfloat => Half2,
610         f::Rgb16Unorm => UShort3Normalized,
611         f::Rgb16Snorm => Short3Normalized,
612         f::Rgb16Uint => UShort3,
613         f::Rgb16Sint => Short3,
614         f::Rgb16Sfloat => Half3,
615         f::Rgba16Unorm => UShort4Normalized,
616         f::Rgba16Snorm => Short4Normalized,
617         f::Rgba16Uint => UShort4,
618         f::Rgba16Sint => Short4,
619         f::Rgba16Sfloat => Half4,
620         f::R32Uint => UInt,
621         f::R32Sint => Int,
622         f::R32Sfloat => Float,
623         f::Rg32Uint => UInt2,
624         f::Rg32Sint => Int2,
625         f::Rg32Sfloat => Float2,
626         f::Rgb32Uint => UInt3,
627         f::Rgb32Sint => Int3,
628         f::Rgb32Sfloat => Float3,
629         f::Rgba32Uint => UInt4,
630         f::Rgba32Sint => Int4,
631         f::Rgba32Sfloat => Float4,
632         _ => return None,
633     })
634 }
635 
resource_options_from_storage_and_cache( storage: MTLStorageMode, cache: MTLCPUCacheMode, ) -> MTLResourceOptions636 pub fn resource_options_from_storage_and_cache(
637     storage: MTLStorageMode,
638     cache: MTLCPUCacheMode,
639 ) -> MTLResourceOptions {
640     MTLResourceOptions::from_bits(
641         ((storage as u64) << MTLResourceStorageModeShift)
642             | ((cache as u64) << MTLResourceCPUCacheModeShift),
643     )
644     .unwrap()
645 }
646 
map_texture_usage( usage: image::Usage, tiling: image::Tiling, view_caps: image::ViewCapabilities, ) -> MTLTextureUsage647 pub fn map_texture_usage(
648     usage: image::Usage,
649     tiling: image::Tiling,
650     view_caps: image::ViewCapabilities,
651 ) -> MTLTextureUsage {
652     use self::hal::image::Usage as U;
653 
654     let mut texture_usage = MTLTextureUsage::Unknown;
655     // We have to view the texture with a different format
656     // in `clear_image` and `copy_image` destinations.
657     if view_caps.contains(image::ViewCapabilities::MUTABLE_FORMAT)
658         || usage.contains(U::TRANSFER_DST)
659     {
660         texture_usage |= MTLTextureUsage::PixelFormatView;
661     }
662 
663     if usage.intersects(U::COLOR_ATTACHMENT | U::DEPTH_STENCIL_ATTACHMENT) {
664         texture_usage |= MTLTextureUsage::RenderTarget;
665     }
666     if usage.intersects(U::SAMPLED | U::INPUT_ATTACHMENT) {
667         texture_usage |= MTLTextureUsage::ShaderRead;
668     }
669     if usage.intersects(U::STORAGE) {
670         texture_usage |= MTLTextureUsage::ShaderRead | MTLTextureUsage::ShaderWrite;
671     }
672 
673     // Note: for blitting, we do actual rendering, so we add more flags for TRANSFER_* usage
674     if usage.contains(U::TRANSFER_DST) && tiling == image::Tiling::Optimal {
675         texture_usage |= MTLTextureUsage::RenderTarget;
676     }
677     if usage.contains(U::TRANSFER_SRC) {
678         texture_usage |= MTLTextureUsage::ShaderRead;
679     }
680 
681     texture_usage
682 }
683 
map_texture_type(view_kind: image::ViewKind) -> MTLTextureType684 pub fn map_texture_type(view_kind: image::ViewKind) -> MTLTextureType {
685     use self::hal::image::ViewKind as Vk;
686     match view_kind {
687         Vk::D1 => MTLTextureType::D1,
688         Vk::D1Array => MTLTextureType::D1Array,
689         Vk::D2 => MTLTextureType::D2,
690         Vk::D2Array => MTLTextureType::D2Array,
691         Vk::D3 => MTLTextureType::D3,
692         Vk::Cube => MTLTextureType::Cube,
693         Vk::CubeArray => MTLTextureType::CubeArray,
694     }
695 }
696 
_map_index_type(index_type: IndexType) -> MTLIndexType697 pub fn _map_index_type(index_type: IndexType) -> MTLIndexType {
698     match index_type {
699         IndexType::U16 => MTLIndexType::UInt16,
700         IndexType::U32 => MTLIndexType::UInt32,
701     }
702 }
703 
map_compare_function(fun: Comparison) -> MTLCompareFunction704 pub fn map_compare_function(fun: Comparison) -> MTLCompareFunction {
705     match fun {
706         Comparison::Never => MTLCompareFunction::Never,
707         Comparison::Less => MTLCompareFunction::Less,
708         Comparison::LessEqual => MTLCompareFunction::LessEqual,
709         Comparison::Equal => MTLCompareFunction::Equal,
710         Comparison::GreaterEqual => MTLCompareFunction::GreaterEqual,
711         Comparison::Greater => MTLCompareFunction::Greater,
712         Comparison::NotEqual => MTLCompareFunction::NotEqual,
713         Comparison::Always => MTLCompareFunction::Always,
714     }
715 }
716 
map_filter(filter: image::Filter) -> MTLSamplerMinMagFilter717 pub fn map_filter(filter: image::Filter) -> MTLSamplerMinMagFilter {
718     match filter {
719         image::Filter::Nearest => MTLSamplerMinMagFilter::Nearest,
720         image::Filter::Linear => MTLSamplerMinMagFilter::Linear,
721     }
722 }
723 
map_wrap_mode(wrap: image::WrapMode) -> MTLSamplerAddressMode724 pub fn map_wrap_mode(wrap: image::WrapMode) -> MTLSamplerAddressMode {
725     match wrap {
726         image::WrapMode::Tile => MTLSamplerAddressMode::Repeat,
727         image::WrapMode::Mirror => MTLSamplerAddressMode::MirrorRepeat,
728         image::WrapMode::Clamp => MTLSamplerAddressMode::ClampToEdge,
729         image::WrapMode::Border => MTLSamplerAddressMode::ClampToBorderColor,
730         image::WrapMode::MirrorClamp => MTLSamplerAddressMode::MirrorClampToEdge,
731     }
732 }
733 
map_border_color(border_color: image::BorderColor) -> MTLSamplerBorderColor734 pub fn map_border_color(border_color: image::BorderColor) -> MTLSamplerBorderColor {
735     match border_color {
736         image::BorderColor::TransparentBlack => MTLSamplerBorderColor::TransparentBlack,
737         image::BorderColor::OpaqueBlack => MTLSamplerBorderColor::OpaqueBlack,
738         image::BorderColor::OpaqueWhite => MTLSamplerBorderColor::OpaqueWhite,
739     }
740 }
741 
map_extent(extent: image::Extent) -> MTLSize742 pub fn map_extent(extent: image::Extent) -> MTLSize {
743     MTLSize {
744         width: extent.width as _,
745         height: extent.height as _,
746         depth: extent.depth as _,
747     }
748 }
749 
map_offset(offset: image::Offset) -> MTLOrigin750 pub fn map_offset(offset: image::Offset) -> MTLOrigin {
751     MTLOrigin {
752         x: offset.x as _,
753         y: offset.y as _,
754         z: offset.z as _,
755     }
756 }
757 
map_stencil_op(op: StencilOp) -> MTLStencilOperation758 pub fn map_stencil_op(op: StencilOp) -> MTLStencilOperation {
759     match op {
760         StencilOp::Keep => MTLStencilOperation::Keep,
761         StencilOp::Zero => MTLStencilOperation::Zero,
762         StencilOp::Replace => MTLStencilOperation::Replace,
763         StencilOp::IncrementClamp => MTLStencilOperation::IncrementClamp,
764         StencilOp::IncrementWrap => MTLStencilOperation::IncrementWrap,
765         StencilOp::DecrementClamp => MTLStencilOperation::DecrementClamp,
766         StencilOp::DecrementWrap => MTLStencilOperation::DecrementWrap,
767         StencilOp::Invert => MTLStencilOperation::Invert,
768     }
769 }
770 
map_winding(face: pso::FrontFace) -> MTLWinding771 pub fn map_winding(face: pso::FrontFace) -> MTLWinding {
772     match face {
773         pso::FrontFace::Clockwise => MTLWinding::Clockwise,
774         pso::FrontFace::CounterClockwise => MTLWinding::CounterClockwise,
775     }
776 }
777 
map_polygon_mode(mode: pso::PolygonMode) -> MTLTriangleFillMode778 pub fn map_polygon_mode(mode: pso::PolygonMode) -> MTLTriangleFillMode {
779     match mode {
780         pso::PolygonMode::Point => {
781             warn!("Unable to fill with points");
782             MTLTriangleFillMode::Lines
783         }
784         pso::PolygonMode::Line => MTLTriangleFillMode::Lines,
785         pso::PolygonMode::Fill => MTLTriangleFillMode::Fill,
786     }
787 }
788 
map_cull_face(face: pso::Face) -> Option<MTLCullMode>789 pub fn map_cull_face(face: pso::Face) -> Option<MTLCullMode> {
790     match face {
791         pso::Face::NONE => Some(MTLCullMode::None),
792         pso::Face::FRONT => Some(MTLCullMode::Front),
793         pso::Face::BACK => Some(MTLCullMode::Back),
794         _ => None,
795     }
796 }
797 
798 #[cfg(feature = "cross")]
map_naga_stage_to_cross(stage: naga::ShaderStage) -> spirv_cross::spirv::ExecutionModel799 pub fn map_naga_stage_to_cross(stage: naga::ShaderStage) -> spirv_cross::spirv::ExecutionModel {
800     use spirv_cross::spirv::ExecutionModel as Em;
801     match stage {
802         naga::ShaderStage::Vertex => Em::Vertex,
803         naga::ShaderStage::Fragment => Em::Fragment,
804         naga::ShaderStage::Compute => Em::GlCompute,
805     }
806 }
807 
808 #[cfg(feature = "cross")]
map_sampler_data_to_cross(info: &image::SamplerDesc) -> spirv_cross::msl::SamplerData809 pub fn map_sampler_data_to_cross(info: &image::SamplerDesc) -> spirv_cross::msl::SamplerData {
810     use spirv_cross::msl;
811     fn map_address(wrap: image::WrapMode) -> msl::SamplerAddress {
812         match wrap {
813             image::WrapMode::Tile => msl::SamplerAddress::Repeat,
814             image::WrapMode::Mirror => msl::SamplerAddress::MirroredRepeat,
815             image::WrapMode::Clamp => msl::SamplerAddress::ClampToEdge,
816             image::WrapMode::Border => msl::SamplerAddress::ClampToBorder,
817             image::WrapMode::MirrorClamp => {
818                 unimplemented!("https://github.com/grovesNL/spirv_cross/issues/138")
819             }
820         }
821     }
822 
823     let lods = info.lod_range.start.0..info.lod_range.end.0;
824     msl::SamplerData {
825         coord: if info.normalized {
826             msl::SamplerCoord::Normalized
827         } else {
828             msl::SamplerCoord::Pixel
829         },
830         min_filter: match info.min_filter {
831             image::Filter::Nearest => msl::SamplerFilter::Nearest,
832             image::Filter::Linear => msl::SamplerFilter::Linear,
833         },
834         mag_filter: match info.mag_filter {
835             image::Filter::Nearest => msl::SamplerFilter::Nearest,
836             image::Filter::Linear => msl::SamplerFilter::Linear,
837         },
838         mip_filter: match info.min_filter {
839             image::Filter::Nearest if info.lod_range.end.0 < 0.5 => msl::SamplerMipFilter::None,
840             image::Filter::Nearest => msl::SamplerMipFilter::Nearest,
841             image::Filter::Linear => msl::SamplerMipFilter::Linear,
842         },
843         s_address: map_address(info.wrap_mode.0),
844         t_address: map_address(info.wrap_mode.1),
845         r_address: map_address(info.wrap_mode.2),
846         compare_func: match info.comparison {
847             Some(func) => unsafe { std::mem::transmute(map_compare_function(func) as u32) },
848             None => msl::SamplerCompareFunc::Always,
849         },
850         border_color: match info.border {
851             image::BorderColor::TransparentBlack => msl::SamplerBorderColor::TransparentBlack,
852             image::BorderColor::OpaqueBlack => msl::SamplerBorderColor::OpaqueBlack,
853             image::BorderColor::OpaqueWhite => msl::SamplerBorderColor::OpaqueWhite,
854         },
855         lod_clamp_min: lods.start.into(),
856         lod_clamp_max: lods.end.into(),
857         max_anisotropy: info.anisotropy_clamp.map_or(0, |aniso| aniso as i32),
858         planes: 0,
859         resolution: msl::FormatResolution::_444,
860         chroma_filter: msl::SamplerFilter::Nearest,
861         x_chroma_offset: msl::ChromaLocation::CositedEven,
862         y_chroma_offset: msl::ChromaLocation::CositedEven,
863         swizzle: [
864             msl::ComponentSwizzle::Identity,
865             msl::ComponentSwizzle::Identity,
866             msl::ComponentSwizzle::Identity,
867             msl::ComponentSwizzle::Identity,
868         ],
869         ycbcr_conversion_enable: false,
870         ycbcr_model: msl::SamplerYCbCrModelConversion::RgbIdentity,
871         ycbcr_range: msl::SamplerYCbCrRange::ItuFull,
872         bpc: 8,
873     }
874 }
875 
map_sampler_data_to_naga( info: &image::SamplerDesc, ) -> naga::back::msl::sampler::InlineSampler876 pub fn map_sampler_data_to_naga(
877     info: &image::SamplerDesc,
878 ) -> naga::back::msl::sampler::InlineSampler {
879     use naga::back::msl::sampler as sm;
880     fn map_address(wrap: image::WrapMode) -> sm::Address {
881         match wrap {
882             image::WrapMode::Tile => sm::Address::Repeat,
883             image::WrapMode::Mirror => sm::Address::MirroredRepeat,
884             image::WrapMode::Clamp => sm::Address::ClampToEdge,
885             image::WrapMode::Border => sm::Address::ClampToBorder,
886             image::WrapMode::MirrorClamp => {
887                 error!("Unsupported address mode - MirrorClamp");
888                 sm::Address::ClampToEdge
889             }
890         }
891     }
892 
893     sm::InlineSampler {
894         coord: if info.normalized {
895             sm::Coord::Normalized
896         } else {
897             sm::Coord::Pixel
898         },
899         min_filter: match info.min_filter {
900             image::Filter::Nearest => sm::Filter::Nearest,
901             image::Filter::Linear => sm::Filter::Linear,
902         },
903         mag_filter: match info.mag_filter {
904             image::Filter::Nearest => sm::Filter::Nearest,
905             image::Filter::Linear => sm::Filter::Linear,
906         },
907         mip_filter: match info.min_filter {
908             image::Filter::Nearest if info.lod_range.end.0 < 0.5 => None,
909             image::Filter::Nearest => Some(sm::Filter::Nearest),
910             image::Filter::Linear => Some(sm::Filter::Linear),
911         },
912         address: [
913             map_address(info.wrap_mode.0),
914             map_address(info.wrap_mode.1),
915             map_address(info.wrap_mode.2),
916         ],
917         compare_func: match info.comparison {
918             Some(func) => match func {
919                 Comparison::Never => sm::CompareFunc::Never,
920                 Comparison::Less => sm::CompareFunc::Less,
921                 Comparison::LessEqual => sm::CompareFunc::LessEqual,
922                 Comparison::Equal => sm::CompareFunc::Equal,
923                 Comparison::GreaterEqual => sm::CompareFunc::GreaterEqual,
924                 Comparison::Greater => sm::CompareFunc::Greater,
925                 Comparison::NotEqual => sm::CompareFunc::NotEqual,
926                 Comparison::Always => sm::CompareFunc::Always,
927             },
928             None => sm::CompareFunc::Never,
929         },
930         border_color: match info.border {
931             image::BorderColor::TransparentBlack => sm::BorderColor::TransparentBlack,
932             image::BorderColor::OpaqueBlack => sm::BorderColor::OpaqueBlack,
933             image::BorderColor::OpaqueWhite => sm::BorderColor::OpaqueWhite,
934         },
935         lod_clamp: if info.lod_range.start.0 > 0.0 || info.lod_range.end.0 < 100.0 {
936             Some(info.lod_range.start.0..info.lod_range.end.0)
937         } else {
938             None
939         },
940         max_anisotropy: info
941             .anisotropy_clamp
942             .and_then(|aniso| NonZeroU32::new(aniso as u32)),
943     }
944 }
945