twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

mtl.go (36020B)


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