summaryrefslogtreecommitdiffstats
path: root/third_party/rust/metal/src/sync.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/metal/src/sync.rs')
-rw-r--r--third_party/rust/metal/src/sync.rs177
1 files changed, 177 insertions, 0 deletions
diff --git a/third_party/rust/metal/src/sync.rs b/third_party/rust/metal/src/sync.rs
new file mode 100644
index 0000000000..e4b3d8aa67
--- /dev/null
+++ b/third_party/rust/metal/src/sync.rs
@@ -0,0 +1,177 @@
+// Copyright 2016 GFX developers
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use super::*;
+use block::{Block, RcBlock};
+use std::mem;
+
+#[cfg(feature = "dispatch_queue")]
+use dispatch;
+
+type MTLSharedEventNotificationBlock<'a> = RcBlock<(&'a SharedEventRef, u64), ()>;
+
+pub enum MTLEvent {}
+
+foreign_obj_type! {
+ type CType = MTLEvent;
+ pub struct Event;
+ pub struct EventRef;
+}
+
+impl EventRef {
+ pub fn device(&self) -> &DeviceRef {
+ unsafe { msg_send![self, device] }
+ }
+}
+
+pub enum MTLSharedEvent {}
+
+foreign_obj_type! {
+ type CType = MTLSharedEvent;
+ pub struct SharedEvent;
+ pub struct SharedEventRef;
+ type ParentType = EventRef;
+}
+
+impl SharedEventRef {
+ pub fn signaled_value(&self) -> u64 {
+ unsafe { msg_send![self, signaledValue] }
+ }
+
+ pub fn set_signaled_value(&self, new_value: u64) {
+ unsafe { msg_send![self, setSignaledValue: new_value] }
+ }
+
+ /// Schedules a notification handler to be called after the shareable event’s signal value
+ /// equals or exceeds a given value.
+ pub fn notify(
+ &self,
+ listener: &SharedEventListenerRef,
+ value: u64,
+ block: MTLSharedEventNotificationBlock,
+ ) {
+ unsafe {
+ // If the block doesn't have a signature, this segfaults.
+ // Taken from https://github.com/servo/pathfinder/blob/e858c8dc1d8ff02a5b603e21e09a64d6b3e11327/metal/src/lib.rs#L2327
+ let block = mem::transmute::<
+ MTLSharedEventNotificationBlock,
+ *mut BlockBase<(&SharedEventRef, u64), ()>,
+ >(block);
+ (*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE;
+ (*block).extra = &BLOCK_EXTRA;
+ let () = msg_send![self, notifyListener:listener atValue:value block:block];
+ mem::forget(block);
+ }
+
+ extern "C" fn dtor(_: *mut BlockBase<(&SharedEventRef, u64), ()>) {}
+
+ const SIGNATURE: &[u8] = b"v16@?0Q8\0";
+ const SIGNATURE_PTR: *const i8 = &SIGNATURE[0] as *const u8 as *const i8;
+ static mut BLOCK_EXTRA: BlockExtra<(&SharedEventRef, u64), ()> = BlockExtra {
+ unknown0: 0 as *mut i32,
+ unknown1: 0 as *mut i32,
+ unknown2: 0 as *mut i32,
+ dtor,
+ signature: &SIGNATURE_PTR,
+ };
+ }
+}
+
+pub enum MTLSharedEventListener {}
+
+foreign_obj_type! {
+ type CType = MTLSharedEventListener;
+ pub struct SharedEventListener;
+ pub struct SharedEventListenerRef;
+}
+
+impl SharedEventListener {
+ pub unsafe fn from_queue_handle(queue: dispatch_queue_t) -> Self {
+ let listener: SharedEventListener = msg_send![class!(MTLSharedEventListener), alloc];
+ let ptr: *mut Object = msg_send![listener.as_ref(), initWithDispatchQueue: queue];
+ if ptr.is_null() {
+ panic!("[MTLSharedEventListener alloc] initWithDispatchQueue failed");
+ }
+ listener
+ }
+
+ #[cfg(feature = "dispatch")]
+ pub fn from_queue(queue: &dispatch::Queue) -> Self {
+ unsafe {
+ let raw_queue = std::mem::transmute::<&dispatch::Queue, *const dispatch_queue_t>(queue);
+ Self::from_queue_handle(*raw_queue)
+ }
+ }
+}
+
+pub enum MTLFence {}
+
+foreign_obj_type! {
+ type CType = MTLFence;
+ pub struct Fence;
+ pub struct FenceRef;
+}
+
+impl FenceRef {
+ pub fn device(&self) -> &DeviceRef {
+ unsafe { msg_send![self, device] }
+ }
+
+ pub fn label(&self) -> &str {
+ unsafe {
+ let label = msg_send![self, label];
+ crate::nsstring_as_str(label)
+ }
+ }
+
+ pub fn set_label(&self, label: &str) {
+ unsafe {
+ let nslabel = crate::nsstring_from_str(label);
+ let () = msg_send![self, setLabel: nslabel];
+ }
+ }
+}
+
+bitflags! {
+ /// The render stages at which a synchronization command is triggered.
+ ///
+ /// Render stages provide finer control for specifying when synchronization must occur,
+ /// allowing for vertex and fragment processing to overlap in execution.
+ ///
+ /// See <https://developer.apple.com/documentation/metal/mtlrenderstages>
+ pub struct MTLRenderStages: NSUInteger {
+ /// The vertex rendering stage.
+ const Vertex = 1 << 0;
+ /// The fragment rendering stage.
+ const Fragment = 1 << 1;
+ /// The tile rendering stage.
+ const Tile = 1 << 2;
+ }
+}
+
+const BLOCK_HAS_COPY_DISPOSE: i32 = 0x02000000;
+const BLOCK_HAS_SIGNATURE: i32 = 0x40000000;
+
+#[repr(C)]
+struct BlockBase<A, R> {
+ isa: *const std::ffi::c_void, // 0x00
+ flags: i32, // 0x08
+ _reserved: i32, // 0x0c
+ invoke: unsafe extern "C" fn(*mut Block<A, R>, ...) -> R, // 0x10
+ extra: *const BlockExtra<A, R>, // 0x18
+}
+
+type BlockExtraDtor<A, R> = extern "C" fn(*mut BlockBase<A, R>);
+
+#[repr(C)]
+struct BlockExtra<A, R> {
+ unknown0: *mut i32, // 0x00
+ unknown1: *mut i32, // 0x08
+ unknown2: *mut i32, // 0x10
+ dtor: BlockExtraDtor<A, R>, // 0x18
+ signature: *const *const i8, // 0x20
+}