adopting metal, part 1 - apple inc. · building pipeline states issuing gpu commands animation and...

178
© 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. Graphics and Games #WWDC16 Session 602 Adopting Metal, Part 1 Warren Moore GPU Software Engineer Matt Collins GPU Software Engineer

Upload: others

Post on 15-Jul-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

© 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Graphics and Games #WWDC16

Session 602

Adopting Metal, Part 1

Warren Moore GPU Software Engineer Matt Collins GPU Software Engineer

Page 2: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Metal

Apple’s low-overhead API for GPUsUnified graphics and computeBuilt for efficient multithreadingDesigned for Apple platforms

Page 3: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Supporting TechnologiesMetal

MetalKit Metal Performance ShadersXcode and Instruments• Metal Compiler• Frame Debugger• Metal System Trace

Page 4: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 5: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 6: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 7: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Maps

SpriteKit

SceneKit

Preview

Safari Core Image

OpenGL ES

UIKit

Core Graphics

Core Animation

Model I/O

Page 8: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 9: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Furious Wings

Page 10: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Affinity

Page 11: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

10

Page 12: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

10

Page 13: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Adopting MetalPart One• Fundamental Concepts• Basic Drawing• Lighting and Texturing

A look at the sessionsMetal at WWDC This Year

Part Two• Dynamic Data Management • CPU-GPU Synchronization• Multithreaded Encoding

Page 14: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

A look at the sessionsMetal at WWDC This Year

What’s New in MetalPart One• Tessellation• Resource Heaps and Memoryless

Render Targets• Improved Tools

Part Two• Function Specialization and Function

Resource Read-Writes• Wide Color and Texture Assets• Additions to Metal Performance Shaders

Page 15: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

A look at the sessionsMetal at WWDC This Year

Advanced Shader Optimization• Shader Performance Fundamentals• Tuning Shader Code

Page 16: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Sample Project

This session• Geometry

Page 17: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Sample Project

This session• Geometry• Animation• Texturing

Page 18: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Sample Project

Adopting Metal Part 2• Updating object data• Multithreaded draw calls

Page 19: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Assumptions

You’re familiar with the fundamentals of graphics programmingYou have experience with a graphics API that has shadersYou’re interested in using Metal to make your games and apps even more awesome

Page 20: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Agenda

Page 21: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 22: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 23: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Conceptual Overview

Use an API that matches the hardware and driverFavor explicit over implicitDo expensive work less often

Page 24: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

An API that Matches the Hardware

Thoroughly modern• Integrates with and exposes latest hardware features • Thin API with no historical cruft

No fancy tricks required for low-overhead operationUniform across platforms (OS X, iOS, tvOS)

Page 25: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

…when implicit has a high costFavor Explicit over Implicit

Command submission model maps closely to actual hardware operationExplicit control over memory and synchronizationWith great responsibility comes great performance

Page 26: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Do Expensive Work Less Often

When How Often

Build time —

Load time Infrequently

Draw time Many times per second

Page 27: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Do Expensive Work Less Often

When How Often OpenGL

Build time — —

Load time Infrequently —

Draw time Many times per secondState validation

Shader compilation Encode work for GPU

Page 28: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Do Expensive Work Less Often

When How Often OpenGL Metal

Build time — — Shader compilation

Load time Infrequently — State validation

Draw time Many times per secondState validation

Shader compilation Encode work for GPU

Encode work for GPU

Page 29: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 30: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 31: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLDevice

Abstract representation of a GPU The “root object” of the Metal object graphUsed to create resources, pipeline state objects, and command queues

Page 32: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTL Device

// API

let device = MTLCreateSystemDefaultDevice()

Page 33: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 34: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 35: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Buffers

Allocations of memory that can store data in a format of your choosingVertex data, index data, constantsCan be read in vertex and fragment functions

Page 36: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Buffer Layout

Vertex Vertex VertexVertex Buffer

Index Buffer Index Index Index Index Index Index Index Index Index

Page 37: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Buffers as Arrays of Structures

Vertex Vertex VertexMTLBuffer

struct Vertex { var position: float4 var color: float4 }

Page 38: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

APIMTLBuffer

Creating a buffer of particular size

let buffer = device.newBuffer(withLength: strideof(myData), options:[])

let buffer = device.newBuffer(withBytes: &myData, length: strideof(myData), options: [])

Creating a buffer containing a copy of existing memory

Page 39: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Defining Geometry for the Demo

Page 40: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Clip Space Coordinates

y=-1

x=-1

x=1

y=1

z=0

z=1

Page 41: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

var vertices = [Vertex]()

vertices.append(Vertex(position: float4(-0.5, 0.25, 0, 1), color: float4(1, 0, 0, 1)))

vertices.append(Vertex(position: float4( 0, -0.5, 0, 1), color: float4(0, 1, 0, 1)))

vertices.append(Vertex(position: float4( 0.5, 0.5, 0, 1), color: float4(0, 0, 1, 1)))

var indices = [UInt16]()

indices.append(0)

indices.append(1)

indices.append(2)

let vertexBuffer = device.newBuffer(withBytes: vertices,

length: strideof(Vertex) * vertices.count,

options: [])

let indexBuffer = device.newBuffer(withBytes: indices,

length: strideof(UInt16) * indices.count,

options: [])

Page 42: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

var vertices = [Vertex]()

