52

Metal

Embed Size (px)

Citation preview

Page 1: Metal
Page 2: Metal

Nilson Soutoxissburg

Venha bater um papo com a galera no IRC @ freenode ;)

#iphonedev #iphonedev-chat

#swift-lang ##OpenGL

Page 3: Metal

Metal?• API gráfica de baixo nível que apresenta uma

abstração muito próxima à arquitetura das GPUs

• “bare metal access”

• “close to the metal”

• Substitui o OpenGL ES

• Camada mais fina entre o software e o hardware

Page 4: Metal

Metal?• Outras tecnologias semelhantes:

• AMD Mantle

• Microsoft DirectX 12

• OpenGL Next

• A ideia é produzir APIs diretamente compatíveis com as arquiteturas das GPUs modernas

• Descartar APIs criadas há mais de 20 anos

Page 5: Metal

Conceitos• Device

• Command Queue

• Command Buffer

• Command Encoder

• Buffers

• Textures

• Functions

• Pipeline

Page 6: Metal

Device

• Representa a GPU

• Funciona como uma factory para criar command queues, buffers, texturas, etc

• Utilizamos a função MTLCreateSystemDefaultDevice para criar uma instância

Page 7: Metal

Command Queue

• Fila de comandos a serem executados pela GPU

• Através dela podemos criar command buffers, depois configurá-los e por fim submetê-los para execução

Page 8: Metal

Command Buffer• Armazena comandos para serem executados pela

GPU

• Em geral, utilizamos um command buffer para desenhar um frame de uma animação

• Possível enfileirar mais que um comando para fazer uma renderização em múltiplos passos

• Podemos ser notificados através de blocos quando o comando terminar sua execução

Page 9: Metal

Command Encoder• Configura um comando para um command buffer

• Podemos criar 4 tipos de comandos:

• Render: um passo de renderização, para desenhar algo na tela ou numa textura

• Compute: permite usar a GPU para fazer cálculos de propósito geral (GPGPU)

• Blit: operações de cópia de memória entre buffers e texturas

• Parallel: permite codificar vários comandos em múltiplas threads

Page 10: Metal

Buffer• Representa um buffer de memória que pode ser

usado pela GPU

• Pode conter qualquer coisa

• Por exemplo, utilizamos buffers para armazenar vértices (vertex buffers) que formam os triângulos que queremos desenhar, matrizes de transformação, e dados de iluminação

Page 11: Metal

Texture

• Representa uma imagem que pode ser utilizada pela GPU

• Pode ser usada para desenhar o conteúdo da imagem na tela ou como destino para o resultado de uma renderização (render to target)

• Pode ter uma, duas ou três dimensões

Page 12: Metal

Function• Representa um shader

• Vertex shader

• Fragment shader

• Compute kernel

• Função que é executada diretamente na GPU (programmable pipeline)

• Deve ser escrita usando a Metal Shading Language, linguagem baseada no C++11

Page 13: Metal

Pipeline• Configura as partes fixas do pipeline gráfico, e.g.

blending e antialiasing

• Especifica quais functions devem ser usadas

• Descreve o formato de dados dos vértices

• Um command encoder deve especificar o pipeline que deve ser utilizado em sua execução

Page 14: Metal

Pipeline

Page 15: Metal

Metal Objects

Page 16: Metal

Criando um Projeto• Single View Application

Page 17: Metal

Criando um Projeto• Adicionar frameworks

Page 18: Metal

Criando um Projeto• Metal.framework e QuartzCore.framework

Page 19: Metal

Criando um Projeto• Criar um shader (Metal File)

Page 20: Metal

Codificando…• Renomeie o arquivo ViewController.m para

ViewController.mm para que o compilador o interprete como um arquivo do tipo Objective-C++

• Assim podemos utilizar o simd.h que possui definições de tipos de dados vetoriais como float2, float3, float4, float3x3…

• Bastante útil para declarar a estrutura de dados dos vértices e fazer cálculos comuns em computação gráfica

Page 21: Metal

Codificando…

• Imports no ViewController.mm:!

#import "ViewController.h" !#import <Metal/Metal.h> #import <QuartzCore/CAMetalLayer.h> #import <simd/simd.h>

Page 22: Metal

Codificando…

• Cada um dos nossos 3 vértices devem ter uma posição (x, y) e uma cor (r, g, b, a)

!typedef struct { simd::float2 position; simd::float4 color; } Vertex;

Page 23: Metal

Codificando…• Nossas properties!@interface ViewController () !@property (nonatomic, strong) id<MTLDevice> device; @property (nonatomic, strong) id<MTLBuffer> vertexBuffer; @property (nonatomic, strong) id<MTLRenderPipelineState> pipeline; @property (nonatomic, strong) id<MTLCommandQueue> commandQueue; @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, strong) CAMetalLayer *metalLayer; !@end

Page 24: Metal

Codificando…

• O CADisplayLink é utilizado para chamar nosso método de desenho várias vezes por segundo

• O CAMetalLayer é um CALayer capaz de apresentar o conteúdo desenhado pela GPU na tela do dispositivo

Page 25: Metal

Codificando…• Criando o device e o metalLayer no viewDidLoad

self.device = MTLCreateSystemDefaultDevice(); !self.metalLayer = [CAMetalLayer layer];!

self.metalLayer.device = self.device;!

self.metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;!

self.metalLayer.framebufferOnly = YES;!

self.metalLayer.frame = self.view.bounds;!

[self.view.layer addSublayer:self.metalLayer];

Page 26: Metal

