mtl_gpu/encoder/
parallel_render_encoder.rs1use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::{Referencing, UInteger};
9use mtl_sys::{msg_send_0, msg_send_1, sel};
10
11use crate::enums::{StoreAction, StoreActionOptions};
12
13#[repr(transparent)]
20pub struct ParallelRenderCommandEncoder(pub(crate) NonNull<c_void>);
21
22impl ParallelRenderCommandEncoder {
23 #[inline]
29 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
30 NonNull::new(ptr).map(Self)
31 }
32
33 #[inline]
35 pub fn as_raw(&self) -> *mut c_void {
36 self.0.as_ptr()
37 }
38
39 pub fn device(&self) -> crate::Device {
47 unsafe {
48 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(device));
49 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
50 crate::Device::from_raw(ptr).expect("encoder has no device")
51 }
52 }
53
54 pub fn command_buffer(&self) -> crate::CommandBuffer {
58 unsafe {
59 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(commandBuffer));
60 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
61 crate::CommandBuffer::from_raw(ptr).expect("encoder has no command buffer")
62 }
63 }
64
65 pub fn label(&self) -> Option<String> {
69 unsafe {
70 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
71 if ptr.is_null() {
72 return None;
73 }
74 let utf8_ptr: *const std::ffi::c_char =
75 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
76 if utf8_ptr.is_null() {
77 return None;
78 }
79 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
80 Some(c_str.to_string_lossy().into_owned())
81 }
82 }
83
84 pub fn set_label(&self, label: &str) {
88 if let Some(ns_label) = mtl_foundation::String::from_str(label) {
89 unsafe {
90 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
91 }
92 }
93 }
94
95 #[inline]
99 pub fn end_encoding(&self) {
100 unsafe {
101 msg_send_0::<()>(self.as_ptr(), sel!(endEncoding));
102 }
103 }
104
105 pub fn insert_debug_signpost(&self, string: &str) {
109 if let Some(ns_string) = mtl_foundation::String::from_str(string) {
110 unsafe {
111 msg_send_1::<(), *const c_void>(
112 self.as_ptr(),
113 sel!(insertDebugSignpost:),
114 ns_string.as_ptr(),
115 );
116 }
117 }
118 }
119
120 pub fn push_debug_group(&self, string: &str) {
124 if let Some(ns_string) = mtl_foundation::String::from_str(string) {
125 unsafe {
126 msg_send_1::<(), *const c_void>(
127 self.as_ptr(),
128 sel!(pushDebugGroup:),
129 ns_string.as_ptr(),
130 );
131 }
132 }
133 }
134
135 #[inline]
139 pub fn pop_debug_group(&self) {
140 unsafe {
141 msg_send_0::<()>(self.as_ptr(), sel!(popDebugGroup));
142 }
143 }
144
145 #[inline]
149 pub fn barrier_after_queue_stages(
150 &self,
151 after_stages: crate::enums::Stages,
152 before_stages: crate::enums::Stages,
153 ) {
154 unsafe {
155 mtl_sys::msg_send_2::<(), crate::enums::Stages, crate::enums::Stages>(
156 self.as_ptr(),
157 sel!(barrierAfterQueueStages:beforeQueueStages:),
158 after_stages,
159 before_stages,
160 );
161 }
162 }
163
164 #[inline]
175 pub fn render_command_encoder(&self) -> Option<crate::RenderCommandEncoder> {
176 unsafe {
177 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(renderCommandEncoder));
178 if ptr.is_null() {
179 None
180 } else {
181 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
183 crate::encoder::RenderCommandEncoder::from_raw(ptr)
184 }
185 }
186 }
187
188 #[inline]
192 pub fn set_color_store_action(
193 &self,
194 store_action: StoreAction,
195 color_attachment_index: UInteger,
196 ) {
197 unsafe {
198 mtl_sys::msg_send_2::<(), StoreAction, UInteger>(
199 self.as_ptr(),
200 sel!(setColorStoreAction: atIndex:),
201 store_action,
202 color_attachment_index,
203 );
204 }
205 }
206
207 #[inline]
211 pub fn set_color_store_action_options(
212 &self,
213 store_action_options: StoreActionOptions,
214 color_attachment_index: UInteger,
215 ) {
216 unsafe {
217 mtl_sys::msg_send_2::<(), StoreActionOptions, UInteger>(
218 self.as_ptr(),
219 sel!(setColorStoreActionOptions: atIndex:),
220 store_action_options,
221 color_attachment_index,
222 );
223 }
224 }
225
226 #[inline]
230 pub fn set_depth_store_action(&self, store_action: StoreAction) {
231 unsafe {
232 msg_send_1::<(), StoreAction>(self.as_ptr(), sel!(setDepthStoreAction:), store_action);
233 }
234 }
235
236 #[inline]
240 pub fn set_depth_store_action_options(&self, store_action_options: StoreActionOptions) {
241 unsafe {
242 msg_send_1::<(), StoreActionOptions>(
243 self.as_ptr(),
244 sel!(setDepthStoreActionOptions:),
245 store_action_options,
246 );
247 }
248 }
249
250 #[inline]
254 pub fn set_stencil_store_action(&self, store_action: StoreAction) {
255 unsafe {
256 msg_send_1::<(), StoreAction>(
257 self.as_ptr(),
258 sel!(setStencilStoreAction:),
259 store_action,
260 );
261 }
262 }
263
264 #[inline]
268 pub fn set_stencil_store_action_options(&self, store_action_options: StoreActionOptions) {
269 unsafe {
270 msg_send_1::<(), StoreActionOptions>(
271 self.as_ptr(),
272 sel!(setStencilStoreActionOptions:),
273 store_action_options,
274 );
275 }
276 }
277}
278
279impl Clone for ParallelRenderCommandEncoder {
280 fn clone(&self) -> Self {
281 unsafe {
282 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
283 }
284 Self(self.0)
285 }
286}
287
288impl Drop for ParallelRenderCommandEncoder {
289 fn drop(&mut self) {
290 unsafe {
291 msg_send_0::<()>(self.as_ptr(), sel!(release));
292 }
293 }
294}
295
296impl Referencing for ParallelRenderCommandEncoder {
297 #[inline]
298 fn as_ptr(&self) -> *const c_void {
299 self.0.as_ptr()
300 }
301}
302
303unsafe impl Send for ParallelRenderCommandEncoder {}
304unsafe impl Sync for ParallelRenderCommandEncoder {}
305
306impl std::fmt::Debug for ParallelRenderCommandEncoder {
307 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308 f.debug_struct("ParallelRenderCommandEncoder")
309 .field("label", &self.label())
310 .finish()
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_parallel_render_encoder_size() {
320 assert_eq!(
321 std::mem::size_of::<ParallelRenderCommandEncoder>(),
322 std::mem::size_of::<*mut c_void>()
323 );
324 }
325}