use crate::ffi::*;
use crate::texture::Texture;
#[derive(Debug, Clone, Copy)]
#[repr(usize)]
pub enum LoadAction {
DontCare = MTLLoadActionDontCare,
Load = MTLLoadActionLoad,
Clear = MTLLoadActionClear,
}
#[derive(Debug, Clone, Copy)]
#[repr(usize)]
pub enum StoreAction {
DontCare = MTLStoreActionDontCare,
Store = MTLStoreActionStore,
MultisampleResolve = MTLStoreActionMultisampleResolve,
StoreAndMultisampleResolve = MTLStoreActionStoreAndMultisampleResolve,
}
pub struct ColorAttachmentDesc<'a> {
pub texture: &'a Texture,
pub load_action: LoadAction,
pub store_action: StoreAction,
pub clear_color: [f64; 4],
pub resolve_texture: Option<&'a Texture>,
pub level: u32,
pub slice: u32,
}
impl<'a> ColorAttachmentDesc<'a> {
pub fn clear(texture: &'a Texture, clear: [f64; 4]) -> Self {
Self {
texture,
load_action: LoadAction::Clear,
store_action: StoreAction::Store,
clear_color: clear,
resolve_texture: None,
level: 0,
slice: 0,
}
}
}
pub struct DepthAttachmentDesc<'a> {
pub texture: &'a Texture,
pub load_action: LoadAction,
pub store_action: StoreAction,
pub clear_depth: f64,
}
impl<'a> DepthAttachmentDesc<'a> {
pub fn clear(texture: &'a Texture) -> Self {
Self {
texture,
load_action: LoadAction::Clear,
store_action: StoreAction::DontCare,
clear_depth: 1.0,
}
}
}
pub struct RenderPassDescriptor {
raw: ObjcId,
}
impl RenderPassDescriptor {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
unsafe {
let cls = objc_getClass(c"MTLRenderPassDescriptor".as_ptr()) as ObjcId;
let raw = msg0(cls, SEL_renderPassDescriptor());
retain(raw);
Self { raw }
}
}
pub fn color_attachment(&mut self, index: usize, desc: ColorAttachmentDesc<'_>) {
unsafe {
let array = msg0(self.raw, SEL_colorAttachments());
let slot = msg1_uint_id(array, SEL_objectAtIndexedSubscript(), index);
msg1_void(slot, SEL_setTexture(), desc.texture.as_raw());
msg1_uint_void(slot, SEL_setLoadAction(), desc.load_action as NSUInteger);
msg1_uint_void(slot, SEL_setStoreAction(), desc.store_action as NSUInteger);
msg1_uint_void(slot, SEL_setLevel(), desc.level as NSUInteger);
msg1_uint_void(slot, SEL_setSlice(), desc.slice as NSUInteger);
let clear = MTLClearColor {
red: desc.clear_color[0],
green: desc.clear_color[1],
blue: desc.clear_color[2],
alpha: desc.clear_color[3],
};
type F = unsafe extern "C" fn(ObjcId, ObjcSel, MTLClearColor);
let f: F = std::mem::transmute(objc_msgSend as *const std::ffi::c_void);
f(slot, SEL_setClearColor(), clear);
if let Some(resolve) = desc.resolve_texture {
msg1_void(slot, SEL_setResolveTexture(), resolve.as_raw());
}
}
}
pub fn depth_attachment(&mut self, desc: DepthAttachmentDesc<'_>) {
unsafe {
let slot = msg0(self.raw, SEL_depthAttachment());
msg1_void(slot, SEL_setTexture(), desc.texture.as_raw());
msg1_uint_void(slot, SEL_setLoadAction(), desc.load_action as NSUInteger);
msg1_uint_void(slot, SEL_setStoreAction(), desc.store_action as NSUInteger);
type F = unsafe extern "C" fn(ObjcId, ObjcSel, f64);
let f: F = std::mem::transmute(objc_msgSend as *const std::ffi::c_void);
f(slot, SEL_setClearDepth(), desc.clear_depth);
}
}
pub fn as_raw(&self) -> ObjcId {
self.raw
}
}
impl Drop for RenderPassDescriptor {
#[mutants::skip]
fn drop(&mut self) {
unsafe { release(self.raw) };
}
}