## Overview
<img src="https://upload.wikimedia.org/wikipedia/commons/8/87/Apple_Metal_logo%2C_version_2.png" align="right" width="100" height="100" />
In 2014 apple decided to go against the flow yet again, instead of continuing to support opengl and embrace the new world of vulken, they decided on implementing their own graphics/compute API. This API is known as Metal.
$\quad$While being in direct competition now with DirectX12(Microsoft) and Vulkan(KhronosGroup), Apple have been able to implement an impressive API that supports modern rendering techniques, and that performs in a similar capacity.
$\quad$It is interesting to note **that both OpenGL and Vulkan are indirectly supported on Apple chips**, Vulkan is done so through [MoltenVK](https://github.com/KhronosGroup/MoltenVK). MoltenVK is portability implementation, and converts Vulkan API calls to Metal API calls.
## Prerequisites
There are really two requirements in order to start writing applications using Metal...
* An Apple machine(as of writing Ipads aren't supported dev-environments)
* Latest version of XCode
## Using Metal for Graphics
#todo
> [!info]
> I have no experience in using metal for graphics, this section will be updated in the future when I get round to it...
>
## Using Metal for Compute
Metal not only supports graphical operations but also compute operations. Implementing your own compute pipeline is in fact a lot simpler than I first thought it was.
$\quad$There are a lot of similarities between Metal and the other API's. Basically, in order to trigger a workload you need to allocate a `commandBuffer` from a `commandQueue`. The allocated `commandBuffer` is then used to allocate a related `commandEncoder`. It is then the responsibility of the *encoder* to bind the resources etc, the *encoder* in this case is similar to a Vulkan `commandBuffer`.
$\quad$In order to execute the compute program we need to end the encoding and call `commandBuffer.commit()`.
I followed the youtube tutorial below in setting up and understanding how to get things going.
<iframe width="560" height="315" src="https://www.youtube.com/embed/VQK28rRK6OU?si=GeAaIviqwuSHlFE_" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
### The Compute Shader
To define a compute shader, create a `.metal` file and within it, depending on what it is used for you will either define the *main* as a `kernel`, `vertex`, `fragment`. In the tutorial above we write the following code:
``` c
kernel void additionCompute(constant float *arr0 [[ buffer(0) ]],
constant float *arr1 [[ buffer(1) ]],
device float *resultArr [[ buffer(2) ]],
uint index [[ thread_position_in_grid ]]) {
resultArr[index] = arr0[index] + arr1[index];
}
```
$\quad$Shaders are then during build time compiled in XCode. The compiled shaders are then loaded into a library, and after which we are able to fetch the function *"pointer"* and use it to create a pipeline. See code below:
``` swift
let device = MTLCreateSystemDefaultDevice()!
let commandQueue = device.makeCommandQueue()!
let lib = device.makeDefaultLibrary()!
let subtractFunction = lib.makeFunction(name: "subtractCompute")!
```
$\quad$*Note: because the compiled shaders are loaded into a library, we are able to store multiple shader functions in one .metal file. As seen below!*
``` C
kernel void additionCompute(constant float *arr0 [[ buffer(0) ]],
constant float *arr1 [[ buffer(1) ]],
device float *resultArr [[ buffer(2) ]],
uint index [[ thread_position_in_grid ]]) {
resultArr[index] = arr0[index] + arr1[index];
}
kernel void subtractCompute(constant float *arr0 [[ buffer(0) ]],
constant float *arr1 [[ buffer(1) ]],
device float *resultArr [[ buffer(2) ]],
uint index [[ thread_position_in_grid ]]) {
resultArr[index] = arr0[index] - arr1[index];
}
```
#### Interesting Shader tools:
* `function constants`: For more info read [[Function Constants and Übershaders]]
## Resources
If you are interested in using Metal there are some resources that I could recommend
* [Apple Documentation](https://developer.apple.com/metal/)
### GetIntoGameDev
I regularly come back to *GetIntoGameDev*. He's is very thorough with explaining what is going on, and you can simply follow along with his implementatioon.
<iframe width="560" height="315" src="https://www.youtube.com/embed/JjfIKllh6B8?si=sEXpp0ugxM4Hi7jH" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
### 2etime
He seems to have stopped making youtube videos but he does have a series where he writes basic renderer using `swift` <iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?si=FQ3BbB4_kQ8SfNun&list=PLEXt1-oJUa4BVgjZt9tK2MhV_DW7PVDsg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>