use crate::{api, define_mtl, define_obj_type, define_opts, mtl, ns, objc};
#[doc(alias = "MTLPrimitiveType")]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(usize)]
pub enum Primitive {
Point = 0,
Line = 1,
LineStrip = 2,
Triangle = 3,
TriangleStrip = 4,
}
#[doc(alias = "MTLVisibilityResultMode")]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(usize)]
pub enum VisibilityResultMode {
#[doc(alias = "MTLVisibilityResultModeDisabled")]
Disabled = 0,
#[doc(alias = "MTLVisibilityResultModeBoolean")]
Boolean = 1,
#[doc(alias = "MTLVisibilityResultModeCounting")]
Counting = 2,
}
#[doc(alias = "MTLScissorRect")]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
#[repr(C)]
pub struct ScissorRect {
pub x: usize,
pub y: usize,
pub w: usize,
pub h: usize,
}
#[doc(alias = "MTLViewport")]
#[derive(Default, Debug, PartialEq, Copy, Clone)]
#[repr(C)]
pub struct Viewport {
pub x: f64,
pub y: f64,
pub w: f64,
pub h: f64,
pub z_near: f64,
pub z_far: f64,
}
impl Viewport {
#[inline]
pub const fn with_scissor_rect(rect: &ScissorRect) -> Self {
Self {
x: rect.x as _,
y: rect.y as _,
w: rect.w as _,
h: rect.h as _,
z_near: 0.0,
z_far: 1.0,
}
}
}
#[doc(alias = "MTLCullMode")]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(usize)]
pub enum CullMode {
None = 0,
Front = 1,
Back = 2,
}
#[doc(alias = "MTLWinding")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(usize)]
pub enum Winding {
#[doc(alias = "MTLWindingClockwise")]
Cw = 0,
#[doc(alias = "MTLWindingCounterClockwise")]
Ccw = 1,
}
#[doc(alias = "MTLDepthClipMode")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(usize)]
pub enum DepthClipMode {
Clip = 0,
Clamp = 1,
}
#[doc(alias = "MTLTriangleFillMode")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(usize)]
pub enum TriangleFillMode {
#[doc(alias = "MTLTriangleFillModeFill")]
Fill = 0,
#[doc(alias = "MTLTriangleFillModeLines")]
Lines = 1,
}
#[doc(alias = "MTLDrawPrimitivesIndirectArguments")]
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[repr(C)]
pub struct DrawPrimitivesIndirectArgs {
pub vertex_count: u32,
pub inst_count: u32,
pub vertex_start: u32,
pub base_instance: u32,
}
#[doc(alias = "MTLDrawIndexedPrimitivesIndirectArguments")]
#[derive(Debug, Hash, Copy, Clone, Eq, PartialEq)]
#[repr(C)]
pub struct DrawIndexedPrimitivesIndirectArgs {
pub index_count: u32,
pub inst_count: u32,
pub index_start: u32,
pub base_vertex: i32,
pub base_instance: u32,
}
#[doc(alias = "MTLVertexAmplificationViewMapping")]
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[repr(C)]
pub struct VertexAmplificationViewMapping {
pub viewport_array_index_offset: u32,
pub render_target_array_index_offset: u32,
}
#[doc(alias = "MTLDrawPatchIndirectArguments")]
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[repr(C)]
pub struct DrawPatchIndirectArgs {
pub patch_count: u32,
pub instance_count: u32,
pub patch_start: u32,
pub base_instance: u32,
}
#[doc(alias = "MTLQuadTessellationFactorsHalf")]
#[derive(Debug, Hash, Copy, Clone, Eq, PartialEq)]
#[repr(C)]
pub struct QuadTessellationFactorsHalf {
pub edge_tessellation_factor: [u16; 4],
pub inside_tessellation_factor: [u16; 2],
}
#[doc(alias = "MTLTriangleTessellationFactorsHalf")]
#[derive(Debug, Hash, Copy, Clone, Eq, PartialEq)]
#[repr(C)]
pub struct TriangleTessellationFactorsHalf {
pub edge_tessellation_factor: [u16; 3],
pub inside_tessellation_factor: u16,
}
define_opts!(
#[doc(alias = "MTLRenderStages")]
pub RenderStages(usize)
);
impl RenderStages {
#[doc(alias = "MTLRenderStageVertex")]
pub const VERTEX: Self = Self(1usize << 0);
#[doc(alias = "MTLRenderStageFragment")]
pub const FRAGMENT: Self = Self(1usize << 1);
#[doc(alias = "MTLRenderStageTile")]
pub const TILE: Self = Self(1usize << 2);
#[doc(alias = "MTLRenderStageObject")]
pub const OBJECT: Self = Self(1usize << 3);
#[doc(alias = "MTLRenderStageMesh")]
pub const MESH: Self = Self(1usize << 4);
}
define_obj_type!(
#[doc(alias = "MTLRenderCommandEncoder")]
pub RenderCmdEncoder(mtl::CmdEncoder)
);
impl RenderCmdEncoder {
define_mtl!(use_heap);
#[objc::msg_send(setRenderPipelineState:)]
pub fn set_render_ps(&mut self, val: &mtl::RenderPipelineState);
#[objc::msg_send(setViewport:)]
pub fn set_vp(&mut self, val: mtl::Viewport);
#[inline]
pub fn set_vp_rect<F: Into<f64>>(&mut self, x: F, y: F, width: F, height: F) {
self.set_vp(mtl::Viewport {
x: x.into(),
y: y.into(),
w: width.into(),
h: height.into(),
z_near: 0.into(),
z_far: 1.into(),
})
}
#[objc::msg_send(setViewports:count:)]
pub fn set_vps_count(&mut self, val: *const mtl::Viewport, count: usize);
#[inline]
pub fn set_vps(&mut self, val: &[mtl::Viewport]) {
self.set_vps_count(val.as_ptr(), val.len());
}
#[objc::msg_send(setScissorRect:)]
pub fn set_scissor_rect(&mut self, val: mtl::ScissorRect);
#[objc::msg_send(setScissorRects:count:)]
pub fn set_scissor_rects_count(&mut self, val: *const mtl::ScissorRect, count: usize);
#[inline]
pub fn set_scissor_rects(&mut self, val: &[mtl::ScissorRect]) {
self.set_scissor_rects_count(val.as_ptr(), val.len());
}
#[objc::msg_send(setTriangleFillMode:)]
pub fn set_triangle_fill_mode(&mut self, val: mtl::TriangleFillMode);
#[objc::msg_send(setFrontFacingWinding:)]
pub fn set_ffw(&mut self, val: mtl::Winding);
#[objc::msg_send(setCullMode:)]
pub fn set_cull_mode(&mut self, val: mtl::CullMode);
#[objc::msg_send(setDepthStencilState:)]
pub fn set_depth_stencil_state(&mut self, val: Option<&mtl::DepthStencilState>);
#[objc::msg_send(setStencilReferenceValue:)]
pub fn set_stencil_reference_value(&mut self, val: u32);
#[objc::msg_send(setStencilFrontReferenceValue:backReferenceValue:)]
pub fn set_stencil_front_back_reference_values(
&mut self,
front_reference_val: u32,
back_reference_val: u32,
);
#[objc::msg_send(setVisibilityResultMode:offset:)]
pub fn set_visibility_result_mode(&mut self, val: mtl::VisibilityResultMode, offset: usize);
#[objc::msg_send(setColorStoreAction:atIndex:)]
pub fn set_color_store_action_at(&mut self, val: mtl::StoreAction, index: usize);
#[objc::msg_send(setDepthStoreAction:)]
pub fn set_depth_store_action(&mut self, val: mtl::StoreAction);
#[objc::msg_send(setStencilStoreAction:)]
pub fn set_stencil_store_action(&mut self, val: mtl::StoreAction);
#[objc::msg_send(setVertexBytes:length:atIndex:)]
pub fn copy_bytes_to_vertex_at(
&mut self,
bytes: *const u8,
length: ns::UInteger,
binding_index: ns::UInteger,
);
#[inline]
pub fn copy_slice_to_vertex_at<T>(&mut self, slice: &[T], index: usize) {
self.copy_bytes_to_vertex_at(slice.as_ptr().cast(), std::mem::size_of_val(slice), index)
}
#[inline]
pub fn copy_to_vertex_at<T>(&mut self, val: &T, index: usize) {
self.copy_bytes_to_vertex_at(val as *const T as _, std::mem::size_of::<T>(), index)
}
#[objc::msg_send(setVertexBuffer:offset:atIndex:)]
pub fn set_vertex_buf_at(&mut self, buf: Option<&mtl::Buf>, offset: usize, index: usize);
#[objc::msg_send(useResource:usage:stages:)]
pub fn use_resource(
&mut self,
resources: &mtl::Res,
usage: mtl::ResUsage,
stages: mtl::RenderStages,
);
#[objc::msg_send(useResources:count:usage:stages:)]
pub unsafe fn use_resources_count(
&mut self,
resources: *const &mtl::Res,
count: usize,
usage: mtl::ResUsage,
stages: mtl::RenderStages,
);
#[doc(alias = "useResources:count:usage:stages:")]
#[inline]
pub fn use_resources(
&mut self,
resources: &[&mtl::Res],
usage: crate::mtl::ResUsage,
stages: mtl::RenderStages,
) {
unsafe { self.use_resources_count(resources.as_ptr(), resources.len(), usage, stages) };
}
#[objc::msg_send(setVertexBufferOffset:atIndex:)]
pub fn set_vertex_buf_offset_at(&mut self, offset: usize, index: usize);
#[objc::msg_send(setVertexBuffers:offsets:withRange:)]
pub fn set_vertex_bufs_offsets_with_range(
&mut self,
bufs: *const &mtl::Buf,
offsets: *const usize,
range: ns::Range,
);
pub fn set_vertex_bufs<const N: usize>(&mut self, bufs: &[&mtl::Buf; N]) {
self.set_vertex_bufs_offsets_with_range(
bufs.as_ptr(),
[0; N].as_ptr(),
ns::Range::new(0, N),
)
}
#[objc::msg_send(setVertexSamplerState:atIndex:)]
pub fn set_vertex_sampler_state_at(
&mut self,
sampler: Option<&mtl::SamplerState>,
at_index: usize,
);
#[objc::msg_send(setFragmentBuffer:offset:atIndex:)]
pub fn set_fragment_buf_at(&mut self, buf: Option<&mtl::Buf>, offset: usize, at_index: usize);
#[objc::msg_send(setFragmentBytes:length:atIndex:)]
pub fn copy_bytes_to_fragment_at(&mut self, bytes: *const u8, len: usize, at_index: usize);
#[inline]
pub fn copy_slice_to_fragment_at<T>(&mut self, slice: &[T], at_index: usize) {
self.copy_bytes_to_fragment_at(
slice.as_ptr().cast(),
std::mem::size_of_val(slice),
at_index,
)
}
#[inline]
pub fn copy_to_fragment_at<T>(&mut self, val: &T, index: usize) {
self.copy_bytes_to_fragment_at(val as *const T as _, std::mem::size_of::<T>(), index)
}
#[objc::msg_send(setFragmentTexture:atIndex:)]
pub fn set_fragment_texture_at(&mut self, val: Option<&mtl::Texture>, index: usize);
#[objc::msg_send(setFragmentTextures:withRange:)]
pub fn set_fragment_textures_with_range(
&mut self,
ptr: *const Option<&mtl::Texture>,
range: ns::Range,
);
#[inline]
pub fn set_fragment_textures_with_array<const N: usize>(
&mut self,
arr: &[Option<&mtl::Texture>; N],
) {
self.set_fragment_textures_with_range(arr.as_ptr(), ns::Range::new(0, N));
}
#[inline]
pub fn set_fragment_textures_with_slice(&mut self, slice: &[Option<&mtl::Texture>]) {
self.set_fragment_textures_with_range(slice.as_ptr(), ns::Range::new(0, slice.len()));
}
#[objc::msg_send(drawPrimitives:vertexStart:vertexCount:)]
pub fn draw_primitives(
&mut self,
primitive_type: Primitive,
vertex_start: usize,
vertex_count: usize,
);
#[objc::msg_send(drawPrimitives:vertexStart:vertexCount:instanceCount:)]
pub fn draw_primitives_instance_count(
&mut self,
primitive_type: Primitive,
vertex_start: usize,
vertex_count: usize,
instance_count: usize,
);
#[objc::msg_send(drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:instanceCount:)]
pub fn draw_indexed_primitives_instance_count(
&mut self,
primitive_type: mtl::Primitive,
index_count: usize,
index_type: mtl::IndexType,
index_buffer: &mtl::Buf,
index_buffer_offset: usize,
instance_count: usize,
);
#[objc::msg_send(drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:instanceCount:baseVertex:baseInstance:)]
pub fn draw_indexed_primitives_index_type_index_count_instance_count(
&mut self,
primitive_type: mtl::Primitive,
index_count: usize,
index_type: mtl::IndexType,
index_buf: &mtl::Buf,
index_buf_offset: usize,
inst_count: usize,
base_vertex: isize,
base_instance: usize,
);
#[inline]
pub fn draw_indexed_triangles_u16(
&mut self,
index_buf: &mtl::Buf,
index_range: &std::ops::Range<usize>,
inst_range: &std::ops::Range<usize>,
) {
self.draw_indexed_primitives_index_type_index_count_instance_count(
mtl::Primitive::Triangle,
index_range.len(),
mtl::IndexType::U16,
index_buf,
index_range.start * std::mem::size_of::<u16>(),
inst_range.len(),
0, inst_range.start,
);
}
#[inline]
pub fn draw_indexed_triangles_u32(
&mut self,
index_buf: &mtl::Buf,
index_range: &std::ops::Range<usize>,
instance_range: &std::ops::Range<usize>,
) {
self.draw_indexed_primitives_index_type_index_count_instance_count(
mtl::Primitive::Triangle,
index_range.len(),
mtl::IndexType::U32,
index_buf,
index_range.start * std::mem::size_of::<u32>(),
instance_range.len(),
0, instance_range.start,
);
}
#[objc::msg_send(drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:)]
pub fn draw_indexed_primitives(
&mut self,
primitive_type: mtl::Primitive,
index_count: usize,
index_type: mtl::IndexType,
index_buf: &mtl::Buf,
index_buf_offset: usize,
);
#[objc::msg_send(updateFence:afterStages:)]
pub fn update_fence_after_stages(&self, fence: &mtl::Fence, stages: mtl::RenderStages);
#[objc::msg_send(waitForFence:beforeStages:)]
pub fn wait_fence_before_stages(&self, fence: &mtl::Fence, stages: mtl::RenderStages);
#[objc::msg_send(dispatchThreadsPerTile:)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn dispatch_threads_per_tile(&self, val: mtl::Size);
#[objc::msg_send(tileWidth)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn tile_width(&self) -> usize;
#[objc::msg_send(tileHeight)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn tile_height(&self) -> usize;
#[objc::msg_send(setTileBytes:length:atIndex:)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn copy_bytes_to_tile_at(
&mut self,
bytes: *const std::ffi::c_void,
len: ns::UInteger,
at_index: ns::UInteger,
);
#[inline]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn copy_slice_to_tile_at<T>(&mut self, slice: &[T], index: usize) {
self.copy_bytes_to_tile_at(slice.as_ptr().cast(), std::mem::size_of_val(slice), index)
}
#[inline]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn copy_to_tile_at<T>(&mut self, val: &T, index: usize) {
self.copy_bytes_to_tile_at(val as *const T as _, std::mem::size_of::<T>(), index)
}
#[objc::msg_send(setTileBuffer:offset:atIndex:)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn set_tile_buf_at(&mut self, buf: Option<&mtl::Buf>, offset: usize, index: usize);
#[objc::msg_send(setTileTexture:atIndex:)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn set_tile_texture_at(&mut self, texture: Option<&mtl::Texture>, index: usize);
#[objc::msg_send(setTileTextures:withRange:)]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn set_tile_textures_with_range(
&mut self,
ptr: *const Option<&mtl::Texture>,
range: ns::Range,
);
#[inline]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn set_tile_textures_with_slice(&mut self, textures: &[Option<&mtl::Texture>]) {
self.set_tile_textures_with_range(textures.as_ptr(), ns::Range::new(0, textures.len()));
}
#[inline]
#[api::available(macos = 11.0, maccatalyst = 14.0, ios = 11.0, tvos = 14.5)]
pub fn set_tile_textures_with_array<const N: usize>(
&mut self,
textures: &[Option<&mtl::Texture>; N],
) {
self.set_tile_textures_with_range(textures.as_ptr(), ns::Range::new(0, N));
}
#[objc::msg_send(executeCommandsInBuffer:withRange:)]
#[api::available(macos = 10.14, ios = 12.0)]
pub fn execute_cmds_in_buf_with_range(&mut self, icb: &mtl::IndirectCmdBuf, range: ns::Range);
#[inline]
#[api::available(macos = 10.14, ios = 12.0)]
pub fn execute_cmds_in_buf(
&mut self,
icb: &mtl::IndirectCmdBuf,
range: std::ops::Range<usize>,
) {
self.execute_cmds_in_buf_with_range(icb, ns::Range::new(range.start, range.len()))
}
}