-
Notifications
You must be signed in to change notification settings - Fork 0
Inner Workings
Aluminum uses a Parser
object to iterate through provided type tree until it reaches the leafs.
The iterated objects are wrapped in an associated enum that provides easy access to children:
enum MetalType: Hashable {
case argument(MTLArgument)
case array(MTLArrayType)
case `struct`(MTLStructType)
case pointer(MTLPointerType)
case structMember(MTLStructMember)
}
where each case is a different Metal reflection object.
Once parser reaches the leafs the entire path is iterated with a DataTypeIterator
.
This is an iterator that internally uses an array of DataTypeRecognizer
in order to identify different types of Metal structures to allow correct binding.
The DataType
is much easier to work with since each case is a single item (composed of several MetalType
).
Currently the known DataTypes are:
enum DataType: Equatable {
case argument(MTLArgument)
case argumentContainingArgumentBuffer(MTLArgument, MTLPointerType)
case textureArgument(MTLArgument)
case samplerArgument(MTLArgument)
case encodableArgument(MTLArgument)
case argumentBuffer(MTLPointerType)
case structMember(MTLStructMember)
case array(MTLArrayType)
case buffer(MTLPointerType)
case encodableBuffer(MTLPointerType)
case metalArray(MTLArrayType, MTLStructMember)
case atomicVariable(MTLStructMember)
}
DataType
are parsed from a MetalType
array, which results in DataType
arrays. Internally the arrays are called paths (since a DataType
array is like a path to a bindable target). The paths are referenced using a naming system.
Very short:
- .named: any non metal structure that has a name.
- .indexed: arrays, and arguments that have arrays (more than 1 element).
Once an encoder requests to encode something, the constructed named path references a DataType
array which is used to understand what is the type at the last item, and how to access it (how to calculate offset or index).
For example:
RootEncoder
starts with a hidden root path that is composed of it's argument name (i.e. .named("argument")
).
When we wish to encode something the encoder uses the request to construct a path.
Here the used 'visual' path (which is parsed by regex to internally transform into [.index(0)]
) is used to call:
let childEncoder = encoder.childEncoder(for: "[0]")
which will return a wrapped argument encoder (ArgumentBufferEncoder
) for index 0 in it's array.
Internally the child encoder will store the path [.named("argument"), .index(0)]
and will use it as it's root path.