Read the notes of the Apple document and show it to yourself.
Primary goal of Metal is to minimize the CPU overhead incurred by executing GPU workloads.
Used in two ways:
- Graphics
- Data-parallel computation
The Metal APP cannot run in the background or it will be terminated.
Command Organization and execution Model
?
- Mtldevice is the modeling of GPUs.
- Command queue, which consists of several command buffer queues, and is responsible for the order in which these command buffer is executed.
- Command buffer, which contains the encoded commands (instructions to be executed on the device).
- Command Encoder, add the commands to the order buffer.
Transient and Non-transient Objects in Metal
Command buffer and command Encoder are lightweight and designed for single use.
The following creation is more resource-intensive and should be reused.
- Command queues
- Data buffers
- Textures
- Sampler states
- Libraries
- Compute states
- Render Pipeline states
- Depth/stencil states
Registering Handler Blocks for Command Buffer execution
The methods in the block may be called on any thread and should not be time-consuming.
- Addscheduledhandler:
- Waituntilscheduled:
- Addcompletedhandler:
- waituntilcompleted
Resource Objects:buffers and Textures
MTLBuffer
There are two types.
MTLBuffer
: Unformatted (unformatted) memory that can represent any type of data.
MTLTexture
: Image data with Format (formatted).
Buffers is typeless allocations of Memory
contents
method returns the CPU memory address of buffer.
newTextureWithDescriptor:offset:bytesPerRow:
The texture method creates an object that points to the data in buffer.
Textures is formatted Image Data
can have the following structure
- A 1 D, 3D
- An array of 1D or 2D images
- A Cube of six 2D images
Creating a Texture Object
- Newtexturewithdescriptor:
For MTLDevice
calls, MTLTexture
objects are created and storage spaces are allocated. Use MTLTextureDescriptor
to describe the nature of the texture.
- Newtextureviewwithpixelformat:
MTLTexture
a shared memory address for the call, return MTLTexture
object, and original texture. The new texture interprets the original texture data in a new pixel format.
- NewTextureWithDescriptor:offset:bytesPerRow:
On the MTLBuffer
call, return the MTLTexture
object, and the original buffer shared memory address.
Use Texture descriptor to create texture objects
MTLTextureDescriptor
Defines the nature of the texture, just to create a texture object. After you create a texture object, there is no effect on its modification.
MTLTextureDescriptor* txDesc = [[MTLTextureDescriptor alloc] init]; txDesc.textureType = MTLTextureType3D; txDesc.height = 64; txDesc.width = 64; txDesc.depth = 64; txDesc.pixelFormat = MTLPixelFormatBGRA8Unorm; txDesc.arrayLength = 1; txDesc.mipmapLevelCount = 1; id <MTLTexture> aTexture = [device newTextureWithDescriptor:txDesc];
Copying Image Data to and from a Texture
- Writing data to Textures
- ReplaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:
- ReplaceRegion:mipmapLevel:withBytes:bytesPerRow:
- Read the data out of the texture
- GetBytes:bytesPerRow:bytesPerImage:fromRegion:mipmapLevel:slice:
- GetBytes:bytesPerRow:fromRegion:mipmapLevel:
Examples are as follows:
// pixelSize is the size of one pixel, in bytes// width, height - number of pixels in each dimensionNSUInteger myRowBytes = width * pixelSize;NSUInteger myImageBytes = rowBytes * height;[tex replaceRegion:MTLRegionMake2D(0,0,width,height) mipmapLevel:0 slice:0 withBytes:textureData bytesPerRow:myRowBytes bytesPerImage:myImageBytes];
Pixel Formats for Textures
There are three types of pixels:
- Ordinary formats
- Packed formats
- Compressed formats
Creating a Sampler states Object for Texture Lookup
- Creating
MTLSamplerDescriptor
Objects
- Setting the nature of an object
- Creates an
MTLSamplerState
object.
MTLSamplerState
object is used only to create MTLSamplerState
objects. Once created, modifications to it do not affect objects that have already been created MTLSamplerState
.
// create MTLSamplerDescriptorMTLSamplerDescriptor *desc = [[MTLSamplerDescriptor alloc] init];desc.minFilter = MTLSamplerMinMagFilterLinear;desc.magFilter = MTLSamplerMinMagFilterLinear;desc.sAddressMode = MTLSamplerAddressModeRepeat;desc.tAddressMode = MTLSamplerAddressModeRepeat;// all properties below have default valuesdesc.mipFilter = MTLSamplerMipFilterNotMipmapped;desc.maxAnisotropy = 1U;desc.normalizedCoords = YES;desc.lodMinClamp = 0.0f;desc.lodMaxClamp = FLT_MAX;// create MTLSamplerStateid <MTLSamplerState> sampler = [device newSamplerStateWithDescriptor:desc];
Maintaining coherency between CPU and GPU Memory
Both the CPU and the GPU can access the MTLResource
object.
The GPU can only record changes to the MTLCommandBuffer
commit
CPU pair before the method call MTLResource
.
The CPU MTLCommandBuffer
can only see changes to the GPU pair after it has been instructed in the GPU to complete MTLResource
.
Functions and librariesmtlfunction represents a Shader or Compute Function
Only vertex
fragment
functions that are, or modified, kernel
can be represented as MTLFunction
.
A Library is a Repository of Functions
MTLFunction
There can be two sources in the Library:
- Binary Metal Shading Language code compiled in build phase
- String containing Metal Shading language source code, compiled at run time
Creating a Library from Compiled Code
You can improve efficiency without having to compile the source code at run time.
Can be obtained by the following methods MTLLibrary
.
- Newdefaultlibrary
- Newlibrarywithfile:error:
- Newlibrarywithdata:error:
Creating a Library from Source Code
- NewLibraryWithSource:options:error: Synchronization method
- NewLibraryWithSource:options:completionHandler: Async method
Graphics Rendering:render Command Encoder
?
Creating a Render Pass descriptor
MTLRenderPassDescriptor
Represents the destination of the encoded rendering commands (destination). MTLRenderPassDescriptor
the properties can include up to 4 colors of attachments, a pixel depth data of attachment, a pixel stencil the attachment of the data.
Load and Store Actions
Specifies the action at the beginning and end of the rendering pass.
loadAction
Including:
- Mtlloadactionclear writes the specified value for each pixel.
- Mtlloadactionload Saving existing values
- The mtlloadactiondontcare can have any value at the starting stage and has the highest performance.
Storeaction includes
- Mtlstoreactionstore Save the last pixel value, the default value of color attachments
- Mtlstoreactionmultisampleresolve
- Mtlstoreactiondontcare will improve performance. The default value for depth and stencil attachments.
An example is as follows:
Mtltexturedescriptor *colortexdesc = [Mtltexturedescriptor Texture2ddescriptorwithpixelformat:mtlpixelformatrgba 8Unorm width:image_width height:image_height mipmapped:no];id <MTLTexture> Colortex = [Device Newtexturewi THDESCRIPTOR:COLORTEXDESC]; Mtltexturedescriptor *depthtexdesc = [Mtltexturedescriptor texture2ddescriptorwithpixelformat:mtlpixelformatdept H32float width:image_width height:image_height mipmapped:no];id <MTLTexture> Depthtex = [Device newtexture WITHDESCRIPTOR:DEPTHTEXDESC]; Mtlrenderpassdescriptor *renderpassdesc = [Mtlrenderpassdescriptor renderpassdescriptor]; Renderpassdesc.colorattachments[0].texture = Colortex;renderpassdesc.colorattachments[0].loadaction = Mtlloadactionclear;renderpassdesc.colorattachments[0].storeaction = Mtlstoreactionstore; Renderpassdesc.colorattachments[0].clearcolor = Mtlclearcolormake (0.0,1.0,0.0,1.0); RenderPassDesc.depthAttachment.texture = Depthtex;renderpassdesc.depthattachment.loadaction =Mtlloadactionclear;renderpassdesc.depthattachment.storeaction = Mtlstoreactionstore; RenderPassDesc.depthAttachment.clearDepth = 1.0;
Using the render Pass descriptor to Create a render Command Encoder
id <MTLRenderCommandEncoder> renderCE = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDesc];
Displaying Rendered Content with Core Animation
Use CAMetalLayer
.
Creating a Render Pipeline state
MTLRenderPipelineState
The object life cycle is long and should be cached for reuse.
MTLRenderPipelineState
The object is immutable. First create one MTLRenderPipelineDescriptor
, set the properties, and then create MTLRenderPipelineState
.
?
Examples are as follows:
MTLRenderPipelineDescriptor *renderPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];renderPipelineDesc.vertexFunction = vertFunc;renderPipelineDesc.fragmentFunction = fragFunc;renderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;// Create MTLRenderPipelineState from MTLRenderPipelineDescriptorNSError *errors = nil;id <MTLRenderPipelineState> pipeline = [device newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors];assert(pipeline && !errors);// Set the pipeline state for MTLRenderCommandEncoder[renderCE setRenderPipelineState:pipeline];
Specifying Resources for a Render Command Encoder
?
Calls setVertex*
and setVertex*
methods.
Drawing Geometric Primitives
Invokes a draw*
method.
Ending a Rendering Pass
Calling endEncoding
methods
Metal Programming Guide