2022 Graphics & Games
WWDC22 · 27 min · Graphics & Games
Program Metal in C++ with metal-cpp
Your C++ games and apps can now tap into the power of Metal. We’ll show you how metal-cpp helps you bridge your C++ code to Metal, explore how each manages object lifecycles, and demonstrate utilities that can help these language cooperate in your app. We’ll also share best practices for designing app architecture to elegantly integrate Objective-C and C++ together.
Watch at developer.apple.com ↗Code shown on screen · 9 snippets
Draw a single triangle in C++
MTL::CommandBuffer* pCmd = _pCommandQueue->commandBuffer();
MTL::RenderCommandEncoder* pEnc = pCmd->renderCommandEncoder( pRpd );
pEnc->setRenderPipelineState( _pPSO );
pEnc->drawPrimitives( MTL::PrimitiveTypeTriangle,
NS::UInteger(0),
NS::UInteger(3));
pEnc->endEncoding();
pCmd->presentDrawable( pView->currentDrawable() );
pCmd->commit(); Draw a single triangle in Objective-C
id<MTLCommandBuffer> cmd = [_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> enc = [cmd renderCommandEncoderWithDescriptor:pRpd];
[enc setRenderPipelineState:_pPSO];
[enc drawPrimitives:MTLPrimitiveTypeTriangle
vertexStart:0
vertexCount:3];
[enc endEncoding];
[cmd presentDrawable:view.currentDrawable];
[cmd commit]; Generate the implementation
How to use autoreleased objects and AutoreleasePool
NS::AutoreleasePool* pPool = NS::AutoreleasePool::alloc()->init();
MTL::CommandBuffer* pCmd = _pCommandQueue->commandBuffer();
MTL::RenderPassDescriptor* pRpd = pView->currentRenderPassDescriptor();
MTL::RenderCommandEncoder* pEnc = pCmd->renderCommandEncoder( pRpd );
pEnc->endEncoding();
pCmd->presentDrawable( pView->currentDrawable() );
pCmd->commit();
pPool->release(); How NS::TransferPtr works
{
auto ptr = NS::TransferPtr( pMRR );
// Do something with ptr
. . .
} How NS::RetainPtr works
{
auto ptr = NS::RetainPtr( pMRR );
// Do something with ptr
. . .
} Create an adapter class calling C++ from Objective-C files
@interface AAPLRendererAdapter ()
{
AAPLRenderer* _pRenderer;
}
@end
@implementation AAPLRendererAdapter
- (void)drawInMTKView:(MTKView *)pMtkView
{
_pRenderer->draw((__bridge MTK::View*)pMtkView);
}
@end Create an adapter class calling Objective-C from C++ files
CA::MetalDrawable* AAPLViewAdapter::currentDrawable() const
{
return (__bridge CA::MetalDrawable*)[(__bridge MTKView *)m_pMTKView currentDrawable];
}
MTL::Texture* AAPLViewAdapter::depthStencilTexture() const
{
return (__bridge MTL::Texture*)[(__bridge MTKView *)m_pMTKView depthStencilTexture];
} Cast between Objective-C and C++ objects and transfer ownership
MTL::Texture* newTextureFromCatalog( MTL::Device* pDevice, const char* name,
MTL::StorageMode storageMode, MTL::TextureUsage usage )
{
NSDictionary<MTKTextureLoaderOption, id>* options = @{
MTKTextureLoaderOptionTextureStorageMode : @( (MTLStorageMode)storageMode ),
MTKTextureLoaderOptionTextureUsage : @( (MTLTextureUsage)usage )
};
MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc]
initWithDevice:(__bridge id<MTLDevice>)pDevice];
NSError* __autoreleasing err = nil;
id< MTLTexture > texture = [textureLoader
newTextureWithName:[NSString stringWithUTF8String:name]
scaleFactor:1
bundle:nil
options:options
error:&err];
return (__bridge_retained MTL::Texture*)texture;
} Resources
Related sessions
-
16 min