Elements to know:
MTLDevice: The software reference to the GPU hardware device
MTLCommandQueue: Responsible for creating and organizing MTLCommandBuffers for each frame
MTLLibrary: Contains the source code from your vertex and fragment shader functions
MTLRenderPipelineState: Sets the information for the draw, such as which shader functions to use, what depth and color settings to use and how to read the vertex data
MTLBuffer: Holds data such as vertext information in a form that you can send to the GPU
####(Typically) only one per app instance: - MTLDevice - MTLCommandQueue - MTLLibrary
Typically on iOS there is only one available GPU. When creating a new MTLDevice via MTLCreateSystemDefaultDevice() you are returning the defaults. However, there is a possiblity that your hardware host device will have multiple (either future iOS hardware, or MacOS), in which case you would want to get a list of available GPU by quering MTLCopyAllDevices().
MTLCommandQueues hold MTLCommandBuffers, this allows the CPU to line up instructions (buffers) into the command queue which hold it in sequential order.
MTLLibrary is the result of compiled .metal files. These .metal files are writen in Metal Shading Language (MSL) which is C-ish looking. Part of the reason Metal is performant is because this compiling is done during app building or initialization of the app.
####Things that are created frequently: - MTLRenderPipelineState - MTLBuffer
MTLRenderPipelineStates are created on a semi-frequently basis, and in some case you create multiple. You may create one for depthRenderPipelineState where you describe the information to draw, shader functions, settings (depth and color) and how to read vertex data.
MTLBuffers are used to hold the specific vertex data. This information is then queued into the MTLCommandQueue.