mtl.m (14044B)
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 viewport.OriginX, 194 viewport.OriginY, 195 viewport.Width, 196 viewport.Height, 197 viewport.ZNear, 198 viewport.ZFar, 199 }]; 200 } 201 202 void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder, 203 void *buffer, uint_t offset, 204 uint_t index) { 205 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 206 setVertexBuffer:(id<MTLBuffer>)buffer 207 offset:(NSUInteger)offset 208 atIndex:(NSUInteger)index]; 209 } 210 211 void RenderCommandEncoder_SetVertexBytes(void *renderCommandEncoder, 212 const void *bytes, size_t length, 213 uint_t index) { 214 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 215 setVertexBytes:bytes 216 length:(NSUInteger)length 217 atIndex:(NSUInteger)index]; 218 } 219 220 void RenderCommandEncoder_SetFragmentBytes(void *renderCommandEncoder, 221 const void *bytes, size_t length, 222 uint_t index) { 223 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 224 setFragmentBytes:bytes 225 length:(NSUInteger)length 226 atIndex:(NSUInteger)index]; 227 } 228 229 void RenderCommandEncoder_SetFragmentTexture(void *renderCommandEncoder, 230 void *texture, uint_t index) { 231 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 232 setFragmentTexture:(id<MTLTexture>)texture 233 atIndex:(NSUInteger)index]; 234 } 235 236 void RenderCommandEncoder_SetBlendColor(void *renderCommandEncoder, float red, 237 float green, float blue, float alpha) { 238 [(id<MTLRenderCommandEncoder>)renderCommandEncoder setBlendColorRed:red 239 green:green 240 blue:blue 241 alpha:alpha]; 242 } 243 244 void RenderCommandEncoder_DrawPrimitives(void *renderCommandEncoder, 245 uint8_t primitiveType, 246 uint_t vertexStart, 247 uint_t vertexCount) { 248 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 249 drawPrimitives:(MTLPrimitiveType)primitiveType 250 vertexStart:(NSUInteger)vertexStart 251 vertexCount:(NSUInteger)vertexCount]; 252 } 253 254 void RenderCommandEncoder_DrawIndexedPrimitives( 255 void *renderCommandEncoder, uint8_t primitiveType, uint_t indexCount, 256 uint8_t indexType, void *indexBuffer, uint_t indexBufferOffset) { 257 [(id<MTLRenderCommandEncoder>)renderCommandEncoder 258 drawIndexedPrimitives:(MTLPrimitiveType)primitiveType 259 indexCount:(NSUInteger)indexCount 260 indexType:(MTLIndexType)indexType 261 indexBuffer:(id<MTLBuffer>)indexBuffer 262 indexBufferOffset:(NSUInteger)indexBufferOffset]; 263 } 264 265 void BlitCommandEncoder_Synchronize(void *blitCommandEncoder, void *resource) { 266 #if !TARGET_OS_IPHONE 267 [(id<MTLBlitCommandEncoder>)blitCommandEncoder 268 synchronizeResource:(id<MTLResource>)resource]; 269 #endif 270 } 271 272 void BlitCommandEncoder_SynchronizeTexture(void *blitCommandEncoder, 273 void *texture, uint_t slice, 274 uint_t level) { 275 #if !TARGET_OS_IPHONE 276 [(id<MTLBlitCommandEncoder>)blitCommandEncoder 277 synchronizeTexture:(id<MTLTexture>)texture 278 slice:(NSUInteger)slice 279 level:(NSUInteger)level]; 280 #endif 281 } 282 283 void BlitCommandEncoder_CopyFromTexture( 284 void *blitCommandEncoder, void *sourceTexture, uint_t sourceSlice, 285 uint_t sourceLevel, struct Origin sourceOrigin, struct Size sourceSize, 286 void *destinationTexture, uint_t destinationSlice, uint_t destinationLevel, 287 struct Origin destinationOrigin) { 288 [(id<MTLBlitCommandEncoder>)blitCommandEncoder 289 copyFromTexture:(id<MTLTexture>)sourceTexture 290 sourceSlice:(NSUInteger)sourceSlice 291 sourceLevel:(NSUInteger)sourceLevel 292 sourceOrigin:(MTLOrigin){sourceOrigin.X, sourceOrigin.Y, 293 sourceOrigin.Z} 294 sourceSize:(MTLSize){sourceSize.Width, sourceSize.Height, 295 sourceSize.Depth} 296 toTexture:(id<MTLTexture>)destinationTexture 297 destinationSlice:(NSUInteger)destinationSlice 298 destinationLevel:(NSUInteger)destinationLevel 299 destinationOrigin:(MTLOrigin){destinationOrigin.X, destinationOrigin.Y, 300 destinationOrigin.Z}]; 301 } 302 303 void *Library_MakeFunction(void *library, const char *name) { 304 return [(id<MTLLibrary>)library 305 newFunctionWithName:[NSString stringWithUTF8String:name]]; 306 } 307 308 void Texture_Release(void *texture) { [(id<MTLTexture>)texture release]; } 309 310 void Texture_GetBytes(void *texture, void *pixelBytes, size_t bytesPerRow, 311 struct Region region, uint_t level) { 312 [(id<MTLTexture>)texture 313 getBytes:(void *)pixelBytes 314 bytesPerRow:(NSUInteger)bytesPerRow 315 fromRegion:(MTLRegion) { 316 {region.Origin.X, region.Origin.Y, region.Origin.Z}, { 317 region.Size.Width, region.Size.Height, region.Size.Depth 318 } 319 } 320 mipmapLevel:(NSUInteger)level]; 321 } 322 323 void Texture_ReplaceRegion(void *texture, struct Region region, uint_t level, 324 void *bytes, uint_t bytesPerRow) { 325 [(id<MTLTexture>)texture replaceRegion:(MTLRegion) { 326 {region.Origin.X, region.Origin.Y, region.Origin.Z}, { 327 region.Size.Width, region.Size.Height, region.Size.Depth 328 } 329 } 330 mipmapLevel:(NSUInteger)level 331 withBytes:bytes 332 bytesPerRow:(NSUInteger)bytesPerRow]; 333 } 334 335 int Texture_Width(void *texture) { return [(id<MTLTexture>)texture width]; } 336 337 int Texture_Height(void *texture) { return [(id<MTLTexture>)texture height]; } 338 339 void Buffer_CopyToContents(void *buffer, void *data, size_t lengthInBytes) { 340 memcpy(((id<MTLBuffer>)buffer).contents, data, lengthInBytes); 341 } 342 343 void Buffer_Retain(void *buffer) { [(id<MTLBuffer>)buffer retain]; } 344 345 void Buffer_Release(void *buffer) { [(id<MTLBuffer>)buffer release]; } 346 347 void Function_Release(void *function) { [(id<MTLFunction>)function release]; } 348 349 void RenderPipelineState_Release(void *renderPipelineState) { 350 [(id<MTLRenderPipelineState>)renderPipelineState release]; 351 }