METAL-PIPELINES-SCRIPT(5) | Metal | METAL-PIPELINES-SCRIPT(5) |
metal-pipelines-script - Metal pipelines script JSON file format
A Metal pipelines script is used to specify a collection of Metal libraries and pipeline descriptors. metal-nt consumes this information to determine which input file to read and which GPU binaries must be generated and stored in a GPU binaries archive.
A Metal pipelines script has a JSON based textual representation. Its canonical file extension is .mtlp-json. The script itself is a single object that can have the members:
The object describing the collection of Metal libraries can have the members:
A named function constant values object can define the members:
A function constant value object can define the members:
If id_type is FunctionConstantName then id must be a string whose value represents the name of function constant variable.
This is the equivalent structure of MTLFunctionStitchingGraph in the Metal API. A function graph object can define the members:
If node_type is InputNode then node must be an object with a single member index whose value represents the index of the given input node.
If node_type is FunctionNode then node must be an object with the following members:
If attribute_type is AlwaysInlineAttribute then attribute must be an empty object.
The object describing the collection of Metal pipelines can have the members:
This is the equivalent structure of MTLComputePipelineDescriptor in the Metal API. A Metal compute pipeline descriptor object can have the members:
This is the equivalent structure of MTLRenderPipelineDescriptor in the Metal API. A Metal render pipeline descriptor object can have the members:
This is the equivalent structure of MTLTileRenderPipelineDescriptor in the Metal API. A Metal tile render pipeline descriptor object can have the members:
This is the equivalent structure of MTLStageInputOutputDescriptor in the Metal API. A Metal stage/output descriptor object can have the members:
This is the equivalent structure of MTLVertexDescriptor in the Metal API. A Metal vertex descriptor object can have the members:
This is the equivalent structure of MTLPipelineBufferDescriptor in the Metal API. A Metal pipeline buffer descriptor can define the members:
This is the equivalent structure of MTLLinkedFunctions in the Metal API. A Metal linked functions object can have the members:
The name of the group of functions.
An array of functions. Each element is the name of function listed in the functions array.
This is the equivalent of MTLVertexFormat and MTLAttributeFormat in the Metal API. It must be one of the following string values:
This is the equivalent of MTLPixelFormat in the Metal API. It must be one of the following string values:
This is the equivalent of MTLBlendOperation in the Metal API. It must be one of the following string values:
This is the equivalent of MTLBlendFactor in the Metal API. It must be one of the following string values:
The object describing the collection of Metal binary functions can have the members:
A Metal binary intersection function descriptor object can have the members:
A Metal binary visible function descriptor object can have the members:
Referencing functions in Metal libraries can be done in different ways based on the kind of library being referenced.
The function name shall be used in the case the desired function is part of the input library specified as a command line argument to metal-nt.
{
"pipelines": {
"compute_pipelines": [
{
"compute_function": "my_kernel_function"
}
]
} }
The syntax alias:<library-identifier>#<function-name> shall be used in the case the desired function is part of a library defined in the libraries object of the Metal script.
{
"libraries": {
"paths": [
{
"label": "lib1",
"path": "path/to/lib1.metallib"
}
]
},
"pipelines": {
"compute_pipelines": [
{
"compute_function": "alias:lib1#my_kernel_function"
}
]
} }
The syntax file:<path-to-library-file>#<function-name> shall be used in the case the desired function is part of a library file on disk.
Paths can either be absolute or relative. Relative paths are always resolved using the library search paths provided with the option -L to metal-nt.
{
"pipelines": {
"compute_pipelines": [
{
"compute_function": "file:path/to/lib1.metallib#my_kernel_function"
}
]
} }
A predicate expression is an arbitrary boolean expression combining builtin predicates and user defined named predicates with the operator && (logical AND), || (logical OR), and ! (logical NOT). If a predicate expression is empty it is evaluated to true.
It is possible to define named predicates in a Metal pipelines script. Each object describing a named predicate can define the members:
A named predicate can be referenced in an expression with the syntax $<predicate-name>().
{
"named_predicates": [
{
"name": "myPredicate1",
"predicate": "supportsFamily(apple6) || supportsFamily(mac2)"
},
{
"name": "myPredicate2",
"predicate": "$myPredicate1() && !supportsFamily(common1)"
}
],
"pipelines": {
"compute_pipelines": [
{
"compute_function": "my_kernel_basic"
},
{
"enable": "$myPredicate1()",
"compute_function": "my_kernel_advanced"
},
{
"enable": "$myPredicate2() || supportsFamily(apple8) || supportsFamily(metal3)",
"compute_function": "my_kernel_more_advanced"
}
]
} }
This example shows a Metal pipelines script with two compute pipelines and three render pipelines. All the functions are from the input library provided as a command line argument to metal-nt.
{
"pipelines": {
"compute_pipelines": [
{
"compute_function": "my_kernel_1"
},
{
"compute_function": "my_kernel_2"
}
],
"render_pipelines": [
{
"vertex_function": "my_vertex",
"fragment_function": "my_fragment_1",
"color_attachments": [
{
"pixel_format": "BGRA8Unorm"
}
]
},
{
"vertex_function": "my_vertex",
"fragment_function": "my_fragment_2",
"color_attachments": [
{
"pixel_format": "BGRA8Unorm"
}
]
},
{
"vertex_function": "my_vertex_side_effects",
"rasterization_enabled": false
}
]
} }
This example shows a Metal pipelines script with two render pipelines. The fragment functions used in these render pipelines are specialized functions, hence the script contains a description of the specialization process. Since the only way to reference the specialized function libraries is via the library unique identifier, the ALIAS URI syntax is used to reference the specialized functions.
{
"named_function_constant_values": [
{
"name": "my_common_fc_values",
"constant_values": [
{
"id_type": "FunctionConstantIndex",
"id": {
"data": 0
},
"value_type": "ConstantUInt",
"value": {
"data": 42
}
},
{
"id_type": "FunctionConstantName",
"id": "base_color",
"value_type": "ConstantFloat4",
"value": {
"data": [0.5, 0.22, 0.25, 1.0]
}
}
]
}
],
"libraries": {
"specialized_functions": [
{
"label": "fragment_1_lib",
"function": "my_fragment",
"named_constant_values": "my_common_fc_values",
"constant_values": [
{
"id_type": "FunctionConstantName",
"id": "base_color",
"value_type": "ConstantFloat4",
"value": {
"data": [0.25, 0.25, 0.5, 1.0]
}
},
]
},
{
"label": "fragment_2_lib",
"function": "my_fragment",
"named_constant_values": "my_common_fc_values",
"constant_values": [
{
"id_type": "FunctionConstantIndex",
"id": {
"data": 0
},
"value_type": "ConstantUInt",
"value": {
"data": 23
}
}
]
}
]
},
"pipelines": {
"render_pipelines": [
{
"vertex_function": "my_vertex",
"fragment_function": "alias:fragment_1_lib#my_fragment",
"color_attachments": [
{
"pixel_format": "BGRA8Unorm"
}
]
},
{
"vertex_function": "my_vertex",
"fragment_function": "alias:fragment_2_lib#my_fragment",
"color_attachments": [
{
"pixel_format": "BGRA8Unorm"
}
]
}
]
} }
Note that in fragment_1_lib the function constant value for the variable base_color provided by my_common_fc_values is overridden locally. Similarly in fragment_2_lib the function constant value for the variable with index 0 provided by my_common_fc_values is overridden locally.
This example shows a Metal pipelines script with three compute pipelines where functions are from libraries either defined as input libraries on disk in the Metal script (see paths), or directly referenced using the FILE URI syntax, or from specialized function libraries using the ALIAS URI syntax.
{
"libraries": {
"paths": [
{
"label": "lib1",
"path": "libraries/lib1.metallib"
}
],
"specialized_functions": [
{
"label": "kernel_42_lib",
"function": "alias:lib1#my_kernel",
"specialized_name": "my_specialized_kernel",
"constant_values": [
{
"id_type": "FunctionConstantIndex",
"id": {
"data": 0
},
"value_type": "ConstantUInt",
"value": {
"data": 42
}
}
]
}
]
},
"pipelines": {
"compute_pipelines": [
{
"compute_function": "alias:kernel_42_lib#my_specialized_kernel"
},
{
"compute_function": "file:/path/to/custom/lib.metallib#custom_kernel"
},
{
"compute_function": "alias:lib1#base_kernel"
}
]
} }
This example shows a Metal pipelines script with a compute pipeline with a linked_functions object.
{
"libraries": {
"paths": [
{
"label": "visible_functions",
"path": "libraries/visible_fns.metallib"
},
{
"label": "intersection_functions",
"path": "libraries/intersection_fns.metallib"
}
]
},
"pipelines": {
"compute_pipelines": [
{
"compute_function": "my_kernel",
"linked_functions": {
"functions": [
"my_visible_1",
"alias:visible_functions#helper_visible_1",
"alias:visible_functions#helper_visible_2",
"alias:visible_functions#helper_visible_3",
"alias:intersection_functions#triangle_intersection_1",
"alias:intersection_functions#triangle_intersection_2",
"alias:intersection_functions#triangle_intersection_3"
],
"binary_functions": [
"bounding_box_intersection_1",
"bounding_box_intersection_2",
"bounding_box_intersection_3"
],
"groups": [
{
"name": "helpers_group_1",
"functions": ["helper_visible_1", "helper_visible_2"]
},
{
"name": "helpers_group_2",
"functions": ["helper_visible_3"]
}
]
}
}
]
} }
Note that the elements in binary_functions array are simple function names, while the elements in the functions array can be any form of function reference.
This example shows a Metal pipelines script with separately compiled visible and intersection functions.
{
"libraries": {
"paths": [
{
"label": "visible_functions",
"path": "libraries/visible_fns.metallib"
},
{
"label": "intersection_functions",
"path": "libraries/intersection_fns.metallib"
}
]
},
"functions": {
"visible_functions": [
{
"function": "file:/path/to/other.metallib#my_visible_1",
},
{
"function": "my_visible_2",
},
{
"function": "alias:visible_functions#my_visible_1",
}
],
"intersection_functions": [
{
"function": "my_intersection_1",
},
{
"function": "alias:intersection_functions#my_intersection_2",
},
{
"function": "file:/path/to/other.metallib#my_intersection_1",
}
]
} }
This example shows a Metal pipelines script with a compute pipeline and separately compiled visible function using a stitched function. The only way to reference the stitched libraries is via the library unique identifier, the ALIAS URI syntax is used to reference the stitched functions.
{
"libraries": {
"stitched_libraries": [
{
"label": "stitched_functions",
"functions": [
"mul",
"add"
],
"function_graphs": [
{
"function_name": "muladd",
"nodes": [
{
"node_type": "InputNode",
"node": {
"index": 0
}
},
{
"node_type": "InputNode",
"node": {
"index": 1
}
},
{
"node_type": "FunctionNode",
"node": {
"name": "mul",
"arguments": [
{
"id": 0
},
{
"id": 1
}
]
}
},
{
"node_type": "InputNode",
"node": {
"index": 2
}
},
{
"node_type": "FunctionNode",
"node": {
"name": "add",
"arguments": [
{
"id": 2
},
{
"id": 3
}
]
}
}
],
"output_node": {
"id": 4
}
}
]
}
]
},
"pipelines": {
"compute_pipelines": [
{
"compute_function": "my_kernel",
"linked_functions": {
"functions": [
"alias:stitched_functions#muladd",
]
}
}
]
},
"functions": {
"visible_functions": [
{
"function": "alias:stitched_functions#muladd",
}
]
} }
2014-2024, The Metal Team
April 30, 2024 | 32023 |