Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/src/FNAPlatform/MetalDevice_MTL.cs
1909 lines | 51.3 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Runtime.InteropServices;
#endregion
/* =============================
* Objective-C Runtime Reference
* =============================
* A function call takes the form of objc_msgSend(<receiver>, <message>, <args>)
*
* To send the "quack" message to a "duck" instance, we need two things:
* 1) A pointer to the duck instance. This is the receiver.
* 2) A Selector (read: char* with extra metadata) for the "quack" message.
*
* To create a "quack" selector, we have to call sel_registerName() with a
* parameter of "quack" turned into an array of UTF8 bytes. This is tedious,
* so we do this here by calling the convenience method Selector("quack").
*
* To get a property of obj: objc_msgSend(obj, Selector("propertyName"))
* To set a property of obj: objc_msgSend(obj, Selector("setPropertyName"), val)
*
* ===========
* Other notes
* ===========
* The size of NSUInteger varies depending on CPU arch (32 bit / 64 bit).
* Since all modern Apple devices are 64 bit, we can just use ulong (UInt64)
* instead of uint (UInt32). This makes the structs the correct size.
*/
namespace Microsoft.Xna.Framework.Graphics
{
internal partial class MetalDevice : IGLDevice
{
#region Private ObjC Runtime Entry Points
const string objcLibrary = "/usr/lib/libobjc.A.dylib";
[DllImport(objcLibrary)]
private static extern IntPtr objc_getClass(string name);
[DllImport(objcLibrary)]
private static extern void objc_release(IntPtr obj);
[DllImport(objcLibrary)]
private static extern IntPtr objc_retain(IntPtr obj);
[DllImport(objcLibrary)]
private static extern IntPtr objc_autoreleasePoolPush();
[DllImport(objcLibrary)]
private static extern void objc_autoreleasePoolPop(IntPtr pool);
[DllImport(objcLibrary)]
private static extern IntPtr sel_registerName(byte[] name);
/* Here come the obj_msgSend overloads... */
// Void
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, ulong arg2);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, ulong arg2, ulong arg3);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg1, ulong arg2, ulong arg3);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg1, ulong arg2);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, uint arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, bool arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, double arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, MTLViewport viewport);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, MTLScissorRect scissorRect);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, MTLClearColor color);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, NSRange range);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, float arg1, float arg2, float arg3);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, float arg1, float arg2, float arg3, float arg4);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, MTLRegion region, ulong level, ulong slice, IntPtr bytes, ulong bytesPerRow, ulong bytesPerImage);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr srcTexture, ulong srcSlice, ulong srcLevel, MTLOrigin srcOrigin, MTLSize srcSize, IntPtr dstTexture, ulong dstSlice, ulong dstLevel, MTLOrigin dstOrigin);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, ulong primitiveType, ulong indexCount, ulong indexType, IntPtr indexBuffer, ulong indexBufferOffset, ulong instanceCount);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr pixelBytes, ulong bytesPerRow, ulong bytesPerImage, MTLRegion region, ulong level, ulong slice);
// IntPtr
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, string arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg1, ulong arg2);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, MTLPixelFormat arg1, ulong arg2, bool arg3);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, MTLPixelFormat arg1, ulong arg2, ulong arg3, bool arg4);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, out IntPtr arg2);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern IntPtr intptr_objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2, out IntPtr arg3);
// Ulong
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern ulong ulong_objc_msgSend(IntPtr receiver, IntPtr selector);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern ulong ulong_objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg);
// Bool
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern bool bool_objc_msgSend(IntPtr receiver, IntPtr selector);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern bool bool_objc_msgSend(IntPtr receiver, IntPtr selector, ulong arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern bool bool_objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg);
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern bool bool_objc_msgSend(IntPtr receiver, IntPtr selector, NSOperatingSystemVersion arg);
// CGSize
[DllImport(objcLibrary, EntryPoint = "objc_msgSend")]
private static extern CGSize cgsize_objc_msgSend(IntPtr receiver, IntPtr selector);
#endregion
#region C-Style Metal Function Imports
const string metalLibrary = "/System/Library/Frameworks/Metal.framework/Metal";
[DllImport(metalLibrary)]
internal static extern IntPtr MTLCreateSystemDefaultDevice();
#endregion
#region Private MTL Enums
private enum MTLLoadAction : ulong
{
DontCare = 0,
Load = 1,
Clear = 2
}
private enum MTLStoreAction : ulong
{
DontCare = 0,
Store = 1,
MultisampleResolve = 2
}
private enum MTLPrimitiveType : ulong
{
Point = 0,
Line = 1,
LineStrip = 2,
Triangle = 3,
TriangleStrip = 4
}
private enum MTLIndexType : ulong
{
UInt16 = 0,
UInt32 = 1
}
private enum MTLPixelFormat : ulong
{
Invalid = 0,
A8Unorm = 1,
R16Float = 25,
RG8Snorm = 32,
B5G6R5Unorm = 40,
ABGR4Unorm = 42,
BGR5A1Unorm = 43,
R32Float = 55,
RG16Unorm = 60,
RG16Snorm = 62,
RG16Float = 65,
RGBA8Unorm = 70,
BGRA8Unorm = 80,
RGB10A2Unorm = 90,
RG32Float = 105,
RGBA16Unorm = 110,
RGBA16Float = 115,
RGBA32Float = 125,
BC1_RGBA = 130,
BC2_RGBA = 132,
BC3_RGBA = 134,
Depth16Unorm = 250,
Depth32Float = 252,
Depth24Unorm_Stencil8 = 255,
Depth32Float_Stencil8 = 260,
}
private enum MTLSamplerMinMagFilter
{
Nearest = 0,
Linear = 1
}
private enum MTLTextureUsage
{
ShaderRead = 1,
RenderTarget = 4
}
private enum MTLTextureType
{
Multisample2D = 4,
Texture3D = 7
}
private enum MTLStorageMode
{
Private = 2
}
private enum MTLBlendFactor
{
Zero = 0,
One = 1,
SourceColor = 2,
OneMinusSourceColor = 3,
SourceAlpha = 4,
OneMinusSourceAlpha = 5,
DestinationColor = 6,
OneMinusDestinationColor = 7,
DestinationAlpha = 8,
OneMinusDestinationAlpha = 9,
SourceAlphaSaturated = 10,
BlendColor = 11,
OneMinusBlendColor = 12
}
private enum MTLBlendOperation
{
Add = 0,
Subtract = 1,
ReverseSubtract = 2,
Min = 3,
Max = 4
}
private enum MTLCullMode
{
None = 0,
Front = 1,
Back = 2
}
private enum MTLTriangleFillMode
{
Fill = 0,
Lines = 1
}
private enum MTLSamplerAddressMode
{
ClampToEdge = 0,
Repeat = 2,
MirrorRepeat = 3
}
private enum MTLSamplerMipFilter
{
Nearest = 1,
Linear = 2
}
private enum MTLVertexFormat
{
UChar4 = 3,
UChar4Normalized = 9,
Short2 = 16,
Short4 = 18,
Short2Normalized = 22,
Short4Normalized = 24,
Half2 = 25,
Half4 = 27,
Float = 28,
Float2 = 29,
Float3 = 30,
Float4 = 31
}
private enum MTLVertexStepFunction
{
PerInstance = 2
}
private enum MTLCompareFunction
{
Never = 0,
Less = 1,
Equal = 2,
LessEqual = 3,
Greater = 4,
NotEqual = 5,
GreaterEqual = 6,
Always = 7
}
private enum MTLStencilOperation
{
Keep = 0,
Zero = 1,
Replace = 2,
IncrementClamp = 3,
DecrementClamp = 4,
Invert = 5,
IncrementWrap = 6,
DecrementWrap = 7
}
private enum MTLVisibilityResultMode
{
Disabled = 0,
Counting = 2
}
private enum MTLResourceOptions
{
CPUCacheModeDefaultCache = 0,
CPUCacheModeWriteCombined = 1
}
private enum MTLPurgeableState
{
NonVolatile = 2,
Empty = 4
}
#endregion
#region Private MTL Structs
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLClearColor
{
public double red;
public double green;
public double blue;
public double alpha;
public MTLClearColor(
double red,
double green,
double blue,
double alpha
) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLViewport
{
public double originX;
public double originY;
public double width;
public double height;
public double znear;
public double zfar;
public MTLViewport(
double originX,
double originY,
double width,
double height,
double znear,
double zfar
) {
this.originX = originX;
this.originY = originY;
this.width = width;
this.height = height;
this.znear = znear;
this.zfar = zfar;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLScissorRect
{
ulong x;
ulong y;
ulong width;
ulong height;
public MTLScissorRect(
int x,
int y,
int width,
int height
) {
this.x = (ulong) x;
this.y = (ulong) y;
this.width = (ulong) width;
this.height = (ulong) height;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLOrigin
{
ulong x;
ulong y;
ulong z;
public MTLOrigin(int x, int y, int z)
{
this.x = (ulong) x;
this.y = (ulong) y;
this.z = (ulong) z;
}
public static MTLOrigin Zero = new MTLOrigin(0, 0, 0);
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLSize
{
ulong width;
ulong height;
ulong depth;
public MTLSize(int width, int height, int depth)
{
this.width = (ulong) width;
this.height = (ulong) height;
this.depth = (ulong) depth;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MTLRegion
{
MTLOrigin origin;
MTLSize size;
public MTLRegion(MTLOrigin origin, MTLSize size)
{
this.origin = origin;
this.size = size;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct CGSize
{
public double width;
public double height;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct NSRange
{
public ulong loc;
public ulong len;
public NSRange(int loc, int len)
{
this.loc = (ulong) loc;
this.len = (ulong) len;
}
}
#endregion
#region Selectors
private static IntPtr Selector(string name)
{
name += Char.MinValue; // null terminator
return sel_registerName(System.Text.Encoding.UTF8.GetBytes(name));
}
private static IntPtr selRespondsToSelector = Selector("respondsToSelector:");
private static bool RespondsToSelector(IntPtr obj, IntPtr selector)
{
return bool_objc_msgSend(obj, selRespondsToSelector, selector);
}
#endregion
#region ObjC Class References
private static IntPtr classTextureDescriptor = objc_getClass("MTLTextureDescriptor");
private static IntPtr classRenderPassDescriptor = objc_getClass("MTLRenderPassDescriptor");
private static IntPtr classRenderPipelineDescriptor = objc_getClass("MTLRenderPipelineDescriptor");
private static IntPtr classDepthStencilDescriptor = objc_getClass("MTLDepthStencilDescriptor");
private static IntPtr classStencilDescriptor = objc_getClass("MTLStencilDescriptor");
private static IntPtr classMTLSamplerDescriptor = objc_getClass("MTLSamplerDescriptor");
private static IntPtr classMTLVertexDescriptor = objc_getClass("MTLVertexDescriptor");
private static IntPtr classNSProcessInfo = objc_getClass("NSProcessInfo");
private static IntPtr classNSString = objc_getClass("NSString");
#endregion
#region NSString <-> C# String
private static IntPtr selUtf8 = Selector("UTF8String");
private static string NSStringToUTF8(IntPtr nsstr)
{
return Marshal.PtrToStringAnsi(
intptr_objc_msgSend(nsstr, selUtf8)
);
}
private static IntPtr selAlloc = Selector("alloc");
private static IntPtr selInitWithUtf8 = Selector("initWithUTF8String:");
private static IntPtr UTF8ToNSString(string str)
{
return intptr_objc_msgSend(
intptr_objc_msgSend(classNSString, selAlloc),
selInitWithUtf8,
str
);
}
#endregion
#region iOS/tvOS GPU Check
private static IntPtr selSupportsFamily = Selector("supportsFamily:");
private static IntPtr selSupportsFeatureSet = Selector("supportsFeatureSet:");
private bool HasModernAppleGPU()
{
// "Modern" = A9 or later
const ulong GPUFamilyCommon2 = 3002;
const ulong iOS_GPUFamily3_v1 = 4;
const ulong tvOS_GPUFamily2_v1 = 30003;
// Can we use the GPUFamily API?
if (RespondsToSelector(device, selSupportsFamily))
{
return bool_objc_msgSend(
device,
selSupportsFamily,
GPUFamilyCommon2
);
}
// Fall back to checking FeatureSets...
bool iosCompat = bool_objc_msgSend(
device,
selSupportsFeatureSet,
iOS_GPUFamily3_v1
);
bool tvosCompat = bool_objc_msgSend(
device,
selSupportsFeatureSet,
tvOS_GPUFamily2_v1
);
return iosCompat || tvosCompat;
}
#endregion
#region OS Version Check
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct NSOperatingSystemVersion
{
public long major;
public long minor;
public long patch;
}
private static IntPtr selOperatingSystemAtLeast = Selector("isOperatingSystemAtLeastVersion:");
private static IntPtr selProcessInfo = Selector("processInfo");
private static bool OperatingSystemAtLeast(long major, long minor, long patch)
{
NSOperatingSystemVersion version = new NSOperatingSystemVersion
{
major = major,
minor = minor,
patch = patch
};
IntPtr processInfo = intptr_objc_msgSend(
classNSProcessInfo,
selProcessInfo
);
return bool_objc_msgSend(
processInfo,
selOperatingSystemAtLeast,
version
);
}
#endregion
#region MTLDevice
private static IntPtr selName = Selector("name");
private static string mtlGetDeviceName(IntPtr device)
{
return NSStringToUTF8(intptr_objc_msgSend(device, selName));
}
private static IntPtr selSupportsSampleCount = Selector("supportsSampleCount:");
private static bool mtlSupportsSampleCount(IntPtr device, int count)
{
return bool_objc_msgSend(device, selSupportsSampleCount, (ulong) count);
}
private static IntPtr selCommandQueue = Selector("newCommandQueue");
private static IntPtr mtlNewCommandQueue(IntPtr device)
{
return intptr_objc_msgSend(device, selCommandQueue);
}
private static IntPtr selNewBufferWithLength = Selector("newBufferWithLength:options:");
private static IntPtr mtlNewBufferWithLength(IntPtr device, int length, MTLResourceOptions options)
{
return intptr_objc_msgSend(
device,
selNewBufferWithLength,
(ulong) length,
(ulong) options
);
}
private static IntPtr selNewTextureWithDescriptor = Selector("newTextureWithDescriptor:");
private static IntPtr mtlNewTextureWithDescriptor(IntPtr device, IntPtr texDesc)
{
return intptr_objc_msgSend(
device,
selNewTextureWithDescriptor,
texDesc
);
}
private static IntPtr selNewSamplerStateWithDescriptor = Selector("newSamplerStateWithDescriptor:");
private static IntPtr mtlNewSamplerStateWithDescriptor(IntPtr device, IntPtr sampDesc)
{
return intptr_objc_msgSend(
device,
selNewSamplerStateWithDescriptor,
sampDesc
);
}
private static IntPtr selSupportsDepth24Stencil8 = Selector("isDepth24Stencil8PixelFormatSupported");
private static bool mtlSupportsDepth24Stencil8(IntPtr device)
{
return bool_objc_msgSend(device, selSupportsDepth24Stencil8);
}
#endregion
#region MTLBuffer
private static IntPtr selContents = Selector("contents");
private static IntPtr mtlGetBufferContentsPtr(IntPtr buffer)
{
return intptr_objc_msgSend(buffer, selContents);
}
#endregion
#region MTLCommandBuffer
private static IntPtr selRenderCommandEncoder = Selector("renderCommandEncoderWithDescriptor:");
private static IntPtr mtlMakeRenderCommandEncoder(
IntPtr commandBuffer,
IntPtr renderPassDesc
) {
return intptr_objc_msgSend(
commandBuffer,
selRenderCommandEncoder,
renderPassDesc
);
}
private static IntPtr selPresentDrawable = Selector("presentDrawable:");
private static void mtlPresentDrawable(
IntPtr commandBuffer,
IntPtr drawable
) {
objc_msgSend(
commandBuffer,
selPresentDrawable,
drawable
);
}
private static IntPtr selCommit = Selector("commit");
private static void mtlCommitCommandBuffer(IntPtr commandBuffer)
{
objc_msgSend(commandBuffer, selCommit);
}
private static IntPtr selWaitUntilCompleted = Selector("waitUntilCompleted");
private static void mtlCommandBufferWaitUntilCompleted(IntPtr commandBuffer)
{
objc_msgSend(commandBuffer, selWaitUntilCompleted);
}
#endregion
#region MTLCommandQueue
private static IntPtr selCommandBuffer = Selector("commandBuffer");
private static IntPtr mtlMakeCommandBuffer(IntPtr queue)
{
return intptr_objc_msgSend(queue, selCommandBuffer);
}
#endregion
#region Attachment Methods
private static IntPtr selColorAttachments = Selector("colorAttachments");
private static IntPtr selObjectAtIndexedSubscript = Selector("objectAtIndexedSubscript:");
private static IntPtr mtlGetColorAttachment(IntPtr desc, int index)
{
IntPtr attachments = intptr_objc_msgSend(
desc,
selColorAttachments
);
return intptr_objc_msgSend(
attachments,
selObjectAtIndexedSubscript,
(ulong) index
);
}
private static IntPtr selDepthAttachment = Selector("depthAttachment");
private static IntPtr mtlGetDepthAttachment(IntPtr desc)
{
return intptr_objc_msgSend(desc, selDepthAttachment);
}
private static IntPtr selStencilAttachment = Selector("stencilAttachment");
private static IntPtr mtlGetStencilAttachment(IntPtr desc)
{
return intptr_objc_msgSend(desc, selStencilAttachment);
}
private static IntPtr selSetLoadAction = Selector("setLoadAction:");
private static void mtlSetAttachmentLoadAction(
IntPtr attachment,
MTLLoadAction loadAction
) {
objc_msgSend(attachment, selSetLoadAction, (ulong) loadAction);
}
private static IntPtr selSetStoreAction = Selector("setStoreAction:");
private static void mtlSetAttachmentStoreAction(
IntPtr attachment,
MTLStoreAction storeAction
) {
objc_msgSend(attachment, selSetStoreAction, (ulong) storeAction);
}
private static IntPtr selSetTexture = Selector("setTexture:");
private static void mtlSetAttachmentTexture(
IntPtr attachment,
IntPtr texture
) {
objc_msgSend(attachment, selSetTexture, texture);
}
private static IntPtr selSetSlice = Selector("setSlice:");
private static void mtlSetAttachmentSlice(
IntPtr attachment,
int slice
) {
objc_msgSend(attachment, selSetSlice, (ulong) slice);
}
private static IntPtr selSetPixelFormat = Selector("setPixelFormat:");
private static void mtlSetAttachmentPixelFormat(
IntPtr attachment,
MTLPixelFormat pixelFormat
) {
objc_msgSend(attachment, selSetPixelFormat, (ulong) pixelFormat);
}
private static IntPtr selSetResolveTexture = Selector("setResolveTexture:");
private static void mtlSetAttachmentResolveTexture(
IntPtr attachment,
IntPtr resolveTexture
) {
objc_msgSend(attachment, selSetResolveTexture, resolveTexture);
}
private static IntPtr selSetResolveSlice = Selector("setResolveSlice:");
private static void mtlSetAttachmentResolveSlice(
IntPtr attachment,
int resolveSlice
) {
objc_msgSend(attachment, selSetResolveSlice, (ulong) resolveSlice);
}
private static IntPtr selSetClearColor = Selector("setClearColor:");
private static void mtlSetColorAttachmentClearColor(
IntPtr colorAttachment,
float r,
float g,
float b,
float a
) {
MTLClearColor clearColor = new MTLClearColor(r, g, b, a);
objc_msgSend(colorAttachment, selSetClearColor, clearColor);
}
private static IntPtr selSetClearDepth = Selector("setClearDepth:");
private static void mtlSetDepthAttachmentClearDepth(
IntPtr depthAttachment,
float clearDepth
) {
objc_msgSend(depthAttachment, selSetClearDepth, clearDepth);
}
private static IntPtr selSetClearStencil = Selector("setClearStencil:");
private static void mtlSetStencilAttachmentClearStencil(
IntPtr stencilAttachment,
int clearStencil
) {
objc_msgSend(stencilAttachment, selSetClearStencil, (ulong) clearStencil);
}
private static IntPtr selBlendingEnabled = Selector("setBlendingEnabled:");
private static void mtlSetAttachmentBlendingEnabled(
IntPtr colorAttachment,
bool enabled
) {
objc_msgSend(colorAttachment, selBlendingEnabled, enabled);
}
private static IntPtr selSetAlphaBlendOperation = Selector("setAlphaBlendOperation:");
private static void mtlSetAttachmentAlphaBlendOperation(
IntPtr colorAttachment,
MTLBlendOperation op
) {
objc_msgSend(colorAttachment, selSetAlphaBlendOperation, (ulong) op);
}
private static IntPtr selSetRGBBlendOperation = Selector("setRgbBlendOperation:");
private static void mtlSetAttachmentRGBBlendOperation(
IntPtr colorAttachment,
MTLBlendOperation op
) {
objc_msgSend(colorAttachment, selSetRGBBlendOperation, (ulong) op);
}
private static IntPtr selSetDestinationAlphaBlendFactor = Selector("setDestinationAlphaBlendFactor:");
private static void mtlSetAttachmentDestinationAlphaBlendFactor(
IntPtr colorAttachment,
MTLBlendFactor blend
) {
objc_msgSend(colorAttachment, selSetDestinationAlphaBlendFactor, (ulong) blend);
}
private static IntPtr selSetDestinationRGBBlendFactor = Selector("setDestinationRGBBlendFactor:");
private static void mtlSetAttachmentDestinationRGBBlendFactor(
IntPtr colorAttachment,
MTLBlendFactor blend
) {
objc_msgSend(colorAttachment, selSetDestinationRGBBlendFactor, (ulong) blend);
}
private static IntPtr selSetSourceAlphaBlendFactor = Selector("setSourceAlphaBlendFactor:");
private static void mtlSetAttachmentSourceAlphaBlendFactor(
IntPtr colorAttachment,
MTLBlendFactor blend
) {
objc_msgSend(colorAttachment, selSetSourceAlphaBlendFactor, (ulong) blend);
}
private static IntPtr selSetSourceRGBBlendFactor = Selector("setSourceRGBBlendFactor:");
private static void mtlSetAttachmentSourceRGBBlendFactor(
IntPtr colorAttachment,
MTLBlendFactor blend
) {
objc_msgSend(colorAttachment, selSetSourceRGBBlendFactor, (ulong) blend);
}
private static IntPtr selSetWriteMask = Selector("setWriteMask:");
private static void mtlSetAttachmentWriteMask(
IntPtr colorAttachment,
int mask
) {
objc_msgSend(colorAttachment, selSetWriteMask, (ulong) mask);
}
#endregion
#region MTLRenderPassDescriptor
private static IntPtr selRenderPassDescriptor = Selector("renderPassDescriptor");
private static IntPtr mtlMakeRenderPassDescriptor()
{
return intptr_objc_msgSend(classRenderPassDescriptor, selRenderPassDescriptor);
}
private static IntPtr selSetVisibilityBuffer = Selector("setVisibilityResultBuffer:");
private static void mtlSetVisibilityResultBuffer(
IntPtr renderPassDesc,
IntPtr buffer
) {
objc_msgSend(renderPassDesc, selSetVisibilityBuffer, buffer);
}
#endregion
#region MTLRenderCommandEncoder
private static IntPtr selSetBlendColor = Selector("setBlendColorRed:green:blue:alpha:");
private static void mtlSetBlendColor(
IntPtr renderCommandEncoder,
float red,
float green,
float blue,
float alpha
) {
objc_msgSend(renderCommandEncoder, selSetBlendColor, red, green, blue, alpha);
}
private static IntPtr selSetStencilReference = Selector("setStencilReferenceValue:");
private static void mtlSetStencilReferenceValue(
IntPtr renderCommandEncoder,
uint referenceValue
) {
objc_msgSend(renderCommandEncoder, selSetStencilReference, referenceValue);
}
private static IntPtr selSetViewport = Selector("setViewport:");
private static void mtlSetViewport(
IntPtr renderCommandEncoder,
int x,
int y,
int w,
int h,
double minDepth,
double maxDepth
) {
MTLViewport viewport = new MTLViewport(x, y, w, h, minDepth, maxDepth);
objc_msgSend(renderCommandEncoder, selSetViewport, viewport);
}
private static IntPtr selSetScissorRect = Selector("setScissorRect:");
private static void mtlSetScissorRect(
IntPtr renderCommandEncoder,
int x,
int y,
int w,
int h
) {
MTLScissorRect rect = new MTLScissorRect(x, y, w, h);
objc_msgSend(renderCommandEncoder, selSetScissorRect, rect);
}
private static IntPtr selEndEncoding = Selector("endEncoding");
private static void mtlEndEncoding(IntPtr commandEncoder)
{
objc_msgSend(commandEncoder, selEndEncoding);
}
private static IntPtr selDrawIndexedPrimitives = Selector("drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:instanceCount:");
private static void mtlDrawIndexedPrimitives(
IntPtr renderCommandEncoder,
MTLPrimitiveType primitiveType,
int indexCount,
MTLIndexType indexType,
IntPtr indexBuffer,
int indexBufferOffset,
int instanceCount
) {
objc_msgSend(
renderCommandEncoder,
selDrawIndexedPrimitives,
(ulong) primitiveType,
(ulong) indexCount,
(ulong) indexType,
indexBuffer,
(ulong) indexBufferOffset,
(ulong) instanceCount
);
}
private static IntPtr selDrawPrimitives = Selector("drawPrimitives:vertexStart:vertexCount:");
private static void mtlDrawPrimitives(
IntPtr renderCommandEncoder,
MTLPrimitiveType primitive,
int vertexStart,
int vertexCount
) {
objc_msgSend(
renderCommandEncoder,
selDrawPrimitives,
(ulong) primitive,
(ulong) vertexStart,
(ulong) vertexCount
);
}
private static IntPtr selSetCullMode = Selector("setCullMode:");
private static void mtlSetCullMode(
IntPtr renderCommandEncoder,
MTLCullMode cullMode
) {
objc_msgSend(
renderCommandEncoder,
selSetCullMode,
(ulong) cullMode
);
}
private static IntPtr selSetTriangleFillMode = Selector("setTriangleFillMode:");
private static void mtlSetTriangleFillMode(
IntPtr renderCommandEncoder,
MTLTriangleFillMode fillMode
) {
objc_msgSend(
renderCommandEncoder,
selSetTriangleFillMode,
(ulong) fillMode
);
}
private static IntPtr selSetDepthBias = Selector("setDepthBias:slopeScale:clamp:");
private static void mtlSetDepthBias(
IntPtr renderCommandEncoder,
float depthBias,
float slopeScaleDepthBias,
float clamp
) {
objc_msgSend(
renderCommandEncoder,
selSetDepthBias,
depthBias,
slopeScaleDepthBias,
clamp
);
}
private static IntPtr selSetDepthStencilState = Selector("setDepthStencilState:");
private static void mtlSetDepthStencilState(
IntPtr renderCommandEncoder,
IntPtr depthStencilState
) {
objc_msgSend(
renderCommandEncoder,
selSetDepthStencilState,
depthStencilState
);
}
private static IntPtr selInsertDebugSignpost = Selector("insertDebugSignpost:");
private static void mtlInsertDebugSignpost(
IntPtr renderCommandEncoder,
string message
) {
objc_msgSend(
renderCommandEncoder,
selInsertDebugSignpost,
UTF8ToNSString(message)
);
}
private static IntPtr selSetRenderPipelineState = Selector("setRenderPipelineState:");
private static void mtlSetRenderPipelineState(
IntPtr renderCommandEncoder,
IntPtr pipelineState
) {
objc_msgSend(renderCommandEncoder, selSetRenderPipelineState, pipelineState);
}
private static IntPtr selSetVertexBuffer = Selector("setVertexBuffer:offset:atIndex:");
private static void mtlSetVertexBuffer(
IntPtr renderCommandEncoder,
IntPtr vertexBuffer,
int offset,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetVertexBuffer,
vertexBuffer,
(ulong) offset,
(ulong) index
);
}
private static IntPtr selSetVertexBufferOffset = Selector("setVertexBufferOffset:atIndex:");
private static void mtlSetVertexBufferOffset(
IntPtr renderCommandEncoder,
int offset,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetVertexBufferOffset,
(ulong) offset,
(ulong) index
);
}
private static IntPtr selSetFragmentBuffer = Selector("setFragmentBuffer:offset:atIndex:");
private static void mtlSetFragmentBuffer(
IntPtr renderCommandEncoder,
IntPtr fragmentBuffer,
int offset,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetFragmentBuffer,
fragmentBuffer,
(ulong) offset,
(ulong) index
);
}
private static IntPtr selSetFragmentBufferOffset = Selector("setFragmentBufferOffset:atIndex:");
private static void mtlSetFragmentBufferOffset(
IntPtr renderCommandEncoder,
int offset,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetFragmentBufferOffset,
(ulong) offset,
(ulong) index
);
}
private static IntPtr selSetFragmentTexture = Selector("setFragmentTexture:atIndex:");
private static void mtlSetFragmentTexture(
IntPtr renderCommandEncoder,
IntPtr fragmentTexture,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetFragmentTexture,
fragmentTexture,
(ulong) index
);
}
private static IntPtr selSetFragmentSamplerState = Selector("setFragmentSamplerState:atIndex:");
private static void mtlSetFragmentSamplerState(
IntPtr renderCommandEncoder,
IntPtr samplerState,
int index
) {
objc_msgSend(
renderCommandEncoder,
selSetFragmentSamplerState,
samplerState,
(ulong) index
);
}
private static IntPtr selSetVisibilityResultMode = Selector("setVisibilityResultMode:offset:");
private static void mtlSetVisibilityResultMode(
IntPtr renderCommandEncoder,
MTLVisibilityResultMode mode,
int offset
) {
objc_msgSend(
renderCommandEncoder,
selSetVisibilityResultMode,
(ulong) mode,
(ulong) offset
);
}
#endregion
#region CAMetalLayer
private static IntPtr selLayer = Selector("layer");
private static IntPtr mtlGetLayer(IntPtr view)
{
return intptr_objc_msgSend(view, selLayer);
}
private static IntPtr selSetDevice = Selector("setDevice:");
private static void mtlSetLayerDevice(IntPtr layer, IntPtr device)
{
objc_msgSend(layer, selSetDevice, device);
}
private static IntPtr selNextDrawable = Selector("nextDrawable");
private static IntPtr mtlNextDrawable(IntPtr layer)
{
return intptr_objc_msgSend(layer, selNextDrawable);
}
private static IntPtr selPixelFormat = Selector("pixelFormat");
private static MTLPixelFormat mtlGetLayerPixelFormat(IntPtr layer)
{
return (MTLPixelFormat) ulong_objc_msgSend(layer, selPixelFormat);
}
private static IntPtr selDrawableSize = Selector("drawableSize");
private static CGSize mtlGetDrawableSize(IntPtr layer)
{
return (CGSize) cgsize_objc_msgSend(layer, selDrawableSize);
}
private static IntPtr selDisplaySyncEnabled = Selector("setDisplaySyncEnabled:");
private static void mtlSetDisplaySyncEnabled(
IntPtr layer,
bool enabled
) {
objc_msgSend(layer, selDisplaySyncEnabled, enabled);
}
private static IntPtr selSetFramebufferOnly = Selector("setFramebufferOnly:");
private static void mtlSetLayerFramebufferOnly(
IntPtr layer,
bool framebufferOnly
) {
objc_msgSend(layer, selSetFramebufferOnly, framebufferOnly);
}
private static IntPtr selSetMagnificationFilter = Selector("setMagnificationFilter:");
private static void mtlSetLayerMagnificationFilter(
IntPtr layer,
IntPtr val
) {
objc_msgSend(layer, selSetMagnificationFilter, val);
}
#endregion
#region CAMetalDrawable
private static IntPtr selTexture = Selector("texture");
private static IntPtr mtlGetTextureFromDrawable(IntPtr drawable)
{
return intptr_objc_msgSend(drawable, selTexture);
}
#endregion
#region MTLTextureDescriptor
private static IntPtr selTexture2DDescriptor = Selector("texture2DDescriptorWithPixelFormat:width:height:mipmapped:");
private static IntPtr mtlMakeTexture2DDescriptor(
MTLPixelFormat pixelFormat,
int width,
int height,
bool mipmapped
) {
return intptr_objc_msgSend(
classTextureDescriptor,
selTexture2DDescriptor,
pixelFormat,
(ulong) width,
(ulong) height,
mipmapped
);
}
private static IntPtr selTextureCubeDescriptor = Selector("textureCubeDescriptorWithPixelFormat:size:mipmapped:");
private static IntPtr mtlMakeTextureCubeDescriptor(
MTLPixelFormat pixelFormat,
int size,
bool mipmapped
) {
return intptr_objc_msgSend(
classTextureDescriptor,
selTextureCubeDescriptor,
pixelFormat,
(ulong) size,
mipmapped
);
}
private static IntPtr selSetUsage = Selector("setUsage:");
private static void mtlSetTextureUsage(
IntPtr texDesc,
MTLTextureUsage usage
) {
objc_msgSend(texDesc, selSetUsage, (ulong) usage);
}
private static IntPtr selSetTextureType = Selector("setTextureType:");
private static void mtlSetTextureType(
IntPtr texDesc,
MTLTextureType type
) {
objc_msgSend(texDesc, selSetTextureType, (ulong) type);
}
private static IntPtr selSetSampleCount = Selector("setSampleCount:");
private static void mtlSetTextureSampleCount(
IntPtr texDesc,
int sampleCount
) {
objc_msgSend(texDesc, selSetSampleCount, (ulong) sampleCount);
}
private static IntPtr selSetDepth = Selector("setDepth:");
private static void mtlSetTextureDepth(
IntPtr texDesc,
int depth
) {
objc_msgSend(texDesc, selSetDepth, (ulong) depth);
}
#endregion
#region MTLTexture
private static IntPtr selReplaceRegion = Selector("replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:");
private static void mtlReplaceRegion(
IntPtr texture,
MTLRegion region,
int level,
int slice,
IntPtr pixelBytes,
int bytesPerRow,
int bytesPerImage
) {
objc_msgSend(
texture,
selReplaceRegion,
region,
(ulong) level,
(ulong) slice,
pixelBytes,
(ulong) bytesPerRow,
(ulong) bytesPerImage
);
}
private static IntPtr selGetBytes = Selector("getBytes:bytesPerRow:bytesPerImage:fromRegion:mipmapLevel:slice:");
private static void mtlGetTextureBytes(
IntPtr texture,
IntPtr pixelBytes,
int bytesPerRow,
int bytesPerImage,
MTLRegion region,
int level,
int slice
) {
objc_msgSend(
texture,
selGetBytes,
pixelBytes,
(ulong) bytesPerRow,
(ulong) bytesPerImage,
region,
(ulong) level,
(ulong) slice
);
}
private static IntPtr selWidth = Selector("width");
private static ulong mtlGetTextureWidth(IntPtr texture)
{
return ulong_objc_msgSend(texture, selWidth);
}
private static IntPtr selHeight = Selector("height");
private static ulong mtlGetTextureHeight(IntPtr texture)
{
return ulong_objc_msgSend(texture, selHeight);
}
private static IntPtr selSetPurgeableState = Selector("setPurgeableState:");
private static MTLPurgeableState mtlSetPurgeableState(
IntPtr resource,
MTLPurgeableState state
) {
return (MTLPurgeableState) ulong_objc_msgSend(
resource,
selSetPurgeableState,
(ulong) state
);
}
#region MTLBlitCommandEncoder
private static IntPtr selBlitCommandEncoder = Selector("blitCommandEncoder");
private static IntPtr mtlMakeBlitCommandEncoder(IntPtr commandBuffer)
{
return intptr_objc_msgSend(commandBuffer, selBlitCommandEncoder);
}
private static IntPtr selCopyFromTexture = Selector("copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:");
private static void mtlBlitTextureToTexture(
IntPtr blitCommandEncoder,
IntPtr srcTexture,
int srcSlice,
int srcLevel,
MTLOrigin srcOrigin,
MTLSize srcSize,
IntPtr dstTexture,
int dstSlice,
int dstLevel,
MTLOrigin dstOrigin
) {
objc_msgSend(
blitCommandEncoder,
selCopyFromTexture,
srcTexture,
(ulong) srcSlice,
(ulong) srcLevel,
srcOrigin,
srcSize,
dstTexture,
(ulong) dstSlice,
(ulong) dstLevel,
dstOrigin
);
}
private static IntPtr selSynchronizeResource = Selector("synchronizeResource:");
private static void mtlSynchronizeResource(
IntPtr blitCommandEncoder,
IntPtr resource
) {
objc_msgSend(blitCommandEncoder, selSynchronizeResource, resource);
}
private static IntPtr selGenerateMipmaps = Selector("generateMipmapsForTexture:");
private static void mtlGenerateMipmapsForTexture(
IntPtr blitCommandEncoder,
IntPtr texture
) {
objc_msgSend(blitCommandEncoder, selGenerateMipmaps, texture);
}
#endregion
#region MTLRenderPipelineState
private static IntPtr selNew = Selector("new");
private static IntPtr mtlNewRenderPipelineDescriptor()
{
return intptr_objc_msgSend(classRenderPipelineDescriptor, selNew);
}
private static IntPtr selSetVertexFunction = Selector("setVertexFunction:");
private static void mtlSetPipelineVertexFunction(
IntPtr pipelineDescriptor,
IntPtr vertexFunction
) {
objc_msgSend(pipelineDescriptor, selSetVertexFunction, vertexFunction);
}
private static IntPtr selSetFragmentFunction = Selector("setFragmentFunction:");
private static void mtlSetPipelineFragmentFunction(
IntPtr pipelineDescriptor,
IntPtr fragmentFunction
) {
objc_msgSend(pipelineDescriptor, selSetFragmentFunction, fragmentFunction);
}
private static IntPtr selSetVertexDescriptor = Selector("setVertexDescriptor:");
private static void mtlSetPipelineVertexDescriptor(
IntPtr pipelineDescriptor,
IntPtr vertexDescriptor
) {
objc_msgSend(pipelineDescriptor, selSetVertexDescriptor, vertexDescriptor);
}
private static IntPtr selNewRenderPipelineState = Selector("newRenderPipelineStateWithDescriptor:error:");
private static IntPtr mtlNewRenderPipelineStateWithDescriptor(
IntPtr device,
IntPtr pipelineDescriptor
) {
IntPtr error = IntPtr.Zero;
IntPtr pipeline = intptr_objc_msgSend(
device,
selNewRenderPipelineState,
pipelineDescriptor,
out error
);
if (error != IntPtr.Zero)
{
throw new Exception("Metal Error: " + GetNSErrorDescription(error));
}
return pipeline;
}
private static IntPtr selSetDepthAttachmentPixelFormat = Selector("setDepthAttachmentPixelFormat:");
private static void mtlSetDepthAttachmentPixelFormat(
IntPtr pipelineDescriptor,
MTLPixelFormat format
) {
objc_msgSend(pipelineDescriptor, selSetDepthAttachmentPixelFormat, (ulong) format);
}
private static IntPtr selSetStencilAttachmentPixelFormat = Selector("setStencilAttachmentPixelFormat:");
private static void mtlSetStencilAttachmentPixelFormat(
IntPtr pipelineDescriptor,
MTLPixelFormat format
) {
objc_msgSend(pipelineDescriptor, selSetStencilAttachmentPixelFormat, (ulong) format);
}
private static void mtlSetPipelineSampleCount(
IntPtr pipelineDescriptor,
int sampleCount
) {
objc_msgSend(pipelineDescriptor, selSetSampleCount, (ulong) sampleCount);
}
#endregion
#region Sampler Descriptor
// selNew already defined
private static IntPtr mtlNewSamplerDescriptor()
{
return intptr_objc_msgSend(classMTLSamplerDescriptor, selNew);
}
private static IntPtr selSetMinFilter = Selector("setMinFilter:");
private static void mtlSetSamplerMinFilter(
IntPtr samplerDesc,
MTLSamplerMinMagFilter filter
) {
objc_msgSend(samplerDesc, selSetMinFilter, (uint) filter);
}
private static IntPtr selSetMagFilter = Selector("setMagFilter:");
private static void mtlSetSamplerMagFilter(
IntPtr samplerDesc,
MTLSamplerMinMagFilter filter
) {
objc_msgSend(samplerDesc, selSetMagFilter, (uint) filter);
}
private static IntPtr selSetMipFilter = Selector("setMipFilter:");
private static void mtlSetSamplerMipFilter(
IntPtr samplerDesc,
MTLSamplerMipFilter filter
) {
objc_msgSend(samplerDesc, selSetMipFilter, (uint) filter);
}
private static IntPtr selSetLodMinClamp = Selector("setLodMinClamp:");
private static void mtlSetSamplerLodMinClamp(
IntPtr samplerDesc,
float clamp
) {
objc_msgSend(samplerDesc, selSetLodMinClamp, clamp);
}
private static IntPtr selSetMaxAnisotropy = Selector("setMaxAnisotropy:");
private static void mtlSetSamplerMaxAnisotropy(
IntPtr samplerDesc,
int maxAnisotropy
) {
objc_msgSend(samplerDesc, selSetMaxAnisotropy, (ulong) maxAnisotropy);
}
private static IntPtr selSetRAddressMode = Selector("setRAddressMode:");
private static void mtlSetSampler_rAddressMode(
IntPtr samplerDesc,
MTLSamplerAddressMode mode
) {
objc_msgSend(samplerDesc, selSetRAddressMode, (ulong) mode);
}
private static IntPtr selSetSAddressMode = Selector("setSAddressMode:");
private static void mtlSetSampler_sAddressMode(
IntPtr samplerDesc,
MTLSamplerAddressMode mode
) {
objc_msgSend(samplerDesc, selSetSAddressMode, (ulong) mode);
}
private static IntPtr selSetTAddressMode = Selector("setTAddressMode:");
private static void mtlSetSampler_tAddressMode(
IntPtr samplerDesc,
MTLSamplerAddressMode mode
) {
objc_msgSend(samplerDesc, selSetTAddressMode, (ulong) mode);
}
#endregion
#region Vertex Descriptor
private static IntPtr selVertexDescriptor = Selector("vertexDescriptor");
private static IntPtr mtlMakeVertexDescriptor()
{
return intptr_objc_msgSend(classMTLVertexDescriptor, selVertexDescriptor);
}
private static IntPtr selAttributes = Selector("attributes");
private static IntPtr mtlGetVertexAttributeDescriptor(
IntPtr vertexDesc,
int index
) {
IntPtr attributes = intptr_objc_msgSend(
vertexDesc,
selAttributes
);
return intptr_objc_msgSend(
attributes,
selObjectAtIndexedSubscript,
(ulong) index
);
}
private static IntPtr selSetFormat = Selector("setFormat:");
private static void mtlSetVertexAttributeFormat(
IntPtr vertexAttribute,
MTLVertexFormat format
) {
objc_msgSend(vertexAttribute, selSetFormat, (ulong) format);
}
private static IntPtr selSetOffset = Selector("setOffset:");
private static void mtlSetVertexAttributeOffset(
IntPtr vertexAttribute,
int offset
) {
objc_msgSend(vertexAttribute, selSetOffset, (ulong) offset);
}
private static IntPtr selSetBufferIndex = Selector("setBufferIndex:");
private static void mtlSetVertexAttributeBufferIndex(
IntPtr vertexAttribute,
int bufferIndex
) {
objc_msgSend(vertexAttribute, selSetBufferIndex, (ulong) bufferIndex);
}
private static IntPtr selLayouts = Selector("layouts");
private static IntPtr mtlGetVertexBufferLayoutDescriptor(
IntPtr vertexDesc,
int index
) {
IntPtr layouts = intptr_objc_msgSend(
vertexDesc,
selLayouts
);
return intptr_objc_msgSend(
layouts,
selObjectAtIndexedSubscript,
(ulong) index
);
}
private static IntPtr selSetStride = Selector("setStride:");
private static void mtlSetVertexBufferLayoutStride(
IntPtr vertexBufferLayout,
int stride
) {
objc_msgSend(vertexBufferLayout, selSetStride, (ulong) stride);
}
private static IntPtr selSetStepFunction = Selector("setStepFunction:");
private static void mtlSetVertexBufferLayoutStepFunction(
IntPtr vertexBufferLayout,
MTLVertexStepFunction stepFunc
) {
objc_msgSend(vertexBufferLayout, selSetStepFunction, (ulong) stepFunc);
}
private static IntPtr selSetStepRate = Selector("setStepRate:");
private static void mtlSetVertexBufferLayoutStepRate(
IntPtr vertexBufferLayout,
int stepRate
) {
objc_msgSend(vertexBufferLayout, selSetStepRate, (ulong) stepRate);
}
#endregion
#region Storage Modes
private static IntPtr selSetStorageMode = Selector("setStorageMode:");
private static void mtlSetStorageMode(
IntPtr resource,
MTLStorageMode mode
) {
objc_msgSend(resource, selSetStorageMode, (ulong) mode);
}
#endregion
#region MTLLibrary
private static IntPtr selNewLibraryWithSource = Selector("newLibraryWithSource:options:error:");
private static IntPtr mtlNewLibraryWithSource(
IntPtr device,
IntPtr shaderSourceNSString,
IntPtr compileOptions
) {
IntPtr error = IntPtr.Zero;
IntPtr library = intptr_objc_msgSend(
device,
selNewLibraryWithSource,
shaderSourceNSString,
compileOptions,
out error
);
if (error != IntPtr.Zero)
{
throw new Exception("Metal Error: " + GetNSErrorDescription(error));
}
return library;
}
private static IntPtr selNewFunctionWithName = Selector("newFunctionWithName:");
private static IntPtr mtlNewFunctionWithName(
IntPtr library,
IntPtr shaderNameNSString
) {
return intptr_objc_msgSend(
library,
selNewFunctionWithName,
shaderNameNSString
);
}
#endregion
#region Depth-Stencil State
private static IntPtr mtlNewDepthStencilDescriptor()
{
return intptr_objc_msgSend(classDepthStencilDescriptor, selNew);
}
private static IntPtr mtlNewStencilDescriptor()
{
return intptr_objc_msgSend(classStencilDescriptor, selNew);
}
private static IntPtr selSetDepthCompareFunction = Selector("setDepthCompareFunction:");
private static void mtlSetDepthCompareFunction(
IntPtr depthStencilDescriptor,
MTLCompareFunction func
) {
objc_msgSend(depthStencilDescriptor, selSetDepthCompareFunction, (ulong) func);
}
private static IntPtr selSetDepthWriteEnabled = Selector("setDepthWriteEnabled:");
private static void mtlSetDepthWriteEnabled(
IntPtr depthStencilDescriptor,
bool enabled
) {
objc_msgSend(depthStencilDescriptor, selSetDepthWriteEnabled, enabled);
}
private static IntPtr selSetBackFaceStencil = Selector("setBackFaceStencil:");
private static void mtlSetBackFaceStencil(
IntPtr depthStencilDescriptor,
IntPtr stencilDescriptor
) {
objc_msgSend(depthStencilDescriptor, selSetBackFaceStencil, stencilDescriptor);
}
private static IntPtr selSetFrontFaceStencil = Selector("setFrontFaceStencil:");
private static void mtlSetFrontFaceStencil(
IntPtr depthStencilDescriptor,
IntPtr stencilDescriptor
) {
objc_msgSend(depthStencilDescriptor, selSetFrontFaceStencil, stencilDescriptor);
}
private static IntPtr selNewDepthStencilStateWithDescriptor = Selector("newDepthStencilStateWithDescriptor:");
private static IntPtr mtlNewDepthStencilStateWithDescriptor(
IntPtr device,
IntPtr descriptor
) {
return intptr_objc_msgSend(
device,
selNewDepthStencilStateWithDescriptor,
descriptor
);
}
private static IntPtr selSetStencilFailureOperation = Selector("setStencilFailureOperation:");
private static void mtlSetStencilFailureOperation(
IntPtr stencilDescriptor,
MTLStencilOperation op
) {
objc_msgSend(stencilDescriptor, selSetStencilFailureOperation, (ulong) op);
}
private static IntPtr selSetDepthFailureOperation = Selector("setDepthFailureOperation:");
private static void mtlSetDepthFailureOperation(
IntPtr stencilDescriptor,
MTLStencilOperation op
) {
objc_msgSend(stencilDescriptor, selSetDepthFailureOperation, (ulong) op);
}
private static IntPtr selSetDepthStencilPassOperation = Selector("setDepthStencilPassOperation:");
private static void mtlSetDepthStencilPassOperation(
IntPtr stencilDescriptor,
MTLStencilOperation op
) {
objc_msgSend(stencilDescriptor, selSetDepthStencilPassOperation, (ulong) op);
}
private static IntPtr selSetStencilCompareFunction = Selector("setStencilCompareFunction:");
private static void mtlSetStencilCompareFunction(
IntPtr stencilDescriptor,
MTLCompareFunction func
) {
objc_msgSend(stencilDescriptor, selSetStencilCompareFunction, (ulong) func);
}
private static IntPtr selSetStencilReadMask = Selector("setReadMask:");
private static void mtlSetStencilReadMask(
IntPtr stencilDescriptor,
uint mask
) {
objc_msgSend(stencilDescriptor, selSetStencilReadMask, mask);
}
private static IntPtr selSetStencilWriteMask = Selector("setWriteMask:");
private static void mtlSetStencilWriteMask(
IntPtr stencilDescriptor,
uint mask
) {
objc_msgSend(stencilDescriptor, selSetStencilWriteMask, mask);
}
#endregion
#region Error Handling
private static IntPtr selLocalizedDescription = Selector("localizedDescription");
private static string GetNSErrorDescription(IntPtr error)
{
return NSStringToUTF8(intptr_objc_msgSend(error, selLocalizedDescription));
}
#endregion
#endregion
}
}