2021 Graphics & Games
WWDC21 · 30 min · Graphics & Games
Create image processing apps powered by Apple silicon
Discover how to optimize your image processing app for Apple silicon. Explore how to take advantage of Metal render command encoders, tile shading, unified memory architecture, and memoryless attachments. We’ll show you how to use Apple’s unique tile based deferred renderer architecture to create power efficient apps with low memory footprint, and take you through best practices when migrating your compute-based apps from discrete GPUs to Apple silicon.
Watch at developer.apple.com ↗Code shown on screen · 4 snippets
Memoryless attachments
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(…)
let outputTexture = device.makeTexture(descriptor: textureDescriptor)
textureDescriptor.storageMode = .memoryless
let tempTexture = device.makeTexture(descriptor: textureDescriptor)
let renderPassDesc = MTLRenderPassDescriptor()
renderPassDesc.colorAttachments[0].texture = outputTexture
renderPassDesc.colorAttachments[0].loadAction = .dontCare
renderPassDesc.colorAttachments[0].storeAction = .store
renderPassDesc.colorAttachments[1].texture = tempTexture
renderPassDesc.colorAttachments[1].loadAction = .clear
renderPassDesc.colorAttachments[1].storeAction = .dontCare
let renderPass = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDesc) Uber-shaders impact on registers
fragment float4 processPixel(const constant ParamsStr* cs [[ buffer(0) ]])
{
if (cs->inputIsHDR) {
// do HDR stuff
} else {
// do non-HDR stuff
}
if (cs->tonemapEnabled) {
// tone map
}
} Function constants for Uber-shaders
constant bool featureAEnabled[[function_constant(0)]];
constant bool featureBEnabled[[function_constant(1)]];
fragment float4 processPixel(...)
{
if (featureAEnabled) {
// do A stuff
} else {
// do not-A stuff
}
if (featureBEnabled) {
// do B stuff
}
} Image processing filter graph
typedef struct
{
float4 OPTexture [[ color(0) ]];
float4 IntermediateTex [[ color(1) ]];
} FragmentIO;
fragment FragmentIO Unpack(RasterizerData in [[ stage_in ]],
texture2d<float, access::sample> srcImageTexture [[texture(0)]])
{
FragmentIO out;
//...
// Run necessary per-pixel operations
out.OPTexture = // assign computed value;
out.IntermediateTex = // assign computed value;
return out;
}
fragment FragmentIO CSC(RasterizerData in [[ stage_in ]], FragmentIO Input)
{
FragmentIO out;
//...
out.IntermediateTex = // assign computed value;
return out;
} Resources
Related sessions
-
24 min -
45 min