vertices.append(Vertex(position: float4(-0.5, 0.25, 0, 1), color: float4(1, 0, 0, 1)))

vertices.append(Vertex(position: float4( 0, -0.5, 0, 1), color: float4(0, 1, 0, 1)))

vertices.append(Vertex(position: float4( 0.5, 0.5, 0, 1), color: float4(0, 0, 1, 1)))

var indices = [UInt16]()

indices.append(0)

indices.append(1)

indices.append(2)

let vertexBuffer = device.newBuffer(withBytes: vertices,

length: strideof(Vertex) * vertices.count,

options: [])

let indexBuffer = device.newBuffer(withBytes: indices,

length: strideof(UInt16) * indices.count,

options: [])

Page 43: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

var vertices = [Vertex]()

vertices.append(Vertex(position: float4(-0.5, 0.25, 0, 1), color: float4(1, 0, 0, 1)))

vertices.append(Vertex(position: float4( 0, -0.5, 0, 1), color: float4(0, 1, 0, 1)))

vertices.append(Vertex(position: float4( 0.5, 0.5, 0, 1), color: float4(0, 0, 1, 1)))

var indices = [UInt16]()

indices.append(0)

indices.append(1)

indices.append(2)

let vertexBuffer = device.newBuffer(withBytes: vertices,

length: strideof(Vertex) * vertices.count,

options: [])

let indexBuffer = device.newBuffer(withBytes: indices,

length: strideof(UInt16) * indices.count,

options: [])

Page 44: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

var vertices = [Vertex]()

vertices.append(Vertex(position: float4(-0.5, 0.25, 0, 1), color: float4(1, 0, 0, 1)))

vertices.append(Vertex(position: float4( 0, -0.5, 0, 1), color: float4(0, 1, 0, 1)))

vertices.append(Vertex(position: float4( 0.5, 0.5, 0, 1), color: float4(0, 0, 1, 1)))

var indices = [UInt16]()

indices.append(0)

indices.append(1)

indices.append(2)

let vertexBuffer = device.newBuffer(withBytes: vertices,

length: strideof(Vertex) * vertices.count,

options: [])

let indexBuffer = device.newBuffer(withBytes: indices,

length: strideof(UInt16) * indices.count,

options: [])

Page 45: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 46: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 47: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Metal Shading Language

Extended subset of C++14Unified language for graphics and computeLets you write programs for the GPU

Page 48: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Depth Attachment

Color Attachments Present

Buffer

VertexFetch

Sampler

Texture

Buffer

Rasterization

Sampler

Texture

Buffer

FramebufferWrite

Function Function

VertexProcessing

Fragment Processing

Page 49: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Depth Attachment

Color Attachments Present

Buffer

VertexFetch

Sampler

Texture

Buffer

Rasterization

Sampler

Texture

Buffer

FramebufferWrite

Function Function

VertexProcessing

Fragment Processing

Page 50: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 51: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 52: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 53: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

finished running MetalTexturedMesh OSX: MetalTextured…

Page 54: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

finished running MetalTexturedMesh OSX: MetalTextured…

Page 55: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 56: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high
Page 57: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Build-Time Compilation

Shading language files (.metal)• Compiled by Xcode using Metal toolchain• Produce .metallibs (collection of compiled functions)• default.metallib copied automatically into app bundle

Page 58: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLLibrary

A collection of compiled function objectsMultiple ways to create• Loaded from default.metallib• Loaded from .metallib built with command-line toolchain• Built from source at run time

Page 59: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLLibrary

// API

let library = device.newDefaultLibrary()

Page 60: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLFunction

Metal object representing a single functionAssociated with a particular pipeline stage• Vertex (vertex) • Fragment (fragment)• Compute (kernel)

Page 61: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 62: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 63: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(...)

{

VertexOut out;

...

return out;

}

fragment half4 fragment_lighting(VertexOut fragmentIn [[stage_in]])

{

...

return color;

}

Page 64: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLFunction

// API

let vertexFunction = library.newFunction(withName: "vertex_transform")

let fragmentFunction = library.newFunction(withName: "fragment_lighting")

Page 65: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 66: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 67: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Validate

Validate

Compile Shaders

The Virtue of Precompiled State

Set Blend Func

Set Depth Func

Set Other State

Draw

Set Blend Func

Set Other State

Draw

OpenGL

Page 68: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Virtue of Precompiled StateOpenGL

Validate

Validate

Compile Shaders

Set Blend Func

Set Depth Func

Set Other State

Draw

Set Blend Func

Set Other State

Draw

Page 69: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Metal

The Virtue of Precompiled State

Validate

Validate

Compile Shaders

Set Blend FuncSet Depth Func

Set Other State

Draw

Set Blend FuncSet Other State

Draw

Set Pipeline State

Set Pipeline State

Page 70: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Precompiled State vs. “Any Time” State

Set on Pipeline State Set While Drawing

Vertex and Fragment Function Front Face Winding

Alpha Blending Cull Mode

MSAA Sample Count Fill Mode

Pixel Formats for Render Targets Scissor

Vertex Descriptor Viewport

Page 71: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLRenderPipelineState

Represents a “configuration” of the GPU pipelineContains validated set of state used during renderingUsually created at application load time

Page 72: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Render Pipeline Descriptor

Vertex Function

Pixel formatsBlend states

Vertex Descriptor

MTLRenderPipelineDescriptor

