1use crate::{ffi, ArgumentEncoder, MetalDevice, SamplerState};
2
3const DATA_TYPE_TEXTURE: usize = 58;
4const DATA_TYPE_SAMPLER: usize = 59;
5const DATA_TYPE_POINTER: usize = 60;
6
7pub mod argument_buffers_tier {
9 pub const TIER1: usize = 0;
11 pub const TIER2: usize = 1;
13}
14
15pub mod binding_access {
17 pub const READ_ONLY: usize = 0;
19 pub const READ_WRITE: usize = 1;
21 pub const WRITE_ONLY: usize = 2;
23}
24
25pub mod texture_type {
27 pub const TYPE_1D: usize = 0;
29 pub const TYPE_1D_ARRAY: usize = 1;
31 pub const TYPE_2D: usize = 2;
33 pub const TYPE_2D_ARRAY: usize = 3;
35 pub const TYPE_2D_MULTISAMPLE: usize = 4;
37 pub const CUBE: usize = 5;
39 pub const CUBE_ARRAY: usize = 6;
41 pub const TYPE_3D: usize = 7;
43 pub const TYPE_2D_MULTISAMPLE_ARRAY: usize = 8;
45 pub const TEXTURE_BUFFER: usize = 9;
47}
48
49#[derive(Debug, Clone, Copy)]
51pub struct ArgumentDescriptor {
52 data_type: usize,
53 index: usize,
54 array_length: usize,
55 access: usize,
56 texture_type: usize,
57 constant_block_alignment: usize,
58}
59
60impl ArgumentDescriptor {
61 #[must_use]
63 pub const fn buffer(index: usize, access: usize) -> Self {
64 Self {
65 data_type: DATA_TYPE_POINTER,
66 index,
67 array_length: 0,
68 access,
69 texture_type: texture_type::TYPE_2D,
70 constant_block_alignment: 0,
71 }
72 }
73
74 #[must_use]
76 pub const fn texture(index: usize, texture_type: usize, access: usize) -> Self {
77 Self {
78 data_type: DATA_TYPE_TEXTURE,
79 index,
80 array_length: 0,
81 access,
82 texture_type,
83 constant_block_alignment: 0,
84 }
85 }
86
87 #[must_use]
89 pub const fn sampler(index: usize) -> Self {
90 Self {
91 data_type: DATA_TYPE_SAMPLER,
92 index,
93 array_length: 0,
94 access: binding_access::READ_ONLY,
95 texture_type: texture_type::TYPE_2D,
96 constant_block_alignment: 0,
97 }
98 }
99
100 #[must_use]
102 pub const fn constant(data_type: usize, index: usize, array_length: usize) -> Self {
103 Self {
104 data_type,
105 index,
106 array_length,
107 access: binding_access::READ_ONLY,
108 texture_type: texture_type::TYPE_2D,
109 constant_block_alignment: 0,
110 }
111 }
112
113 #[must_use]
115 pub fn with_array_length(mut self, array_length: usize) -> Self {
116 self.array_length = array_length;
117 self
118 }
119
120 #[must_use]
122 pub fn with_constant_block_alignment(mut self, alignment: usize) -> Self {
123 self.constant_block_alignment = alignment;
124 self
125 }
126
127 const fn as_words(self) -> [usize; 6] {
128 [
129 self.data_type,
130 self.index,
131 self.array_length,
132 self.access,
133 self.texture_type,
134 self.constant_block_alignment,
135 ]
136 }
137}
138
139impl MetalDevice {
140 #[must_use]
142 pub fn new_argument_encoder_with_descriptors(
143 &self,
144 descriptors: &[ArgumentDescriptor],
145 ) -> Option<ArgumentEncoder> {
146 let mut words = Vec::with_capacity(descriptors.len().saturating_mul(6));
147 for descriptor in descriptors {
148 words.extend_from_slice(&descriptor.as_words());
149 }
150 let ptr = unsafe {
151 ffi::am_device_new_argument_encoder_with_descriptors(
152 self.as_ptr(),
153 words.as_ptr(),
154 descriptors.len(),
155 )
156 };
157 if ptr.is_null() {
158 None
159 } else {
160 Some(unsafe { ArgumentEncoder::from_retained_ptr(ptr) })
161 }
162 }
163}
164
165impl ArgumentEncoder {
166 pub fn set_sampler_state(&self, sampler: &SamplerState, index: usize) {
168 unsafe {
169 ffi::am_argument_encoder_set_sampler_state(self.as_ptr(), sampler.as_ptr(), index);
170 };
171 }
172}