zorldo

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

mtl_darwin.m (18124B)


      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 #include "mtl_darwin.h"
     16 #import <Metal/Metal.h>
     17 #include <stdlib.h>
     18 
     19 struct Device CreateSystemDefaultDevice() {
     20   id<MTLDevice> device = MTLCreateSystemDefaultDevice();
     21   if (!device) {
     22     struct Device d;
     23     d.Device = NULL;
     24     return d;
     25   }
     26 
     27   struct Device d;
     28   d.Device = device;
     29 #if !TARGET_OS_IPHONE
     30   d.Headless = device.headless;
     31   d.LowPower = device.lowPower;
     32 #else
     33   d.Headless = 0;
     34   d.LowPower = 0;
     35 #endif
     36   d.Name = device.name.UTF8String;
     37   return d;
     38 }
     39 
     40 uint8_t Device_SupportsFeatureSet(void *device, uint16_t featureSet) {
     41   return [(id<MTLDevice>)device supportsFeatureSet:featureSet];
     42 }
     43 
     44 void *Device_MakeCommandQueue(void *device) {
     45   return [(id<MTLDevice>)device newCommandQueue];
     46 }
     47 
     48 struct Library Device_MakeLibrary(void *device, const char *source,
     49                                   size_t sourceLength) {
     50   NSError *error;
     51   id<MTLLibrary> library = [(id<MTLDevice>)device
     52       newLibraryWithSource:[[NSString alloc] initWithBytes:source
     53                                                     length:sourceLength
     54                                                   encoding:NSUTF8StringEncoding]
     55                    options:NULL // TODO.
     56                      error:&error];
     57 
     58   struct Library l;
     59   l.Library = library;
     60   if (!library) {
     61     l.Error = error.localizedDescription.UTF8String;
     62   }
     63   return l;
     64 }
     65 
     66 struct RenderPipelineState
     67 Device_MakeRenderPipelineState(void *device,
     68                                struct RenderPipelineDescriptor descriptor) {
     69   MTLRenderPipelineDescriptor *renderPipelineDescriptor =
     70       [[MTLRenderPipelineDescriptor alloc] init];
     71   renderPipelineDescriptor.vertexFunction = descriptor.VertexFunction;
     72   renderPipelineDescriptor.fragmentFunction = descriptor.FragmentFunction;
     73   renderPipelineDescriptor.colorAttachments[0].pixelFormat =
     74       descriptor.ColorAttachment0PixelFormat;
     75   renderPipelineDescriptor.colorAttachments[0].blendingEnabled =
     76       descriptor.ColorAttachment0BlendingEnabled;
     77   renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor =
     78       descriptor.ColorAttachment0DestinationAlphaBlendFactor;
     79   renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor =
     80       descriptor.ColorAttachment0DestinationRGBBlendFactor;
     81   renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor =
     82       descriptor.ColorAttachment0SourceAlphaBlendFactor;
     83   renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor =
     84       descriptor.ColorAttachment0SourceRGBBlendFactor;
     85   renderPipelineDescriptor.colorAttachments[0].writeMask =
     86       descriptor.ColorAttachment0WriteMask;
     87   renderPipelineDescriptor.stencilAttachmentPixelFormat =
     88       descriptor.StencilAttachmentPixelFormat;
     89   NSError *error;
     90   id<MTLRenderPipelineState> renderPipelineState = [(id<MTLDevice>)device
     91       newRenderPipelineStateWithDescriptor:renderPipelineDescriptor
     92                                      error:&error];
     93   [renderPipelineDescriptor release];
     94   struct RenderPipelineState rps;
     95   rps.RenderPipelineState = renderPipelineState;
     96   if (!renderPipelineState) {
     97     rps.Error = error.localizedDescription.UTF8String;
     98   }
     99   return rps;
    100 }
    101 
    102 void *Device_MakeBufferWithBytes(void *device, const void *bytes, size_t length,
    103                                  uint16_t options) {
    104   return [(id<MTLDevice>)device newBufferWithBytes:(const void *)bytes
    105                                             length:(NSUInteger)length
    106                                            options:(MTLResourceOptions)options];
    107 }
    108 
    109 void *Device_MakeBufferWithLength(void *device, size_t length,
    110                                   uint16_t options) {
    111   return
    112       [(id<MTLDevice>)device newBufferWithLength:(NSUInteger)length
    113                                          options:(MTLResourceOptions)options];
    114 }
    115 
    116 void *Device_MakeTexture(void *device, struct TextureDescriptor descriptor) {
    117   MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
    118   textureDescriptor.textureType = descriptor.TextureType;
    119   textureDescriptor.pixelFormat = descriptor.PixelFormat;
    120   textureDescriptor.width = descriptor.Width;
    121   textureDescriptor.height = descriptor.Height;
    122   textureDescriptor.storageMode = descriptor.StorageMode;
    123   textureDescriptor.usage = descriptor.Usage;
    124   id<MTLTexture> texture =
    125       [(id<MTLDevice>)device newTextureWithDescriptor:textureDescriptor];
    126   [textureDescriptor release];
    127   return texture;
    128 }
    129 
    130 void *Device_MakeDepthStencilState(void *device,
    131                                    struct DepthStencilDescriptor descriptor) {
    132   MTLDepthStencilDescriptor *depthStencilDescriptor =
    133       [[MTLDepthStencilDescriptor alloc] init];
    134   depthStencilDescriptor.backFaceStencil.stencilFailureOperation =
    135       descriptor.BackFaceStencilStencilFailureOperation;
    136   depthStencilDescriptor.backFaceStencil.depthFailureOperation =
    137       descriptor.BackFaceStencilDepthFailureOperation;
    138   depthStencilDescriptor.backFaceStencil.depthStencilPassOperation =
    139       descriptor.BackFaceStencilDepthStencilPassOperation;
    140   depthStencilDescriptor.backFaceStencil.stencilCompareFunction =
    141       descriptor.BackFaceStencilStencilCompareFunction;
    142   depthStencilDescriptor.frontFaceStencil.stencilFailureOperation =
    143       descriptor.FrontFaceStencilStencilFailureOperation;
    144   depthStencilDescriptor.frontFaceStencil.depthFailureOperation =
    145       descriptor.FrontFaceStencilDepthFailureOperation;
    146   depthStencilDescriptor.frontFaceStencil.depthStencilPassOperation =
    147       descriptor.FrontFaceStencilDepthStencilPassOperation;
    148   depthStencilDescriptor.frontFaceStencil.stencilCompareFunction =
    149       descriptor.FrontFaceStencilStencilCompareFunction;
    150   id<MTLDepthStencilState> depthStencilState = [(id<MTLDevice>)device
    151       newDepthStencilStateWithDescriptor:depthStencilDescriptor];
    152   [depthStencilDescriptor release];
    153   return depthStencilState;
    154 }
    155 
    156 void CommandQueue_Release(void *commandQueue) {
    157   [(id<MTLCommandQueue>)commandQueue release];
    158 }
    159 
    160 void *CommandQueue_MakeCommandBuffer(void *commandQueue) {
    161   return [(id<MTLCommandQueue>)commandQueue commandBuffer];
    162 }
    163 
    164 void CommandBuffer_Retain(void *commandBuffer) {
    165   [(id<MTLCommandBuffer>)commandBuffer retain];
    166 }
    167 
    168 void CommandBuffer_Release(void *commandBuffer) {
    169   [(id<MTLCommandBuffer>)commandBuffer release];
    170 }
    171 
    172 uint8_t CommandBuffer_Status(void *commandBuffer) {
    173   return [(id<MTLCommandBuffer>)commandBuffer status];
    174 }
    175 
    176 void CommandBuffer_PresentDrawable(void *commandBuffer, void *drawable) {
    177   [(id<MTLCommandBuffer>)commandBuffer
    178       presentDrawable:(id<MTLDrawable>)drawable];
    179 }
    180 
    181 void CommandBuffer_Commit(void *commandBuffer) {
    182   [(id<MTLCommandBuffer>)commandBuffer commit];
    183 }
    184 
    185 void CommandBuffer_WaitUntilCompleted(void *commandBuffer) {
    186   [(id<MTLCommandBuffer>)commandBuffer waitUntilCompleted];
    187 }
    188 
    189 void CommandBuffer_WaitUntilScheduled(void *commandBuffer) {
    190   [(id<MTLCommandBuffer>)commandBuffer waitUntilScheduled];
    191 }
    192 
    193 void *
    194 CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
    195                                        struct RenderPassDescriptor descriptor) {
    196   MTLRenderPassDescriptor *renderPassDescriptor =
    197       [[MTLRenderPassDescriptor alloc] init];
    198   renderPassDescriptor.colorAttachments[0].loadAction =
    199       descriptor.ColorAttachment0LoadAction;
    200   renderPassDescriptor.colorAttachments[0].storeAction =
    201       descriptor.ColorAttachment0StoreAction;
    202   renderPassDescriptor.colorAttachments[0].clearColor =
    203       MTLClearColorMake(descriptor.ColorAttachment0ClearColor.Red,
    204                         descriptor.ColorAttachment0ClearColor.Green,
    205                         descriptor.ColorAttachment0ClearColor.Blue,
    206                         descriptor.ColorAttachment0ClearColor.Alpha);
    207   renderPassDescriptor.colorAttachments[0].texture =
    208       (id<MTLTexture>)descriptor.ColorAttachment0Texture;
    209   renderPassDescriptor.stencilAttachment.loadAction =
    210       descriptor.StencilAttachmentLoadAction;
    211   renderPassDescriptor.stencilAttachment.storeAction =
    212       descriptor.StencilAttachmentStoreAction;
    213   renderPassDescriptor.stencilAttachment.texture =
    214       (id<MTLTexture>)descriptor.StencilAttachmentTexture;
    215   id<MTLRenderCommandEncoder> rce = [(id<MTLCommandBuffer>)commandBuffer
    216       renderCommandEncoderWithDescriptor:renderPassDescriptor];
    217   [renderPassDescriptor release];
    218   return rce;
    219 }
    220 
    221 void *CommandBuffer_MakeBlitCommandEncoder(void *commandBuffer) {
    222   return [(id<MTLCommandBuffer>)commandBuffer blitCommandEncoder];
    223 }
    224 
    225 void CommandEncoder_EndEncoding(void *commandEncoder) {
    226   [(id<MTLCommandEncoder>)commandEncoder endEncoding];
    227 }
    228 
    229 void RenderCommandEncoder_Release(void *renderCommandEncoder) {
    230   [(id<MTLRenderCommandEncoder>)renderCommandEncoder release];
    231 }
    232 
    233 void RenderCommandEncoder_SetRenderPipelineState(void *renderCommandEncoder,
    234                                                  void *renderPipelineState) {
    235   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    236       setRenderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState];
    237 }
    238 
    239 void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
    240                                       struct Viewport viewport) {
    241   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    242       setViewport:(MTLViewport){
    243                       .originX = viewport.OriginX,
    244                       .originY = viewport.OriginY,
    245                       .width = viewport.Width,
    246                       .height = viewport.Height,
    247                       .znear = viewport.ZNear,
    248                       .zfar = viewport.ZFar,
    249                   }];
    250 }
    251 
    252 void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
    253                                          struct ScissorRect scissorRect) {
    254   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    255       setScissorRect:(MTLScissorRect){
    256                          .x = scissorRect.X,
    257                          .y = scissorRect.Y,
    258                          .width = scissorRect.Width,
    259                          .height = scissorRect.Height,
    260                      }];
    261 }
    262 
    263 void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
    264                                           void *buffer, uint_t offset,
    265                                           uint_t index) {
    266   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    267       setVertexBuffer:(id<MTLBuffer>)buffer
    268                offset:(NSUInteger)offset
    269               atIndex:(NSUInteger)index];
    270 }
    271 
    272 void RenderCommandEncoder_SetVertexBytes(void *renderCommandEncoder,
    273                                          const void *bytes, size_t length,
    274                                          uint_t index) {
    275   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    276       setVertexBytes:bytes
    277               length:(NSUInteger)length
    278              atIndex:(NSUInteger)index];
    279 }
    280 
    281 void RenderCommandEncoder_SetFragmentBytes(void *renderCommandEncoder,
    282                                            const void *bytes, size_t length,
    283                                            uint_t index) {
    284   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    285       setFragmentBytes:bytes
    286                 length:(NSUInteger)length
    287                atIndex:(NSUInteger)index];
    288 }
    289 
    290 void RenderCommandEncoder_SetFragmentTexture(void *renderCommandEncoder,
    291                                              void *texture, uint_t index) {
    292   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    293       setFragmentTexture:(id<MTLTexture>)texture
    294                  atIndex:(NSUInteger)index];
    295 }
    296 
    297 void RenderCommandEncoder_SetBlendColor(void *renderCommandEncoder, float red,
    298                                         float green, float blue, float alpha) {
    299   [(id<MTLRenderCommandEncoder>)renderCommandEncoder setBlendColorRed:red
    300                                                                 green:green
    301                                                                  blue:blue
    302                                                                 alpha:alpha];
    303 }
    304 
    305 void RenderCommandEncoder_SetDepthStencilState(void *renderCommandEncoder,
    306                                                void *depthStencilState) {
    307   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    308       setDepthStencilState:(id<MTLDepthStencilState>)depthStencilState];
    309 }
    310 
    311 void RenderCommandEncoder_DrawPrimitives(void *renderCommandEncoder,
    312                                          uint8_t primitiveType,
    313                                          uint_t vertexStart,
    314                                          uint_t vertexCount) {
    315   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    316       drawPrimitives:(MTLPrimitiveType)primitiveType
    317          vertexStart:(NSUInteger)vertexStart
    318          vertexCount:(NSUInteger)vertexCount];
    319 }
    320 
    321 void RenderCommandEncoder_DrawIndexedPrimitives(
    322     void *renderCommandEncoder, uint8_t primitiveType, uint_t indexCount,
    323     uint8_t indexType, void *indexBuffer, uint_t indexBufferOffset) {
    324   [(id<MTLRenderCommandEncoder>)renderCommandEncoder
    325       drawIndexedPrimitives:(MTLPrimitiveType)primitiveType
    326                  indexCount:(NSUInteger)indexCount
    327                   indexType:(MTLIndexType)indexType
    328                 indexBuffer:(id<MTLBuffer>)indexBuffer
    329           indexBufferOffset:(NSUInteger)indexBufferOffset];
    330 }
    331 
    332 void BlitCommandEncoder_Synchronize(void *blitCommandEncoder, void *resource) {
    333 #if !TARGET_OS_IPHONE
    334   [(id<MTLBlitCommandEncoder>)blitCommandEncoder
    335       synchronizeResource:(id<MTLResource>)resource];
    336 #endif
    337 }
    338 
    339 void BlitCommandEncoder_SynchronizeTexture(void *blitCommandEncoder,
    340                                            void *texture, uint_t slice,
    341                                            uint_t level) {
    342 #if !TARGET_OS_IPHONE
    343   [(id<MTLBlitCommandEncoder>)blitCommandEncoder
    344       synchronizeTexture:(id<MTLTexture>)texture
    345                    slice:(NSUInteger)slice
    346                    level:(NSUInteger)level];
    347 #endif
    348 }
    349 
    350 void BlitCommandEncoder_CopyFromTexture(
    351     void *blitCommandEncoder, void *sourceTexture, uint_t sourceSlice,
    352     uint_t sourceLevel, struct Origin sourceOrigin, struct Size sourceSize,
    353     void *destinationTexture, uint_t destinationSlice, uint_t destinationLevel,
    354     struct Origin destinationOrigin) {
    355   [(id<MTLBlitCommandEncoder>)blitCommandEncoder
    356         copyFromTexture:(id<MTLTexture>)sourceTexture
    357             sourceSlice:(NSUInteger)sourceSlice
    358             sourceLevel:(NSUInteger)sourceLevel
    359            sourceOrigin:(MTLOrigin){.x = sourceOrigin.X,
    360                                     .y = sourceOrigin.Y,
    361                                     .z = sourceOrigin.Z}
    362              sourceSize:(MTLSize){.width = sourceSize.Width,
    363                                   .height = sourceSize.Height,
    364                                   .depth = sourceSize.Depth}
    365               toTexture:(id<MTLTexture>)destinationTexture
    366        destinationSlice:(NSUInteger)destinationSlice
    367        destinationLevel:(NSUInteger)destinationLevel
    368       destinationOrigin:(MTLOrigin){.x = destinationOrigin.X,
    369                                     .y = destinationOrigin.Y,
    370                                     .z = destinationOrigin.Z}];
    371 }
    372 
    373 void *Library_MakeFunction(void *library, const char *name) {
    374   return [(id<MTLLibrary>)library
    375       newFunctionWithName:[NSString stringWithUTF8String:name]];
    376 }
    377 
    378 void Texture_Release(void *texture) { [(id<MTLTexture>)texture release]; }
    379 
    380 void Texture_GetBytes(void *texture, void *pixelBytes, size_t bytesPerRow,
    381                       struct Region region, uint_t level) {
    382   [(id<MTLTexture>)texture getBytes:(void *)pixelBytes
    383                         bytesPerRow:(NSUInteger)bytesPerRow
    384                          fromRegion:(MTLRegion) {
    385                            .origin = {.x = region.Origin.X,
    386                                       .y = region.Origin.Y,
    387                                       .z = region.Origin.Z},
    388                            .size = {
    389                              .width = region.Size.Width,
    390                              .height = region.Size.Height,
    391                              .depth = region.Size.Depth
    392                            }
    393                          }
    394                         mipmapLevel:(NSUInteger)level];
    395 }
    396 
    397 void Texture_ReplaceRegion(void *texture, struct Region region, uint_t level,
    398                            void *bytes, uint_t bytesPerRow) {
    399   [(id<MTLTexture>)texture replaceRegion:(MTLRegion) {
    400     .origin = {.x = region.Origin.X,
    401                .y = region.Origin.Y,
    402                .z = region.Origin.Z},
    403     .size = {
    404       .width = region.Size.Width,
    405       .height = region.Size.Height,
    406       .depth = region.Size.Depth
    407     }
    408   }
    409                              mipmapLevel:(NSUInteger)level
    410                                withBytes:bytes
    411                              bytesPerRow:(NSUInteger)bytesPerRow];
    412 }
    413 
    414 int Texture_Width(void *texture) { return [(id<MTLTexture>)texture width]; }
    415 
    416 int Texture_Height(void *texture) { return [(id<MTLTexture>)texture height]; }
    417 
    418 size_t Buffer_Length(void *buffer) { return [(id<MTLBuffer>)buffer length]; }
    419 
    420 void Buffer_CopyToContents(void *buffer, void *data, size_t lengthInBytes) {
    421   memcpy(((id<MTLBuffer>)buffer).contents, data, lengthInBytes);
    422 #if !TARGET_OS_IPHONE
    423   [(id<MTLBuffer>)buffer didModifyRange:NSMakeRange(0, lengthInBytes)];
    424 #endif
    425 }
    426 
    427 void Buffer_Retain(void *buffer) { [(id<MTLBuffer>)buffer retain]; }
    428 
    429 void Buffer_Release(void *buffer) { [(id<MTLBuffer>)buffer release]; }
    430 
    431 void Function_Release(void *function) { [(id<MTLFunction>)function release]; }
    432 
    433 void RenderPipelineState_Release(void *renderPipelineState) {
    434   [(id<MTLRenderPipelineState>)renderPipelineState release];
    435 }
    436 
    437 void DepthStencilState_Release(void *depthStencilState) {
    438   [(id<MTLDepthStencilState>)depthStencilState release];
    439 }