Fragment Function

Depth and Stencil Pixel Formats

Pixel formatsBlend statesPixel formats

Blend statesColor Framebuffer Attachments

Pixel formatsBlend states

Page 73: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Render Pipeline Descriptor

MTLDevice

MTLRenderPipelineState

Vertex Function

Pixel formatsBlend states

Vertex Descriptor

MTLRenderPipelineDescriptor

Fragment Function

Depth and Stencil Pixel Formats

Pixel formatsBlend statesPixel formats

Blend statesColor Framebuffer Attachments

Pixel formatsBlend states

Page 74: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLRenderPipelineState

// API

let pipelineDescriptor = MTLRenderPipelineDescriptor()

pipelineDescriptor.vertexFunction = vertexFunction

pipelineDescriptor.fragmentFunction = fragmentFunction

pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm

let pipelineState = try device.newRenderPipelineState(with: pipelineDescriptor)

Page 75: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLRenderPipelineState

// API

let pipelineDescriptor = MTLRenderPipelineDescriptor()

pipelineDescriptor.vertexFunction = vertexFunction

pipelineDescriptor.fragmentFunction = fragmentFunction

pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm

let pipelineState = try device.newRenderPipelineState(with: pipelineDescriptor)

Page 76: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLRenderPipelineState

// API

let pipelineDescriptor = MTLRenderPipelineDescriptor()

pipelineDescriptor.vertexFunction = vertexFunction

pipelineDescriptor.fragmentFunction = fragmentFunction

pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm

let pipelineState = try device.newRenderPipelineState(with: pipelineDescriptor)

Page 77: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Pipeline States are Persistent Objects

Create them during load timeKeep them around, as you do your device and resourcesSwitch among them when drawing

Page 78: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 79: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 80: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Issuing GPU Commands

Interfacing with UIKit and AppKitMetal Command Submission ModelRender PassesDraw CallsGetting on the Screen

Page 81: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTKView

Cross-platform view class• NSView on OS X• UIView on iOS & tvOS

Reduces boilerplate code• Creates and manages a CALayer• Issues periodic drawing callbacks• Manages render targets

CAMetalLayer

CA/CVDisplayLink

Other Attachment Textures

Drawable Drawable Drawable

MTKView

Page 82: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Drawables

Wrap a texture to be displayed on screenManaged by CAMetalLayer• Kept in an internal queue• Reused across frames

CAMetalLayer

CA/CVDisplayLink

Other Attachment Textures

MTKView

Drawable Drawable Drawable

Page 83: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Drawables

Wrap a texture to be displayed on screenManaged by CAMetalLayer• Kept in an internal queue• Reused across frames

CAMetalLayer

CA/CVDisplayLink

Other Attachment Textures

MTKView

Drawable Drawable Drawable

Page 84: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTKView // Configuration

// Clear to solid white

view.clearColor = MTLClearColorMake(1, 1, 1, 1)

// Use a BGRA 8-bit normalized texture for the drawable

view.colorPixelFormat = .bgra8Unorm

// Use a 32-bit depth buffer

view.depthStencilPixelFormat = .depth32Float

// Make the renderer object responsible for drawing on our behalf

view.delegate = renderer

Page 85: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Implementing MTKViewDelegate

func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {

// Respond to resize

}

func draw(in metalView: MTKView)

{

// Our command buffer is a container for the work we want to perform with the GPU.

let commandBuffer = commandQueue.commandBuffer()

// Encode render passes

...

// Now that we're done issuing commands, we commit our buffer so the GPU can get to work.

commandBuffer.commit()

}

Page 86: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Submission Model

DeviceCommand Queue

Command Buffer Command Buffer

Render Command Encoder

Render Command Encoder

Compute Command Encoder

Page 87: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Submission Model

Explicit command buffer construction and submission • Each buffer is a parcel of work for the GPU• Command buffer submission is under your control

Command encoders• Translate from API calls to work for the GPU • No deferred state validation

Page 88: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Submission Model

Multithreaded command encoding • Multiple command buffers can be encoded in parallel• App decides execution order

Scales to allow tens of thousands of draw calls per frameMore on this in Part II

Page 89: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Queues

Command Buffer Command Buffer

Render Command Encoder

Render Command Encoder

Compute Command Encoder

DeviceCommand Queue

Page 90: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Queues

Command Buffer Command Buffer

Render Command Encoder

Render Command Encoder

Compute Command Encoder

DeviceCommand Queue

Page 91: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLCommandQueue

Manage the work that has been queued up for the device• Should be created up-front and live as long as your device• You’ll often need only one • Thread-safe

Page 92: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLCommandQueue

// API

// Create the command queue we will be using to submit work to the GPU.

let commandQueue = device.newCommandQueue()

Page 93: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Buffers

Device

Render Command Encoder

Render Command Encoder

Compute Command Encoder

Command Queue

Command Buffer Command Buffer

Page 94: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Buffers

Device

Render Command Encoder

Render Command Encoder

Compute Command Encoder

Command Queue

Command Buffer Command Buffer

Page 95: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLCommandBuffer

Contains sets of commands to be executed by the GPUEnqueued on a command queue for schedulingTransient objects• Create one or more per frame• Not reusable; fire-and-forget

Page 96: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLCommandBuffer

// API

// Our command buffer is a container for the work we want to perform with the GPU.

