zorldo

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

mtl.m (15174B)


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