Swift code generator for Metal encoding code. This tool enables bugs-free, rapid shader-driven development, reduces your GPU codebase by at least a factor of two and prevents any encoding bugs (i.e. wrong resources indexes, shader names etc)
Currently, mtlswift supports two execution commands:
mtlswift generate ...This command generates encoders from provided shaders and stops execution.mtlswift watch ...This command makes mtlswift subscribe to the files changes of provided shaders and continuously update the result.
The user is able to provide multiple paths to the shaders files or folders containing them, for example:
mtlswift watch ../shaders_folder/ ../../another_shaders_folder/Shaders.metalWARNING: This tool currently generates encoders for
Alloysyntax. We will probably support vanilla Metal code in the future.
List of currently supported arguments:
-
--output ...,-oThis argument specifies the output file path. If multiple inputs are provided, the encoders file will contain concatenated result. -
--ignore ...,-iThe user is able to specify folder or a file to be ignored. This argument might be passed multiple times, for example:mtlswift watch . -i shaders_to_ignore.metal -i folder_to_ignore/ -
--recursive,-rThis flag enables recursive search for.metalfiles in provided folders.
To support encoders generation first of all you need to add namespace mtlswift {} at the beginning of the file.
#include <metal_stdlib>
using namespace metal;
namespace mtlswift {}Every custom annotation starts with mtlswift:. The program uses this declaration prefix to identify the start of a declaration. It must be written in a doc string way right before the kernel.
/// mtlswift: ...
kernel void exampleKernel(...-
dispatch:A dispatch type to use. All of dispatch types has to be followed by either constant amount of threads via literals (like
X, Y, Z), specifying a target texture to cover viaover:argument or stating that amount of threads will be provided by user by usingprovided. You can see all of the examples into each section, but you can choose the combination yourself.-
evenDispatch threadgroups of a uniform threadgroup size.
Width,heightanddepthdescribe the grid size./// mtlswift:dispatch:even:1024, 768, 1 kernel void exampleKernel(texture2d<half, access::read_write> inPlaceTexture [[ texture(0) ]], ...
-
exactDispatch threads with threadgroups of non-uniform size.
/// mtlswift:dispatch:exact:over:inPlaceTexture kernel void exampleKernel(texture2d<half, access::read_write> inPlaceTexture [[ texture(0) ]], ...
-
optimal(function_constant_index)Uses
exacttype if GPU supports non uniform threadgroup size andoverif it doesn't. This declaration requires a boolean function constant index to be passed to make the decision what dispatch type to use.constant bool deviceSupportsNonuniformThreadgroups [[function_constant(0)]]; /// mtlswift:dispatch:optimal(0):provided kernel void exampleKernel(texture2d<half, access::read> sourceTexture [[ texture(0) ]], ...
-
noneThe dispatch type set by default. In this case user has to dispatch kernel manually, after calling
encodemethod
-
-
threadgroupSize:Specify the threadgroup size.
-
X, Y, ZAllows to specify constant X, Y and Z dimensions for threadgroup size.
-
maxThis parameter sets the pipeline state's
max2dThreadgroupSize. -
executionWidthThis parameter sets the pipeline state's
executionWidthThreadgroupSize. -
providedIn this case user has to pass the threadgroup size and an argument to
encode(...function.
/// mtlswift:threadgroupSize:provided kernel void exampleKernel(texture2d<half, access::read> sourceTexture [[ texture(0) ]], ...
-
-
swiftParameterType:The type of the buffers passed to the kernel.
/// mtlswift:swiftParameterType:offset:vector_ushort2 /// mtlswift:swiftParameterType:intensities:vector_float3 kernel void exampleKernel(constant ushort2& offset [[ buffer(0) ]], constant float3& intensities [[buffer(1)]], ...
-
swiftParameterName:The name of the buffers passed to the kernel.
/// mtlswift:swiftParameterName:intensities:parameters kernel void exampleKernel(constant ushort2& offset [[ buffer(0) ]], constant float3& intensities [[buffer(1)]], ...
-
swiftName:Encoder's name in generated Swift code. Must be followed by a valid Swift identifier.
-
accessLevel:Specifies the access visibility of the encoder. Must be followed by either
public,open,internal,privateorfileprivate.internalis the default.
- @eugenebokhan is responsible for nice CLI that this tool has and also for docs that can guide you around
MIT