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 }