Codificando…• Criando o vertexBuffer

Vertex vertices[3]; vertices[0].position = { 0, 0.5}; vertices[0].color = {1, 0, 0, 1}; vertices[1].position = {-0.5, -0.5}; vertices[1].color = {0, 1, 0, 1}; vertices[2].position = { 0.5, -0.5}; vertices[2].color = {0, 0, 1, 1}; !self.vertexBuffer = [self.device newBufferWithBytes:vertices length:sizeof(vertices) options:0];

Page 27: Metal

Codificando…• Sistema de coordenadas

Page 28: Metal

Codificando…• Descrevendo a estrutura dos vértices

MTLVertexDescriptor *vertexDescriptor = [[MTLVertexDescriptor alloc] init]; [vertexDescriptor.attributes objectAtIndexedSubscript:0].format = MTLVertexFormatFloat2; [vertexDescriptor.attributes objectAtIndexedSubscript:0].bufferIndex = 0; [vertexDescriptor.attributes objectAtIndexedSubscript:0].offset = offsetof(Vertex, position); [vertexDescriptor.attributes objectAtIndexedSubscript:1].format = MTLVertexFormatFloat4; [vertexDescriptor.attributes objectAtIndexedSubscript:1].bufferIndex = 0; [vertexDescriptor.attributes objectAtIndexedSubscript:1].offset = offsetof(Vertex, color);

Page 29: Metal

Codificando…

• Obtendo referências para as funções do nosso shader

id<MTLLibrary> library = [self.device newDefaultLibrary]; id<MTLFunction> vertexFunction = [library newFunctionWithName:@"basic_vertex"]; id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"basic_fragment"];

Page 30: Metal

Codificando…• Criar o pipeline gráfico

MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; pipelineDescriptor.vertexDescriptor = vertexDescriptor; pipelineDescriptor.vertexFunction = vertexFunction; pipelineDescriptor.fragmentFunction = fragmentFunction; [pipelineDescriptor.colorAttachments objectAtIndexedSubscript:0].pixelFormat = self.metalLayer.pixelFormat; self.pipeline = [self.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];

Page 31: Metal

Codificando…

• Command queue e display link

self.commandQueue = [self.device newCommandQueue];

!self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

Page 32: Metal

Codificando…• Agora é só renderizar…

• Em nosso método render, primeiro obtemos o drawable do nosso layer que servirá como alvo da renderização

- (void)render { id<CAMetalDrawable> drawable = [self.metalLayer nextDrawable];

Page 33: Metal

Codificando…• Configuramos um render pass descriptor que será

usado para criar um command encoder

MTLRenderPassDescriptor *renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init]; MTLRenderPassColorAttachmentDescriptor *colorAttachment = [renderPassDescriptor.colorAttachments objectAtIndexedSubscript:0]; colorAttachment.texture = drawable.texture; colorAttachment.loadAction = MTLLoadActionClear; colorAttachment.clearColor = MTLClearColorMake(0, 0.4, 0.02, 1);

Page 34: Metal

Codificando…

• Criamos um command buffer e em seguida um command encoder…

id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer]; id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

Page 35: Metal

Codificando…• Configuramos o command encoder

[commandEncoder setRenderPipelineState:self.pipeline]; [commandEncoder setVertexBuffer:self.vertexBuffer offset:0 atIndex:0]; [commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; [commandEncoder endEncoding];

Page 36: Metal

Codificando…

• E finalizamos submetendo o command buffer para execução

[commandBuffer presentDrawable:drawable]; [commandBuffer commit];

Page 37: Metal

Codificando…• Mas ainda faltam os shaders!

#include <metal_stdlib> using namespace metal; !struct VertexInput { float2 position [[attribute(0)]]; float4 color [[attribute(1)]]; }; !struct VertexOutput { float4 position [[position]]; float4 color; };

Page 38: Metal

Codificando…

• Vertex shader

vertex VertexOutput basic_vertex(VertexInput in [[stage_in]]) { VertexOutput out; out.position = float4(in.position, 0, 1); out.color = in.color; return out; }

Page 39: Metal

Codificando…

• Fragment shader

fragment float4 basic_fragment(VertexOutput in [[stage_in]]) { return in.color; }

Page 40: Metal

Codificando…• Pronto!

Page 41: Metal

Ferramentas• O Xcode 6 possui poderosas ferramentas de

debugging para o Metal

• Permite capturar um frame da app e analisar cada buffer, textura, comando, etc

• Facilita encontrar o que pode estar causando problemas obscuros como obter uma tela vazia após desenhar vários objetos

Page 42: Metal

Ferramentas

Page 43: Metal

Ferramentas

Page 44: Metal

Projeto exemplo• https://github.com/xissburg/MetalExamples

Page 45: Metal

Compatibilidade

• iOS 8 em diante

• Não funciona no simulador

Page 46: Metal

Compatibilidade

Page 47: Metal

Compatibilidade

Page 48: Metal

Compatibilidade

Page 49: Metal

Conclusões• O Metal apresenta uma API concisa e

relativamente fácil de usar

• Permite maior controle sobre a GPU

• Maior performance, low-overhead

• Compatibilidade ainda limitada

• Dificulta desenvolvimento cross-platform

Page 51: Metal

Referências

• Things that drive me nuts about OpenGL - Rich Geldreich's Tech Blog

• OpenGL 4.5 released, next-gen OpenGL unveiled: Cross-platform Mantle killer, DX12 competitor

Page 52: Metal

Obrigado pela atenção!

• Dúvidas?

• Sugestões?

• Comentários?