1 // Copyright 2017 GFX developers
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 
8 use block::{Block, ConcreteBlock};
9 use cocoa_foundation::base::id;
10 use cocoa_foundation::foundation::NSUInteger;
11 use foreign_types::ForeignType;
12 use objc::runtime::{Object, NO, YES};
13 
14 use super::*;
15 
16 use std::ffi::CStr;
17 use std::os::raw::c_char;
18 use std::path::Path;
19 use std::ptr;
20 
21 #[allow(non_camel_case_types)]
22 #[repr(u64)]
23 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
24 pub enum MTLFeatureSet {
25     iOS_GPUFamily1_v1 = 0,
26     iOS_GPUFamily2_v1 = 1,
27     iOS_GPUFamily1_v2 = 2,
28     iOS_GPUFamily2_v2 = 3,
29     iOS_GPUFamily3_v1 = 4,
30     iOS_GPUFamily1_v3 = 5,
31     iOS_GPUFamily2_v3 = 6,
32     iOS_GPUFamily3_v2 = 7,
33     iOS_GPUFamily1_v4 = 8,
34     iOS_GPUFamily2_v4 = 9,
35     iOS_GPUFamily3_v3 = 10,
36     iOS_GPUFamily4_v1 = 11,
37     iOS_GPUFamily1_v5 = 12,
38     iOS_GPUFamily2_v5 = 13,
39     iOS_GPUFamily3_v4 = 14,
40     iOS_GPUFamily4_v2 = 15,
41     iOS_GPUFamily5_v1 = 16,
42 
43     tvOS_GPUFamily1_v1 = 30000,
44     tvOS_GPUFamily1_v2 = 30001,
45     tvOS_GPUFamily1_v3 = 30002,
46     tvOS_GPUFamily2_v1 = 30003,
47     tvOS_GPUFamily1_v4 = 30004,
48     tvOS_GPUFamily2_v2 = 30005,
49 
50     macOS_GPUFamily1_v1 = 10000,
51     macOS_GPUFamily1_v2 = 10001,
52     //macOS_ReadWriteTextureTier2 = 10002, TODO: Uncomment when feature tables updated
53     macOS_GPUFamily1_v3 = 10003,
54     macOS_GPUFamily1_v4 = 10004,
55     macOS_GPUFamily2_v1 = 10005,
56 }
57 
58 #[repr(i64)]
59 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
60 pub enum MTLGPUFamily {
61     Common1 = 3001,
62     Common2 = 3002,
63     Common3 = 3003,
64     Apple1 = 1001,
65     Apple2 = 1002,
66     Apple3 = 1003,
67     Apple4 = 1004,
68     Apple5 = 1005,
69     Apple6 = 1006,
70     Mac1 = 2001,
71     Mac2 = 2002,
72     MacCatalyst1 = 4001,
73     MacCatalyst2 = 4002,
74 }
75 
76 #[repr(u64)]
77 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
78 pub enum MTLDeviceLocation {
79     BuiltIn = 0,
80     Slot = 1,
81     External = 2,
82     Unspecified = u64::MAX,
83 }
84 
85 bitflags! {
86     pub struct PixelFormatCapabilities: u32 {
87         const Filter = 1 << 0;
88         const Write = 1 << 1;
89         const Color = 1 << 2;
90         const Blend = 1 << 3;
91         const Msaa = 1 << 4;
92         const Resolve = 1 << 5;
93     }
94 }
95 
96 #[allow(non_camel_case_types)]
97 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
98 enum OS {
99     iOS,
100     tvOS,
101     macOS,
102 }
103 
104 const KB: u32 = 1024;
105 const MB: u32 = 1024 * KB;
106 const GB: u32 = 1024 * MB;
107 
108 impl MTLFeatureSet {
os(&self) -> OS109     fn os(&self) -> OS {
110         let value = *self as u64;
111         if value < 10_000 {
112             OS::iOS
113         } else if value < 20_000 {
114             OS::macOS
115         } else if value >= 30_000 || value < 40_000 {
116             OS::tvOS
117         } else {
118             unreachable!()
119         }
120     }
121 
122     // returns the minor version on macos
os_version(&self) -> u32123     fn os_version(&self) -> u32 {
124         use MTLFeatureSet::*;
125         match self {
126             iOS_GPUFamily1_v1 | iOS_GPUFamily2_v1 => 8,
127             iOS_GPUFamily1_v2 | iOS_GPUFamily2_v2 | iOS_GPUFamily3_v1 => 9,
128             iOS_GPUFamily1_v3 | iOS_GPUFamily2_v3 | iOS_GPUFamily3_v2 => 10,
129             iOS_GPUFamily1_v4 | iOS_GPUFamily2_v4 | iOS_GPUFamily3_v3 | iOS_GPUFamily4_v1 => 11,
130             iOS_GPUFamily1_v5 | iOS_GPUFamily2_v5 | iOS_GPUFamily3_v4 | iOS_GPUFamily4_v2
131             | iOS_GPUFamily5_v1 => 12,
132             tvOS_GPUFamily1_v1 => 9,
133             tvOS_GPUFamily1_v2 => 10,
134             tvOS_GPUFamily1_v3 | tvOS_GPUFamily2_v1 => 11,
135             tvOS_GPUFamily1_v4 | tvOS_GPUFamily2_v2 => 12,
136             macOS_GPUFamily1_v1 => 11,
137             macOS_GPUFamily1_v2 => 12,
138             macOS_GPUFamily1_v3 => 13,
139             macOS_GPUFamily1_v4 | macOS_GPUFamily2_v1 => 14,
140         }
141     }
142 
gpu_family(&self) -> u32143     fn gpu_family(&self) -> u32 {
144         use MTLFeatureSet::*;
145         match self {
146             iOS_GPUFamily1_v1 | iOS_GPUFamily1_v2 | iOS_GPUFamily1_v3 | iOS_GPUFamily1_v4
147             | iOS_GPUFamily1_v5 | tvOS_GPUFamily1_v1 | tvOS_GPUFamily1_v2 | tvOS_GPUFamily1_v3
148             | tvOS_GPUFamily1_v4 | macOS_GPUFamily1_v1 | macOS_GPUFamily1_v2
149             | macOS_GPUFamily1_v3 | macOS_GPUFamily1_v4 => 1,
150             iOS_GPUFamily2_v1 | iOS_GPUFamily2_v2 | iOS_GPUFamily2_v3 | iOS_GPUFamily2_v4
151             | iOS_GPUFamily2_v5 | tvOS_GPUFamily2_v1 | tvOS_GPUFamily2_v2 | macOS_GPUFamily2_v1 => {
152                 2
153             }
154             iOS_GPUFamily3_v1 | iOS_GPUFamily3_v2 | iOS_GPUFamily3_v3 | iOS_GPUFamily3_v4 => 3,
155             iOS_GPUFamily4_v1 | iOS_GPUFamily4_v2 => 4,
156             iOS_GPUFamily5_v1 => 5,
157         }
158     }
159 
version(&self) -> u32160     fn version(&self) -> u32 {
161         use MTLFeatureSet::*;
162         match self {
163             iOS_GPUFamily1_v1 | iOS_GPUFamily2_v1 | iOS_GPUFamily3_v1 | iOS_GPUFamily4_v1
164             | iOS_GPUFamily5_v1 | macOS_GPUFamily1_v1 | macOS_GPUFamily2_v1
165             | tvOS_GPUFamily1_v1 | tvOS_GPUFamily2_v1 => 1,
166             iOS_GPUFamily1_v2 | iOS_GPUFamily2_v2 | iOS_GPUFamily3_v2 | iOS_GPUFamily4_v2
167             | macOS_GPUFamily1_v2 | tvOS_GPUFamily1_v2 | tvOS_GPUFamily2_v2 => 2,
168             iOS_GPUFamily1_v3 | iOS_GPUFamily2_v3 | iOS_GPUFamily3_v3 | macOS_GPUFamily1_v3
169             | tvOS_GPUFamily1_v3 => 3,
170             iOS_GPUFamily1_v4 | iOS_GPUFamily2_v4 | iOS_GPUFamily3_v4 | tvOS_GPUFamily1_v4
171             | macOS_GPUFamily1_v4 => 4,
172             iOS_GPUFamily1_v5 | iOS_GPUFamily2_v5 => 5,
173         }
174     }
175 
supports_metal_kit(&self) -> bool176     pub fn supports_metal_kit(&self) -> bool {
177         true
178     }
179 
supports_metal_performance_shaders(&self) -> bool180     pub fn supports_metal_performance_shaders(&self) -> bool {
181         match self.os() {
182             OS::iOS => self.gpu_family() >= 2,
183             OS::tvOS => true,
184             OS::macOS => self.os_version() >= 13,
185         }
186     }
187 
supports_programmable_blending(&self) -> bool188     pub fn supports_programmable_blending(&self) -> bool {
189         self.os() != OS::macOS
190     }
191 
supports_pvrtc_pixel_formats(&self) -> bool192     pub fn supports_pvrtc_pixel_formats(&self) -> bool {
193         self.os() != OS::macOS
194     }
195 
supports_eac_etc_pixel_formats(&self) -> bool196     pub fn supports_eac_etc_pixel_formats(&self) -> bool {
197         self.os() != OS::macOS
198     }
199 
supports_astc_pixel_formats(&self) -> bool200     pub fn supports_astc_pixel_formats(&self) -> bool {
201         match self.os() {
202             OS::iOS => self.gpu_family() >= 2,
203             OS::tvOS => true,
204             OS::macOS => false,
205         }
206     }
207 
supports_linear_textures(&self) -> bool208     pub fn supports_linear_textures(&self) -> bool {
209         self.os() != OS::macOS || self.os_version() >= 13
210     }
211 
supports_bc_pixel_formats(&self) -> bool212     pub fn supports_bc_pixel_formats(&self) -> bool {
213         self.os() == OS::macOS
214     }
215 
supports_msaa_depth_resolve(&self) -> bool216     pub fn supports_msaa_depth_resolve(&self) -> bool {
217         match self.os() {
218             OS::iOS => self.gpu_family() >= 3,
219             OS::tvOS => self.gpu_family() >= 2,
220             OS::macOS => false,
221         }
222     }
223 
supports_counting_occlusion_query(&self) -> bool224     pub fn supports_counting_occlusion_query(&self) -> bool {
225         match self.os() {
226             OS::iOS => self.gpu_family() >= 3,
227             OS::tvOS => self.gpu_family() >= 2,
228             OS::macOS => true,
229         }
230     }
231 
supports_base_vertex_instance_drawing(&self) -> bool232     pub fn supports_base_vertex_instance_drawing(&self) -> bool {
233         match self.os() {
234             OS::iOS => self.gpu_family() >= 3,
235             OS::tvOS => self.gpu_family() >= 2,
236             OS::macOS => true,
237         }
238     }
239 
supports_indirect_buffers(&self) -> bool240     pub fn supports_indirect_buffers(&self) -> bool {
241         match self.os() {
242             OS::iOS => self.gpu_family() >= 3,
243             OS::tvOS => self.gpu_family() >= 2,
244             OS::macOS => true,
245         }
246     }
247 
supports_cube_map_texture_arrays(&self) -> bool248     pub fn supports_cube_map_texture_arrays(&self) -> bool {
249         match self.os() {
250             OS::iOS => self.gpu_family() >= 4,
251             OS::tvOS => false,
252             OS::macOS => true,
253         }
254     }
255 
supports_texture_barriers(&self) -> bool256     pub fn supports_texture_barriers(&self) -> bool {
257         self.os() == OS::macOS
258     }
259 
supports_layered_rendering(&self) -> bool260     pub fn supports_layered_rendering(&self) -> bool {
261         match self.os() {
262             OS::iOS => self.gpu_family() >= 5,
263             OS::tvOS => false,
264             OS::macOS => true,
265         }
266     }
267 
supports_tessellation(&self) -> bool268     pub fn supports_tessellation(&self) -> bool {
269         match self.os() {
270             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 10,
271             OS::tvOS => self.gpu_family() >= 2,
272             OS::macOS => self.os_version() >= 12,
273         }
274     }
275 
supports_resource_heaps(&self) -> bool276     pub fn supports_resource_heaps(&self) -> bool {
277         match self.os() {
278             OS::iOS => self.os_version() >= 10,
279             OS::tvOS => self.os_version() >= 10,
280             OS::macOS => self.os_version() >= 13,
281         }
282     }
283 
supports_memoryless_render_targets(&self) -> bool284     pub fn supports_memoryless_render_targets(&self) -> bool {
285         match self.os() {
286             OS::iOS => self.os_version() >= 10,
287             OS::tvOS => self.os_version() >= 10,
288             OS::macOS => false,
289         }
290     }
291 
supports_function_specialization(&self) -> bool292     pub fn supports_function_specialization(&self) -> bool {
293         match self.os() {
294             OS::iOS => self.os_version() >= 10,
295             OS::tvOS => self.os_version() >= 10,
296             OS::macOS => self.os_version() >= 12,
297         }
298     }
299 
supports_function_buffer_read_writes(&self) -> bool300     pub fn supports_function_buffer_read_writes(&self) -> bool {
301         match self.os() {
302             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 10,
303             OS::tvOS => self.gpu_family() >= 2,
304             OS::macOS => self.os_version() >= 12,
305         }
306     }
307 
supports_function_texture_read_writes(&self) -> bool308     pub fn supports_function_texture_read_writes(&self) -> bool {
309         match self.os() {
310             OS::iOS => self.gpu_family() >= 4,
311             OS::tvOS => false,
312             OS::macOS => self.os_version() >= 12,
313         }
314     }
315 
supports_array_of_textures(&self) -> bool316     pub fn supports_array_of_textures(&self) -> bool {
317         match self.os() {
318             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 10,
319             OS::tvOS => self.gpu_family() >= 2,
320             OS::macOS => self.os_version() >= 13,
321         }
322     }
323 
supports_array_of_samplers(&self) -> bool324     pub fn supports_array_of_samplers(&self) -> bool {
325         match self.os() {
326             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 11,
327             OS::tvOS => self.gpu_family() >= 2,
328             OS::macOS => self.os_version() >= 12,
329         }
330     }
331 
supports_stencil_texture_views(&self) -> bool332     pub fn supports_stencil_texture_views(&self) -> bool {
333         match self.os() {
334             OS::iOS => self.os_version() >= 10,
335             OS::tvOS => self.os_version() >= 10,
336             OS::macOS => self.os_version() >= 12,
337         }
338     }
339 
supports_depth_16_pixel_format(&self) -> bool340     pub fn supports_depth_16_pixel_format(&self) -> bool {
341         self.os() == OS::macOS && self.os_version() >= 12
342     }
343 
supports_extended_range_pixel_formats(&self) -> bool344     pub fn supports_extended_range_pixel_formats(&self) -> bool {
345         match self.os() {
346             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 10,
347             OS::tvOS => self.gpu_family() >= 2,
348             OS::macOS => false,
349         }
350     }
351 
supports_wide_color_pixel_format(&self) -> bool352     pub fn supports_wide_color_pixel_format(&self) -> bool {
353         match self.os() {
354             OS::iOS => self.os_version() >= 11,
355             OS::tvOS => self.os_version() >= 11,
356             OS::macOS => self.os_version() >= 13,
357         }
358     }
359 
supports_combined_msaa_store_and_resolve_action(&self) -> bool360     pub fn supports_combined_msaa_store_and_resolve_action(&self) -> bool {
361         match self.os() {
362             OS::iOS => self.gpu_family() >= 3 && self.os_version() >= 10,
363             OS::tvOS => self.gpu_family() >= 2,
364             OS::macOS => self.os_version() >= 12,
365         }
366     }
367 
supports_deferred_store_action(&self) -> bool368     pub fn supports_deferred_store_action(&self) -> bool {
369         match self.os() {
370             OS::iOS => self.os_version() >= 10,
371             OS::tvOS => self.os_version() >= 10,
372             OS::macOS => self.os_version() >= 12,
373         }
374     }
375 
supports_msaa_blits(&self) -> bool376     pub fn supports_msaa_blits(&self) -> bool {
377         match self.os() {
378             OS::iOS => self.os_version() >= 10,
379             OS::tvOS => self.os_version() >= 10,
380             OS::macOS => true,
381         }
382     }
383 
supports_srgb_writes(&self) -> bool384     pub fn supports_srgb_writes(&self) -> bool {
385         match self.os() {
386             OS::iOS => self.gpu_family() >= 3 || (self.gpu_family() >= 2 && self.version() >= 3),
387             OS::tvOS => self.os_version() >= 10,
388             OS::macOS => self.gpu_family() >= 2,
389         }
390     }
391 
supports_16_bit_unsigned_integer_coordinates(&self) -> bool392     pub fn supports_16_bit_unsigned_integer_coordinates(&self) -> bool {
393         match self.os() {
394             OS::iOS => self.os_version() >= 10,
395             OS::tvOS => self.os_version() >= 10,
396             OS::macOS => self.os_version() >= 12,
397         }
398     }
399 
supports_extract_insert_and_reverse_bits(&self) -> bool400     pub fn supports_extract_insert_and_reverse_bits(&self) -> bool {
401         match self.os() {
402             OS::iOS => self.os_version() >= 10,
403             OS::tvOS => self.os_version() >= 10,
404             OS::macOS => self.os_version() >= 12,
405         }
406     }
407 
supports_simd_barrier(&self) -> bool408     pub fn supports_simd_barrier(&self) -> bool {
409         match self.os() {
410             OS::iOS => self.os_version() >= 10,
411             OS::tvOS => self.os_version() >= 10,
412             OS::macOS => self.os_version() >= 13,
413         }
414     }
415 
supports_sampler_max_anisotropy(&self) -> bool416     pub fn supports_sampler_max_anisotropy(&self) -> bool {
417         match self.os() {
418             OS::iOS => self.os_version() >= 10,
419             OS::tvOS => self.os_version() >= 10,
420             OS::macOS => self.os_version() >= 13,
421         }
422     }
423 
supports_sampler_lod_clamp(&self) -> bool424     pub fn supports_sampler_lod_clamp(&self) -> bool {
425         match self.os() {
426             OS::iOS => self.os_version() >= 10,
427             OS::tvOS => self.os_version() >= 10,
428             OS::macOS => self.os_version() >= 13,
429         }
430     }
431 
supports_border_color(&self) -> bool432     pub fn supports_border_color(&self) -> bool {
433         self.os() == OS::macOS && self.os_version() >= 12
434     }
435 
supports_dual_source_blending(&self) -> bool436     pub fn supports_dual_source_blending(&self) -> bool {
437         match self.os() {
438             OS::iOS => self.os_version() >= 11,
439             OS::tvOS => self.os_version() >= 11,
440             OS::macOS => self.os_version() >= 12,
441         }
442     }
443 
supports_argument_buffers(&self) -> bool444     pub fn supports_argument_buffers(&self) -> bool {
445         match self.os() {
446             OS::iOS => self.os_version() >= 11,
447             OS::tvOS => self.os_version() >= 11,
448             OS::macOS => self.os_version() >= 13,
449         }
450     }
451 
supports_programmable_sample_positions(&self) -> bool452     pub fn supports_programmable_sample_positions(&self) -> bool {
453         match self.os() {
454             OS::iOS => self.os_version() >= 11,
455             OS::tvOS => self.os_version() >= 11,
456             OS::macOS => self.os_version() >= 13,
457         }
458     }
459 
supports_uniform_type(&self) -> bool460     pub fn supports_uniform_type(&self) -> bool {
461         match self.os() {
462             OS::iOS => self.os_version() >= 11,
463             OS::tvOS => self.os_version() >= 11,
464             OS::macOS => self.os_version() >= 13,
465         }
466     }
467 
supports_imageblocks(&self) -> bool468     pub fn supports_imageblocks(&self) -> bool {
469         self.os() == OS::iOS && self.gpu_family() >= 4
470     }
471 
supports_tile_shaders(&self) -> bool472     pub fn supports_tile_shaders(&self) -> bool {
473         self.os() == OS::iOS && self.gpu_family() >= 4
474     }
475 
supports_imageblock_sample_coverage_control(&self) -> bool476     pub fn supports_imageblock_sample_coverage_control(&self) -> bool {
477         self.os() == OS::iOS && self.gpu_family() >= 4
478     }
479 
supports_threadgroup_sharing(&self) -> bool480     pub fn supports_threadgroup_sharing(&self) -> bool {
481         self.os() == OS::iOS && self.gpu_family() >= 4
482     }
483 
supports_post_depth_coverage(&self) -> bool484     pub fn supports_post_depth_coverage(&self) -> bool {
485         self.os() == OS::iOS && self.gpu_family() >= 4
486     }
487 
supports_quad_scoped_permute_operations(&self) -> bool488     pub fn supports_quad_scoped_permute_operations(&self) -> bool {
489         match self.os() {
490             OS::iOS => self.gpu_family() >= 4,
491             OS::tvOS => false,
492             OS::macOS => self.os_version() >= 13,
493         }
494     }
495 
supports_raster_order_groups(&self) -> bool496     pub fn supports_raster_order_groups(&self) -> bool {
497         match self.os() {
498             OS::iOS => self.gpu_family() >= 4,
499             OS::tvOS => false,
500             OS::macOS => self.os_version() >= 13,
501         }
502     }
503 
supports_non_uniform_threadgroup_size(&self) -> bool504     pub fn supports_non_uniform_threadgroup_size(&self) -> bool {
505         match self.os() {
506             OS::iOS => self.gpu_family() >= 4,
507             OS::tvOS => false,
508             OS::macOS => self.os_version() >= 13,
509         }
510     }
511 
supports_multiple_viewports(&self) -> bool512     pub fn supports_multiple_viewports(&self) -> bool {
513         match self.os() {
514             OS::iOS => self.gpu_family() >= 5,
515             OS::tvOS => false,
516             OS::macOS => self.os_version() >= 13,
517         }
518     }
519 
supports_device_notifications(&self) -> bool520     pub fn supports_device_notifications(&self) -> bool {
521         self.os() == OS::macOS && self.os_version() >= 13
522     }
523 
supports_stencil_feedback(&self) -> bool524     pub fn supports_stencil_feedback(&self) -> bool {
525         match self.os() {
526             OS::iOS => self.gpu_family() >= 5,
527             OS::tvOS => false,
528             OS::macOS => self.gpu_family() >= 2,
529         }
530     }
531 
supports_stencil_resolve(&self) -> bool532     pub fn supports_stencil_resolve(&self) -> bool {
533         match self.os() {
534             OS::iOS => self.gpu_family() >= 5,
535             OS::tvOS => false,
536             OS::macOS => self.gpu_family() >= 2,
537         }
538     }
539 
supports_binary_archive(&self) -> bool540     pub fn supports_binary_archive(&self) -> bool {
541         match self.os() {
542             OS::iOS => self.gpu_family() >= 3,
543             OS::tvOS => self.gpu_family() >= 3,
544             OS::macOS => self.gpu_family() >= 1,
545         }
546     }
547 
max_vertex_attributes(&self) -> u32548     pub fn max_vertex_attributes(&self) -> u32 {
549         31
550     }
551 
max_buffer_argument_entries(&self) -> u32552     pub fn max_buffer_argument_entries(&self) -> u32 {
553         31
554     }
555 
max_texture_argument_entries(&self) -> u32556     pub fn max_texture_argument_entries(&self) -> u32 {
557         if self.os() == OS::macOS {
558             128
559         } else {
560             31
561         }
562     }
563 
max_sampler_state_argument_entries(&self) -> u32564     pub fn max_sampler_state_argument_entries(&self) -> u32 {
565         16
566     }
567 
max_threadgroup_memory_argument_entries(&self) -> u32568     pub fn max_threadgroup_memory_argument_entries(&self) -> u32 {
569         31
570     }
571 
max_inlined_constant_data_buffers(&self) -> u32572     pub fn max_inlined_constant_data_buffers(&self) -> u32 {
573         if self.os() == OS::macOS {
574             14
575         } else {
576             31
577         }
578     }
579 
max_inline_constant_buffer_length(&self) -> u32580     pub fn max_inline_constant_buffer_length(&self) -> u32 {
581         4 * KB
582     }
583 
max_threads_per_threadgroup(&self) -> u32584     pub fn max_threads_per_threadgroup(&self) -> u32 {
585         if self.os() == OS::macOS || self.gpu_family() >= 4 {
586             1024
587         } else {
588             512
589         }
590     }
591 
max_total_threadgroup_memory_allocation(&self) -> u32592     pub fn max_total_threadgroup_memory_allocation(&self) -> u32 {
593         match (self.os(), self.gpu_family()) {
594             (OS::iOS, 5) => 64 * KB,
595             (OS::iOS, 4) => {
596                 if self.os_version() >= 12 {
597                     64 * KB
598                 } else {
599                     32 * KB
600                 }
601             }
602             (OS::iOS, 3) => 16 * KB,
603             (OS::iOS, _) => 16 * KB - 32,
604             (OS::tvOS, 1) => 16 * KB - 32,
605             (OS::tvOS, _) => 16 * KB,
606             (OS::macOS, _) => 32 * KB,
607         }
608     }
609 
max_total_tile_memory_allocation(&self) -> u32610     pub fn max_total_tile_memory_allocation(&self) -> u32 {
611         if self.os() == OS::iOS && self.gpu_family() == 4 {
612             32 * KB
613         } else {
614             0
615         }
616     }
617 
threadgroup_memory_length_alignment(&self) -> u32618     pub fn threadgroup_memory_length_alignment(&self) -> u32 {
619         16
620     }
621 
max_constant_buffer_function_memory_allocation(&self) -> Option<u32>622     pub fn max_constant_buffer_function_memory_allocation(&self) -> Option<u32> {
623         if self.os() == OS::macOS {
624             Some(64 * KB)
625         } else {
626             None
627         }
628     }
629 
max_fragment_inputs(&self) -> u32630     pub fn max_fragment_inputs(&self) -> u32 {
631         if self.os() == OS::macOS {
632             32
633         } else {
634             60
635         }
636     }
637 
max_fragment_input_components(&self) -> u32638     pub fn max_fragment_input_components(&self) -> u32 {
639         if self.os() == OS::macOS {
640             128
641         } else {
642             60
643         }
644     }
645 
max_function_constants(&self) -> u32646     pub fn max_function_constants(&self) -> u32 {
647         match self.os() {
648             OS::iOS if self.os_version() >= 11 => 65536,
649             OS::tvOS if self.os_version() >= 10 => 65536,
650             OS::macOS if self.os_version() >= 12 => 65536,
651             _ => 0,
652         }
653     }
654 
max_tessellation_factor(&self) -> u32655     pub fn max_tessellation_factor(&self) -> u32 {
656         if self.supports_tessellation() {
657             match self.os() {
658                 OS::iOS if self.gpu_family() >= 5 => 64,
659                 OS::iOS => 16,
660                 OS::tvOS => 16,
661                 OS::macOS => 64,
662             }
663         } else {
664             0
665         }
666     }
667 
max_viewports_and_scissor_rectangles(&self) -> u32668     pub fn max_viewports_and_scissor_rectangles(&self) -> u32 {
669         if self.supports_multiple_viewports() {
670             16
671         } else {
672             1
673         }
674     }
675 
max_raster_order_groups(&self) -> u32676     pub fn max_raster_order_groups(&self) -> u32 {
677         if self.supports_raster_order_groups() {
678             8
679         } else {
680             0
681         }
682     }
683 
max_buffer_length(&self) -> u32684     pub fn max_buffer_length(&self) -> u32 {
685         if self.os() == OS::macOS && self.os_version() >= 12 {
686             1 * GB
687         } else {
688             256 * MB
689         }
690     }
691 
min_buffer_offset_alignment(&self) -> u32692     pub fn min_buffer_offset_alignment(&self) -> u32 {
693         if self.os() == OS::macOS {
694             256
695         } else {
696             4
697         }
698     }
699 
max_1d_texture_size(&self) -> u32700     pub fn max_1d_texture_size(&self) -> u32 {
701         match (self.os(), self.gpu_family()) {
702             (OS::iOS, 1) | (OS::iOS, 2) => {
703                 if self.version() <= 2 {
704                     4096
705                 } else {
706                     8192
707                 }
708             }
709             (OS::tvOS, 1) => 8192,
710             _ => 16384,
711         }
712     }
713 
max_2d_texture_size(&self) -> u32714     pub fn max_2d_texture_size(&self) -> u32 {
715         match (self.os(), self.gpu_family()) {
716             (OS::iOS, 1) | (OS::iOS, 2) => {
717                 if self.version() <= 2 {
718                     4096
719                 } else {
720                     8192
721                 }
722             }
723             (OS::tvOS, 1) => 8192,
724             _ => 16384,
725         }
726     }
727 
max_cube_map_texture_size(&self) -> u32728     pub fn max_cube_map_texture_size(&self) -> u32 {
729         match (self.os(), self.gpu_family()) {
730             (OS::iOS, 1) | (OS::iOS, 2) => {
731                 if self.version() <= 2 {
732                     4096
733                 } else {
734                     8192
735                 }
736             }
737             (OS::tvOS, 1) => 8192,
738             _ => 16384,
739         }
740     }
741 
max_3d_texture_size(&self) -> u32742     pub fn max_3d_texture_size(&self) -> u32 {
743         2048
744     }
745 
max_array_layers(&self) -> u32746     pub fn max_array_layers(&self) -> u32 {
747         2048
748     }
749 
copy_texture_buffer_alignment(&self) -> u32750     pub fn copy_texture_buffer_alignment(&self) -> u32 {
751         match (self.os(), self.gpu_family()) {
752             (OS::iOS, 1) | (OS::iOS, 2) | (OS::tvOS, 1) => 64,
753             (OS::iOS, _) | (OS::tvOS, _) => 16,
754             (OS::macOS, _) => 256,
755         }
756     }
757 
758     /// If this function returns `None` but linear textures are supported,
759     /// the buffer alignment can be discovered via API query
new_texture_buffer_alignment(&self) -> Option<u32>760     pub fn new_texture_buffer_alignment(&self) -> Option<u32> {
761         match self.os() {
762             OS::iOS => {
763                 if self.os_version() >= 11 {
764                     None
765                 } else if self.gpu_family() == 3 {
766                     Some(16)
767                 } else {
768                     Some(64)
769                 }
770             }
771             OS::tvOS => {
772                 if self.os_version() >= 11 {
773                     None
774                 } else {
775                     Some(64)
776                 }
777             }
778             OS::macOS => None,
779         }
780     }
781 
max_color_render_targets(&self) -> u32782     pub fn max_color_render_targets(&self) -> u32 {
783         if self.os() == OS::iOS && self.gpu_family() == 1 {
784             4
785         } else {
786             8
787         }
788     }
789 
max_point_primitive_size(&self) -> u32790     pub fn max_point_primitive_size(&self) -> u32 {
791         511
792     }
793 
max_total_color_render_target_size(&self) -> Option<u32>794     pub fn max_total_color_render_target_size(&self) -> Option<u32> {
795         match (self.os(), self.gpu_family()) {
796             (OS::iOS, 1) => Some(128),
797             (OS::iOS, 2) | (OS::iOS, 3) => Some(256),
798             (OS::iOS, _) => Some(512),
799             (OS::tvOS, _) => Some(256),
800             (OS::macOS, _) => None,
801         }
802     }
803 
max_visibility_query_offset(&self) -> u32804     pub fn max_visibility_query_offset(&self) -> u32 {
805         64 * KB - 8
806     }
807 
a8_unorm_capabilities(&self) -> PixelFormatCapabilities808     pub fn a8_unorm_capabilities(&self) -> PixelFormatCapabilities {
809         PixelFormatCapabilities::Filter
810     }
811 
r8_unorm_capabilities(&self) -> PixelFormatCapabilities812     pub fn r8_unorm_capabilities(&self) -> PixelFormatCapabilities {
813         PixelFormatCapabilities::all()
814     }
815 
r8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities816     pub fn r8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities {
817         if self.os() == OS::macOS {
818             PixelFormatCapabilities::empty()
819         } else if self.supports_srgb_writes() {
820             PixelFormatCapabilities::all()
821         } else {
822             !PixelFormatCapabilities::Write
823         }
824     }
825 
r8_snorm_capabilities(&self) -> PixelFormatCapabilities826     pub fn r8_snorm_capabilities(&self) -> PixelFormatCapabilities {
827         if self.os() == OS::iOS && self.gpu_family() == 1 {
828             !PixelFormatCapabilities::Resolve
829         } else {
830             PixelFormatCapabilities::all()
831         }
832     }
833 
r8_uint_capabilities(&self) -> PixelFormatCapabilities834     pub fn r8_uint_capabilities(&self) -> PixelFormatCapabilities {
835         PixelFormatCapabilities::Write
836             | PixelFormatCapabilities::Color
837             | PixelFormatCapabilities::Msaa
838     }
839 
r8_sint_capabilities(&self) -> PixelFormatCapabilities840     pub fn r8_sint_capabilities(&self) -> PixelFormatCapabilities {
841         PixelFormatCapabilities::Write
842             | PixelFormatCapabilities::Color
843             | PixelFormatCapabilities::Msaa
844     }
845 
r16_unorm_capabilities(&self) -> PixelFormatCapabilities846     pub fn r16_unorm_capabilities(&self) -> PixelFormatCapabilities {
847         if self.os() != OS::macOS {
848             !PixelFormatCapabilities::Resolve
849         } else {
850             PixelFormatCapabilities::all()
851         }
852     }
853 
r16_snorm_capabilities(&self) -> PixelFormatCapabilities854     pub fn r16_snorm_capabilities(&self) -> PixelFormatCapabilities {
855         if self.os() != OS::macOS {
856             !PixelFormatCapabilities::Resolve
857         } else {
858             PixelFormatCapabilities::all()
859         }
860     }
861 
r16_uint_capabilities(&self) -> PixelFormatCapabilities862     pub fn r16_uint_capabilities(&self) -> PixelFormatCapabilities {
863         PixelFormatCapabilities::Write
864             | PixelFormatCapabilities::Color
865             | PixelFormatCapabilities::Msaa
866     }
867 
r16_sint_capabilities(&self) -> PixelFormatCapabilities868     pub fn r16_sint_capabilities(&self) -> PixelFormatCapabilities {
869         PixelFormatCapabilities::Write
870             | PixelFormatCapabilities::Color
871             | PixelFormatCapabilities::Msaa
872     }
873 
r16_float_capabilities(&self) -> PixelFormatCapabilities874     pub fn r16_float_capabilities(&self) -> PixelFormatCapabilities {
875         PixelFormatCapabilities::all()
876     }
877 
rg8_unorm_capabilities(&self) -> PixelFormatCapabilities878     pub fn rg8_unorm_capabilities(&self) -> PixelFormatCapabilities {
879         PixelFormatCapabilities::all()
880     }
881 
rg8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities882     pub fn rg8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities {
883         if self.os() == OS::macOS {
884             PixelFormatCapabilities::empty()
885         } else if self.supports_srgb_writes() {
886             PixelFormatCapabilities::all()
887         } else {
888             !PixelFormatCapabilities::Write
889         }
890     }
891 
rg8_snorm_capabilities(&self) -> PixelFormatCapabilities892     pub fn rg8_snorm_capabilities(&self) -> PixelFormatCapabilities {
893         if self.os() == OS::iOS && self.gpu_family() == 1 {
894             !PixelFormatCapabilities::Resolve
895         } else {
896             PixelFormatCapabilities::all()
897         }
898     }
899 
rg8_uint_capabilities(&self) -> PixelFormatCapabilities900     pub fn rg8_uint_capabilities(&self) -> PixelFormatCapabilities {
901         PixelFormatCapabilities::Write
902             | PixelFormatCapabilities::Color
903             | PixelFormatCapabilities::Msaa
904     }
905 
rg8_sint_capabilities(&self) -> PixelFormatCapabilities906     pub fn rg8_sint_capabilities(&self) -> PixelFormatCapabilities {
907         PixelFormatCapabilities::Write
908             | PixelFormatCapabilities::Color
909             | PixelFormatCapabilities::Msaa
910     }
911 
b5_g6_r5_unorm_capabilities(&self) -> PixelFormatCapabilities912     pub fn b5_g6_r5_unorm_capabilities(&self) -> PixelFormatCapabilities {
913         if self.os() == OS::macOS {
914             PixelFormatCapabilities::empty()
915         } else {
916             !PixelFormatCapabilities::Write
917         }
918     }
919 
a1_bgr5_unorm_capabilities(&self) -> PixelFormatCapabilities920     pub fn a1_bgr5_unorm_capabilities(&self) -> PixelFormatCapabilities {
921         if self.os() == OS::macOS {
922             PixelFormatCapabilities::empty()
923         } else {
924             !PixelFormatCapabilities::Write
925         }
926     }
927 
abgr4_unorm_capabilities(&self) -> PixelFormatCapabilities928     pub fn abgr4_unorm_capabilities(&self) -> PixelFormatCapabilities {
929         if self.os() == OS::macOS {
930             PixelFormatCapabilities::empty()
931         } else {
932             !PixelFormatCapabilities::Write
933         }
934     }
935 
bgr5_a1_unorm_capabilities(&self) -> PixelFormatCapabilities936     pub fn bgr5_a1_unorm_capabilities(&self) -> PixelFormatCapabilities {
937         if self.os() == OS::macOS {
938             PixelFormatCapabilities::empty()
939         } else {
940             !PixelFormatCapabilities::Write
941         }
942     }
943 
r32_uint_capabilities(&self) -> PixelFormatCapabilities944     pub fn r32_uint_capabilities(&self) -> PixelFormatCapabilities {
945         if self.os() == OS::iOS && self.os_version() == 8 {
946             PixelFormatCapabilities::Color
947         } else if self.os() == OS::macOS {
948             PixelFormatCapabilities::Color
949                 | PixelFormatCapabilities::Write
950                 | PixelFormatCapabilities::Msaa
951         } else {
952             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
953         }
954     }
955 
r32_sint_capabilities(&self) -> PixelFormatCapabilities956     pub fn r32_sint_capabilities(&self) -> PixelFormatCapabilities {
957         if self.os() == OS::iOS && self.os_version() == 8 {
958             PixelFormatCapabilities::Color
959         } else if self.os() == OS::macOS {
960             PixelFormatCapabilities::Color
961                 | PixelFormatCapabilities::Write
962                 | PixelFormatCapabilities::Msaa
963         } else {
964             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
965         }
966     }
967 
r32_float_capabilities(&self) -> PixelFormatCapabilities968     pub fn r32_float_capabilities(&self) -> PixelFormatCapabilities {
969         if self.os() == OS::iOS && self.os_version() == 8 {
970             PixelFormatCapabilities::Color
971                 | PixelFormatCapabilities::Blend
972                 | PixelFormatCapabilities::Msaa
973         } else if self.os() == OS::macOS {
974             PixelFormatCapabilities::all()
975         } else {
976             PixelFormatCapabilities::Write
977                 | PixelFormatCapabilities::Color
978                 | PixelFormatCapabilities::Blend
979                 | PixelFormatCapabilities::Msaa
980         }
981     }
982 
rg16_unorm_capabilities(&self) -> PixelFormatCapabilities983     pub fn rg16_unorm_capabilities(&self) -> PixelFormatCapabilities {
984         if self.os() == OS::macOS {
985             PixelFormatCapabilities::all()
986         } else {
987             !PixelFormatCapabilities::Resolve
988         }
989     }
990 
rg16_snorm_capabilities(&self) -> PixelFormatCapabilities991     pub fn rg16_snorm_capabilities(&self) -> PixelFormatCapabilities {
992         if self.os() == OS::macOS {
993             PixelFormatCapabilities::all()
994         } else {
995             !PixelFormatCapabilities::Resolve
996         }
997     }
998 
rg16_uint_capabilities(&self) -> PixelFormatCapabilities999     pub fn rg16_uint_capabilities(&self) -> PixelFormatCapabilities {
1000         PixelFormatCapabilities::Write
1001             | PixelFormatCapabilities::Color
1002             | PixelFormatCapabilities::Msaa
1003     }
1004 
rg16_sint_capabilities(&self) -> PixelFormatCapabilities1005     pub fn rg16_sint_capabilities(&self) -> PixelFormatCapabilities {
1006         PixelFormatCapabilities::Write
1007             | PixelFormatCapabilities::Color
1008             | PixelFormatCapabilities::Msaa
1009     }
1010 
rg16_float_capabilities(&self) -> PixelFormatCapabilities1011     pub fn rg16_float_capabilities(&self) -> PixelFormatCapabilities {
1012         PixelFormatCapabilities::all()
1013     }
1014 
rgba8_unorm_capabilities(&self) -> PixelFormatCapabilities1015     pub fn rgba8_unorm_capabilities(&self) -> PixelFormatCapabilities {
1016         PixelFormatCapabilities::all()
1017     }
1018 
rgba8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities1019     pub fn rgba8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities {
1020         if self.supports_srgb_writes() {
1021             PixelFormatCapabilities::all()
1022         } else {
1023             !PixelFormatCapabilities::Write
1024         }
1025     }
1026 
rgba8_snorm_capabilities(&self) -> PixelFormatCapabilities1027     pub fn rgba8_snorm_capabilities(&self) -> PixelFormatCapabilities {
1028         if self.os() == OS::iOS && self.gpu_family() == 1 {
1029             !PixelFormatCapabilities::Resolve
1030         } else {
1031             PixelFormatCapabilities::all()
1032         }
1033     }
1034 
rgba8_uint_capabilities(&self) -> PixelFormatCapabilities1035     pub fn rgba8_uint_capabilities(&self) -> PixelFormatCapabilities {
1036         PixelFormatCapabilities::Write
1037             | PixelFormatCapabilities::Color
1038             | PixelFormatCapabilities::Msaa
1039     }
1040 
rgba8_sint_capabilities(&self) -> PixelFormatCapabilities1041     pub fn rgba8_sint_capabilities(&self) -> PixelFormatCapabilities {
1042         PixelFormatCapabilities::Write
1043             | PixelFormatCapabilities::Color
1044             | PixelFormatCapabilities::Msaa
1045     }
1046 
bgra8_unorm_capabilities(&self) -> PixelFormatCapabilities1047     pub fn bgra8_unorm_capabilities(&self) -> PixelFormatCapabilities {
1048         PixelFormatCapabilities::all()
1049     }
1050 
bgra8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities1051     pub fn bgra8_unorm_srgb_capabilities(&self) -> PixelFormatCapabilities {
1052         if self.supports_srgb_writes() {
1053             PixelFormatCapabilities::all()
1054         } else {
1055             !PixelFormatCapabilities::Write
1056         }
1057     }
1058 
rgb10_a2_unorm_capabilities(&self) -> PixelFormatCapabilities1059     pub fn rgb10_a2_unorm_capabilities(&self) -> PixelFormatCapabilities {
1060         let supports_writes = match self.os() {
1061             OS::iOS => self.gpu_family() >= 3,
1062             OS::tvOS => self.gpu_family() >= 2,
1063             OS::macOS => true,
1064         };
1065         if supports_writes {
1066             PixelFormatCapabilities::all()
1067         } else {
1068             !PixelFormatCapabilities::Write
1069         }
1070     }
1071 
rgb10_a2_uint_capabilities(&self) -> PixelFormatCapabilities1072     pub fn rgb10_a2_uint_capabilities(&self) -> PixelFormatCapabilities {
1073         let supports_writes = match self.os() {
1074             OS::iOS => self.gpu_family() >= 3,
1075             OS::tvOS => self.gpu_family() >= 2,
1076             OS::macOS => true,
1077         };
1078         if supports_writes {
1079             PixelFormatCapabilities::Write
1080                 | PixelFormatCapabilities::Color
1081                 | PixelFormatCapabilities::Msaa
1082         } else {
1083             PixelFormatCapabilities::Color | PixelFormatCapabilities::Msaa
1084         }
1085     }
1086 
rg11_b10_float_capabilities(&self) -> PixelFormatCapabilities1087     pub fn rg11_b10_float_capabilities(&self) -> PixelFormatCapabilities {
1088         let supports_writes = match self.os() {
1089             OS::iOS => self.gpu_family() >= 3,
1090             OS::tvOS => self.gpu_family() >= 2,
1091             OS::macOS => true,
1092         };
1093         if supports_writes {
1094             PixelFormatCapabilities::all()
1095         } else {
1096             !PixelFormatCapabilities::Write
1097         }
1098     }
1099 
rgb9_e5_float_capabilities(&self) -> PixelFormatCapabilities1100     pub fn rgb9_e5_float_capabilities(&self) -> PixelFormatCapabilities {
1101         if self.os() == OS::macOS {
1102             PixelFormatCapabilities::Filter
1103         } else {
1104             let supports_writes = match self.os() {
1105                 OS::iOS => self.gpu_family() >= 3,
1106                 OS::tvOS => self.gpu_family() >= 2,
1107                 OS::macOS => false,
1108             };
1109             if supports_writes {
1110                 PixelFormatCapabilities::all()
1111             } else {
1112                 !PixelFormatCapabilities::Write
1113             }
1114         }
1115     }
1116 
rg32_uint_capabilities(&self) -> PixelFormatCapabilities1117     pub fn rg32_uint_capabilities(&self) -> PixelFormatCapabilities {
1118         if self.os() == OS::iOS && self.os_version() == 8 {
1119             PixelFormatCapabilities::Color
1120         } else if self.os() == OS::macOS {
1121             PixelFormatCapabilities::Color
1122                 | PixelFormatCapabilities::Write
1123                 | PixelFormatCapabilities::Msaa
1124         } else {
1125             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
1126         }
1127     }
1128 
rg32_sint_capabilities(&self) -> PixelFormatCapabilities1129     pub fn rg32_sint_capabilities(&self) -> PixelFormatCapabilities {
1130         if self.os() == OS::iOS && self.os_version() == 8 {
1131             PixelFormatCapabilities::Color
1132         } else if self.os() == OS::macOS {
1133             PixelFormatCapabilities::Color
1134                 | PixelFormatCapabilities::Write
1135                 | PixelFormatCapabilities::Msaa
1136         } else {
1137             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
1138         }
1139     }
1140 
rg32_float_capabilities(&self) -> PixelFormatCapabilities1141     pub fn rg32_float_capabilities(&self) -> PixelFormatCapabilities {
1142         if self.os() == OS::macOS {
1143             PixelFormatCapabilities::all()
1144         } else if self.os() == OS::iOS && self.os_version() == 8 {
1145             PixelFormatCapabilities::Color | PixelFormatCapabilities::Blend
1146         } else {
1147             PixelFormatCapabilities::Write
1148                 | PixelFormatCapabilities::Color
1149                 | PixelFormatCapabilities::Blend
1150         }
1151     }
1152 
rgba16_unorm_capabilities(&self) -> PixelFormatCapabilities1153     pub fn rgba16_unorm_capabilities(&self) -> PixelFormatCapabilities {
1154         if self.os() == OS::macOS {
1155             PixelFormatCapabilities::all()
1156         } else {
1157             !PixelFormatCapabilities::Write
1158         }
1159     }
1160 
rgba16_snorm_capabilities(&self) -> PixelFormatCapabilities1161     pub fn rgba16_snorm_capabilities(&self) -> PixelFormatCapabilities {
1162         if self.os() == OS::macOS {
1163             PixelFormatCapabilities::all()
1164         } else {
1165             !PixelFormatCapabilities::Write
1166         }
1167     }
1168 
rgba16_uint_capabilities(&self) -> PixelFormatCapabilities1169     pub fn rgba16_uint_capabilities(&self) -> PixelFormatCapabilities {
1170         PixelFormatCapabilities::Write
1171             | PixelFormatCapabilities::Color
1172             | PixelFormatCapabilities::Msaa
1173     }
1174 
rgba16_sint_capabilities(&self) -> PixelFormatCapabilities1175     pub fn rgba16_sint_capabilities(&self) -> PixelFormatCapabilities {
1176         PixelFormatCapabilities::Write
1177             | PixelFormatCapabilities::Color
1178             | PixelFormatCapabilities::Msaa
1179     }
1180 
rgba16_float_capabilities(&self) -> PixelFormatCapabilities1181     pub fn rgba16_float_capabilities(&self) -> PixelFormatCapabilities {
1182         PixelFormatCapabilities::all()
1183     }
1184 
rgba32_uint_capabilities(&self) -> PixelFormatCapabilities1185     pub fn rgba32_uint_capabilities(&self) -> PixelFormatCapabilities {
1186         if self.os() == OS::iOS && self.os_version() == 8 {
1187             PixelFormatCapabilities::Color
1188         } else if self.os() == OS::macOS {
1189             PixelFormatCapabilities::Color
1190                 | PixelFormatCapabilities::Write
1191                 | PixelFormatCapabilities::Msaa
1192         } else {
1193             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
1194         }
1195     }
1196 
rgba32_sint_capabilities(&self) -> PixelFormatCapabilities1197     pub fn rgba32_sint_capabilities(&self) -> PixelFormatCapabilities {
1198         if self.os() == OS::iOS && self.os_version() == 8 {
1199             PixelFormatCapabilities::Color
1200         } else if self.os() == OS::macOS {
1201             PixelFormatCapabilities::Color
1202                 | PixelFormatCapabilities::Write
1203                 | PixelFormatCapabilities::Msaa
1204         } else {
1205             PixelFormatCapabilities::Color | PixelFormatCapabilities::Write
1206         }
1207     }
1208 
rgba32_float_capabilities(&self) -> PixelFormatCapabilities1209     pub fn rgba32_float_capabilities(&self) -> PixelFormatCapabilities {
1210         if self.os() == OS::macOS {
1211             PixelFormatCapabilities::all()
1212         } else if self.os() == OS::iOS && self.version() == 8 {
1213             PixelFormatCapabilities::Color
1214         } else {
1215             PixelFormatCapabilities::Write | PixelFormatCapabilities::Color
1216         }
1217     }
1218 
pvrtc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities1219     pub fn pvrtc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities {
1220         if self.supports_pvrtc_pixel_formats() {
1221             PixelFormatCapabilities::Filter
1222         } else {
1223             PixelFormatCapabilities::empty()
1224         }
1225     }
1226 
eac_etc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities1227     pub fn eac_etc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities {
1228         if self.supports_eac_etc_pixel_formats() {
1229             PixelFormatCapabilities::Filter
1230         } else {
1231             PixelFormatCapabilities::empty()
1232         }
1233     }
1234 
astc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities1235     pub fn astc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities {
1236         if self.supports_astc_pixel_formats() {
1237             PixelFormatCapabilities::Filter
1238         } else {
1239             PixelFormatCapabilities::empty()
1240         }
1241     }
1242 
bc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities1243     pub fn bc_pixel_formats_capabilities(&self) -> PixelFormatCapabilities {
1244         if self.supports_bc_pixel_formats() {
1245             PixelFormatCapabilities::Filter
1246         } else {
1247             PixelFormatCapabilities::empty()
1248         }
1249     }
1250 
gbgr422_capabilities(&self) -> PixelFormatCapabilities1251     pub fn gbgr422_capabilities(&self) -> PixelFormatCapabilities {
1252         PixelFormatCapabilities::Filter
1253     }
1254 
bgrg422_capabilities(&self) -> PixelFormatCapabilities1255     pub fn bgrg422_capabilities(&self) -> PixelFormatCapabilities {
1256         PixelFormatCapabilities::Filter
1257     }
1258 
depth16_unorm_capabilities(&self) -> PixelFormatCapabilities1259     pub fn depth16_unorm_capabilities(&self) -> PixelFormatCapabilities {
1260         if self.supports_depth_16_pixel_format() {
1261             PixelFormatCapabilities::Filter
1262                 | PixelFormatCapabilities::Msaa
1263                 | PixelFormatCapabilities::Resolve
1264         } else {
1265             PixelFormatCapabilities::empty()
1266         }
1267     }
1268 
depth32_float_capabilities(&self) -> PixelFormatCapabilities1269     pub fn depth32_float_capabilities(&self) -> PixelFormatCapabilities {
1270         if self.os() == OS::macOS {
1271             PixelFormatCapabilities::Filter
1272                 | PixelFormatCapabilities::Msaa
1273                 | PixelFormatCapabilities::Resolve
1274         } else if self.supports_msaa_depth_resolve() {
1275             PixelFormatCapabilities::Msaa | PixelFormatCapabilities::Resolve
1276         } else {
1277             PixelFormatCapabilities::Msaa
1278         }
1279     }
1280 
stencil8_capabilities(&self) -> PixelFormatCapabilities1281     pub fn stencil8_capabilities(&self) -> PixelFormatCapabilities {
1282         PixelFormatCapabilities::Msaa
1283     }
1284 
depth24_unorm_stencil8_capabilities(&self) -> PixelFormatCapabilities1285     pub fn depth24_unorm_stencil8_capabilities(&self) -> PixelFormatCapabilities {
1286         if self.os() == OS::macOS {
1287             PixelFormatCapabilities::Filter
1288                 | PixelFormatCapabilities::Msaa
1289                 | PixelFormatCapabilities::Resolve
1290         } else {
1291             PixelFormatCapabilities::empty()
1292         }
1293     }
1294 
depth32_float_stencil8_capabilities(&self) -> PixelFormatCapabilities1295     pub fn depth32_float_stencil8_capabilities(&self) -> PixelFormatCapabilities {
1296         if self.os() == OS::macOS {
1297             PixelFormatCapabilities::Filter
1298                 | PixelFormatCapabilities::Msaa
1299                 | PixelFormatCapabilities::Resolve
1300         } else if self.supports_msaa_depth_resolve() {
1301             PixelFormatCapabilities::Msaa | PixelFormatCapabilities::Resolve
1302         } else {
1303             PixelFormatCapabilities::Msaa
1304         }
1305     }
1306 
x24_stencil8_capabilities(&self) -> PixelFormatCapabilities1307     pub fn x24_stencil8_capabilities(&self) -> PixelFormatCapabilities {
1308         if self.os() == OS::macOS {
1309             PixelFormatCapabilities::Msaa
1310         } else {
1311             PixelFormatCapabilities::empty()
1312         }
1313     }
1314 
x32_stencil8_capabilities(&self) -> PixelFormatCapabilities1315     pub fn x32_stencil8_capabilities(&self) -> PixelFormatCapabilities {
1316         PixelFormatCapabilities::Msaa
1317     }
1318 
bgra10_xr_capabilities(&self) -> PixelFormatCapabilities1319     pub fn bgra10_xr_capabilities(&self) -> PixelFormatCapabilities {
1320         if self.supports_extended_range_pixel_formats() {
1321             PixelFormatCapabilities::all()
1322         } else {
1323             PixelFormatCapabilities::empty()
1324         }
1325     }
1326 
bgra10_xr_srgb_capabilities(&self) -> PixelFormatCapabilities1327     pub fn bgra10_xr_srgb_capabilities(&self) -> PixelFormatCapabilities {
1328         if self.supports_extended_range_pixel_formats() {
1329             PixelFormatCapabilities::all()
1330         } else {
1331             PixelFormatCapabilities::empty()
1332         }
1333     }
1334 
bgr10_xr_capabilities(&self) -> PixelFormatCapabilities1335     pub fn bgr10_xr_capabilities(&self) -> PixelFormatCapabilities {
1336         if self.supports_extended_range_pixel_formats() {
1337             PixelFormatCapabilities::all()
1338         } else {
1339             PixelFormatCapabilities::empty()
1340         }
1341     }
1342 
bgr10_xr_srgb_capabilities(&self) -> PixelFormatCapabilities1343     pub fn bgr10_xr_srgb_capabilities(&self) -> PixelFormatCapabilities {
1344         if self.supports_extended_range_pixel_formats() {
1345             PixelFormatCapabilities::all()
1346         } else {
1347             PixelFormatCapabilities::empty()
1348         }
1349     }
1350 
bgr10_a2_unorm_capabilities(&self) -> PixelFormatCapabilities1351     pub fn bgr10_a2_unorm_capabilities(&self) -> PixelFormatCapabilities {
1352         if self.supports_wide_color_pixel_format() {
1353             if self.os() == OS::macOS {
1354                 !PixelFormatCapabilities::Write
1355             } else {
1356                 PixelFormatCapabilities::all()
1357             }
1358         } else {
1359             PixelFormatCapabilities::empty()
1360         }
1361     }
1362 }
1363 
1364 #[repr(u64)]
1365 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1366 pub enum MTLArgumentBuffersTier {
1367     Tier1 = 0,
1368     Tier2 = 1,
1369 }
1370 
1371 #[repr(u64)]
1372 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1373 pub enum MTLReadWriteTextureTier {
1374     TierNone = 0,
1375     Tier1 = 1,
1376     Tier2 = 2,
1377 }
1378 
1379 /// Only available on (macos(11.0), ios(14.0))
1380 #[repr(u64)]
1381 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1382 pub enum MTLCounterSamplingPoint {
1383     AtStageBoundary = 0,
1384     AtDrawBoundary = 1,
1385     AtDispatchBoundary = 2,
1386     AtTileDispatchBoundary = 3,
1387     AtBlitBoundary = 4,
1388 }
1389 
1390 /// Only available on (macos(11.0), macCatalyst(14.0), ios(13.0))
1391 #[repr(u64)]
1392 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1393 pub enum MTLSparseTextureRegionAlignmentMode {
1394     Outward = 0,
1395     Inward = 1,
1396 }
1397 
1398 bitflags! {
1399     struct MTLPipelineOption: NSUInteger {
1400         const None                      = 0;
1401         const ArgumentInfo              = 1 << 0;
1402         const BufferTypeInfo            = 1 << 1;
1403         /// Only available on (macos(11.0), ios(14.0))
1404         const FailOnBinaryArchiveMiss   = 1 << 2;
1405     }
1406 }
1407 
1408 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1409 #[repr(C)]
1410 pub struct MTLAccelerationStructureSizes {
1411     pub acceleration_structure_size: NSUInteger,
1412     pub build_scratch_buffer_size: NSUInteger,
1413     pub refit_scratch_buffer_size: NSUInteger,
1414 }
1415 
1416 #[link(name = "Metal", kind = "framework")]
1417 extern "C" {
MTLCreateSystemDefaultDevice() -> *mut MTLDevice1418     fn MTLCreateSystemDefaultDevice() -> *mut MTLDevice;
1419     #[cfg(not(target_os = "ios"))]
MTLCopyAllDevices() -> *mut Object1420     fn MTLCopyAllDevices() -> *mut Object; //TODO: Array
1421 }
1422 
1423 #[allow(non_camel_case_types)]
1424 type dispatch_data_t = id;
1425 #[allow(non_camel_case_types)]
1426 pub type dispatch_queue_t = id;
1427 #[allow(non_camel_case_types)]
1428 type dispatch_block_t = *const Block<(), ()>;
1429 
1430 #[cfg_attr(
1431     any(target_os = "macos", target_os = "ios"),
1432     link(name = "System", kind = "dylib")
1433 )]
1434 #[cfg_attr(
1435     not(any(target_os = "macos", target_os = "ios")),
1436     link(name = "dispatch", kind = "dylib")
1437 )]
1438 #[allow(improper_ctypes)]
1439 extern "C" {
1440     static _dispatch_main_q: dispatch_queue_t;
1441 
dispatch_data_create( buffer: *const std::ffi::c_void, size: crate::c_size_t, queue: dispatch_queue_t, destructor: dispatch_block_t, ) -> dispatch_data_t1442     fn dispatch_data_create(
1443         buffer: *const std::ffi::c_void,
1444         size: crate::c_size_t,
1445         queue: dispatch_queue_t,
1446         destructor: dispatch_block_t,
1447     ) -> dispatch_data_t;
dispatch_release(object: dispatch_data_t)1448     fn dispatch_release(object: dispatch_data_t); // actually dispatch_object_t
1449 }
1450 
1451 /*type MTLNewLibraryCompletionHandler = extern fn(library: id, error: id);
1452 type MTLNewRenderPipelineStateCompletionHandler = extern fn(renderPipelineState: id, error: id);
1453 type MTLNewRenderPipelineStateWithReflectionCompletionHandler = extern fn(renderPipelineState: id, reflection: id, error: id);
1454 type MTLNewComputePipelineStateCompletionHandler = extern fn(computePipelineState: id, error: id);
1455 type MTLNewComputePipelineStateWithReflectionCompletionHandler = extern fn(computePipelineState: id, reflection: id, error: id);*/
1456 
1457 pub enum MTLDevice {}
1458 
1459 foreign_obj_type! {
1460     type CType = MTLDevice;
1461     pub struct Device;
1462     pub struct DeviceRef;
1463 }
1464 
1465 impl Device {
system_default() -> Option<Self>1466     pub fn system_default() -> Option<Self> {
1467         // `MTLCreateSystemDefaultDevice` may return null if Metal is not supported
1468         unsafe { MTLCreateSystemDefaultDevice().as_mut().map(|x| Self(x)) }
1469     }
1470 
all() -> Vec<Self>1471     pub fn all() -> Vec<Self> {
1472         #[cfg(target_os = "ios")]
1473         {
1474             Self::system_default().into_iter().collect()
1475         }
1476         #[cfg(not(target_os = "ios"))]
1477         unsafe {
1478             let array = MTLCopyAllDevices();
1479             let count: NSUInteger = msg_send![array, count];
1480             let ret = (0..count)
1481                 .map(|i| msg_send![array, objectAtIndex: i])
1482                 // The elements of this array are references---we convert them to owned references
1483                 // (which just means that we increment the reference count here, and it is
1484                 // decremented in the `Drop` impl for `Device`)
1485                 .map(|device: *mut Object| msg_send![device, retain])
1486                 .collect();
1487             let () = msg_send![array, release];
1488             ret
1489         }
1490     }
1491 }
1492 
1493 impl DeviceRef {
name(&self) -> &str1494     pub fn name(&self) -> &str {
1495         unsafe {
1496             let name = msg_send![self, name];
1497             crate::nsstring_as_str(name)
1498         }
1499     }
1500 
1501     #[cfg(feature = "private")]
vendor(&self) -> &str1502     pub unsafe fn vendor(&self) -> &str {
1503         let name = msg_send![self, vendorName];
1504         crate::nsstring_as_str(name)
1505     }
1506 
1507     #[cfg(feature = "private")]
family_name(&self) -> &str1508     pub unsafe fn family_name(&self) -> &str {
1509         let name = msg_send![self, familyName];
1510         crate::nsstring_as_str(name)
1511     }
1512 
registry_id(&self) -> u641513     pub fn registry_id(&self) -> u64 {
1514         unsafe { msg_send![self, registryID] }
1515     }
1516 
location(&self) -> MTLDeviceLocation1517     pub fn location(&self) -> MTLDeviceLocation {
1518         unsafe { msg_send![self, location] }
1519     }
1520 
location_number(&self) -> NSUInteger1521     pub fn location_number(&self) -> NSUInteger {
1522         unsafe { msg_send![self, locationNumber] }
1523     }
1524 
max_threadgroup_memory_length(&self) -> NSUInteger1525     pub fn max_threadgroup_memory_length(&self) -> NSUInteger {
1526         unsafe { msg_send![self, maxThreadgroupMemoryLength] }
1527     }
1528 
max_threads_per_threadgroup(&self) -> MTLSize1529     pub fn max_threads_per_threadgroup(&self) -> MTLSize {
1530         unsafe { msg_send![self, maxThreadsPerThreadgroup] }
1531     }
1532 
is_low_power(&self) -> bool1533     pub fn is_low_power(&self) -> bool {
1534         unsafe {
1535             match msg_send![self, isLowPower] {
1536                 YES => true,
1537                 NO => false,
1538                 _ => unreachable!(),
1539             }
1540         }
1541     }
1542 
is_headless(&self) -> bool1543     pub fn is_headless(&self) -> bool {
1544         unsafe {
1545             match msg_send![self, isHeadless] {
1546                 YES => true,
1547                 NO => false,
1548                 _ => unreachable!(),
1549             }
1550         }
1551     }
1552 
is_removable(&self) -> bool1553     pub fn is_removable(&self) -> bool {
1554         unsafe {
1555             match msg_send![self, isRemovable] {
1556                 YES => true,
1557                 NO => false,
1558                 _ => unreachable!(),
1559             }
1560         }
1561     }
1562 
1563     /// Only available on (macos(11.0), ios(14.0))
supports_raytracing(&self) -> bool1564     pub fn supports_raytracing(&self) -> bool {
1565         unsafe {
1566             match msg_send![self, supportsRaytracing] {
1567                 YES => true,
1568                 NO => false,
1569                 _ => unreachable!(),
1570             }
1571         }
1572     }
1573 
has_unified_memory(&self) -> bool1574     pub fn has_unified_memory(&self) -> bool {
1575         unsafe {
1576             match msg_send![self, hasUnifiedMemory] {
1577                 YES => true,
1578                 NO => false,
1579                 _ => unreachable!(),
1580             }
1581         }
1582     }
1583 
recommended_max_working_set_size(&self) -> u641584     pub fn recommended_max_working_set_size(&self) -> u64 {
1585         unsafe { msg_send![self, recommendedMaxWorkingSetSize] }
1586     }
1587 
max_transfer_rate(&self) -> u641588     pub fn max_transfer_rate(&self) -> u64 {
1589         unsafe { msg_send![self, maxTransferRate] }
1590     }
1591 
supports_feature_set(&self, feature: MTLFeatureSet) -> bool1592     pub fn supports_feature_set(&self, feature: MTLFeatureSet) -> bool {
1593         unsafe {
1594             match msg_send![self, supportsFeatureSet: feature] {
1595                 YES => true,
1596                 NO => false,
1597                 _ => unreachable!(),
1598             }
1599         }
1600     }
1601 
supports_family(&self, family: MTLGPUFamily) -> bool1602     pub fn supports_family(&self, family: MTLGPUFamily) -> bool {
1603         unsafe {
1604             match msg_send![self, supportsFamily: family] {
1605                 YES => true,
1606                 NO => false,
1607                 _ => unreachable!(),
1608             }
1609         }
1610     }
1611 
supports_vertex_amplification_count(&self, count: NSUInteger) -> bool1612     pub fn supports_vertex_amplification_count(&self, count: NSUInteger) -> bool {
1613         unsafe {
1614             match msg_send![self, supportsVertexAmplificationCount: count] {
1615                 YES => true,
1616                 NO => false,
1617                 _ => unreachable!(),
1618             }
1619         }
1620     }
1621 
supports_texture_sample_count(&self, count: NSUInteger) -> bool1622     pub fn supports_texture_sample_count(&self, count: NSUInteger) -> bool {
1623         unsafe {
1624             match msg_send![self, supportsTextureSampleCount: count] {
1625                 YES => true,
1626                 NO => false,
1627                 _ => unreachable!(),
1628             }
1629         }
1630     }
1631 
supports_shader_barycentric_coordinates(&self) -> bool1632     pub fn supports_shader_barycentric_coordinates(&self) -> bool {
1633         unsafe {
1634             match msg_send![self, supportsShaderBarycentricCoordinates] {
1635                 YES => true,
1636                 NO => false,
1637                 _ => unreachable!(),
1638             }
1639         }
1640     }
1641 
supports_function_pointers(&self) -> bool1642     pub fn supports_function_pointers(&self) -> bool {
1643         unsafe {
1644             match msg_send![self, supportsFunctionPointers] {
1645                 YES => true,
1646                 NO => false,
1647                 _ => unreachable!(),
1648             }
1649         }
1650     }
1651 
1652     /// Only available on (macos(11.0), ios(14.0))
supports_dynamic_libraries(&self) -> bool1653     pub fn supports_dynamic_libraries(&self) -> bool {
1654         unsafe {
1655             match msg_send![self, supportsDynamicLibraries] {
1656                 YES => true,
1657                 NO => false,
1658                 _ => unreachable!(),
1659             }
1660         }
1661     }
1662 
1663     /// Only available on (macos(11.0), ios(14.0))
supports_counter_sampling(&self, sampling_point: MTLCounterSamplingPoint) -> bool1664     pub fn supports_counter_sampling(&self, sampling_point: MTLCounterSamplingPoint) -> bool {
1665         unsafe {
1666             match msg_send![self, supportsCounterSampling: sampling_point] {
1667                 YES => true,
1668                 NO => false,
1669                 _ => unreachable!(),
1670             }
1671         }
1672     }
1673 
d24_s8_supported(&self) -> bool1674     pub fn d24_s8_supported(&self) -> bool {
1675         unsafe {
1676             match msg_send![self, isDepth24Stencil8PixelFormatSupported] {
1677                 YES => true,
1678                 NO => false,
1679                 _ => unreachable!(),
1680             }
1681         }
1682     }
1683 
new_fence(&self) -> Fence1684     pub fn new_fence(&self) -> Fence {
1685         unsafe { msg_send![self, newFence] }
1686     }
1687 
new_command_queue(&self) -> CommandQueue1688     pub fn new_command_queue(&self) -> CommandQueue {
1689         unsafe { msg_send![self, newCommandQueue] }
1690     }
1691 
new_command_queue_with_max_command_buffer_count( &self, count: NSUInteger, ) -> CommandQueue1692     pub fn new_command_queue_with_max_command_buffer_count(
1693         &self,
1694         count: NSUInteger,
1695     ) -> CommandQueue {
1696         unsafe { msg_send![self, newCommandQueueWithMaxCommandBufferCount: count] }
1697     }
1698 
new_default_library(&self) -> Library1699     pub fn new_default_library(&self) -> Library {
1700         unsafe { msg_send![self, newDefaultLibrary] }
1701     }
1702 
new_library_with_source( &self, src: &str, options: &CompileOptionsRef, ) -> Result<Library, String>1703     pub fn new_library_with_source(
1704         &self,
1705         src: &str,
1706         options: &CompileOptionsRef,
1707     ) -> Result<Library, String> {
1708         use cocoa_foundation::base::nil as cocoa_nil;
1709         use cocoa_foundation::foundation::NSString as cocoa_NSString;
1710 
1711         unsafe {
1712             let source = cocoa_NSString::alloc(cocoa_nil).init_str(src);
1713             let mut err: *mut Object = ptr::null_mut();
1714             let library: *mut MTLLibrary = msg_send![self, newLibraryWithSource:source
1715                                                                         options:options
1716                                                                           error:&mut err];
1717             let () = msg_send![source, release];
1718             if !err.is_null() {
1719                 let desc: *mut Object = msg_send![err, localizedDescription];
1720                 let compile_error: *const c_char = msg_send![desc, UTF8String];
1721                 let message = CStr::from_ptr(compile_error).to_string_lossy().into_owned();
1722                 if library.is_null() {
1723                     return Err(message);
1724                 } else {
1725                     warn!("Shader warnings: {}", message);
1726                 }
1727             }
1728 
1729             assert!(!library.is_null());
1730             Ok(Library::from_ptr(library))
1731         }
1732     }
1733 
new_library_with_file<P: AsRef<Path>>(&self, file: P) -> Result<Library, String>1734     pub fn new_library_with_file<P: AsRef<Path>>(&self, file: P) -> Result<Library, String> {
1735         use cocoa_foundation::base::nil as cocoa_nil;
1736         use cocoa_foundation::foundation::NSString as cocoa_NSString;
1737 
1738         unsafe {
1739             let filename =
1740                 cocoa_NSString::alloc(cocoa_nil).init_str(file.as_ref().to_string_lossy().as_ref());
1741 
1742             let library: *mut MTLLibrary = try_objc! { err =>
1743                 msg_send![self, newLibraryWithFile:filename.as_ref()
1744                                              error:&mut err]
1745             };
1746 
1747             Ok(Library::from_ptr(library))
1748         }
1749     }
1750 
new_library_with_data(&self, library_data: &[u8]) -> Result<Library, String>1751     pub fn new_library_with_data(&self, library_data: &[u8]) -> Result<Library, String> {
1752         unsafe {
1753             let destructor_block = ConcreteBlock::new(|| {}).copy();
1754             let data = dispatch_data_create(
1755                 library_data.as_ptr() as *const std::ffi::c_void,
1756                 library_data.len() as crate::c_size_t,
1757                 &_dispatch_main_q as *const _ as dispatch_queue_t,
1758                 &*destructor_block.deref(),
1759             );
1760 
1761             let library: *mut MTLLibrary = try_objc! { err =>
1762                  msg_send![self, newLibraryWithData:data
1763                                               error:&mut err]
1764             };
1765             dispatch_release(data);
1766             Ok(Library::from_ptr(library))
1767         }
1768     }
1769 
1770     /// Only available on (macos(11.0), ios(14.0))
new_dynamic_library(&self, library: &LibraryRef) -> Result<DynamicLibrary, String>1771     pub fn new_dynamic_library(&self, library: &LibraryRef) -> Result<DynamicLibrary, String> {
1772         unsafe {
1773             let mut err: *mut Object = ptr::null_mut();
1774             let dynamic_library: *mut MTLDynamicLibrary = msg_send![self, newDynamicLibrary:library
1775                                                                                       error:&mut err];
1776             if !err.is_null() {
1777                 // FIXME: copy pasta
1778                 let desc: *mut Object = msg_send![err, localizedDescription];
1779                 let compile_error: *const c_char = msg_send![desc, UTF8String];
1780                 let message = CStr::from_ptr(compile_error).to_string_lossy().into_owned();
1781                 Err(message)
1782             } else {
1783                 Ok(DynamicLibrary::from_ptr(dynamic_library))
1784             }
1785         }
1786     }
1787 
1788     /// Only available on (macos(11.0), ios(14.0))
new_dynamic_library_with_url(&self, url: &URLRef) -> Result<DynamicLibrary, String>1789     pub fn new_dynamic_library_with_url(&self, url: &URLRef) -> Result<DynamicLibrary, String> {
1790         unsafe {
1791             let mut err: *mut Object = ptr::null_mut();
1792             let dynamic_library: *mut MTLDynamicLibrary = msg_send![self, newDynamicLibraryWithURL:url
1793                                                                                              error:&mut err];
1794             if !err.is_null() {
1795                 // FIXME: copy pasta
1796                 let desc: *mut Object = msg_send![err, localizedDescription];
1797                 let compile_error: *const c_char = msg_send![desc, UTF8String];
1798                 let message = CStr::from_ptr(compile_error).to_string_lossy().into_owned();
1799                 Err(message)
1800             } else {
1801                 Ok(DynamicLibrary::from_ptr(dynamic_library))
1802             }
1803         }
1804     }
1805 
1806     /// Only available on (macos(11.0), ios(14.0))
new_binary_archive_with_descriptor( &self, descriptor: &BinaryArchiveDescriptorRef, ) -> Result<BinaryArchive, String>1807     pub fn new_binary_archive_with_descriptor(
1808         &self,
1809         descriptor: &BinaryArchiveDescriptorRef,
1810     ) -> Result<BinaryArchive, String> {
1811         unsafe {
1812             let mut err: *mut Object = ptr::null_mut();
1813             let binary_archive: *mut MTLBinaryArchive = msg_send![self, newBinaryArchiveWithDescriptor:descriptor
1814                                                      error:&mut err];
1815             if !err.is_null() {
1816                 // TODO: copy pasta
1817                 let desc: *mut Object = msg_send![err, localizedDescription];
1818                 let c_msg: *const c_char = msg_send![desc, UTF8String];
1819                 let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned();
1820                 Err(message)
1821             } else {
1822                 Ok(BinaryArchive::from_ptr(binary_archive))
1823             }
1824         }
1825     }
1826 
new_render_pipeline_state_with_reflection( &self, descriptor: &RenderPipelineDescriptorRef, reflection: &RenderPipelineReflectionRef, ) -> Result<RenderPipelineState, String>1827     pub fn new_render_pipeline_state_with_reflection(
1828         &self,
1829         descriptor: &RenderPipelineDescriptorRef,
1830         reflection: &RenderPipelineReflectionRef,
1831     ) -> Result<RenderPipelineState, String> {
1832         unsafe {
1833             let reflection_options =
1834                 MTLPipelineOption::ArgumentInfo | MTLPipelineOption::BufferTypeInfo;
1835 
1836             let pipeline_state: *mut MTLRenderPipelineState = try_objc! { err =>
1837                 msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
1838                                                              options:reflection_options
1839                                                           reflection:reflection
1840                                                                error:&mut err]
1841             };
1842 
1843             Ok(RenderPipelineState::from_ptr(pipeline_state))
1844         }
1845     }
1846 
1847     /// Useful for debugging binary archives.
new_render_pipeline_state_with_fail_on_binary_archive_miss( &self, descriptor: &RenderPipelineDescriptorRef, ) -> Result<RenderPipelineState, String>1848     pub fn new_render_pipeline_state_with_fail_on_binary_archive_miss(
1849         &self,
1850         descriptor: &RenderPipelineDescriptorRef,
1851     ) -> Result<RenderPipelineState, String> {
1852         unsafe {
1853             let pipeline_options = MTLPipelineOption::FailOnBinaryArchiveMiss;
1854 
1855             let reflection: *mut MTLRenderPipelineReflection = std::ptr::null_mut();
1856 
1857             let pipeline_state: *mut MTLRenderPipelineState = try_objc! { err =>
1858                 msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
1859                                                              options:pipeline_options
1860                                                           reflection:reflection
1861                                                                error:&mut err]
1862             };
1863 
1864             Ok(RenderPipelineState::from_ptr(pipeline_state))
1865         }
1866     }
1867 
new_render_pipeline_state( &self, descriptor: &RenderPipelineDescriptorRef, ) -> Result<RenderPipelineState, String>1868     pub fn new_render_pipeline_state(
1869         &self,
1870         descriptor: &RenderPipelineDescriptorRef,
1871     ) -> Result<RenderPipelineState, String> {
1872         unsafe {
1873             let pipeline_state: *mut MTLRenderPipelineState = try_objc! { err =>
1874                 msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
1875                                                                error:&mut err]
1876             };
1877 
1878             Ok(RenderPipelineState::from_ptr(pipeline_state))
1879         }
1880     }
1881 
new_compute_pipeline_state_with_function( &self, function: &FunctionRef, ) -> Result<ComputePipelineState, String>1882     pub fn new_compute_pipeline_state_with_function(
1883         &self,
1884         function: &FunctionRef,
1885     ) -> Result<ComputePipelineState, String> {
1886         unsafe {
1887             let pipeline_state: *mut MTLComputePipelineState = try_objc! { err =>
1888                 msg_send![self, newComputePipelineStateWithFunction:function
1889                                                               error:&mut err]
1890             };
1891 
1892             Ok(ComputePipelineState::from_ptr(pipeline_state))
1893         }
1894     }
1895 
new_compute_pipeline_state( &self, descriptor: &ComputePipelineDescriptorRef, ) -> Result<ComputePipelineState, String>1896     pub fn new_compute_pipeline_state(
1897         &self,
1898         descriptor: &ComputePipelineDescriptorRef,
1899     ) -> Result<ComputePipelineState, String> {
1900         unsafe {
1901             let pipeline_state: *mut MTLComputePipelineState = try_objc! { err =>
1902                 msg_send![self, newComputePipelineStateWithDescriptor:descriptor
1903                                                                 error:&mut err]
1904             };
1905 
1906             Ok(ComputePipelineState::from_ptr(pipeline_state))
1907         }
1908     }
1909 
new_buffer(&self, length: u64, options: MTLResourceOptions) -> Buffer1910     pub fn new_buffer(&self, length: u64, options: MTLResourceOptions) -> Buffer {
1911         unsafe {
1912             msg_send![self, newBufferWithLength:length
1913                                         options:options]
1914         }
1915     }
1916 
new_buffer_with_data( &self, bytes: *const std::ffi::c_void, length: NSUInteger, options: MTLResourceOptions, ) -> Buffer1917     pub fn new_buffer_with_data(
1918         &self,
1919         bytes: *const std::ffi::c_void,
1920         length: NSUInteger,
1921         options: MTLResourceOptions,
1922     ) -> Buffer {
1923         unsafe {
1924             msg_send![self, newBufferWithBytes:bytes
1925                                         length:length
1926                                        options:options]
1927         }
1928     }
1929 
new_texture(&self, descriptor: &TextureDescriptorRef) -> Texture1930     pub fn new_texture(&self, descriptor: &TextureDescriptorRef) -> Texture {
1931         unsafe { msg_send![self, newTextureWithDescriptor: descriptor] }
1932     }
1933 
new_sampler(&self, descriptor: &SamplerDescriptorRef) -> SamplerState1934     pub fn new_sampler(&self, descriptor: &SamplerDescriptorRef) -> SamplerState {
1935         unsafe { msg_send![self, newSamplerStateWithDescriptor: descriptor] }
1936     }
1937 
new_depth_stencil_state( &self, descriptor: &DepthStencilDescriptorRef, ) -> DepthStencilState1938     pub fn new_depth_stencil_state(
1939         &self,
1940         descriptor: &DepthStencilDescriptorRef,
1941     ) -> DepthStencilState {
1942         unsafe { msg_send![self, newDepthStencilStateWithDescriptor: descriptor] }
1943     }
1944 
argument_buffers_support(&self) -> MTLArgumentBuffersTier1945     pub fn argument_buffers_support(&self) -> MTLArgumentBuffersTier {
1946         unsafe { msg_send![self, argumentBuffersSupport] }
1947     }
1948 
read_write_texture_support(&self) -> MTLReadWriteTextureTier1949     pub fn read_write_texture_support(&self) -> MTLReadWriteTextureTier {
1950         unsafe { msg_send![self, readWriteTextureSupport] }
1951     }
1952 
raster_order_groups_supported(&self) -> bool1953     pub fn raster_order_groups_supported(&self) -> bool {
1954         unsafe {
1955             match msg_send![self, rasterOrderGroupsSupported] {
1956                 YES => true,
1957                 NO => false,
1958                 _ => unreachable!(),
1959             }
1960         }
1961     }
1962 
1963     /// Only available on (macos(11.0), ios(14.0))
supports_32bit_float_filtering(&self) -> bool1964     pub fn supports_32bit_float_filtering(&self) -> bool {
1965         unsafe {
1966             match msg_send![self, supports32BitFloatFiltering] {
1967                 YES => true,
1968                 NO => false,
1969                 _ => unreachable!(),
1970             }
1971         }
1972     }
1973 
1974     /// Only available on (macos(11.0), ios(14.0))
supports_32bit_MSAA(&self) -> bool1975     pub fn supports_32bit_MSAA(&self) -> bool {
1976         unsafe {
1977             match msg_send![self, supports32BitMSAA] {
1978                 YES => true,
1979                 NO => false,
1980                 _ => unreachable!(),
1981             }
1982         }
1983     }
1984 
1985     /// Only available on (macos(11.0), ios(14.0))
supports_query_texture_LOD(&self) -> bool1986     pub fn supports_query_texture_LOD(&self) -> bool {
1987         unsafe {
1988             match msg_send![self, supportsQueryTextureLOD] {
1989                 YES => true,
1990                 NO => false,
1991                 _ => unreachable!(),
1992             }
1993         }
1994     }
1995 
1996     /// Only available on (macos(11.0), ios(14.0))
supports_BC_texture_compression(&self) -> bool1997     pub fn supports_BC_texture_compression(&self) -> bool {
1998         unsafe {
1999             match msg_send![self, supportsBCTextureCompression] {
2000                 YES => true,
2001                 NO => false,
2002                 _ => unreachable!(),
2003             }
2004         }
2005     }
2006 
2007     /// Only available on (macos(11.0), ios(14.0))
supports_pull_model_interpolation(&self) -> bool2008     pub fn supports_pull_model_interpolation(&self) -> bool {
2009         unsafe {
2010             match msg_send![self, supportsPullModelInterpolation] {
2011                 YES => true,
2012                 NO => false,
2013                 _ => unreachable!(),
2014             }
2015         }
2016     }
2017 
new_argument_encoder( &self, arguments: &ArrayRef<ArgumentDescriptor>, ) -> ArgumentEncoder2018     pub fn new_argument_encoder(
2019         &self,
2020         arguments: &ArrayRef<ArgumentDescriptor>,
2021     ) -> ArgumentEncoder {
2022         unsafe { msg_send![self, newArgumentEncoderWithArguments: arguments] }
2023     }
2024 
new_heap(&self, descriptor: &HeapDescriptorRef) -> Heap2025     pub fn new_heap(&self, descriptor: &HeapDescriptorRef) -> Heap {
2026         unsafe { msg_send![self, newHeapWithDescriptor: descriptor] }
2027     }
2028 
new_event(&self) -> Event2029     pub fn new_event(&self) -> Event {
2030         unsafe { msg_send![self, newEvent] }
2031     }
2032 
new_shared_event(&self) -> SharedEvent2033     pub fn new_shared_event(&self) -> SharedEvent {
2034         unsafe { msg_send![self, newSharedEvent] }
2035     }
2036 
heap_buffer_size_and_align( &self, length: NSUInteger, options: MTLResourceOptions, ) -> MTLSizeAndAlign2037     pub fn heap_buffer_size_and_align(
2038         &self,
2039         length: NSUInteger,
2040         options: MTLResourceOptions,
2041     ) -> MTLSizeAndAlign {
2042         unsafe { msg_send![self, heapBufferSizeAndAlignWithLength: length options: options] }
2043     }
2044 
heap_texture_size_and_align( &self, descriptor: &TextureDescriptorRef, ) -> MTLSizeAndAlign2045     pub fn heap_texture_size_and_align(
2046         &self,
2047         descriptor: &TextureDescriptorRef,
2048     ) -> MTLSizeAndAlign {
2049         unsafe { msg_send![self, heapTextureSizeAndAlignWithDescriptor: descriptor] }
2050     }
2051 
minimum_linear_texture_alignment_for_pixel_format( &self, format: MTLPixelFormat, ) -> NSUInteger2052     pub fn minimum_linear_texture_alignment_for_pixel_format(
2053         &self,
2054         format: MTLPixelFormat,
2055     ) -> NSUInteger {
2056         unsafe { msg_send![self, minimumLinearTextureAlignmentForPixelFormat: format] }
2057     }
2058 
minimum_texture_buffer_alignment_for_pixel_format( &self, format: MTLPixelFormat, ) -> NSUInteger2059     pub fn minimum_texture_buffer_alignment_for_pixel_format(
2060         &self,
2061         format: MTLPixelFormat,
2062     ) -> NSUInteger {
2063         unsafe { msg_send![self, minimumTextureBufferAlignmentForPixelFormat: format] }
2064     }
2065 
max_argument_buffer_sampler_count(&self) -> NSUInteger2066     pub fn max_argument_buffer_sampler_count(&self) -> NSUInteger {
2067         unsafe { msg_send![self, maxArgumentBufferSamplerCount] }
2068     }
2069 
current_allocated_size(&self) -> NSUInteger2070     pub fn current_allocated_size(&self) -> NSUInteger {
2071         unsafe { msg_send![self, currentAllocatedSize] }
2072     }
2073 
2074     /// Only available on (macos(10.14), ios(12.0), tvos(12.0))
max_buffer_length(&self) -> NSUInteger2075     pub fn max_buffer_length(&self) -> NSUInteger {
2076         unsafe { msg_send![self, maxBufferLength] }
2077     }
2078 }
2079