|
|
#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
|
|
|
}
|
|
|
}
|