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 }