zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

mtl_darwin.go (44139B)


      1 // Copyright 2018 The Ebiten Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // Package mtl provides access to Apple's Metal API (https://developer.apple.com/documentation/metal).
     16 //
     17 // Package mtl requires macOS version 10.13 or newer.
     18 //
     19 // This package is in very early stages of development.
     20 // The API will change when opportunities for improvement are discovered; it is not yet frozen.
     21 // Less than 20% of the Metal API surface is implemented.
     22 // Current functionality is sufficient to render very basic geometry.
     23 package mtl
     24 
     25 import (
     26 	"errors"
     27 	"fmt"
     28 	"unsafe"
     29 )
     30 
     31 // #cgo !ios CFLAGS: -mmacosx-version-min=10.12
     32 // #cgo LDFLAGS: -framework Metal -framework CoreGraphics -framework Foundation
     33 //
     34 // #include "mtl_darwin.h"
     35 // #include <stdlib.h>
     36 import "C"
     37 
     38 // FeatureSet defines a specific platform, hardware, and software configuration.
     39 //
     40 // Reference: https://developer.apple.com/documentation/metal/mtlfeatureset.
     41 type FeatureSet uint16
     42 
     43 // The device feature sets that define specific platform, hardware, and software configurations.
     44 const (
     45 	MacOSGPUFamily1V1          FeatureSet = 10000 // The GPU family 1, version 1 feature set for macOS.
     46 	MacOSGPUFamily1V2          FeatureSet = 10001 // The GPU family 1, version 2 feature set for macOS.
     47 	MacOSReadWriteTextureTier2 FeatureSet = 10002 // The read-write texture, tier 2 feature set for macOS.
     48 	MacOSGPUFamily1V3          FeatureSet = 10003 // The GPU family 1, version 3 feature set for macOS.
     49 	MacOSGPUFamily1V4          FeatureSet = 10004 // The GPU family 1, version 4 feature set for macOS.
     50 	MacOSGPUFamily2V1          FeatureSet = 10005 // The GPU family 2, version 1 feature set for macOS.
     51 )
     52 
     53 const (
     54 	FeatureSet_iOS_GPUFamily1_v1           FeatureSet = 0
     55 	FeatureSet_iOS_GPUFamily1_v2           FeatureSet = 2
     56 	FeatureSet_iOS_GPUFamily1_v3           FeatureSet = 5
     57 	FeatureSet_iOS_GPUFamily1_v4           FeatureSet = 8
     58 	FeatureSet_iOS_GPUFamily1_v5           FeatureSet = 12
     59 	FeatureSet_iOS_GPUFamily2_v1           FeatureSet = 1
     60 	FeatureSet_iOS_GPUFamily2_v2           FeatureSet = 3
     61 	FeatureSet_iOS_GPUFamily2_v3           FeatureSet = 6
     62 	FeatureSet_iOS_GPUFamily2_v4           FeatureSet = 9
     63 	FeatureSet_iOS_GPUFamily2_v5           FeatureSet = 13
     64 	FeatureSet_iOS_GPUFamily3_v1           FeatureSet = 4
     65 	FeatureSet_iOS_GPUFamily3_v2           FeatureSet = 7
     66 	FeatureSet_iOS_GPUFamily3_v3           FeatureSet = 10
     67 	FeatureSet_iOS_GPUFamily3_v4           FeatureSet = 14
     68 	FeatureSet_iOS_GPUFamily4_v1           FeatureSet = 11
     69 	FeatureSet_iOS_GPUFamily4_v2           FeatureSet = 15
     70 	FeatureSet_iOS_GPUFamily5_v1           FeatureSet = 16
     71 	FeatureSet_tvOS_GPUFamily1_v1          FeatureSet = 30000
     72 	FeatureSet_tvOS_GPUFamily1_v2          FeatureSet = 30001
     73 	FeatureSet_tvOS_GPUFamily1_v3          FeatureSet = 30002
     74 	FeatureSet_tvOS_GPUFamily1_v4          FeatureSet = 30004
     75 	FeatureSet_tvOS_GPUFamily2_v1          FeatureSet = 30003
     76 	FeatureSet_tvOS_GPUFamily2_v2          FeatureSet = 30005
     77 	FeatureSet_macOS_GPUFamily1_v1         FeatureSet = 10000
     78 	FeatureSet_macOS_GPUFamily1_v2         FeatureSet = 10001
     79 	FeatureSet_macOS_GPUFamily1_v3         FeatureSet = 10003
     80 	FeatureSet_macOS_GPUFamily1_v4         FeatureSet = 10004
     81 	FeatureSet_macOS_GPUFamily2_v1         FeatureSet = 10005
     82 	FeatureSet_macOS_ReadWriteTextureTier2 FeatureSet = 10002
     83 )
     84 
     85 // TextureType defines The dimension of each image, including whether multiple images are arranged into an array or
     86 // a cube.
     87 //
     88 // Reference: https://developer.apple.com/documentation/metal/mtltexturetype
     89 type TextureType uint16
     90 
     91 const (
     92 	TextureType2D TextureType = 2
     93 )
     94 
     95 // PixelFormat defines data formats that describe the organization
     96 // and characteristics of individual pixels in a texture.
     97 //
     98 // Reference: https://developer.apple.com/documentation/metal/mtlpixelformat.
     99 type PixelFormat uint16
    100 
    101 // The data formats that describe the organization and characteristics
    102 // of individual pixels in a texture.
    103 const (
    104 	PixelFormatRGBA8UNorm     PixelFormat = 70  // Ordinary format with four 8-bit normalized unsigned integer components in RGBA order.
    105 	PixelFormatRGBA8UNormSRGB PixelFormat = 71  // Ordinary format with four 8-bit normalized unsigned integer components in RGBA order with conversion between sRGB and linear space.
    106 	PixelFormatBGRA8UNorm     PixelFormat = 80  // Ordinary format with four 8-bit normalized unsigned integer components in BGRA order.
    107 	PixelFormatBGRA8UNormSRGB PixelFormat = 81  // Ordinary format with four 8-bit normalized unsigned integer components in BGRA order with conversion between sRGB and linear space.
    108 	PixelFormatStencil8       PixelFormat = 253 // A pixel format with an 8-bit unsigned integer component, used for a stencil render target.
    109 )
    110 
    111 // PrimitiveType defines geometric primitive types for drawing commands.
    112 //
    113 // Reference: https://developer.apple.com/documentation/metal/mtlprimitivetype.
    114 type PrimitiveType uint8
    115 
    116 // Geometric primitive types for drawing commands.
    117 const (
    118 	PrimitiveTypePoint         PrimitiveType = 0
    119 	PrimitiveTypeLine          PrimitiveType = 1
    120 	PrimitiveTypeLineStrip     PrimitiveType = 2
    121 	PrimitiveTypeTriangle      PrimitiveType = 3
    122 	PrimitiveTypeTriangleStrip PrimitiveType = 4
    123 )
    124 
    125 // LoadAction defines actions performed at the start of a rendering pass
    126 // for a render command encoder.
    127 //
    128 // Reference: https://developer.apple.com/documentation/metal/mtlloadaction.
    129 type LoadAction uint8
    130 
    131 // Actions performed at the start of a rendering pass for a render command encoder.
    132 const (
    133 	LoadActionDontCare LoadAction = 0
    134 	LoadActionLoad     LoadAction = 1
    135 	LoadActionClear    LoadAction = 2
    136 )
    137 
    138 // StoreAction defines actions performed at the end of a rendering pass
    139 // for a render command encoder.
    140 //
    141 // Reference: https://developer.apple.com/documentation/metal/mtlstoreaction.
    142 type StoreAction uint8
    143 
    144 // Actions performed at the end of a rendering pass for a render command encoder.
    145 const (
    146 	StoreActionDontCare                   StoreAction = 0
    147 	StoreActionStore                      StoreAction = 1
    148 	StoreActionMultisampleResolve         StoreAction = 2
    149 	StoreActionStoreAndMultisampleResolve StoreAction = 3
    150 	StoreActionUnknown                    StoreAction = 4
    151 	StoreActionCustomSampleDepthStore     StoreAction = 5
    152 )
    153 
    154 // StorageMode defines defines the memory location and access permissions of a resource.
    155 //
    156 // Reference: https://developer.apple.com/documentation/metal/mtlstoragemode.
    157 type StorageMode uint8
    158 
    159 const (
    160 	// StorageModeShared indicates that the resource is stored in system memory
    161 	// accessible to both the CPU and the GPU.
    162 	StorageModeShared StorageMode = 0
    163 
    164 	// StorageModeManaged indicates that the resource exists as a synchronized
    165 	// memory pair with one copy stored in system memory accessible to the CPU
    166 	// and another copy stored in video memory accessible to the GPU.
    167 	StorageModeManaged StorageMode = 1
    168 
    169 	// StorageModePrivate indicates that the resource is stored in memory
    170 	// only accessible to the GPU. In iOS and tvOS, the resource is stored in
    171 	// system memory. In macOS, the resource is stored in video memory.
    172 	StorageModePrivate StorageMode = 2
    173 
    174 	// StorageModeMemoryless indicates that the resource is stored in on-tile memory,
    175 	// without CPU or GPU memory backing. The contents of the on-tile memory are undefined
    176 	// and do not persist; the only way to populate the resource is to render into it.
    177 	// Memoryless resources are limited to temporary render targets (i.e., Textures configured
    178 	// with a TextureDescriptor and used with a RenderPassAttachmentDescriptor).
    179 	StorageModeMemoryless StorageMode = 3
    180 )
    181 
    182 // ResourceOptions defines optional arguments used to create
    183 // and influence behavior of buffer and texture objects.
    184 //
    185 // Reference: https://developer.apple.com/documentation/metal/mtlresourceoptions.
    186 type ResourceOptions uint16
    187 
    188 const (
    189 	// ResourceCPUCacheModeDefaultCache is the default CPU cache mode for the resource.
    190 	// Guarantees that read and write operations are executed in the expected order.
    191 	ResourceCPUCacheModeDefaultCache ResourceOptions = ResourceOptions(CPUCacheModeDefaultCache) << resourceCPUCacheModeShift
    192 
    193 	// ResourceCPUCacheModeWriteCombined is a write-combined CPU cache mode for the resource.
    194 	// Optimized for resources that the CPU will write into, but never read.
    195 	ResourceCPUCacheModeWriteCombined ResourceOptions = ResourceOptions(CPUCacheModeWriteCombined) << resourceCPUCacheModeShift
    196 
    197 	// ResourceStorageModeShared indicates that the resource is stored in system memory
    198 	// accessible to both the CPU and the GPU.
    199 	ResourceStorageModeShared ResourceOptions = ResourceOptions(StorageModeShared) << resourceStorageModeShift
    200 
    201 	// ResourceStorageModeManaged indicates that the resource exists as a synchronized
    202 	// memory pair with one copy stored in system memory accessible to the CPU
    203 	// and another copy stored in video memory accessible to the GPU.
    204 	ResourceStorageModeManaged ResourceOptions = ResourceOptions(StorageModeManaged) << resourceStorageModeShift
    205 
    206 	// ResourceStorageModePrivate indicates that the resource is stored in memory
    207 	// only accessible to the GPU. In iOS and tvOS, the resource is stored
    208 	// in system memory. In macOS, the resource is stored in video memory.
    209 	ResourceStorageModePrivate ResourceOptions = ResourceOptions(StorageModePrivate) << resourceStorageModeShift
    210 
    211 	// ResourceStorageModeMemoryless indicates that the resource is stored in on-tile memory,
    212 	// without CPU or GPU memory backing. The contents of the on-tile memory are undefined
    213 	// and do not persist; the only way to populate the resource is to render into it.
    214 	// Memoryless resources are limited to temporary render targets (i.e., Textures configured
    215 	// with a TextureDescriptor and used with a RenderPassAttachmentDescriptor).
    216 	ResourceStorageModeMemoryless ResourceOptions = ResourceOptions(StorageModeMemoryless) << resourceStorageModeShift
    217 
    218 	// ResourceHazardTrackingModeUntracked indicates that the command encoder dependencies
    219 	// for this resource are tracked manually with Fence objects. This value is always set
    220 	// for resources sub-allocated from a Heap object and may optionally be specified for
    221 	// non-heap resources.
    222 	ResourceHazardTrackingModeUntracked ResourceOptions = 1 << resourceHazardTrackingModeShift
    223 )
    224 
    225 const (
    226 	resourceCPUCacheModeShift       = 0
    227 	resourceStorageModeShift        = 4
    228 	resourceHazardTrackingModeShift = 8
    229 )
    230 
    231 // CPUCacheMode is the CPU cache mode that defines the CPU mapping of a resource.
    232 //
    233 // Reference: https://developer.apple.com/documentation/metal/mtlcpucachemode.
    234 type CPUCacheMode uint8
    235 
    236 const (
    237 	// CPUCacheModeDefaultCache is the default CPU cache mode for the resource.
    238 	// Guarantees that read and write operations are executed in the expected order.
    239 	CPUCacheModeDefaultCache CPUCacheMode = 0
    240 
    241 	// CPUCacheModeWriteCombined is a write-combined CPU cache mode for the resource.
    242 	// Optimized for resources that the CPU will write into, but never read.
    243 	CPUCacheModeWriteCombined CPUCacheMode = 1
    244 )
    245 
    246 // IndexType is the index type for an index buffer that references vertices of geometric primitives.
    247 //
    248 // Reference: https://developer.apple.com/documentation/metal/mtlstoragemode
    249 type IndexType uint8
    250 
    251 const (
    252 	// IndexTypeUInt16 is a 16-bit unsigned integer used as a primitive index.
    253 	IndexTypeUInt16 IndexType = 0
    254 
    255 	// IndexTypeUInt32 is a 32-bit unsigned integer used as a primitive index.
    256 	IndexTypeUInt32 IndexType = 1
    257 )
    258 
    259 type TextureUsage uint8
    260 
    261 const (
    262 	TextureUsageUnknown         TextureUsage = 0x0000
    263 	TextureUsageShaderRead      TextureUsage = 0x0001
    264 	TextureUsageShaderWrite     TextureUsage = 0x0002
    265 	TextureUsageRenderTarget    TextureUsage = 0x0004
    266 	TextureUsagePixelFormatView TextureUsage = 0x0008
    267 )
    268 
    269 type BlendFactor uint8
    270 
    271 const (
    272 	BlendFactorZero                     BlendFactor = 0
    273 	BlendFactorOne                      BlendFactor = 1
    274 	BlendFactorSourceColor              BlendFactor = 2
    275 	BlendFactorOneMinusSourceColor      BlendFactor = 3
    276 	BlendFactorSourceAlpha              BlendFactor = 4
    277 	BlendFactorOneMinusSourceAlpha      BlendFactor = 5
    278 	BlendFactorDestinationColor         BlendFactor = 6
    279 	BlendFactorOneMinusDestinationColor BlendFactor = 7
    280 	BlendFactorDestinationAlpha         BlendFactor = 8
    281 	BlendFactorOneMinusDestinationAlpha BlendFactor = 9
    282 	BlendFactorSourceAlphaSaturated     BlendFactor = 10
    283 	BlendFactorBlendColor               BlendFactor = 11
    284 	BlendFactorOneMinusBlendColor       BlendFactor = 12
    285 	BlendFactorBlendAlpha               BlendFactor = 13
    286 	BlendFactorOneMinusBlendAlpha       BlendFactor = 14
    287 	BlendFactorSource1Color             BlendFactor = 15
    288 	BlendFactorOneMinusSource1Color     BlendFactor = 16
    289 	BlendFactorSource1Alpha             BlendFactor = 17
    290 	BlendFactorOneMinusSource1Alpha     BlendFactor = 18
    291 )
    292 
    293 type ColorWriteMask uint8
    294 
    295 const (
    296 	ColorWriteMaskNone  ColorWriteMask = 0
    297 	ColorWriteMaskRed   ColorWriteMask = 0x1 << 3
    298 	ColorWriteMaskGreen ColorWriteMask = 0x1 << 2
    299 	ColorWriteMaskBlue  ColorWriteMask = 0x1 << 1
    300 	ColorWriteMaskAlpha ColorWriteMask = 0x1 << 0
    301 	ColorWriteMaskAll   ColorWriteMask = 0xf
    302 )
    303 
    304 type StencilOperation uint8
    305 
    306 const (
    307 	StencilOperationKeep           StencilOperation = 0
    308 	StencilOperationZero           StencilOperation = 1
    309 	StencilOperationReplace        StencilOperation = 2
    310 	StencilOperationIncrementClamp StencilOperation = 3
    311 	StencilOperationDecrementClamp StencilOperation = 4
    312 	StencilOperationInvert         StencilOperation = 5
    313 	StencilOperationIncrementWrap  StencilOperation = 6
    314 	StencilOperationDecrementWrap  StencilOperation = 7
    315 )
    316 
    317 type CompareFunction uint8
    318 
    319 const (
    320 	CompareFunctionNever        CompareFunction = 0
    321 	CompareFunctionLess         CompareFunction = 1
    322 	CompareFunctionEqual        CompareFunction = 2
    323 	CompareFunctionLessEqual    CompareFunction = 3
    324 	CompareFunctionGreater      CompareFunction = 4
    325 	CompareFunctionNotEqual     CompareFunction = 5
    326 	CompareFunctionGreaterEqual CompareFunction = 6
    327 	CompareFunctionAlways       CompareFunction = 7
    328 )
    329 
    330 type CommandBufferStatus uint8
    331 
    332 const (
    333 	CommandBufferStatusNotEnqueued CommandBufferStatus = 0 //The command buffer is not enqueued yet.
    334 	CommandBufferStatusEnqueued    CommandBufferStatus = 1 // The command buffer is enqueued.
    335 	CommandBufferStatusCommitted   CommandBufferStatus = 2 // The command buffer is committed for execution.
    336 	CommandBufferStatusScheduled   CommandBufferStatus = 3 // The command buffer is scheduled.
    337 	CommandBufferStatusCompleted   CommandBufferStatus = 4 // The command buffer completed execution successfully.
    338 	CommandBufferStatusError       CommandBufferStatus = 5 // Execution of the command buffer was aborted due to an error during execution.
    339 )
    340 
    341 // Resource represents a memory allocation for storing specialized data
    342 // that is accessible to the GPU.
    343 //
    344 // Reference: https://developer.apple.com/documentation/metal/mtlresource.
    345 type Resource interface {
    346 	// resource returns the underlying id<MTLResource> pointer.
    347 	resource() unsafe.Pointer
    348 }
    349 
    350 // RenderPipelineDescriptor configures new RenderPipelineState objects.
    351 //
    352 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpipelinedescriptor.
    353 type RenderPipelineDescriptor struct {
    354 	// VertexFunction is a programmable function that processes individual vertices in a rendering pass.
    355 	VertexFunction Function
    356 
    357 	// FragmentFunction is a programmable function that processes individual fragments in a rendering pass.
    358 	FragmentFunction Function
    359 
    360 	// ColorAttachments is an array of attachments that store color data.
    361 	ColorAttachments [1]RenderPipelineColorAttachmentDescriptor
    362 
    363 	// StencilAttachmentPixelFormat is the pixel format of the attachment that stores stencil data.
    364 	StencilAttachmentPixelFormat PixelFormat
    365 }
    366 
    367 // RenderPipelineColorAttachmentDescriptor describes a color render target that specifies
    368 // the color configuration and color operations associated with a render pipeline.
    369 //
    370 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpipelinecolorattachmentdescriptor.
    371 type RenderPipelineColorAttachmentDescriptor struct {
    372 	// PixelFormat is the pixel format of the color attachment's texture.
    373 	PixelFormat PixelFormat
    374 
    375 	BlendingEnabled bool
    376 
    377 	DestinationAlphaBlendFactor BlendFactor
    378 	DestinationRGBBlendFactor   BlendFactor
    379 	SourceAlphaBlendFactor      BlendFactor
    380 	SourceRGBBlendFactor        BlendFactor
    381 
    382 	WriteMask ColorWriteMask
    383 }
    384 
    385 // RenderPassDescriptor describes a group of render targets that serve as
    386 // the output destination for pixels generated by a render pass.
    387 //
    388 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpassdescriptor.
    389 type RenderPassDescriptor struct {
    390 	// ColorAttachments is array of state information for attachments that store color data.
    391 	ColorAttachments [1]RenderPassColorAttachmentDescriptor
    392 
    393 	// StencilAttachment is state information for an attachment that stores stencil data.
    394 	StencilAttachment RenderPassStencilAttachment
    395 }
    396 
    397 // RenderPassColorAttachmentDescriptor describes a color render target that serves
    398 // as the output destination for color pixels generated by a render pass.
    399 //
    400 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpasscolorattachmentdescriptor.
    401 type RenderPassColorAttachmentDescriptor struct {
    402 	RenderPassAttachmentDescriptor
    403 	ClearColor ClearColor
    404 }
    405 
    406 // RenderPassStencilAttachment describes a stencil render target that serves as the output
    407 // destination for stencil pixels generated by a render pass.
    408 //
    409 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpassstencilattachmentdescriptor
    410 type RenderPassStencilAttachment struct {
    411 	RenderPassAttachmentDescriptor
    412 }
    413 
    414 // RenderPassAttachmentDescriptor describes a render target that serves
    415 // as the output destination for pixels generated by a render pass.
    416 //
    417 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpassattachmentdescriptor.
    418 type RenderPassAttachmentDescriptor struct {
    419 	LoadAction  LoadAction
    420 	StoreAction StoreAction
    421 	Texture     Texture
    422 }
    423 
    424 // ClearColor is an RGBA value used for a color pixel.
    425 //
    426 // Reference: https://developer.apple.com/documentation/metal/mtlclearcolor.
    427 type ClearColor struct {
    428 	Red, Green, Blue, Alpha float64
    429 }
    430 
    431 // TextureDescriptor configures new Texture objects.
    432 //
    433 // Reference: https://developer.apple.com/documentation/metal/mtltexturedescriptor.
    434 type TextureDescriptor struct {
    435 	TextureType TextureType
    436 	PixelFormat PixelFormat
    437 	Width       int
    438 	Height      int
    439 	StorageMode StorageMode
    440 	Usage       TextureUsage
    441 }
    442 
    443 // Device is abstract representation of the GPU that
    444 // serves as the primary interface for a Metal app.
    445 //
    446 // Reference: https://developer.apple.com/documentation/metal/mtldevice.
    447 type Device struct {
    448 	device unsafe.Pointer
    449 
    450 	// Headless indicates whether a device is configured as headless.
    451 	Headless bool
    452 
    453 	// LowPower indicates whether a device is low-power.
    454 	LowPower bool
    455 
    456 	// Name is the name of the device.
    457 	Name string
    458 }
    459 
    460 // CreateSystemDefaultDevice returns the preferred system default Metal device.
    461 //
    462 // Reference: https://developer.apple.com/documentation/metal/1433401-mtlcreatesystemdefaultdevice.
    463 func CreateSystemDefaultDevice() (Device, error) {
    464 	d := C.CreateSystemDefaultDevice()
    465 	if d.Device == nil {
    466 		return Device{}, errors.New("Metal is not supported on this system")
    467 	}
    468 
    469 	return Device{
    470 		device:   d.Device,
    471 		Headless: d.Headless != 0,
    472 		LowPower: d.LowPower != 0,
    473 		Name:     C.GoString(d.Name),
    474 	}, nil
    475 }
    476 
    477 // Device returns the underlying id<MTLDevice> pointer.
    478 func (d Device) Device() unsafe.Pointer { return d.device }
    479 
    480 // SupportsFeatureSet reports whether device d supports feature set fs.
    481 //
    482 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433418-supportsfeatureset.
    483 func (d Device) SupportsFeatureSet(fs FeatureSet) bool {
    484 	return C.Device_SupportsFeatureSet(d.device, C.uint16_t(fs)) != 0
    485 }
    486 
    487 // MakeCommandQueue creates a serial command submission queue.
    488 //
    489 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433388-makecommandqueue.
    490 func (d Device) MakeCommandQueue() CommandQueue {
    491 	return CommandQueue{C.Device_MakeCommandQueue(d.device)}
    492 }
    493 
    494 // MakeLibrary creates a new library that contains
    495 // the functions stored in the specified source string.
    496 //
    497 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433431-makelibrary.
    498 func (d Device) MakeLibrary(source string, opt CompileOptions) (Library, error) {
    499 	cs := C.CString(source)
    500 	defer C.free(unsafe.Pointer(cs))
    501 
    502 	l := C.Device_MakeLibrary(d.device, cs, C.size_t(len(source)))
    503 	if l.Library == nil {
    504 		return Library{}, errors.New(C.GoString(l.Error))
    505 	}
    506 
    507 	return Library{l.Library}, nil
    508 }
    509 
    510 // MakeRenderPipelineState creates a render pipeline state object.
    511 //
    512 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433369-makerenderpipelinestate.
    513 func (d Device) MakeRenderPipelineState(rpd RenderPipelineDescriptor) (RenderPipelineState, error) {
    514 	blendingEnabled := 0
    515 	if rpd.ColorAttachments[0].BlendingEnabled {
    516 		blendingEnabled = 1
    517 	}
    518 	c := &rpd.ColorAttachments[0]
    519 	descriptor := C.struct_RenderPipelineDescriptor{
    520 		VertexFunction:                              rpd.VertexFunction.function,
    521 		FragmentFunction:                            rpd.FragmentFunction.function,
    522 		ColorAttachment0PixelFormat:                 C.uint16_t(c.PixelFormat),
    523 		ColorAttachment0BlendingEnabled:             C.uint8_t(blendingEnabled),
    524 		ColorAttachment0DestinationAlphaBlendFactor: C.uint8_t(c.DestinationAlphaBlendFactor),
    525 		ColorAttachment0DestinationRGBBlendFactor:   C.uint8_t(c.DestinationRGBBlendFactor),
    526 		ColorAttachment0SourceAlphaBlendFactor:      C.uint8_t(c.SourceAlphaBlendFactor),
    527 		ColorAttachment0SourceRGBBlendFactor:        C.uint8_t(c.SourceRGBBlendFactor),
    528 		ColorAttachment0WriteMask:                   C.uint8_t(c.WriteMask),
    529 		StencilAttachmentPixelFormat:                C.uint8_t(rpd.StencilAttachmentPixelFormat),
    530 	}
    531 	rps := C.Device_MakeRenderPipelineState(d.device, descriptor)
    532 	if rps.RenderPipelineState == nil {
    533 		return RenderPipelineState{}, errors.New(C.GoString(rps.Error))
    534 	}
    535 
    536 	return RenderPipelineState{rps.RenderPipelineState}, nil
    537 }
    538 
    539 // MakeBufferWithBytes allocates a new buffer of a given length
    540 // and initializes its contents by copying existing data into it.
    541 //
    542 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433429-makebuffer.
    543 func (d Device) MakeBufferWithBytes(bytes unsafe.Pointer, length uintptr, opt ResourceOptions) Buffer {
    544 	return Buffer{C.Device_MakeBufferWithBytes(d.device, bytes, C.size_t(length), C.uint16_t(opt))}
    545 }
    546 
    547 // MakeBufferWithLength allocates a new zero-filled buffer of a given length.
    548 //
    549 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433375-newbufferwithlength
    550 func (d Device) MakeBufferWithLength(length uintptr, opt ResourceOptions) Buffer {
    551 	return Buffer{C.Device_MakeBufferWithLength(d.device, C.size_t(length), C.uint16_t(opt))}
    552 }
    553 
    554 // MakeTexture creates a texture object with privately owned storage
    555 // that contains texture state.
    556 //
    557 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433425-maketexture.
    558 func (d Device) MakeTexture(td TextureDescriptor) Texture {
    559 	descriptor := C.struct_TextureDescriptor{
    560 		TextureType: C.uint16_t(td.TextureType),
    561 		PixelFormat: C.uint16_t(td.PixelFormat),
    562 		Width:       C.uint_t(td.Width),
    563 		Height:      C.uint_t(td.Height),
    564 		StorageMode: C.uint8_t(td.StorageMode),
    565 		Usage:       C.uint8_t(td.Usage),
    566 	}
    567 	return Texture{
    568 		texture: C.Device_MakeTexture(d.device, descriptor),
    569 	}
    570 }
    571 
    572 // MakeDepthStencilState creates a new object that contains depth and stencil test state.
    573 //
    574 // Reference: https://developer.apple.com/documentation/metal/mtldevice/1433412-makedepthstencilstate
    575 func (d Device) MakeDepthStencilState(dsd DepthStencilDescriptor) DepthStencilState {
    576 	descriptor := C.struct_DepthStencilDescriptor{
    577 		BackFaceStencilStencilFailureOperation:    C.uint8_t(dsd.BackFaceStencil.StencilFailureOperation),
    578 		BackFaceStencilDepthFailureOperation:      C.uint8_t(dsd.BackFaceStencil.DepthFailureOperation),
    579 		BackFaceStencilDepthStencilPassOperation:  C.uint8_t(dsd.BackFaceStencil.DepthStencilPassOperation),
    580 		BackFaceStencilStencilCompareFunction:     C.uint8_t(dsd.BackFaceStencil.StencilCompareFunction),
    581 		FrontFaceStencilStencilFailureOperation:   C.uint8_t(dsd.FrontFaceStencil.StencilFailureOperation),
    582 		FrontFaceStencilDepthFailureOperation:     C.uint8_t(dsd.FrontFaceStencil.DepthFailureOperation),
    583 		FrontFaceStencilDepthStencilPassOperation: C.uint8_t(dsd.FrontFaceStencil.DepthStencilPassOperation),
    584 		FrontFaceStencilStencilCompareFunction:    C.uint8_t(dsd.FrontFaceStencil.StencilCompareFunction),
    585 	}
    586 	return DepthStencilState{
    587 		depthStencilState: C.Device_MakeDepthStencilState(d.device, descriptor),
    588 	}
    589 }
    590 
    591 // CompileOptions specifies optional compilation settings for
    592 // the graphics or compute functions within a library.
    593 //
    594 // Reference: https://developer.apple.com/documentation/metal/mtlcompileoptions.
    595 type CompileOptions struct {
    596 	// TODO.
    597 }
    598 
    599 // Drawable is a displayable resource that can be rendered or written to.
    600 //
    601 // Reference: https://developer.apple.com/documentation/metal/mtldrawable.
    602 type Drawable interface {
    603 	// Drawable returns the underlying id<MTLDrawable> pointer.
    604 	Drawable() unsafe.Pointer
    605 }
    606 
    607 // CommandQueue is a queue that organizes the order
    608 // in which command buffers are executed by the GPU.
    609 //
    610 // Reference: https://developer.apple.com/documentation/metal/mtlcommandqueue.
    611 type CommandQueue struct {
    612 	commandQueue unsafe.Pointer
    613 }
    614 
    615 func (c CommandQueue) Release() {
    616 	C.CommandQueue_Release(c.commandQueue)
    617 }
    618 
    619 // MakeCommandBuffer creates a command buffer.
    620 //
    621 // Reference: https://developer.apple.com/documentation/metal/mtlcommandqueue/1508686-makecommandbuffer.
    622 func (cq CommandQueue) MakeCommandBuffer() CommandBuffer {
    623 	return CommandBuffer{C.CommandQueue_MakeCommandBuffer(cq.commandQueue)}
    624 }
    625 
    626 // CommandBuffer is a container that stores encoded commands
    627 // that are committed to and executed by the GPU.
    628 //
    629 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer.
    630 type CommandBuffer struct {
    631 	commandBuffer unsafe.Pointer
    632 }
    633 
    634 func (cb CommandBuffer) Retain() {
    635 	C.CommandBuffer_Retain(cb.commandBuffer)
    636 }
    637 
    638 func (cb CommandBuffer) Release() {
    639 	C.CommandBuffer_Release(cb.commandBuffer)
    640 }
    641 
    642 // Status returns the current stage in the lifetime of the command buffer.
    643 //
    644 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443048-status
    645 func (cb CommandBuffer) Status() CommandBufferStatus {
    646 	return CommandBufferStatus(C.CommandBuffer_Status(cb.commandBuffer))
    647 }
    648 
    649 // PresentDrawable registers a drawable presentation to occur as soon as possible.
    650 //
    651 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443029-presentdrawable.
    652 func (cb CommandBuffer) PresentDrawable(d Drawable) {
    653 	C.CommandBuffer_PresentDrawable(cb.commandBuffer, d.Drawable())
    654 }
    655 
    656 // Commit commits this command buffer for execution as soon as possible.
    657 //
    658 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443003-commit.
    659 func (cb CommandBuffer) Commit() {
    660 	C.CommandBuffer_Commit(cb.commandBuffer)
    661 }
    662 
    663 // WaitUntilCompleted waits for the execution of this command buffer to complete.
    664 //
    665 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443039-waituntilcompleted.
    666 func (cb CommandBuffer) WaitUntilCompleted() {
    667 	C.CommandBuffer_WaitUntilCompleted(cb.commandBuffer)
    668 }
    669 
    670 // WaitUntilScheduled blocks execution of the current thread until the command buffer is scheduled.
    671 //
    672 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443036-waituntilscheduled.
    673 func (cb CommandBuffer) WaitUntilScheduled() {
    674 	C.CommandBuffer_WaitUntilScheduled(cb.commandBuffer)
    675 }
    676 
    677 // MakeRenderCommandEncoder creates an encoder object that can
    678 // encode graphics rendering commands into this command buffer.
    679 //
    680 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1442999-makerendercommandencoder.
    681 func (cb CommandBuffer) MakeRenderCommandEncoder(rpd RenderPassDescriptor) RenderCommandEncoder {
    682 	descriptor := C.struct_RenderPassDescriptor{
    683 		ColorAttachment0LoadAction:  C.uint8_t(rpd.ColorAttachments[0].LoadAction),
    684 		ColorAttachment0StoreAction: C.uint8_t(rpd.ColorAttachments[0].StoreAction),
    685 		ColorAttachment0ClearColor: C.struct_ClearColor{
    686 			Red:   C.double(rpd.ColorAttachments[0].ClearColor.Red),
    687 			Green: C.double(rpd.ColorAttachments[0].ClearColor.Green),
    688 			Blue:  C.double(rpd.ColorAttachments[0].ClearColor.Blue),
    689 			Alpha: C.double(rpd.ColorAttachments[0].ClearColor.Alpha),
    690 		},
    691 		ColorAttachment0Texture:      rpd.ColorAttachments[0].Texture.texture,
    692 		StencilAttachmentLoadAction:  C.uint8_t(rpd.StencilAttachment.LoadAction),
    693 		StencilAttachmentStoreAction: C.uint8_t(rpd.StencilAttachment.StoreAction),
    694 		StencilAttachmentTexture:     rpd.StencilAttachment.Texture.texture,
    695 	}
    696 	return RenderCommandEncoder{CommandEncoder{C.CommandBuffer_MakeRenderCommandEncoder(cb.commandBuffer, descriptor)}}
    697 }
    698 
    699 // MakeBlitCommandEncoder creates an encoder object that can encode
    700 // memory operation (blit) commands into this command buffer.
    701 //
    702 // Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443001-makeblitcommandencoder.
    703 func (cb CommandBuffer) MakeBlitCommandEncoder() BlitCommandEncoder {
    704 	return BlitCommandEncoder{CommandEncoder{C.CommandBuffer_MakeBlitCommandEncoder(cb.commandBuffer)}}
    705 }
    706 
    707 // CommandEncoder is an encoder that writes sequential GPU commands
    708 // into a command buffer.
    709 //
    710 // Reference: https://developer.apple.com/documentation/metal/mtlcommandencoder.
    711 type CommandEncoder struct {
    712 	commandEncoder unsafe.Pointer
    713 }
    714 
    715 // EndEncoding declares that all command generation from this encoder is completed.
    716 //
    717 // Reference: https://developer.apple.com/documentation/metal/mtlcommandencoder/1458038-endencoding.
    718 func (ce CommandEncoder) EndEncoding() {
    719 	C.CommandEncoder_EndEncoding(ce.commandEncoder)
    720 }
    721 
    722 // RenderCommandEncoder is an encoder that specifies graphics-rendering commands
    723 // and executes graphics functions.
    724 //
    725 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder.
    726 type RenderCommandEncoder struct {
    727 	CommandEncoder
    728 }
    729 
    730 func (rce RenderCommandEncoder) Release() {
    731 	C.RenderCommandEncoder_Release(rce.commandEncoder)
    732 }
    733 
    734 // SetRenderPipelineState sets the current render pipeline state object.
    735 //
    736 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515811-setrenderpipelinestate.
    737 func (rce RenderCommandEncoder) SetRenderPipelineState(rps RenderPipelineState) {
    738 	C.RenderCommandEncoder_SetRenderPipelineState(rce.commandEncoder, rps.renderPipelineState)
    739 }
    740 
    741 func (rce RenderCommandEncoder) SetViewport(viewport Viewport) {
    742 	C.RenderCommandEncoder_SetViewport(rce.commandEncoder, viewport.c())
    743 }
    744 
    745 // SetScissorRect sets the scissor rectangle for a fragment scissor test.
    746 //
    747 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515583-setscissorrect
    748 func (rce RenderCommandEncoder) SetScissorRect(scissorRect ScissorRect) {
    749 	C.RenderCommandEncoder_SetScissorRect(rce.commandEncoder, scissorRect.c())
    750 }
    751 
    752 // SetVertexBuffer sets a buffer for the vertex shader function at an index
    753 // in the buffer argument table with an offset that specifies the start of the data.
    754 //
    755 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515829-setvertexbuffer.
    756 func (rce RenderCommandEncoder) SetVertexBuffer(buf Buffer, offset, index int) {
    757 	C.RenderCommandEncoder_SetVertexBuffer(rce.commandEncoder, buf.buffer, C.uint_t(offset), C.uint_t(index))
    758 }
    759 
    760 // SetVertexBytes sets a block of data for the vertex function.
    761 //
    762 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515846-setvertexbytes.
    763 func (rce RenderCommandEncoder) SetVertexBytes(bytes unsafe.Pointer, length uintptr, index int) {
    764 	C.RenderCommandEncoder_SetVertexBytes(rce.commandEncoder, bytes, C.size_t(length), C.uint_t(index))
    765 }
    766 
    767 func (rce RenderCommandEncoder) SetFragmentBytes(bytes unsafe.Pointer, length uintptr, index int) {
    768 	C.RenderCommandEncoder_SetFragmentBytes(rce.commandEncoder, bytes, C.size_t(length), C.uint_t(index))
    769 }
    770 
    771 // SetFragmentTexture sets a texture for the fragment function at an index in the texture argument table.
    772 //
    773 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515390-setfragmenttexture
    774 func (rce RenderCommandEncoder) SetFragmentTexture(texture Texture, index int) {
    775 	C.RenderCommandEncoder_SetFragmentTexture(rce.commandEncoder, texture.texture, C.uint_t(index))
    776 }
    777 
    778 func (rce RenderCommandEncoder) SetBlendColor(red, green, blue, alpha float32) {
    779 	C.RenderCommandEncoder_SetBlendColor(rce.commandEncoder, C.float(red), C.float(green), C.float(blue), C.float(alpha))
    780 }
    781 
    782 // SetDepthStencilState sets the depth and stencil test state.
    783 //
    784 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1516119-setdepthstencilstate
    785 func (rce RenderCommandEncoder) SetDepthStencilState(depthStencilState DepthStencilState) {
    786 	C.RenderCommandEncoder_SetDepthStencilState(rce.commandEncoder, depthStencilState.depthStencilState)
    787 }
    788 
    789 // DrawPrimitives renders one instance of primitives using vertex data
    790 // in contiguous array elements.
    791 //
    792 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1516326-drawprimitives.
    793 func (rce RenderCommandEncoder) DrawPrimitives(typ PrimitiveType, vertexStart, vertexCount int) {
    794 	C.RenderCommandEncoder_DrawPrimitives(rce.commandEncoder, C.uint8_t(typ), C.uint_t(vertexStart), C.uint_t(vertexCount))
    795 }
    796 
    797 // DrawIndexedPrimitives encodes a command to render one instance of primitives using an index list specified in a buffer.
    798 //
    799 // Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515542-drawindexedprimitives
    800 func (rce RenderCommandEncoder) DrawIndexedPrimitives(typ PrimitiveType, indexCount int, indexType IndexType, indexBuffer Buffer, indexBufferOffset int) {
    801 	C.RenderCommandEncoder_DrawIndexedPrimitives(rce.commandEncoder, C.uint8_t(typ), C.uint_t(indexCount), C.uint8_t(indexType), indexBuffer.buffer, C.uint_t(indexBufferOffset))
    802 }
    803 
    804 // BlitCommandEncoder is an encoder that specifies resource copy
    805 // and resource synchronization commands.
    806 //
    807 // Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder.
    808 type BlitCommandEncoder struct {
    809 	CommandEncoder
    810 }
    811 
    812 // Synchronize flushes any copy of the specified resource from its corresponding
    813 // Device caches and, if needed, invalidates any CPU caches.
    814 //
    815 // Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400775-synchronize.
    816 func (bce BlitCommandEncoder) Synchronize(resource Resource) {
    817 	C.BlitCommandEncoder_Synchronize(bce.commandEncoder, resource.resource())
    818 }
    819 
    820 func (bce BlitCommandEncoder) SynchronizeTexture(texture Texture, slice int, level int) {
    821 	C.BlitCommandEncoder_SynchronizeTexture(bce.commandEncoder, texture.texture, C.uint_t(slice), C.uint_t(level))
    822 }
    823 
    824 func (bce BlitCommandEncoder) CopyFromTexture(sourceTexture Texture, sourceSlice int, sourceLevel int, sourceOrigin Origin, sourceSize Size, destinationTexture Texture, destinationSlice int, destinationLevel int, destinationOrigin Origin) {
    825 	C.BlitCommandEncoder_CopyFromTexture(bce.commandEncoder, sourceTexture.texture, C.uint_t(sourceSlice), C.uint_t(sourceLevel), sourceOrigin.c(), sourceSize.c(), destinationTexture.texture, C.uint_t(destinationSlice), C.uint_t(destinationLevel), destinationOrigin.c())
    826 }
    827 
    828 // Library is a collection of compiled graphics or compute functions.
    829 //
    830 // Reference: https://developer.apple.com/documentation/metal/mtllibrary.
    831 type Library struct {
    832 	library unsafe.Pointer
    833 }
    834 
    835 // MakeFunction returns a pre-compiled, non-specialized function.
    836 //
    837 // Reference: https://developer.apple.com/documentation/metal/mtllibrary/1515524-makefunction.
    838 func (l Library) MakeFunction(name string) (Function, error) {
    839 	f := C.Library_MakeFunction(l.library, C.CString(name))
    840 	if f == nil {
    841 		return Function{}, fmt.Errorf("function %q not found", name)
    842 	}
    843 
    844 	return Function{f}, nil
    845 }
    846 
    847 // Texture is a memory allocation for storing formatted
    848 // image data that is accessible to the GPU.
    849 //
    850 // Reference: https://developer.apple.com/documentation/metal/mtltexture.
    851 type Texture struct {
    852 	texture unsafe.Pointer
    853 }
    854 
    855 // NewTexture returns a Texture that wraps an existing id<MTLTexture> pointer.
    856 func NewTexture(texture unsafe.Pointer) Texture {
    857 	return Texture{texture: texture}
    858 }
    859 
    860 // resource implements the Resource interface.
    861 func (t Texture) resource() unsafe.Pointer { return t.texture }
    862 
    863 func (t Texture) Release() {
    864 	C.Texture_Release(t.texture)
    865 }
    866 
    867 // GetBytes copies a block of pixels from the storage allocation of texture
    868 // slice zero into system memory at a specified address.
    869 //
    870 // Reference: https://developer.apple.com/documentation/metal/mtltexture/1515751-getbytes.
    871 func (t Texture) GetBytes(pixelBytes *byte, bytesPerRow uintptr, region Region, level int) {
    872 	r := region.c()
    873 	C.Texture_GetBytes(t.texture, unsafe.Pointer(pixelBytes), C.size_t(bytesPerRow), r, C.uint_t(level))
    874 }
    875 
    876 // ReplaceRegion copies a block of pixels from the caller's pointer into the storage allocation for slice 0 of a texture.
    877 //
    878 // Reference: https://developer.apple.com/documentation/metal/mtltexture/1515464-replaceregion
    879 func (t Texture) ReplaceRegion(region Region, level int, pixelBytes unsafe.Pointer, bytesPerRow int) {
    880 	r := region.c()
    881 	C.Texture_ReplaceRegion(t.texture, r, C.uint_t(level), pixelBytes, C.uint_t(bytesPerRow))
    882 }
    883 
    884 // Width is the width of the texture image for the base level mipmap, in pixels.
    885 //
    886 // Reference: https://developer.apple.com/documentation/metal/mtltexture/1515339-width
    887 func (t Texture) Width() int {
    888 	return int(C.Texture_Width(t.texture))
    889 }
    890 
    891 // Height is the height of the texture image for the base level mipmap, in pixels.
    892 //
    893 // Reference: https://developer.apple.com/documentation/metal/mtltexture/1515938-height
    894 func (t Texture) Height() int {
    895 	return int(C.Texture_Height(t.texture))
    896 }
    897 
    898 // Buffer is a memory allocation for storing unformatted data
    899 // that is accessible to the GPU.
    900 //
    901 // Reference: https://developer.apple.com/documentation/metal/mtlbuffer.
    902 type Buffer struct {
    903 	buffer unsafe.Pointer
    904 }
    905 
    906 func (b Buffer) resource() unsafe.Pointer { return b.buffer }
    907 
    908 func (b Buffer) Length() uintptr {
    909 	return uintptr(C.Buffer_Length(b.buffer))
    910 }
    911 
    912 func (b Buffer) CopyToContents(data unsafe.Pointer, lengthInBytes uintptr) {
    913 	C.Buffer_CopyToContents(b.buffer, data, C.size_t(lengthInBytes))
    914 }
    915 
    916 func (b Buffer) Retain() {
    917 	C.Buffer_Retain(b.buffer)
    918 }
    919 
    920 func (b Buffer) Release() {
    921 	C.Buffer_Release(b.buffer)
    922 }
    923 
    924 func (b Buffer) Native() unsafe.Pointer {
    925 	return b.buffer
    926 }
    927 
    928 // Function represents a programmable graphics or compute function executed by the GPU.
    929 //
    930 // Reference: https://developer.apple.com/documentation/metal/mtlfunction.
    931 type Function struct {
    932 	function unsafe.Pointer
    933 }
    934 
    935 func (f Function) Release() {
    936 	C.Function_Release(f.function)
    937 }
    938 
    939 // RenderPipelineState contains the graphics functions
    940 // and configuration state used in a render pass.
    941 //
    942 // Reference: https://developer.apple.com/documentation/metal/mtlrenderpipelinestate.
    943 type RenderPipelineState struct {
    944 	renderPipelineState unsafe.Pointer
    945 }
    946 
    947 func (r RenderPipelineState) Release() {
    948 	C.RenderPipelineState_Release(r.renderPipelineState)
    949 }
    950 
    951 // Region is a rectangular block of pixels in an image or texture,
    952 // defined by its upper-left corner and its size.
    953 //
    954 // Reference: https://developer.apple.com/documentation/metal/mtlregion.
    955 type Region struct {
    956 	Origin Origin // The location of the upper-left corner of the block.
    957 	Size   Size   // The size of the block.
    958 }
    959 
    960 func (r *Region) c() C.struct_Region {
    961 	return C.struct_Region{
    962 		Origin: r.Origin.c(),
    963 		Size:   r.Size.c(),
    964 	}
    965 }
    966 
    967 // Origin represents the location of a pixel in an image or texture relative
    968 // to the upper-left corner, whose coordinates are (0, 0).
    969 //
    970 // Reference: https://developer.apple.com/documentation/metal/mtlorigin.
    971 type Origin struct{ X, Y, Z int }
    972 
    973 func (o *Origin) c() C.struct_Origin {
    974 	return C.struct_Origin{
    975 		X: C.uint_t(o.X),
    976 		Y: C.uint_t(o.Y),
    977 		Z: C.uint_t(o.Z),
    978 	}
    979 }
    980 
    981 // Size represents the set of dimensions that declare the size of an object,
    982 // such as an image, texture, threadgroup, or grid.
    983 //
    984 // Reference: https://developer.apple.com/documentation/metal/mtlsize.
    985 type Size struct{ Width, Height, Depth int }
    986 
    987 func (s *Size) c() C.struct_Size {
    988 	return C.struct_Size{
    989 		Width:  C.uint_t(s.Width),
    990 		Height: C.uint_t(s.Height),
    991 		Depth:  C.uint_t(s.Depth),
    992 	}
    993 }
    994 
    995 // RegionMake2D returns a 2D, rectangular region for image or texture data.
    996 //
    997 // Reference: https://developer.apple.com/documentation/metal/1515675-mtlregionmake2d.
    998 func RegionMake2D(x, y, width, height int) Region {
    999 	return Region{
   1000 		Origin: Origin{x, y, 0},
   1001 		Size:   Size{width, height, 1},
   1002 	}
   1003 }
   1004 
   1005 type Viewport struct {
   1006 	OriginX float64
   1007 	OriginY float64
   1008 	Width   float64
   1009 	Height  float64
   1010 	ZNear   float64
   1011 	ZFar    float64
   1012 }
   1013 
   1014 func (v *Viewport) c() C.struct_Viewport {
   1015 	return C.struct_Viewport{
   1016 		OriginX: C.double(v.OriginX),
   1017 		OriginY: C.double(v.OriginY),
   1018 		Width:   C.double(v.Width),
   1019 		Height:  C.double(v.Height),
   1020 		ZNear:   C.double(v.ZNear),
   1021 		ZFar:    C.double(v.ZFar),
   1022 	}
   1023 }
   1024 
   1025 // ScissorRect represents a rectangle for the scissor fragment test.
   1026 //
   1027 // Reference: https://developer.apple.com/documentation/metal/mtlscissorrect
   1028 type ScissorRect struct {
   1029 	X      int
   1030 	Y      int
   1031 	Width  int
   1032 	Height int
   1033 }
   1034 
   1035 func (s *ScissorRect) c() C.struct_ScissorRect {
   1036 	return C.struct_ScissorRect{
   1037 		X:      C.uint_t(s.X),
   1038 		Y:      C.uint_t(s.Y),
   1039 		Width:  C.uint_t(s.Width),
   1040 		Height: C.uint_t(s.Height),
   1041 	}
   1042 }
   1043 
   1044 // DepthStencilState is a depth and stencil state object that specifies the depth and stencil configuration and operations used in a render pass.
   1045 //
   1046 // Reference: https://developer.apple.com/documentation/metal/mtldepthstencilstate
   1047 type DepthStencilState struct {
   1048 	depthStencilState unsafe.Pointer
   1049 }
   1050 
   1051 func (d DepthStencilState) Release() {
   1052 	C.DepthStencilState_Release(d.depthStencilState)
   1053 }
   1054 
   1055 // DepthStencilDescriptor is an object that configures new MTLDepthStencilState objects.
   1056 //
   1057 // Reference: https://developer.apple.com/documentation/metal/mtldepthstencildescriptor
   1058 type DepthStencilDescriptor struct {
   1059 	// BackFaceStencil is the stencil descriptor for back-facing primitives.
   1060 	BackFaceStencil StencilDescriptor
   1061 
   1062 	// FrontFaceStencil is The stencil descriptor for front-facing primitives.
   1063 	FrontFaceStencil StencilDescriptor
   1064 }
   1065 
   1066 // StencilDescriptor is an object that defines the front-facing or back-facing stencil operations of a depth and stencil state object.
   1067 //
   1068 // Reference: https://developer.apple.com/documentation/metal/mtlstencildescriptor
   1069 type StencilDescriptor struct {
   1070 	// StencilFailureOperation is the operation that is performed to update the values in the stencil attachment when the stencil test fails.
   1071 	StencilFailureOperation StencilOperation
   1072 
   1073 	// DepthFailureOperation is the operation that is performed to update the values in the stencil attachment when the stencil test passes, but the depth test fails.
   1074 	DepthFailureOperation StencilOperation
   1075 
   1076 	// DepthStencilPassOperation is the operation that is performed to update the values in the stencil attachment when both the stencil test and the depth test pass.
   1077 	DepthStencilPassOperation StencilOperation
   1078 
   1079 	// StencilCompareFunction is the comparison that is performed between the masked reference value and a masked value in the stencil attachment.
   1080 	StencilCompareFunction CompareFunction
   1081 }