[metal] Import prefixed metal items

A lot of Metal types are prefixed with MTL, which makes it quite clear
where they're coming from. This means that we don't loose any clarity if
we import them instead of having them prefixed with `metal::`.

This will make it easier to migrate to `objc2-metal` since that crate is
named differently from the `metal` crate.
This commit is contained in:
Mads Marquart 2025-04-25 09:53:45 +02:00 committed by Connor Fitzgerald
parent 38b6663f3c
commit 78a5b22458
6 changed files with 211 additions and 213 deletions

View File

@ -1,4 +1,7 @@
use metal::{MTLFeatureSet, MTLGPUFamily, MTLLanguageVersion, MTLReadWriteTextureTier};
use metal::{
MTLArgumentBuffersTier, MTLCounterSamplingPoint, MTLFeatureSet, MTLGPUFamily,
MTLLanguageVersion, MTLPixelFormat, MTLReadWriteTextureTier, NSInteger,
};
use objc::{class, msg_send, sel, sel_impl};
use parking_lot::Mutex;
use wgt::{AstcBlock, AstcChannel};
@ -575,19 +578,18 @@ impl super::PrivateCapabilities {
let mut timestamp_query_support = TimestampQuerySupport::empty();
if version.at_least((11, 0), (14, 0), os_is_mac)
&& device.supports_counter_sampling(metal::MTLCounterSamplingPoint::AtStageBoundary)
&& device.supports_counter_sampling(MTLCounterSamplingPoint::AtStageBoundary)
{
// If we don't support at stage boundary, don't support anything else.
timestamp_query_support.insert(TimestampQuerySupport::STAGE_BOUNDARIES);
if device.supports_counter_sampling(metal::MTLCounterSamplingPoint::AtDrawBoundary) {
if device.supports_counter_sampling(MTLCounterSamplingPoint::AtDrawBoundary) {
timestamp_query_support.insert(TimestampQuerySupport::ON_RENDER_ENCODER);
}
if device.supports_counter_sampling(metal::MTLCounterSamplingPoint::AtDispatchBoundary)
{
if device.supports_counter_sampling(MTLCounterSamplingPoint::AtDispatchBoundary) {
timestamp_query_support.insert(TimestampQuerySupport::ON_COMPUTE_ENCODER);
}
if device.supports_counter_sampling(metal::MTLCounterSamplingPoint::AtBlitBoundary) {
if device.supports_counter_sampling(MTLCounterSamplingPoint::AtBlitBoundary) {
timestamp_query_support.insert(TimestampQuerySupport::ON_BLIT_ENCODER);
}
// `TimestampQuerySupport::INSIDE_WGPU_PASSES` emerges from the other flags.
@ -728,8 +730,7 @@ impl super::PrivateCapabilities {
31
},
max_samplers_per_stage: 16,
max_binding_array_elements: if argument_buffers == metal::MTLArgumentBuffersTier::Tier2
{
max_binding_array_elements: if argument_buffers == MTLArgumentBuffersTier::Tier2 {
1_000_000
} else if family_check && device.supports_family(MTLGPUFamily::Apple4) {
96
@ -753,8 +754,7 @@ impl super::PrivateCapabilities {
buffer_alignment: if os_is_mac || os_is_xr { 256 } else { 64 },
max_buffer_size: if version.at_least((10, 14), (12, 0), os_is_mac) {
// maxBufferLength available on macOS 10.14+ and iOS 12.0+
let buffer_size: metal::NSInteger =
unsafe { msg_send![device.as_ref(), maxBufferLength] };
let buffer_size: NSInteger = unsafe { msg_send![device.as_ref(), maxBufferLength] };
buffer_size as _
} else if os_is_mac {
1 << 30 // 1GB on macOS 10.11 and up
@ -955,7 +955,7 @@ impl super::PrivateCapabilities {
| F::PARTIALLY_BOUND_BINDING_ARRAY,
self.msl_version >= MTLLanguageVersion::V3_0
&& self.supports_arrays_of_textures
&& self.argument_buffers as u64 >= metal::MTLArgumentBuffersTier::Tier2 as u64,
&& self.argument_buffers as u64 >= MTLArgumentBuffersTier::Tier2 as u64,
);
features.set(
F::SHADER_INT64,
@ -1080,9 +1080,9 @@ impl super::PrivateCapabilities {
}
}
pub fn map_format(&self, format: wgt::TextureFormat) -> metal::MTLPixelFormat {
use metal::MTLPixelFormat::*;
pub fn map_format(&self, format: wgt::TextureFormat) -> MTLPixelFormat {
use wgt::TextureFormat as Tf;
use MTLPixelFormat::*;
match format {
Tf::R8Unorm => R8Unorm,
Tf::R8Snorm => R8Snorm,
@ -1229,10 +1229,10 @@ impl super::PrivateCapabilities {
&self,
format: wgt::TextureFormat,
aspects: crate::FormatAspects,
) -> metal::MTLPixelFormat {
) -> MTLPixelFormat {
use crate::FormatAspects as Fa;
use metal::MTLPixelFormat::*;
use wgt::TextureFormat as Tf;
use MTLPixelFormat::*;
match (format, aspects) {
// map combined depth-stencil format to their stencil-only format
// see https://developer.apple.com/library/archive/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/WhatsNewiniOS10tvOS10andOSX1012/WhatsNewiniOS10tvOS10andOSX1012.html#//apple_ref/doc/uid/TP40014221-CH14-DontLinkElementID_77

View File

@ -5,6 +5,10 @@ use alloc::{
vec::Vec,
};
use core::ops::Range;
use metal::{
MTLIndexType, MTLLoadAction, MTLPrimitiveType, MTLScissorRect, MTLSize, MTLStoreAction,
MTLViewport, MTLVisibilityResultMode, NSRange,
};
// has to match `Temp::binding_sizes`
const WORD_SIZE: usize = 4;
@ -15,9 +19,9 @@ impl Default for super::CommandState {
blit: None,
render: None,
compute: None,
raw_primitive_type: metal::MTLPrimitiveType::Point,
raw_primitive_type: MTLPrimitiveType::Point,
index: None,
raw_wg_size: metal::MTLSize::new(0, 0, 0),
raw_wg_size: MTLSize::new(0, 0, 0),
stage_infos: Default::default(),
storage_buffer_length_map: Default::default(),
vertex_buffer_size_map: Default::default(),
@ -81,7 +85,7 @@ impl super::CommandEncoder {
// As explained above, we need to do some write:
// Conveniently, we have a buffer with every query set, that we can use for this for a dummy write,
// since we know that it is going to be overwritten again on timer resolve and HAL doesn't define its state before that.
let raw_range = metal::NSRange {
let raw_range = NSRange {
location: last_query.as_ref().unwrap().1 as u64 * crate::QUERY_SIZE,
length: 1,
};
@ -413,7 +417,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
.as_ref()
.unwrap()
.set_visibility_result_mode(
metal::MTLVisibilityResultMode::Boolean,
MTLVisibilityResultMode::Boolean,
index as u64 * crate::QUERY_SIZE,
);
}
@ -427,7 +431,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
.render
.as_ref()
.unwrap()
.set_visibility_result_mode(metal::MTLVisibilityResultMode::Disabled, 0);
.set_visibility_result_mode(MTLVisibilityResultMode::Disabled, 0);
}
_ => {}
}
@ -473,7 +477,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: Range<u32>) {
let encoder = self.enter_blit();
let raw_range = metal::NSRange {
let raw_range = NSRange {
location: range.start as u64 * crate::QUERY_SIZE,
length: (range.end - range.start) as u64 * crate::QUERY_SIZE,
};
@ -503,7 +507,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
wgt::QueryType::Timestamp => {
encoder.resolve_counters(
set.counter_sample_buffer.as_ref().unwrap(),
metal::NSRange::new(range.start as u64, (range.end - range.start) as u64),
NSRange::new(range.start as u64, (range.end - range.start) as u64),
&buffer.raw,
offset,
);
@ -540,10 +544,10 @@ impl crate::CommandEncoder for super::CommandEncoder {
at_descriptor.set_resolve_texture(Some(&resolve.view.raw));
}
let load_action = if at.ops.contains(crate::AttachmentOps::LOAD) {
metal::MTLLoadAction::Load
MTLLoadAction::Load
} else {
at_descriptor.set_clear_color(conv::map_clear_color(&at.clear_value));
metal::MTLLoadAction::Clear
MTLLoadAction::Clear
};
let store_action = conv::map_store_action(
at.ops.contains(crate::AttachmentOps::STORE),
@ -560,15 +564,15 @@ impl crate::CommandEncoder for super::CommandEncoder {
at_descriptor.set_texture(Some(&at.target.view.raw));
let load_action = if at.depth_ops.contains(crate::AttachmentOps::LOAD) {
metal::MTLLoadAction::Load
MTLLoadAction::Load
} else {
at_descriptor.set_clear_depth(at.clear_value.0 as f64);
metal::MTLLoadAction::Clear
MTLLoadAction::Clear
};
let store_action = if at.depth_ops.contains(crate::AttachmentOps::STORE) {
metal::MTLStoreAction::Store
MTLStoreAction::Store
} else {
metal::MTLStoreAction::DontCare
MTLStoreAction::DontCare
};
at_descriptor.set_load_action(load_action);
at_descriptor.set_store_action(store_action);
@ -583,15 +587,15 @@ impl crate::CommandEncoder for super::CommandEncoder {
at_descriptor.set_texture(Some(&at.target.view.raw));
let load_action = if at.stencil_ops.contains(crate::AttachmentOps::LOAD) {
metal::MTLLoadAction::Load
MTLLoadAction::Load
} else {
at_descriptor.set_clear_stencil(at.clear_value.1);
metal::MTLLoadAction::Clear
MTLLoadAction::Clear
};
let store_action = if at.stencil_ops.contains(crate::AttachmentOps::STORE) {
metal::MTLStoreAction::Store
MTLStoreAction::Store
} else {
metal::MTLStoreAction::DontCare
MTLStoreAction::DontCare
};
at_descriptor.set_load_action(load_action);
at_descriptor.set_store_action(store_action);
@ -953,8 +957,8 @@ impl crate::CommandEncoder for super::CommandEncoder {
format: wgt::IndexFormat,
) {
let (stride, raw_type) = match format {
wgt::IndexFormat::Uint16 => (2, metal::MTLIndexType::UInt16),
wgt::IndexFormat::Uint32 => (4, metal::MTLIndexType::UInt32),
wgt::IndexFormat::Uint16 => (2, MTLIndexType::UInt16),
wgt::IndexFormat::Uint32 => (4, MTLIndexType::UInt32),
};
self.state.index = Some(super::IndexState {
buffer_ptr: AsNative::from(binding.buffer.raw.as_ref()),
@ -1002,7 +1006,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
depth_range.end
};
let encoder = self.state.render.as_ref().unwrap();
encoder.set_viewport(metal::MTLViewport {
encoder.set_viewport(MTLViewport {
originX: rect.x as _,
originY: rect.y as _,
width: rect.w as _,
@ -1013,7 +1017,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
}
unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {
//TODO: support empty scissors by modifying the viewport
let scissor = metal::MTLScissorRect {
let scissor = MTLScissorRect {
x: rect.x as _,
y: rect.y as _,
width: rect.w as _,
@ -1301,7 +1305,7 @@ impl crate::CommandEncoder for super::CommandEncoder {
unsafe fn dispatch(&mut self, count: [u32; 3]) {
if count[0] > 0 && count[1] > 0 && count[2] > 0 {
let encoder = self.state.compute.as_ref().unwrap();
let raw_count = metal::MTLSize {
let raw_count = MTLSize {
width: count[0] as u64,
height: count[1] as u64,
depth: count[2] as u64,

View File

@ -1,43 +1,48 @@
pub fn map_texture_usage(
format: wgt::TextureFormat,
usage: wgt::TextureUses,
) -> metal::MTLTextureUsage {
use metal::{
MTLBlendFactor, MTLBlendOperation, MTLBlitOption, MTLClearColor, MTLColorWriteMask,
MTLCompareFunction, MTLCullMode, MTLOrigin, MTLPrimitiveTopologyClass, MTLPrimitiveType,
MTLRenderStages, MTLResourceUsage, MTLSamplerAddressMode, MTLSamplerBorderColor,
MTLSamplerMinMagFilter, MTLSize, MTLStencilOperation, MTLStoreAction, MTLTextureType,
MTLTextureUsage, MTLVertexFormat, MTLVertexStepFunction, MTLWinding, NSRange,
};
pub fn map_texture_usage(format: wgt::TextureFormat, usage: wgt::TextureUses) -> MTLTextureUsage {
use wgt::TextureUses as Tu;
let mut mtl_usage = metal::MTLTextureUsage::Unknown;
let mut mtl_usage = MTLTextureUsage::Unknown;
mtl_usage.set(
metal::MTLTextureUsage::RenderTarget,
MTLTextureUsage::RenderTarget,
usage.intersects(Tu::COLOR_TARGET | Tu::DEPTH_STENCIL_READ | Tu::DEPTH_STENCIL_WRITE),
);
mtl_usage.set(
metal::MTLTextureUsage::ShaderRead,
MTLTextureUsage::ShaderRead,
usage.intersects(
Tu::RESOURCE | Tu::DEPTH_STENCIL_READ | Tu::STORAGE_READ_ONLY | Tu::STORAGE_READ_WRITE,
),
);
mtl_usage.set(
metal::MTLTextureUsage::ShaderWrite,
MTLTextureUsage::ShaderWrite,
usage.intersects(Tu::STORAGE_WRITE_ONLY | Tu::STORAGE_READ_WRITE),
);
// needed for combined depth/stencil formats since we might
// create a stencil-only view from them
mtl_usage.set(
metal::MTLTextureUsage::PixelFormatView,
MTLTextureUsage::PixelFormatView,
format.is_combined_depth_stencil_format(),
);
mtl_usage.set(
metal::MTLTextureUsage::ShaderAtomic,
MTLTextureUsage::ShaderAtomic,
usage.intersects(Tu::STORAGE_ATOMIC),
);
mtl_usage
}
pub fn map_texture_view_dimension(dim: wgt::TextureViewDimension) -> metal::MTLTextureType {
use metal::MTLTextureType::*;
pub fn map_texture_view_dimension(dim: wgt::TextureViewDimension) -> MTLTextureType {
use wgt::TextureViewDimension as Tvd;
use MTLTextureType::*;
match dim {
Tvd::D1 => D1,
Tvd::D2 => D2,
@ -48,9 +53,9 @@ pub fn map_texture_view_dimension(dim: wgt::TextureViewDimension) -> metal::MTLT
}
}
pub fn map_compare_function(fun: wgt::CompareFunction) -> metal::MTLCompareFunction {
use metal::MTLCompareFunction::*;
pub fn map_compare_function(fun: wgt::CompareFunction) -> MTLCompareFunction {
use wgt::CompareFunction as Cf;
use MTLCompareFunction::*;
match fun {
Cf::Never => Never,
Cf::Less => Less,
@ -63,17 +68,17 @@ pub fn map_compare_function(fun: wgt::CompareFunction) -> metal::MTLCompareFunct
}
}
pub fn map_filter_mode(filter: wgt::FilterMode) -> metal::MTLSamplerMinMagFilter {
use metal::MTLSamplerMinMagFilter::*;
pub fn map_filter_mode(filter: wgt::FilterMode) -> MTLSamplerMinMagFilter {
use MTLSamplerMinMagFilter::*;
match filter {
wgt::FilterMode::Nearest => Nearest,
wgt::FilterMode::Linear => Linear,
}
}
pub fn map_address_mode(address: wgt::AddressMode) -> metal::MTLSamplerAddressMode {
use metal::MTLSamplerAddressMode::*;
pub fn map_address_mode(address: wgt::AddressMode) -> MTLSamplerAddressMode {
use wgt::AddressMode as Fm;
use MTLSamplerAddressMode::*;
match address {
Fm::Repeat => Repeat,
Fm::MirrorRepeat => MirrorRepeat,
@ -83,8 +88,8 @@ pub fn map_address_mode(address: wgt::AddressMode) -> metal::MTLSamplerAddressMo
}
}
pub fn map_border_color(border_color: wgt::SamplerBorderColor) -> metal::MTLSamplerBorderColor {
use metal::MTLSamplerBorderColor::*;
pub fn map_border_color(border_color: wgt::SamplerBorderColor) -> MTLSamplerBorderColor {
use MTLSamplerBorderColor::*;
match border_color {
wgt::SamplerBorderColor::TransparentBlack => TransparentBlack,
wgt::SamplerBorderColor::OpaqueBlack => OpaqueBlack,
@ -95,54 +100,45 @@ pub fn map_border_color(border_color: wgt::SamplerBorderColor) -> metal::MTLSamp
pub fn map_primitive_topology(
topology: wgt::PrimitiveTopology,
) -> (metal::MTLPrimitiveTopologyClass, metal::MTLPrimitiveType) {
) -> (MTLPrimitiveTopologyClass, MTLPrimitiveType) {
use wgt::PrimitiveTopology as Pt;
match topology {
Pt::PointList => (
metal::MTLPrimitiveTopologyClass::Point,
metal::MTLPrimitiveType::Point,
),
Pt::LineList => (
metal::MTLPrimitiveTopologyClass::Line,
metal::MTLPrimitiveType::Line,
),
Pt::LineStrip => (
metal::MTLPrimitiveTopologyClass::Line,
metal::MTLPrimitiveType::LineStrip,
),
Pt::PointList => (MTLPrimitiveTopologyClass::Point, MTLPrimitiveType::Point),
Pt::LineList => (MTLPrimitiveTopologyClass::Line, MTLPrimitiveType::Line),
Pt::LineStrip => (MTLPrimitiveTopologyClass::Line, MTLPrimitiveType::LineStrip),
Pt::TriangleList => (
metal::MTLPrimitiveTopologyClass::Triangle,
metal::MTLPrimitiveType::Triangle,
MTLPrimitiveTopologyClass::Triangle,
MTLPrimitiveType::Triangle,
),
Pt::TriangleStrip => (
metal::MTLPrimitiveTopologyClass::Triangle,
metal::MTLPrimitiveType::TriangleStrip,
MTLPrimitiveTopologyClass::Triangle,
MTLPrimitiveType::TriangleStrip,
),
}
}
pub fn map_color_write(mask: wgt::ColorWrites) -> metal::MTLColorWriteMask {
let mut raw_mask = metal::MTLColorWriteMask::empty();
pub fn map_color_write(mask: wgt::ColorWrites) -> MTLColorWriteMask {
let mut raw_mask = MTLColorWriteMask::empty();
if mask.contains(wgt::ColorWrites::RED) {
raw_mask |= metal::MTLColorWriteMask::Red;
raw_mask |= MTLColorWriteMask::Red;
}
if mask.contains(wgt::ColorWrites::GREEN) {
raw_mask |= metal::MTLColorWriteMask::Green;
raw_mask |= MTLColorWriteMask::Green;
}
if mask.contains(wgt::ColorWrites::BLUE) {
raw_mask |= metal::MTLColorWriteMask::Blue;
raw_mask |= MTLColorWriteMask::Blue;
}
if mask.contains(wgt::ColorWrites::ALPHA) {
raw_mask |= metal::MTLColorWriteMask::Alpha;
raw_mask |= MTLColorWriteMask::Alpha;
}
raw_mask
}
pub fn map_blend_factor(factor: wgt::BlendFactor) -> metal::MTLBlendFactor {
use metal::MTLBlendFactor::*;
pub fn map_blend_factor(factor: wgt::BlendFactor) -> MTLBlendFactor {
use wgt::BlendFactor as Bf;
use MTLBlendFactor::*;
match factor {
Bf::Zero => Zero,
@ -165,9 +161,9 @@ pub fn map_blend_factor(factor: wgt::BlendFactor) -> metal::MTLBlendFactor {
}
}
pub fn map_blend_op(operation: wgt::BlendOperation) -> metal::MTLBlendOperation {
use metal::MTLBlendOperation::*;
pub fn map_blend_op(operation: wgt::BlendOperation) -> MTLBlendOperation {
use wgt::BlendOperation as Bo;
use MTLBlendOperation::*;
match operation {
Bo::Add => Add,
@ -180,11 +176,7 @@ pub fn map_blend_op(operation: wgt::BlendOperation) -> metal::MTLBlendOperation
pub fn map_blend_component(
component: &wgt::BlendComponent,
) -> (
metal::MTLBlendOperation,
metal::MTLBlendFactor,
metal::MTLBlendFactor,
) {
) -> (MTLBlendOperation, MTLBlendFactor, MTLBlendFactor) {
(
map_blend_op(component.operation),
map_blend_factor(component.src_factor),
@ -192,9 +184,9 @@ pub fn map_blend_component(
)
}
pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat {
use metal::MTLVertexFormat::*;
pub fn map_vertex_format(format: wgt::VertexFormat) -> MTLVertexFormat {
use wgt::VertexFormat as Vf;
use MTLVertexFormat::*;
match format {
Vf::Unorm8 => UCharNormalized,
@ -242,16 +234,16 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat {
}
}
pub fn map_step_mode(mode: wgt::VertexStepMode) -> metal::MTLVertexStepFunction {
pub fn map_step_mode(mode: wgt::VertexStepMode) -> MTLVertexStepFunction {
match mode {
wgt::VertexStepMode::Vertex => metal::MTLVertexStepFunction::PerVertex,
wgt::VertexStepMode::Instance => metal::MTLVertexStepFunction::PerInstance,
wgt::VertexStepMode::Vertex => MTLVertexStepFunction::PerVertex,
wgt::VertexStepMode::Instance => MTLVertexStepFunction::PerInstance,
}
}
pub fn map_stencil_op(op: wgt::StencilOperation) -> metal::MTLStencilOperation {
use metal::MTLStencilOperation::*;
pub fn map_stencil_op(op: wgt::StencilOperation) -> MTLStencilOperation {
use wgt::StencilOperation as So;
use MTLStencilOperation::*;
match op {
So::Keep => Keep,
@ -265,46 +257,46 @@ pub fn map_stencil_op(op: wgt::StencilOperation) -> metal::MTLStencilOperation {
}
}
pub fn map_winding(winding: wgt::FrontFace) -> metal::MTLWinding {
pub fn map_winding(winding: wgt::FrontFace) -> MTLWinding {
match winding {
wgt::FrontFace::Cw => metal::MTLWinding::Clockwise,
wgt::FrontFace::Ccw => metal::MTLWinding::CounterClockwise,
wgt::FrontFace::Cw => MTLWinding::Clockwise,
wgt::FrontFace::Ccw => MTLWinding::CounterClockwise,
}
}
pub fn map_cull_mode(face: Option<wgt::Face>) -> metal::MTLCullMode {
pub fn map_cull_mode(face: Option<wgt::Face>) -> MTLCullMode {
match face {
None => metal::MTLCullMode::None,
Some(wgt::Face::Front) => metal::MTLCullMode::Front,
Some(wgt::Face::Back) => metal::MTLCullMode::Back,
None => MTLCullMode::None,
Some(wgt::Face::Front) => MTLCullMode::Front,
Some(wgt::Face::Back) => MTLCullMode::Back,
}
}
pub fn map_range(range: &crate::MemoryRange) -> metal::NSRange {
metal::NSRange {
pub fn map_range(range: &crate::MemoryRange) -> NSRange {
NSRange {
location: range.start,
length: range.end - range.start,
}
}
pub fn map_copy_extent(extent: &crate::CopyExtent) -> metal::MTLSize {
metal::MTLSize {
pub fn map_copy_extent(extent: &crate::CopyExtent) -> MTLSize {
MTLSize {
width: extent.width as u64,
height: extent.height as u64,
depth: extent.depth as u64,
}
}
pub fn map_origin(origin: &wgt::Origin3d) -> metal::MTLOrigin {
metal::MTLOrigin {
pub fn map_origin(origin: &wgt::Origin3d) -> MTLOrigin {
MTLOrigin {
x: origin.x as u64,
y: origin.y as u64,
z: origin.z as u64,
}
}
pub fn map_store_action(store: bool, resolve: bool) -> metal::MTLStoreAction {
use metal::MTLStoreAction::*;
pub fn map_store_action(store: bool, resolve: bool) -> MTLStoreAction {
use MTLStoreAction::*;
match (store, resolve) {
(true, true) => StoreAndMultisampleResolve,
(false, true) => MultisampleResolve,
@ -313,8 +305,8 @@ pub fn map_store_action(store: bool, resolve: bool) -> metal::MTLStoreAction {
}
}
pub fn map_clear_color(color: &wgt::Color) -> metal::MTLClearColor {
metal::MTLClearColor {
pub fn map_clear_color(color: &wgt::Color) -> MTLClearColor {
MTLClearColor {
red: color.r,
green: color.g,
blue: color.b,
@ -322,45 +314,42 @@ pub fn map_clear_color(color: &wgt::Color) -> metal::MTLClearColor {
}
}
pub fn get_blit_option(
format: wgt::TextureFormat,
aspect: crate::FormatAspects,
) -> metal::MTLBlitOption {
pub fn get_blit_option(format: wgt::TextureFormat, aspect: crate::FormatAspects) -> MTLBlitOption {
if format.is_combined_depth_stencil_format() {
match aspect {
crate::FormatAspects::DEPTH => metal::MTLBlitOption::DepthFromDepthStencil,
crate::FormatAspects::STENCIL => metal::MTLBlitOption::StencilFromDepthStencil,
crate::FormatAspects::DEPTH => MTLBlitOption::DepthFromDepthStencil,
crate::FormatAspects::STENCIL => MTLBlitOption::StencilFromDepthStencil,
_ => unreachable!(),
}
} else {
metal::MTLBlitOption::None
MTLBlitOption::None
}
}
pub fn map_render_stages(stage: wgt::ShaderStages) -> metal::MTLRenderStages {
let mut raw_stages = metal::MTLRenderStages::empty();
pub fn map_render_stages(stage: wgt::ShaderStages) -> MTLRenderStages {
let mut raw_stages = MTLRenderStages::empty();
if stage.contains(wgt::ShaderStages::VERTEX) {
raw_stages |= metal::MTLRenderStages::Vertex;
raw_stages |= MTLRenderStages::Vertex;
}
if stage.contains(wgt::ShaderStages::FRAGMENT) {
raw_stages |= metal::MTLRenderStages::Fragment;
raw_stages |= MTLRenderStages::Fragment;
}
raw_stages
}
pub fn map_resource_usage(ty: &wgt::BindingType) -> metal::MTLResourceUsage {
pub fn map_resource_usage(ty: &wgt::BindingType) -> MTLResourceUsage {
match ty {
wgt::BindingType::Texture { .. } => metal::MTLResourceUsage::Sample,
wgt::BindingType::Texture { .. } => MTLResourceUsage::Sample,
wgt::BindingType::StorageTexture { access, .. } => match access {
wgt::StorageTextureAccess::WriteOnly => metal::MTLResourceUsage::Write,
wgt::StorageTextureAccess::ReadOnly => metal::MTLResourceUsage::Read,
wgt::StorageTextureAccess::WriteOnly => MTLResourceUsage::Write,
wgt::StorageTextureAccess::ReadOnly => MTLResourceUsage::Read,
wgt::StorageTextureAccess::Atomic | wgt::StorageTextureAccess::ReadWrite => {
metal::MTLResourceUsage::Read | metal::MTLResourceUsage::Write
MTLResourceUsage::Read | MTLResourceUsage::Write
}
},
wgt::BindingType::Sampler(..) => metal::MTLResourceUsage::empty(),
wgt::BindingType::Sampler(..) => MTLResourceUsage::empty(),
_ => unreachable!(),
}
}

View File

@ -9,14 +9,19 @@ use crate::auxil::map_naga_stage;
use crate::metal::ShaderModuleSource;
use crate::TlasInstance;
use metal::foreign_types::ForeignType;
use metal::{
foreign_types::ForeignType, MTLCommandBufferStatus, MTLDepthClipMode, MTLLanguageVersion,
MTLMutability, MTLPixelFormat, MTLPrimitiveTopologyClass, MTLResourceID, MTLResourceOptions,
MTLSamplerAddressMode, MTLSamplerMipFilter, MTLSize, MTLStorageMode, MTLTextureType,
MTLTriangleFillMode, MTLVertexStepFunction, NSRange,
};
type DeviceResult<T> = Result<T, crate::DeviceError>;
struct CompiledShader {
library: metal::Library,
function: metal::Function,
wg_size: metal::MTLSize,
wg_size: MTLSize,
wg_memory_sizes: Vec<u32>,
/// Bindings of WGSL `storage` globals that contain variable-sized arrays.
@ -120,7 +125,7 @@ impl super::Device {
stage: &crate::ProgrammableStage<super::ShaderModule>,
vertex_buffer_mappings: &[naga::back::msl::VertexBufferMapping],
layout: &super::PipelineLayout,
primitive_class: metal::MTLPrimitiveTopologyClass,
primitive_class: MTLPrimitiveTopologyClass,
naga_stage: naga::ShaderStage,
) -> Result<CompiledShader, crate::PipelineError> {
let naga_shader = if let ShaderModuleSource::Naga(naga) = &stage.module.source {
@ -146,16 +151,16 @@ impl super::Device {
let options = naga::back::msl::Options {
lang_version: match self.shared.private_caps.msl_version {
metal::MTLLanguageVersion::V1_0 => (1, 0),
metal::MTLLanguageVersion::V1_1 => (1, 1),
metal::MTLLanguageVersion::V1_2 => (1, 2),
metal::MTLLanguageVersion::V2_0 => (2, 0),
metal::MTLLanguageVersion::V2_1 => (2, 1),
metal::MTLLanguageVersion::V2_2 => (2, 2),
metal::MTLLanguageVersion::V2_3 => (2, 3),
metal::MTLLanguageVersion::V2_4 => (2, 4),
metal::MTLLanguageVersion::V3_0 => (3, 0),
metal::MTLLanguageVersion::V3_1 => (3, 1),
MTLLanguageVersion::V1_0 => (1, 0),
MTLLanguageVersion::V1_1 => (1, 1),
MTLLanguageVersion::V1_2 => (1, 2),
MTLLanguageVersion::V2_0 => (2, 0),
MTLLanguageVersion::V2_1 => (2, 1),
MTLLanguageVersion::V2_2 => (2, 2),
MTLLanguageVersion::V2_3 => (2, 3),
MTLLanguageVersion::V2_4 => (2, 4),
MTLLanguageVersion::V3_0 => (3, 0),
MTLLanguageVersion::V3_1 => (3, 1),
},
inline_samplers: Default::default(),
spirv_cross_compatibility: false,
@ -177,7 +182,7 @@ impl super::Device {
let pipeline_options = naga::back::msl::PipelineOptions {
allow_and_force_point_size: match primitive_class {
metal::MTLPrimitiveTopologyClass::Point => true,
MTLPrimitiveTopologyClass::Point => true,
_ => false,
},
vertex_pulling_transform: true,
@ -222,7 +227,7 @@ impl super::Device {
.as_ref()
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?;
let wg_size = metal::MTLSize {
let wg_size = MTLSize {
width: ep.workgroup_size[0] as _,
height: ep.workgroup_size[1] as _,
depth: ep.workgroup_size[2] as _,
@ -301,14 +306,14 @@ impl super::Device {
buffers
.object_at(slot as u64)
.unwrap()
.set_mutability(metal::MTLMutability::Immutable);
.set_mutability(MTLMutability::Immutable);
}
}
pub unsafe fn texture_from_raw(
raw: metal::Texture,
format: wgt::TextureFormat,
raw_type: metal::MTLTextureType,
raw_type: MTLTextureType,
array_layers: u32,
mip_levels: u32,
copy_size: crate::CopyExtent,
@ -347,17 +352,14 @@ impl crate::Device for super::Device {
let map_read = desc.usage.contains(wgt::BufferUses::MAP_READ);
let map_write = desc.usage.contains(wgt::BufferUses::MAP_WRITE);
let mut options = metal::MTLResourceOptions::empty();
let mut options = MTLResourceOptions::empty();
options |= if map_read || map_write {
// `crate::MemoryFlags::PREFER_COHERENT` is ignored here
metal::MTLResourceOptions::StorageModeShared
MTLResourceOptions::StorageModeShared
} else {
metal::MTLResourceOptions::StorageModePrivate
MTLResourceOptions::StorageModePrivate
};
options.set(
metal::MTLResourceOptions::CPUCacheModeWriteCombined,
map_write,
);
options.set(MTLResourceOptions::CPUCacheModeWriteCombined, map_write);
//TODO: HazardTrackingModeUntracked
@ -410,21 +412,21 @@ impl crate::Device for super::Device {
let descriptor = metal::TextureDescriptor::new();
let mtl_type = match desc.dimension {
wgt::TextureDimension::D1 => metal::MTLTextureType::D1,
wgt::TextureDimension::D1 => MTLTextureType::D1,
wgt::TextureDimension::D2 => {
if desc.sample_count > 1 {
descriptor.set_sample_count(desc.sample_count as u64);
metal::MTLTextureType::D2Multisample
MTLTextureType::D2Multisample
} else if desc.size.depth_or_array_layers > 1 {
descriptor.set_array_length(desc.size.depth_or_array_layers as u64);
metal::MTLTextureType::D2Array
MTLTextureType::D2Array
} else {
metal::MTLTextureType::D2
MTLTextureType::D2
}
}
wgt::TextureDimension::D3 => {
descriptor.set_depth(desc.size.depth_or_array_layers as u64);
metal::MTLTextureType::D3
MTLTextureType::D3
}
};
@ -434,7 +436,7 @@ impl crate::Device for super::Device {
descriptor.set_mipmap_level_count(desc.mip_level_count as u64);
descriptor.set_pixel_format(mtl_format);
descriptor.set_usage(conv::map_texture_usage(desc.format, desc.usage));
descriptor.set_storage_mode(metal::MTLStorageMode::Private);
descriptor.set_storage_mode(MTLStorageMode::Private);
let raw = self.shared.device.lock().new_texture(&descriptor);
if raw.as_ptr().is_null() {
@ -470,7 +472,7 @@ impl crate::Device for super::Device {
texture: &super::Texture,
desc: &crate::TextureViewDescriptor,
) -> DeviceResult<super::TextureView> {
let raw_type = if texture.raw_type == metal::MTLTextureType::D2Multisample {
let raw_type = if texture.raw_type == MTLTextureType::D2Multisample {
texture.raw_type
} else {
conv::map_texture_view_dimension(desc.dimension)
@ -507,11 +509,11 @@ impl crate::Device for super::Device {
let raw = texture.raw.new_texture_view_from_slice(
raw_format,
raw_type,
metal::NSRange {
NSRange {
location: desc.range.base_mip_level as _,
length: mip_level_count as _,
},
metal::NSRange {
NSRange {
location: desc.range.base_array_layer as _,
length: array_layer_count as _,
},
@ -543,10 +545,10 @@ impl crate::Device for super::Device {
descriptor.set_mag_filter(conv::map_filter_mode(desc.mag_filter));
descriptor.set_mip_filter(match desc.mipmap_filter {
wgt::FilterMode::Nearest if desc.lod_clamp == (0.0..0.0) => {
metal::MTLSamplerMipFilter::NotMipmapped
MTLSamplerMipFilter::NotMipmapped
}
wgt::FilterMode::Nearest => metal::MTLSamplerMipFilter::Nearest,
wgt::FilterMode::Linear => metal::MTLSamplerMipFilter::Linear,
wgt::FilterMode::Nearest => MTLSamplerMipFilter::Nearest,
wgt::FilterMode::Linear => MTLSamplerMipFilter::Linear,
});
let [s, t, r] = desc.address_modes;
@ -567,15 +569,15 @@ impl crate::Device for super::Device {
if let Some(border_color) = desc.border_color {
if let wgt::SamplerBorderColor::Zero = border_color {
if s == wgt::AddressMode::ClampToBorder {
descriptor.set_address_mode_s(metal::MTLSamplerAddressMode::ClampToZero);
descriptor.set_address_mode_s(MTLSamplerAddressMode::ClampToZero);
}
if t == wgt::AddressMode::ClampToBorder {
descriptor.set_address_mode_t(metal::MTLSamplerAddressMode::ClampToZero);
descriptor.set_address_mode_t(MTLSamplerAddressMode::ClampToZero);
}
if r == wgt::AddressMode::ClampToBorder {
descriptor.set_address_mode_r(metal::MTLSamplerAddressMode::ClampToZero);
descriptor.set_address_mode_r(MTLSamplerAddressMode::ClampToZero);
}
} else {
descriptor.set_border_color(conv::map_border_color(border_color));
@ -848,11 +850,11 @@ impl crate::Device for super::Device {
// Create argument buffer for this array
let buffer = self.shared.device.lock().new_buffer(
8 * count as u64,
metal::MTLResourceOptions::HazardTrackingModeUntracked
| metal::MTLResourceOptions::StorageModeShared,
MTLResourceOptions::HazardTrackingModeUntracked
| MTLResourceOptions::StorageModeShared,
);
let contents: &mut [metal::MTLResourceID] = unsafe {
let contents: &mut [MTLResourceID] = unsafe {
core::slice::from_raw_parts_mut(
buffer.contents().cast(),
count as usize,
@ -1050,8 +1052,8 @@ impl crate::Device for super::Device {
let descriptor = metal::RenderPipelineDescriptor::new();
let raw_triangle_fill_mode = match desc.primitive.polygon_mode {
wgt::PolygonMode::Fill => metal::MTLTriangleFillMode::Fill,
wgt::PolygonMode::Line => metal::MTLTriangleFillMode::Lines,
wgt::PolygonMode::Fill => MTLTriangleFillMode::Fill,
wgt::PolygonMode::Line => MTLTriangleFillMode::Lines,
wgt::PolygonMode::Point => panic!(
"{:?} is not enabled for this backend",
wgt::Features::POLYGON_MODE_POINT
@ -1150,8 +1152,7 @@ impl crate::Device for super::Device {
// TODO: This is a workaround for what appears to be a Metal validation bug
// A pixel format is required even though no attachments are provided
if desc.color_targets.is_empty() && desc.depth_stencil.is_none() {
descriptor
.set_depth_attachment_pixel_format(metal::MTLPixelFormat::Depth32Float);
descriptor.set_depth_attachment_pixel_format(MTLPixelFormat::Depth32Float);
}
(None, None)
}
@ -1162,7 +1163,7 @@ impl crate::Device for super::Device {
let ct = if let Some(color_target) = ct.as_ref() {
color_target
} else {
at_descriptor.set_pixel_format(metal::MTLPixelFormat::Invalid);
at_descriptor.set_pixel_format(MTLPixelFormat::Invalid);
continue;
};
@ -1239,7 +1240,7 @@ impl crate::Device for super::Device {
.max()
.unwrap_or(0);
buffer_desc.set_stride(wgt::math::align_to(stride, 4));
buffer_desc.set_step_function(metal::MTLVertexStepFunction::Constant);
buffer_desc.set_step_function(MTLVertexStepFunction::Constant);
buffer_desc.set_step_rate(0);
} else {
buffer_desc.set_stride(vb.array_stride);
@ -1297,9 +1298,9 @@ impl crate::Device for super::Device {
raw_cull_mode: conv::map_cull_mode(desc.primitive.cull_mode),
raw_depth_clip_mode: if self.features.contains(wgt::Features::DEPTH_CLIP_CONTROL) {
Some(if desc.primitive.unclipped_depth {
metal::MTLDepthClipMode::Clamp
MTLDepthClipMode::Clamp
} else {
metal::MTLDepthClipMode::Clip
MTLDepthClipMode::Clip
})
} else {
None
@ -1340,7 +1341,7 @@ impl crate::Device for super::Device {
CompiledShader {
library: desc.library.clone(),
function: desc.function.clone(),
wg_size: metal::MTLSize::new(
wg_size: MTLSize::new(
desc.num_workgroups.0 as u64,
desc.num_workgroups.1 as u64,
desc.num_workgroups.2 as u64,
@ -1354,7 +1355,7 @@ impl crate::Device for super::Device {
&desc.stage,
&[],
desc.layout,
metal::MTLPrimitiveTopologyClass::Unspecified,
MTLPrimitiveTopologyClass::Unspecified,
naga::ShaderStage::Compute,
)?
};
@ -1423,7 +1424,7 @@ impl crate::Device for super::Device {
match desc.ty {
wgt::QueryType::Occlusion => {
let size = desc.count as u64 * crate::QUERY_SIZE;
let options = metal::MTLResourceOptions::empty();
let options = MTLResourceOptions::empty();
//TODO: HazardTrackingModeUntracked
let raw_buffer = self.shared.device.lock().new_buffer(size, options);
if let Some(label) = desc.label {
@ -1438,11 +1439,10 @@ impl crate::Device for super::Device {
wgt::QueryType::Timestamp => {
let size = desc.count as u64 * crate::QUERY_SIZE;
let device = self.shared.device.lock();
let destination_buffer =
device.new_buffer(size, metal::MTLResourceOptions::empty());
let destination_buffer = device.new_buffer(size, MTLResourceOptions::empty());
let csb_desc = metal::CounterSampleBufferDescriptor::new();
csb_desc.set_storage_mode(metal::MTLStorageMode::Shared);
csb_desc.set_storage_mode(MTLStorageMode::Shared);
csb_desc.set_sample_count(desc.count as _);
if let Some(label) = desc.label {
csb_desc.set_label(label);
@ -1508,7 +1508,7 @@ impl crate::Device for super::Device {
unsafe fn get_fence_value(&self, fence: &super::Fence) -> DeviceResult<crate::FenceValue> {
let mut max_value = fence.completed_value.load(atomic::Ordering::Acquire);
for &(value, ref cmd_buf) in fence.pending_command_buffers.iter() {
if cmd_buf.status() == metal::MTLCommandBufferStatus::Completed {
if cmd_buf.status() == MTLCommandBufferStatus::Completed {
max_value = value;
}
}
@ -1538,7 +1538,7 @@ impl crate::Device for super::Device {
let start = time::Instant::now();
loop {
if let metal::MTLCommandBufferStatus::Completed = cmd_buf.status() {
if let MTLCommandBufferStatus::Completed = cmd_buf.status() {
return Ok(true);
}
if start.elapsed().as_millis() >= timeout_ms as u128 {

View File

@ -33,7 +33,12 @@ use std::thread;
use arrayvec::ArrayVec;
use bitflags::bitflags;
use hashbrown::HashMap;
use metal::foreign_types::ForeignTypeRef as _;
use metal::{
foreign_types::ForeignTypeRef as _, MTLArgumentBuffersTier, MTLBuffer, MTLCommandBufferStatus,
MTLCullMode, MTLDepthClipMode, MTLIndexType, MTLLanguageVersion, MTLPrimitiveType,
MTLReadWriteTextureTier, MTLRenderStages, MTLResource, MTLResourceUsage, MTLSamplerState,
MTLSize, MTLTexture, MTLTextureType, MTLTriangleFillMode, MTLWinding,
};
use naga::FastHashMap;
use parking_lot::{Mutex, RwLock};
@ -192,14 +197,14 @@ bitflags!(
#[derive(Clone, Debug)]
struct PrivateCapabilities {
family_check: bool,
msl_version: metal::MTLLanguageVersion,
msl_version: MTLLanguageVersion,
fragment_rw_storage: bool,
read_write_texture_tier: metal::MTLReadWriteTextureTier,
read_write_texture_tier: MTLReadWriteTextureTier,
msaa_desktop: bool,
msaa_apple3: bool,
msaa_apple7: bool,
resource_heaps: bool,
argument_buffers: metal::MTLArgumentBuffersTier,
argument_buffers: MTLArgumentBuffersTier,
shared_textures: bool,
mutable_comparison_samplers: bool,
sampler_clamp_to_border: bool,
@ -517,7 +522,7 @@ impl crate::BufferBinding<'_, Buffer> {
pub struct Texture {
raw: metal::Texture,
format: wgt::TextureFormat,
raw_type: metal::MTLTextureType,
raw_type: MTLTextureType,
array_layers: u32,
mip_levels: u32,
copy_size: crate::CopyExtent,
@ -668,10 +673,10 @@ trait AsNative {
fn as_native(&self) -> &Self::Native;
}
type ResourcePtr = NonNull<metal::MTLResource>;
type BufferPtr = NonNull<metal::MTLBuffer>;
type TexturePtr = NonNull<metal::MTLTexture>;
type SamplerPtr = NonNull<metal::MTLSamplerState>;
type ResourcePtr = NonNull<MTLResource>;
type BufferPtr = NonNull<MTLBuffer>;
type TexturePtr = NonNull<MTLTexture>;
type SamplerPtr = NonNull<MTLSamplerState>;
impl AsNative for ResourcePtr {
type Native = metal::ResourceRef;
@ -742,16 +747,16 @@ struct BufferResource {
#[derive(Debug)]
struct UseResourceInfo {
uses: metal::MTLResourceUsage,
stages: metal::MTLRenderStages,
uses: MTLResourceUsage,
stages: MTLRenderStages,
visible_in_compute: bool,
}
impl Default for UseResourceInfo {
fn default() -> Self {
Self {
uses: metal::MTLResourceUsage::empty(),
stages: metal::MTLRenderStages::empty(),
uses: MTLResourceUsage::empty(),
stages: MTLRenderStages::empty(),
visible_in_compute: false,
}
}
@ -841,11 +846,11 @@ pub struct RenderPipeline {
fs_lib: Option<metal::Library>,
vs_info: PipelineStageInfo,
fs_info: Option<PipelineStageInfo>,
raw_primitive_type: metal::MTLPrimitiveType,
raw_triangle_fill_mode: metal::MTLTriangleFillMode,
raw_front_winding: metal::MTLWinding,
raw_cull_mode: metal::MTLCullMode,
raw_depth_clip_mode: Option<metal::MTLDepthClipMode>,
raw_primitive_type: MTLPrimitiveType,
raw_triangle_fill_mode: MTLTriangleFillMode,
raw_front_winding: MTLWinding,
raw_cull_mode: MTLCullMode,
raw_depth_clip_mode: Option<MTLDepthClipMode>,
depth_stencil: Option<(metal::DepthStencilState, wgt::DepthBiasState)>,
}
@ -860,7 +865,7 @@ pub struct ComputePipeline {
#[allow(dead_code)]
cs_lib: metal::Library,
cs_info: PipelineStageInfo,
work_group_size: metal::MTLSize,
work_group_size: MTLSize,
work_group_memory_sizes: Vec<u32>,
}
@ -899,7 +904,7 @@ impl Fence {
fn get_latest(&self) -> crate::FenceValue {
let mut max_value = self.completed_value.load(atomic::Ordering::Acquire);
for &(value, ref cmd_buf) in self.pending_command_buffers.iter() {
if cmd_buf.status() == metal::MTLCommandBufferStatus::Completed {
if cmd_buf.status() == MTLCommandBufferStatus::Completed {
max_value = value;
}
}
@ -921,7 +926,7 @@ struct IndexState {
buffer_ptr: BufferPtr,
offset: wgt::BufferAddress,
stride: wgt::BufferAddress,
raw_type: metal::MTLIndexType,
raw_type: MTLIndexType,
}
#[derive(Default)]
@ -933,9 +938,9 @@ struct CommandState {
blit: Option<metal::BlitCommandEncoder>,
render: Option<metal::RenderCommandEncoder>,
compute: Option<metal::ComputeCommandEncoder>,
raw_primitive_type: metal::MTLPrimitiveType,
raw_primitive_type: MTLPrimitiveType,
index: Option<IndexState>,
raw_wg_size: metal::MTLSize,
raw_wg_size: MTLSize,
stage_infos: MultiStageData<PipelineStageInfo>,
/// Sizes of currently bound [`wgt::BufferBindingType::Storage`] buffers.

View File

@ -9,7 +9,7 @@ use core_graphics_types::{
base::CGFloat,
geometry::{CGRect, CGSize},
};
use metal::foreign_types::ForeignType;
use metal::{foreign_types::ForeignType, MTLTextureType};
use objc::{
class, msg_send,
rc::{autoreleasepool, StrongPtr},
@ -205,7 +205,7 @@ impl crate::Surface for super::Surface {
texture: super::Texture {
raw: texture,
format: swapchain_format,
raw_type: metal::MTLTextureType::D2,
raw_type: MTLTextureType::D2,
array_layers: 1,
mip_levels: 1,
copy_size: crate::CopyExtent {