let commandBuffer = commandQueue.commandBuffer()

Page 97: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Encoders

DeviceCommand Queue

Render Command Encoder

Render Command Encoder

Compute Command Encoder

Command Buffer Command Buffer

Page 98: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Encoders

DeviceCommand Queue

Render Command Encoder

Render Command Encoder

Compute Command Encoder

Command Buffer Command Buffer

Page 99: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Command Encoders

Translate API calls into work for the GPU Different encoders for different types of work• Render• Compute• Blit

Page 100: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLRenderCommandEncoder

Encodes the work of a single pass into a command buffer• State changes• Draw calls

Has a set of render target attachments

Page 101: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

A Single-Pass Frame

Present

Buffer

VertexFetch

Sampler

Texture

Buffer

Rasterization

Sampler

Texture

Buffer

Function Function

VertexProcessing

Fragment Processing

Depth Attachment

Color Attachments

FramebufferWrite

Page 102: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

A Single-Pass Frame

Present

Buffer

VertexFetch

Sampler

Texture

Buffer

Rasterization

Sampler

Texture

Buffer

Function Function

VertexProcessing

Fragment Processing

Depth Attachment

Color Attachments

FramebufferWrite

Page 103: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLTexture

Render Pass Descriptor

Pixel formatsBlend states

MTLRenderPassDescriptor

Pixel formatsBlend statesPixel formats

Blend statesColor AttachmentsLoad/Store Actions

Clear Color

Depth AttachmentLoad/Store Actions

Clear Depth

Stencil AttachmentLoad/Store Actions

Clear Value

MTLTexture

MTLTexture

Page 104: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

MTLRenderPassDescriptor

Contains a collection of render pass attachments• Color, depth, and stencil• Each refers to a texture to render into• Also specifies “load and store” actions

Page 105: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Load and Store Actions

Color

Depth

Page 106: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Load and Store Actions

Load Action

Color

Depth

Clear

Clear

Page 107: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Load and Store Actions

DrawLoad Action

Color

Depth

Clear

Clear

Page 108: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Load and Store Actions

DrawLoad Action Store Action

Color

Depth

Clear

Clear

Store

Don’t Care

?

Page 109: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Load and Store Actions

Determine how texture contents should be handled at start and end of passLoad Actions• Clear = Clear to specified clear color or clear value• Load = Load pixel contents with result of previous pass• Don’t Care

Store Actions• Store = Write result of rendering into texture• Don’t Care = Discard result of rendering

Page 110: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// MTLRenderCommandEncoder

// API

// Ask the view for a configured render pass descriptor (may block!)

let renderPassDescriptor = view.currentRenderPassDescriptor

// Create a render encoder to clear the screen and draw our objects

let renderEncoder = commandBuffer.renderCommandEncoder(with: renderPassDescriptor)

Page 111: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Argument Tables

Map from Metal resources to shader parametersOne table per resource or state object type• Buffer• Texture• Sampler

Maximum entry counts vary by device• Query them

texture(0) Texture Atexture(1) Texture Ctexture(2) null

… Texture Btexture(n-1) …

Texture Argument Table

buffer(0) Buffer Abuffer(1) Buffer Bbuffer(2) null

… …buffer(n-1) …

Buffer Argument Table

Page 112: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Binding Resources

renderEncoder.setVertexBuffer(vertexBuffer, offset:0, at:0)

Page 113: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Binding Resources

renderEncoder.setVertexBuffer(vertexBuffer, offset:0, at:0)

Argument table index

Page 114: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_passthrough(device VertexIn *vertices [[buffer(0)]],

uint vertexId [[vertex_id]])

{

...

} Argument table index

Page 115: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Setting the Pipeline State

// API

// Set the pipeline state so the GPU knows which vertex and fragment function to invoke.

renderEncoder.setRenderPipelineState(renderPipelineState)

Page 116: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_passthrough(device VertexIn *vertices [[buffer(0)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

out.position = vertices[vertexId].position;

out.color = vertices[vertexId].color;

return out;

}

Page 117: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_passthrough(VertexOut fragmentIn [[stage_in]])

{

return half4(fragmentIn.color);

}

Page 118: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Setting Additional State

// API

// Since we specified the vertices of our triangles in counter-clockwise

// order, we need to switch from the default of clockwise winding.

renderEncoder.setFrontFacing(.counterClockwise)

Page 119: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Draw Calls

Metal has numerous functions for drawing geometry• Indexed• Instanced• Indirect

We’ll just look at basic indexed drawing

Page 120: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Issuing Draw Calls

// Issue the draw call to draw the indexed geometry of the mesh

renderEncoder.drawIndexedPrimitives(.triangle,

indexCount: 3,

indexType: .uInt16,

indexBuffer: indexBuffer,

indexBufferOffset: 0)

Page 121: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Concluding a Pass

// We are finished with this render command encoder, so end it.

renderEncoder.endEncoding()

Page 122: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

RecapRender Command Encoder

Create or request render pass descriptorCreate a render command encoderSet a render pipeline stateSet any other necessary stateIssue draw callsEnd encoding

Page 123: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Create a render encoder to clear the screen and draw our objects let renderEncoder = commandBuffer.renderCommandEncoder(with: renderPassDescriptor)

// Since we specified the vertices of our triangles in counter-clockwise // order, we need to switch from the default of clockwise winding. renderEncoder.setFrontFacing(.counterClockwise)

// Set the pipeline state so the GPU knows which vertex and fragment function to invoke. renderEncoder.setRenderPipelineState(renderPipelineState)

// Bind the buffer containing the array of vertex structures so we can // read it in our vertex shader. renderEncoder.setVertexBuffer(vertexBuffer, offset:0, at:0)

// Issue the draw call to draw the indexed geometry of the mesh renderEncoder.drawIndexedPrimitives(.triangle, indexCount: 3, indexType: .uInt16, indexBuffer: indexBuffer, indexBufferOffset: 0)

Page 124: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Getting onto the Screen

The first color attachment of the render pass is usually a drawable’s textureA request to present to the screen can be added to a command bufferDrawable will be displayed once all preceding passes are complete

commandBuffer.present(drawable)

Page 125: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Finishing Up the Frame

Committing tells the driver the command buffer is ready to execute

// Now that we're done issuing commands, we commit our buffer so the GPU can get to work.

commandBuffer.commit()

Page 126: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

RecapCommand Submission

Create a command queue at startupEach frame, create a command bufferEncode one or more passes with render command encodersPresent drawable to screenCommit command buffer

Page 127: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

DemoDrawing 2D Content

Page 128: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 129: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

AgendaConceptual Overview

Creating a Metal Device

Loading Data

Metal Shading Language

Building Pipeline States

Issuing GPU Commands

Animation and Texturing

Managing Dynamic Data

CPU/GPU Synchronization

Multithreaded Encoding

Page 130: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Animation and Texturing in 3D

Moving into 3DAnimating with a constant buffer Texturing and sampling

Page 131: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Moving into 3D

Specify vertices in model-local space rather than clip spaceMultiply by a suitable model-view-projection matrixAdd properties for vertex normal and texture coordinates

Page 132: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Vertex Format

struct Vertex {

var position: float3

var normal: float3

var texCoords: float2

}

Page 133: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

+ ConstantBuffer Layout

Vertex Vertex Vertex

Index Index Index Index Index Index Index Index Index

Vertex Buffer

Index Buffer

Page 134: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

+ ConstantBuffer Layout

Vertex Vertex Vertex

Index Index Index Index Index Index Index Index Index

Constant Buffer Constant

Vertex Buffer

Index Buffer

Page 135: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Binding Small Constant Buffers

For small (< 4kB) pieces of dataMetal implicitly creates and manages buffersNo synchronization concerns

renderEncoder.setVertexBytes(&constants, length: strideof(ShaderConstants), at: 1)

Page 136: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Structure for Gathering Per-Frame Constants

struct Constants {

var modelViewProjectionMatrix = matrix_identity_float4x4

var normalMatrix = matrix_identity_float3x3

}

// Construct model-to-world, view, and projection matrices

...

// The combined MVP matrix moves our vertices from model space into clip space

let modelViewMatrix = matrix_multiply(viewMatrix, modelToWorldMatrix);

constants.modelViewProjectionMatrix = matrix_multiply(projectionMatrix, modelViewMatrix)

constants.normalMatrix = matrix_inverse_transpose(matrix_upper_left_3x3(modelViewMatrix))

// Bind the uniform buffer so we can read our model-view-projection matrix in the shader.

renderEncoder.setVertexBytes(&constants, length: strideof(ShaderConstants), at: 1)

Page 137: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Structure for Gathering Per-Frame Constants

struct Constants {

var modelViewProjectionMatrix = matrix_identity_float4x4

var normalMatrix = matrix_identity_float3x3

}

// Construct model-to-world, view, and projection matrices

...

// The combined MVP matrix moves our vertices from model space into clip space

let modelViewMatrix = matrix_multiply(viewMatrix, modelToWorldMatrix);

constants.modelViewProjectionMatrix = matrix_multiply(projectionMatrix, modelViewMatrix)

constants.normalMatrix = matrix_inverse_transpose(matrix_upper_left_3x3(modelViewMatrix))

// Bind the uniform buffer so we can read our model-view-projection matrix in the shader.

renderEncoder.setVertexBytes(&constants, length: strideof(ShaderConstants), at: 1)

Page 138: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Creating Buffers with Model I/O

Model I/O can generate common shapes• Box• Ellipsoid• Cylinder• Plane

Get MTLBuffer objects via MetalKit

Page 139: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

let allocator = MTKMeshBufferAllocator(device: device)

let mdlMesh = MDLMesh(boxWithExtent: vector_float3(1, 1, 1),

segments: vector_uint3(10, 10, 10),

inwardNormals: false,

geometryType: .triangles,

allocator: allocator)

Page 140: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

let allocator = MTKMeshBufferAllocator(device: device)

let mdlMesh = MDLMesh(boxWithExtent: vector_float3(1, 1, 1),

segments: vector_uint3(10, 10, 10),

inwardNormals: false,

geometryType: .triangles,

allocator: allocator)

Page 141: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

let allocator = MTKMeshBufferAllocator(device: device)

let mdlMesh = MDLMesh(boxWithExtent: vector_float3(1, 1, 1),

segments: vector_uint3(10, 10, 10),

inwardNormals: false,

geometryType: .triangles,

allocator: allocator)

Page 142: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Attempt to convert the Model I/O mesh to a MetalKit mesh

let mesh: MTKMesh = try MTKMesh(mesh: mdlMesh, device: device)

// Extract the vertex buffer for the whole mesh

let vertexBuffer: MTLBuffer = mesh.vertexBuffers[0].buffer

// Get a reference to the first submesh of the mesh

let submesh = mesh.submeshes[0]

// Extract the index buffer of the submesh

let indexBuffer: MTLBuffer = submesh.indexBuffer.buffer

// Get the primitive type of the mesh (triangle, triangle strip, etc.)

let primitiveType: MTLPrimitiveType = submesh.primitiveType

// Get the number of indices for this submesh

let indexCount: Int = submesh.indexCount

// Get the type of the indices (16-bit or 32-bit uints)

let indexType: MTLIndexType = submesh.indexType

Page 143: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Attempt to convert the Model I/O mesh to a MetalKit mesh

let mesh: MTKMesh = try MTKMesh(mesh: mdlMesh, device: device)

// Extract the vertex buffer for the whole mesh

let vertexBuffer: MTLBuffer = mesh.vertexBuffers[0].buffer

// Get a reference to the first submesh of the mesh

let submesh = mesh.submeshes[0]

// Extract the index buffer of the submesh

let indexBuffer: MTLBuffer = submesh.indexBuffer.buffer

// Get the primitive type of the mesh (triangle, triangle strip, etc.)

let primitiveType: MTLPrimitiveType = submesh.primitiveType

// Get the number of indices for this submesh

let indexCount: Int = submesh.indexCount

// Get the type of the indices (16-bit or 32-bit uints)

let indexType: MTLIndexType = submesh.indexType

Page 144: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Attempt to convert the Model I/O mesh to a MetalKit mesh

let mesh: MTKMesh = try MTKMesh(mesh: mdlMesh, device: device)

// Extract the vertex buffer for the whole mesh

let vertexBuffer: MTLBuffer = mesh.vertexBuffers[0].buffer

// Get a reference to the first submesh of the mesh

let submesh = mesh.submeshes[0]

// Extract the index buffer of the submesh

let indexBuffer: MTLBuffer = submesh.indexBuffer.buffer

// Get the primitive type of the mesh (triangle, triangle strip, etc.)

let primitiveType: MTLPrimitiveType = submesh.primitiveType

// Get the number of indices for this submesh

let indexCount: Int = submesh.indexCount

// Get the type of the indices (16-bit or 32-bit uints)

let indexType: MTLIndexType = submesh.indexType

Page 145: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Attempt to convert the Model I/O mesh to a MetalKit mesh

let mesh: MTKMesh = try MTKMesh(mesh: mdlMesh, device: device)

// Extract the vertex buffer for the whole mesh

let vertexBuffer: MTLBuffer = mesh.vertexBuffers[0].buffer

// Get a reference to the first submesh of the mesh

let submesh = mesh.submeshes[0]

// Extract the index buffer of the submesh

let indexBuffer: MTLBuffer = submesh.indexBuffer.buffer

// Get the primitive type of the mesh (triangle, triangle strip, etc.)

let primitiveType: MTLPrimitiveType = submesh.primitiveType

// Get the number of indices for this submesh

let indexCount: Int = submesh.indexCount

// Get the type of the indices (16-bit or 32-bit uints)

let indexType: MTLIndexType = submesh.indexType

Page 146: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Textures

Blocks of memory in a pre-selected pixel formatStore image data

Page 147: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Texture Descriptors

Parameter objects that gather texture properties• Texture type (2D, array, cube, etc.)• Size• Pixel format• Mipmap level count

Used by device to create MTLTextures

Page 148: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

let descriptor = MTLTextureDescriptor.texture2DDescriptor(with: .bgra8Unorm,

width: 256,

height: 256,

mipmapped: true)

let texture = device.newTexture(with: descriptor)

// Load with texture data and generate mipmaps

...

Page 149: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

let descriptor = MTLTextureDescriptor.texture2DDescriptor(with: .bgra8Unorm,

width: 256,

height: 256,

mipmapped: true)

let texture = device.newTexture(with: descriptor)

// Load with texture data and generate mipmaps

...

Page 150: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Easier texture creationMTKTextureLoader

Utility class provided by MetalKitLoad images from:• Asset catalogs• File URLs• Pre-existing CGImages

Generates and populates MTLTextures of appropriate size and format

Page 151: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Create a texture loader with a MTLDevice

let textureLoader = MTKTextureLoader(device: device)

// Fetch the asset from the asset catalog

let asset = NSDataAsset.init(name: "asset-name")

// Load and use the texture if we successfully retrieved the asset

if let data = asset?.data {

let texture = try textureLoader.newTexture(with: data, options: [:])

// ...

}

Page 152: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Create a texture loader with a MTLDevice

let textureLoader = MTKTextureLoader(device: device)

// Fetch the asset from the asset catalog

let asset = NSDataAsset.init(name: "asset-name")

// Load and use the texture if we successfully retrieved the asset

if let data = asset?.data {

let texture = try textureLoader.newTexture(with: data, options: [:])

// ...

}

Page 153: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Create a texture loader with a MTLDevice

let textureLoader = MTKTextureLoader(device: device)

// Fetch the asset from the asset catalog

let asset = NSDataAsset.init(name: "asset-name")

// Load and use the texture if we successfully retrieved the asset

if let data = asset?.data {

let texture = try textureLoader.newTexture(with: data, options: [:])

// ...

}

Page 154: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Create a texture loader with a MTLDevice

let textureLoader = MTKTextureLoader(device: device)

// Fetch the asset from the asset catalog

let asset = NSDataAsset.init(name: "asset-name")

// Load and use the texture if we successfully retrieved the asset

if let data = asset?.data {

let texture = try textureLoader.newTexture(with: data, options: [:])

// ...

}

Page 155: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Samplers

Contain state related to texture sampling• Filtering modes

- Nearest- Linear

• Address modes- Wrap- Clamp to edge- Clamp to zero

• LOD

Page 156: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Creating a Sampler Object

let samplerDescriptor = MTLSamplerDescriptor()

samplerDescriptor.sAddressMode = .repeat

samplerDescriptor.tAddressMode = .repeat

samplerDescriptor.minFilter = .nearest

samplerDescriptor.magFilter = .linear

let sampler = device.newSamplerState(with: samplerDescriptor)

Page 157: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Creating a Sampler Object

let samplerDescriptor = MTLSamplerDescriptor()

samplerDescriptor.sAddressMode = .repeat

samplerDescriptor.tAddressMode = .repeat

samplerDescriptor.minFilter = .nearest

samplerDescriptor.magFilter = .linear

let sampler = device.newSamplerState(with: samplerDescriptor)

Page 158: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Creating a Sampler Object

let samplerDescriptor = MTLSamplerDescriptor()

samplerDescriptor.sAddressMode = .repeat

samplerDescriptor.tAddressMode = .repeat

samplerDescriptor.minFilter = .nearest

samplerDescriptor.magFilter = .linear

let sampler = device.newSamplerState(with: samplerDescriptor)

Page 159: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Creating a Sampler Object

let samplerDescriptor = MTLSamplerDescriptor()

samplerDescriptor.sAddressMode = .repeat

samplerDescriptor.tAddressMode = .repeat

samplerDescriptor.minFilter = .nearest

samplerDescriptor.magFilter = .linear

let sampler = device.newSamplerState(with: samplerDescriptor)

Page 160: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

// Binding Textures and Samplers

// Bind our texture so we can sample from it in the fragment shader

renderEncoder.setFragmentTexture(texture, at: 0)

// Bind our sampler state so we can use it to sample the texture in the fragment shader

renderEncoder.setFragmentSamplerState(sampler, at: 0)

Page 161: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Vertex Function

Multiplies by the model-view-projection matrix from the constant bufferTransforms vertex positions from model-local space to clip spaceTransforms vertex normals from model-local space to eye space for lighting

Page 162: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(device VertexIn *vertices [[buffer(0)]],

constant Constants &uniforms [[buffer(1)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

// Multiplying the position by the model-view-projection matrix moves us into clip space

out.position = uniforms.modelViewProjectionMatrix * vertices[vertexId].position;

// Transform the vertex normal into eye space so we can use it for lighting

out.normal = uniforms.normalMatrix * vertices[vertexId].normal;

// Just copy the tex coords so they can be interpolated by the rasterizer

out.texCoords = vertices[vertexId].texCoords;

return out;

}

Page 163: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(device VertexIn *vertices [[buffer(0)]],

constant Constants &uniforms [[buffer(1)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

// Multiplying the position by the model-view-projection matrix moves us into clip space

out.position = uniforms.modelViewProjectionMatrix * vertices[vertexId].position;

// Transform the vertex normal into eye space so we can use it for lighting

out.normal = uniforms.normalMatrix * vertices[vertexId].normal;

// Just copy the tex coords so they can be interpolated by the rasterizer

out.texCoords = vertices[vertexId].texCoords;

return out;

}

Page 164: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(device VertexIn *vertices [[buffer(0)]],

constant Constants &uniforms [[buffer(1)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

// Multiplying the position by the model-view-projection matrix moves us into clip space

out.position = uniforms.modelViewProjectionMatrix * vertices[vertexId].position;

// Transform the vertex normal into eye space so we can use it for lighting

out.normal = uniforms.normalMatrix * vertices[vertexId].normal;

// Just copy the tex coords so they can be interpolated by the rasterizer

out.texCoords = vertices[vertexId].texCoords;

return out;

}

Page 165: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(device VertexIn *vertices [[buffer(0)]],

constant Constants &uniforms [[buffer(1)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

// Multiplying the position by the model-view-projection matrix moves us into clip space

out.position = uniforms.modelViewProjectionMatrix * vertices[vertexId].position;

// Transform the vertex normal into eye space so we can use it for lighting

out.normal = uniforms.normalMatrix * vertices[vertexId].normal;

// Just copy the tex coords so they can be interpolated by the rasterizer

out.texCoords = vertices[vertexId].texCoords;

return out;

}

Page 166: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

vertex VertexOut vertex_transform(device VertexIn *vertices [[buffer(0)]],

constant Constants &uniforms [[buffer(1)]],

uint vertexId [[vertex_id]])

{

VertexOut out;

// Multiplying the position by the model-view-projection matrix moves us into clip space

out.position = uniforms.modelViewProjectionMatrix * vertices[vertexId].position;

// Transform the vertex normal into eye space so we can use it for lighting

out.normal = uniforms.normalMatrix * vertices[vertexId].normal;

// Just copy the tex coords so they can be interpolated by the rasterizer

out.texCoords = vertices[vertexId].texCoords;

return out;

}

Page 167: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

The Fragment Function

Computes ambient and diffuse lightingSamples from texture to apply texture to surface

Page 168: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_lit_textured(VertexOut fragmentIn [[stage_in]],

texture2d<float, access::sample> tex2d [[texture(0)]],

sampler sampler2d [[sampler(0)]])

{

// Sample the texture to get the surface color at this point

half3 surfaceColor = half3(tex2d.sample(sampler2d, fragmentIn.texCoords).rgb);

// Re-normalize the interpolated surface normal

half3 normal = normalize(half3(fragmentIn.normal));

// Compute the ambient color contribution

half3 color = ambientLightIntensity * surfaceColor;

// Calculate the diffuse factor as the dot product of the normal and light direction

float diffuseFactor = saturate(dot(normal, -lightDirection));

// Add in the diffuse contribution from the light

color += diffuseFactor * diffuseLightIntensity * surfaceColor;

return half4(color, 1);

}

Page 169: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_lit_textured(VertexOut fragmentIn [[stage_in]],

texture2d<float, access::sample> tex2d [[texture(0)]],

sampler sampler2d [[sampler(0)]])

{

// Sample the texture to get the surface color at this point

half3 surfaceColor = half3(tex2d.sample(sampler2d, fragmentIn.texCoords).rgb);

// Re-normalize the interpolated surface normal

half3 normal = normalize(half3(fragmentIn.normal));

// Compute the ambient color contribution

half3 color = ambientLightIntensity * surfaceColor;

// Calculate the diffuse factor as the dot product of the normal and light direction

float diffuseFactor = saturate(dot(normal, -lightDirection));

// Add in the diffuse contribution from the light

color += diffuseFactor * diffuseLightIntensity * surfaceColor;

return half4(color, 1);

}

Page 170: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_lit_textured(VertexOut fragmentIn [[stage_in]],

texture2d<float, access::sample> tex2d [[texture(0)]],

sampler sampler2d [[sampler(0)]])

{

// Sample the texture to get the surface color at this point

half3 surfaceColor = half3(tex2d.sample(sampler2d, fragmentIn.texCoords).rgb);

// Re-normalize the interpolated surface normal

half3 normal = normalize(half3(fragmentIn.normal));

// Compute the ambient color contribution

half3 color = ambientLightIntensity * surfaceColor;

// Calculate the diffuse factor as the dot product of the normal and light direction

float diffuseFactor = saturate(dot(normal, -lightDirection));

// Add in the diffuse contribution from the light

color += diffuseFactor * diffuseLightIntensity * surfaceColor;

return half4(color, 1);

}

Page 171: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_lit_textured(VertexOut fragmentIn [[stage_in]],

texture2d<float, access::sample> tex2d [[texture(0)]],

sampler sampler2d [[sampler(0)]])

{

// Sample the texture to get the surface color at this point

half3 surfaceColor = half3(tex2d.sample(sampler2d, fragmentIn.texCoords).rgb);

// Re-normalize the interpolated surface normal

half3 normal = normalize(half3(fragmentIn.normal));

// Compute the ambient color contribution

half3 color = ambientLightIntensity * surfaceColor;

// Calculate the diffuse factor as the dot product of the normal and light direction

float diffuseFactor = saturate(dot(normal, -lightDirection));

// Add in the diffuse contribution from the light

color += diffuseFactor * diffuseLightIntensity * surfaceColor;

return half4(color, 1);

}

Page 172: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

fragment half4 fragment_lit_textured(VertexOut fragmentIn [[stage_in]],

texture2d<float, access::sample> tex2d [[texture(0)]],

sampler sampler2d [[sampler(0)]])

{

// Sample the texture to get the surface color at this point

half3 surfaceColor = half3(tex2d.sample(sampler2d, fragmentIn.texCoords).rgb);

// Re-normalize the interpolated surface normal

half3 normal = normalize(half3(fragmentIn.normal));

// Compute the ambient color contribution

half3 color = ambientLightIntensity * surfaceColor;

// Calculate the diffuse factor as the dot product of the normal and light direction

float diffuseFactor = saturate(dot(normal, -lightDirection));

// Add in the diffuse contribution from the light

color += diffuseFactor * diffuseLightIntensity * surfaceColor;

return half4(color, 1);

}

Page 173: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

DemoDrawing 3D textured content

Page 174: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Summary

Metal is a powerful, low-overhead GPU programming technologyDoing expensive work up front saves time where it matters mostExplicit memory management and command submission let you work smarter

Page 175: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

More Information

https://developer.apple.com/wwdc16/602

Page 176: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Related Sessions

Adopting Metal, Part 2 Nob Hill Tuesday 3:00PM

What’s New in Metal, Part 1 Pacific Heights Wednesday 11:00AM

What’s New in Metal, Part 2 Pacific Heights Wednesday 1:40PM

Advanced Metal Shader Optimization Pacific Heights Wednesday 3:00PM

Page 177: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high

Labs

Metal Lab Graphics, Games, and Media Lab A Tuesday 4:00PM

Metal Lab Graphics, Games, and Media Lab A Thursday 12:00PM

Page 178: Adopting Metal, Part 1 - Apple Inc. · Building Pipeline States Issuing GPU Commands Animation and Texturing Managing Dynamic Data ... (OS X, iOS, tvOS) …when implicit has a high