# shader_system_reference.md # General info Shaders are written in a `.tmsl` file. This file is a `JSON` file with special formatting rules that allows the `shader system` to compile your shader. No root is needed but there are many special blocks that will be parsed. Any JSON object that isn’t contained in one of these special blocks will be excluded. # Blocks Note that any block can be omitted depending on the usage of the shader. | **Block Name** | **Description** | | -------------------- | ------------------------------------------------------------------------ | | tessellation_states | Defines the pipeline state for the tessellation stages | | raster_states | Defines the pipeline state for the rasterizer | | depth_stencil_states | Defines how depth testing should occur | | blend_states | Defines how individual render targets should be blended | | multi_sample_states | Defines the pipeline state for render target multi-sampling | | samplers | Sampler definitions that will be used in the shader | | imports | The resources that need to be bound to the shader | | ray_payloads | Defines payload structures that can be used by ray tracing shader stages | | requests | Any creation graph channel that is required for a node to function | | common | Common code block, can contain any HLSL code | | function | The code for a creation graph node | | vertex_shader | Stage and layout definition for the vertex stage | | hull_shader | Stage and layout definition for the hull/tessellation control stage | | domain_shader | Stage and layout definition for the domain/tessellation evaluation stage | | geometry_shader | Stage and layout definition for the geometry stage | | pixel_shader | Stage and layout definition for the pixel/fragment stage | | compute_shader | Stage and layout definition for the compute stage | | raygen_shader | Stage and layout definition for the ray generation stage | | any_hit_shader | Stage and layout definition for the any hit shader | | closest_hit_shader | Stage and layout definition for the closest hit shader | | miss_shader | Stage and layout definition for the miss shader | | intersection_shader | Stage and layout definition for the intersection shader | | creation_graph_node | Defines the parameters for a creation graph node | | compile | Defines the compilation environment for the shader file | | system | Defines the compilation environment for a system shader file | ## Tessellation States ```json tessellation_states: { control_points: 0 } ``` In this block you can specify the amount of control points per tessellation patch. This value must be at least zero, but the maximum is defined by the render backend. The default state of the block is shown above. Note that this block should only be added to stages that have a hull and domain stage, otherwise it’s unused. ## Raster States ```json raster_states: { cull_mode: "back" front_face: "cw" polygon_mode: "fill" depth_bias_enable: false depth_bias_constant_factor: 1 depth_bias_clamp: 1 depth_bias_slope_factor: 1 } ``` In this block you can specify the pipeline options for the rasterizer (if one is present), the default state is shown above. Note that `depthClamp` or `depthBiasClamp` Vulkan device features need to be present for their relative properties. | **Cull Mode** | **Description** | | ------------- | ------------------------------------------------------------------ | | “none" | No face culling will be applied to primitives pass to this shader. | | “front" | Faces where the front side is visible will be culled. | | “back" | Face where the back side is visible will be culled. | | **Front Face Mode** | **Description** | | ------------------- | ------------------------------------------------------------------------ | | “cw" | The front face will be determined by a clock-wise winding order. | | “ccw" | The front face will be determined by a counter-clock-wise winding order. | | **Polygon Mode** | **Description** | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | “fill" | Primitives that define a surface will be filled by the rasterizer. | | “line" | Only the primitives edges will invoke a pixel shader. Note that the `fillModeNonSolid` Vulkan device feature needs to be present in order to use this polygon mode. | | “point" | Only the vertices of the primitives will invoke a pixel shader. Note that the `fillModeNonSolid` Vulkan device feature needs to be present in order to use this polygon mode. | ## Depth Stencil State ```json depth_stencil_states: { depth_test_enable: false depth_write_enable: false depth_compare_op: "never" stencil_test_enable: false stencil_front_fail_op: "keep" stencil_front_pass_op: "keep" stencil_front_depth_fail_op: "keep" stencil_front_compare_op: "never" stencil_front_compare_mask: 0 stencil_front_compare_write_mask: 0 stencil_front_reference: 0 stencil_back_fail_op: "keep" stencil_back_pass_op: "keep" stencil_back_depth_fail_op: "keep" stencil_back_compare_op: "never" stencil_back_compare_mask: 0 stencil_back_compare_write_mask: 0 stencil_back_reference: 0 depth_bound_test_enable: false depth_bound_min: 0 depth_bound_max: 0 } ``` In this block you can specify the depth and stencil pipeline state used with this shader, the default state is shown above. Note that the `depthBounds` Vulkan device extension needs to be present in order to use the depth bound options. | **Compare Operation** | **Description** | | --------------------- | -------------------------------------- | | “never" | The test will always evaluate to false | | “less" | The test checks if `A < B` | | “equal" | The test checks if `A == B` | | “less_equal" | The test checks if `A <= B` | | “greater" | The test checks if `A > B` | | “not_equal" | The test check if `A != B` | | “greater_equal" | The test check if `A >= B` | | **Stencil Operation** | **Description** | | --------------------- | ------------------------------------------------------------------- | | “keep" | Keeps the current stencil value | | “zero" | Sets the stencil value to zero | | “replace" | Replaces the current stencil value with the reference stencil value | | “inc_clamp" | Increments the current stencil value and clamps it to 0xFFFFFFFF | | “dec_clamp" | Decrements the current value and clamps it to zero | | “invert" | Bitwise-invert the current stencil value | | “inc_wrap" | Increments the current stencil value | | “dec_wrap" | Decrements the current stencil value | ## Blend States ```json blend_states: { logical_operation_enable: false logical_operation: "no_op" render_target_0: { blend_enable: false source_blend_factor_color: "source_alpha" destination_blend_factor_color: "one_minus_source_alpha" blend_operation_color: "add" blend_operation_alpha: "add" source_blend_factor_alpha: "zero" destination_blend_factor_alpha: "zero" write_mask: "red|green|blue|alpha" } } ``` Defines the blending parameters for all or some of the render targets participating in the draw call. Note that every render target has all its own blend states defined in a subobject of the `blend_states` object. The name of which is formatted as `render_target_#` where the final index increments from zero to seven. | **Logical Operations** | **Description** | | ---------------------- | --------------- | | “clear" | 0 | | “and" | `S & D` | | “and_reverse" | `S & ~D` | | “copy" | S | | “and_inverted" | `~(S & D)` | | “no_op" | D | | “xor" | `S ^ D` | | “or" | `S | D` | | “nor" | `~(S | D)` | | “equivalent" | `~(S ^ D)` | | “invert" | `~D` | | “or_reverse" | `S | ~D` | | “copy_inverted" | `~S` | | “or_inverted" | `~S | D` | | “nand" | `~(S & D)` | | “set" | 1 | | **Blend Factor** | **Description** | | ----------------------------- | ---------------------------------------- | | “zero" | 0 | | “one" | 1 | | “source_color" | Source RGB | | “one_minus_source_color" | 1 - Source RGB | | “destination_color" | Destination RGB | | “one_minus_destination_color" | 1 - Destination RGB | | “source_alpha" | Source A | | “one_minus_source_alpha" | 1 - Source A | | “destination_alpha" | Destination A | | “one_minus_destination_alpha" | 1 - Destination A | | “constant_color" | (1, 1, 1) (cannot be changed currently) | | “one_minus_constant_color" | (0, 0, 0) (cannot be changed currently) | | “constant_alpha" | 1 (cannot be changed currently) | | “one_minus_constant_alpha" | 0 (cannot be changed currently) | | “source_alpha_saturate" | min(Source Alpha, 1 - Destination Alpha) | | “source1_color" | Seconds Source RGB | | “one_minus_source1_color" | 1 - Second Source RGB | | “source1_alpha" | Second Source A | | “one_minus_source1_alpha" | 1 - Second Source A | | **Blend Operation** | **Description** | | ------------------- | ----------------------------------------------------------- | | “add" | `Src RGBA * Src Blend Factor + Dst RGBA * Dst Blend Factor` | | “subtract" | `Src RGBA * Src Blend Factor - Dst RGBA * Dst Blend Factor` | | “reverse_subtract" | `Dst RGBA * Src Blend Factor - Src RGBA * Src Blend Factor` | | “min" | `min(Src RGBA, Dst RGBA)` | | “max" | `max(Src RGBA, Dst RGBA)` | | **Write Mask** | **Description** | | ------------------------------------- | ------------------------------------------------------ | | “disabled" | No output will be written | | “red" | Only the red channel will be written to | | “green" | Only the green channel will be written to | | “blue" | Only the blue channel will be written to | | “alpha" | Only the alpha channel will be written to | | “red|green" | Both the red and green channels will be written to | | “red|blue" | Both the red and blue channels will be written to | | “green|blue" | Both the green and blue channels will be written to | | “red|green|blue" | The red, green, and blue channels will be written to | | “red|alpha" | Both the red and alpha channels will be written to | | “green|alpha" | Both the green and alpha channels will be written to | | “red|green|alpha" | The red, green, and alpha channels will be written to | | “blue|alpha" | Both the blue and alpha channels will be written to | | “red|blue|alpha" | The red, blue, and alpha channels will be written to | | “green|blue|alpha" | The green, blue, and alpha channels will be written to | | “red|green|blue|alpha" | All channels will be written to | ## Multi-Sample States ```json multi_sample_states: { sample_shading_enable: false min_sample_shading: false alpha_to_coverage_enable: false alpha_to_one_enable: false } ``` This block specifies one multi-sampling parameters for the shading pass, the default state is shown above. Note that sample masks aren’t currently supported. ## Samplers ```json samplers: { sampler_name: { min_filter: "linear" max_filter: "linear" mip_mode: "linear" address_u: "wrap" address_v: "wrap" address_w: "wrap" mip_lod_bias: 0 anisotropy_enable: true max_anisotropy: 16 compare_enable: false compare_op: "less_equal" min_lod: 0 max_lod: 16 border_color: "float_opaque_white" } } ``` In this block you can specify any number of sampler states. The name of these sampler states is defined as the name of a subobject, in the example the sampler state name is `sampler_name`. Note that there is no limit on the amount of sampler states defined here. Also not that these are not resources, a resource definition will be needed in order to use this sampler state. | **Filter Mode** | **Description** | | --------------- | ------------------------------- | | “point" | Uses nearest neighbor filtering | | “linear" | Uses linear filtering | | **Mip Mode** | **Description** | | ------------ | ------------------------------- | | “point" | Uses nearest neighbor filtering | | “linear" | Uses linear filtering | | **Address Mode** | **Description** | | -------------------- | ----------------------------------------------------------------------------- | | “wrap" | Wraps back around to the beginning of the image when out of bounds | | “mirror_wrap" | Wraps backwards from the end to the beginning of the image when out of bounds | | “clamp" | Clamps the sample to the edge of the image when out of bounds | | “clamp_border_color" | Returns the border color when out of bounds | | “mirror_clamp" | Clamps the sample to the opposite edge of the image when out of bounds | | **Compare Operation** | **Description** | | --------------------- | -------------------------------------- | | “never" | The test will always evaluate to false | | “less" | The test checks if `A < B` | | “equal" | The test checks if `A == B` | | “less_equal" | The test checks if `A <= B` | | “greater" | The test checks if `A > B` | | “not_equal" | The test check if `A != B` | | “greater_equal" | The test check if `A >= B` | | **Border Color** | **Description** | | ------------------------- | -------------------- | | “float_transparent_black" | (0.0, 0.0, 0.0, 0.0) | | “int_transparent_black" | (0, 0, 0, 0) | | “float_opaque_black" | (0.0, 0.0, 0.0, 1.0) | | “int_opaque_black" | (0, 0, 0, 1) | | “float_opaque_white" | (1.0, 1.0, 1.0, 1.0) | | “int_opaque_white" | (1, 1, 1, 1) | ## Imports ```json imports: [ { name: "example_constant" type: "float2" elements: 4 } { name: "example_buffer" type: "buffer" uav: true } { name: "example_image" type: "texture_2d" element_type: "float4" elements: 5 } { name: "example_sampler" type: "sampler" sampler: "sampler_name" } ] ``` The imports block defines any resource that needs to be accessible to this shader. Every definition in this import block has a `name` and `type` parameter, but the other parameters vary per resource type. Note that `vector constant` types are represented using the default HLSL format. For example: a 3D vector would become `float3`. Note that sampler resources reference their sampler state by name, this name should be defined in a `samplers` block (see previous header). You can access the resources with `load_` or `get_` function calls. Note that constants are `loaded` whilst you `get` resources. These functions take an index parameter if `elements` was defined. Note that the implementation can choose how these resources are passed to the shader. If `uav` is set to `true` then the resource will be get ReadWrite access qualifiers, not all resources support this, see the table below. ```glsl void example_func() { float2 example_constant = load_example_constant(0); RWByteAddressBuffer example_buffer = get_example_buffer(); Texture2D example_image = get_example_image(3); SamplerState example_sampler = get_example_sampler(); } ``` | **Type** | **Optional parameters** | **Description** | | ---------------------- | -------------------------------- | ---------------------------------------------------------------------------- | | bool# | `elements` | A normal or vector boolean constant | | int# | `elements` | A normal or vector signed integer constant | | uint# | `elements` | A normal or vector unsigned integer constant | | half# | `elements` | A normal or vector half-precision floating-point constant | | float# | `elements` | A normal or vector floating-point constant | | double# | `elements` | A normal or vector double-precision floating-point constant | | struct | `elements` | A predefined structure type | | depth | | The depth value of the current pixel/fragment | | stencil_ref | | The current stencil reference value | | buffer | `elements`, `uav` | One or multiple byte address buffers, readonly by default | | texture_1d | `elements`, `uav` `element_type` | One or multiple 1D textures, readonly by default | | texture_2d | `elements`, `uav` `element_type` | One or multiple 2D textures, readonly by default | | texture_3d | `elements`, `uav` `element_type` | One or multiple 3D textures, readonly by default | | texture_cube | `elements`, `uav` `element_type` | One or multiple cube sampled textures, readonly by default | | texture_1d_array | `elements`, `uav` `element_type` | One or multiple 1D texture arrays, readonly by default | | texture_2d_array | `elements`, `uav` `element_type` | One or multiple 2D texture arrays, readonly by default | | texture_cube_array | `elements`, `uav` `element_type` | One or multiple cube texture arrays, readonly by default | | sampler | `sampler` | A named sampler with sample parameters of type `sampler` | | sampler_comparison | `sampler` | A named comparison enabled sampler with sample parameters of type `sampler`. | | acceleration_structure | | A readonly top-level acceleration structure | ## Payloads ```json ray_payloads: { example_payload: [ { name: "field_1" type: "float2" } { name: "field_2" type: "float4" elements: 2 } ] } ``` The payloads block defines available ray payloads in ray tracing shader stages. These are defined as simple structs and will be available as variables under the `payload` name. Note that you can use all constant types in these payloads, but no resources. The syntax is the same as with the `import` block. ## Requests ```json requests: [ { channel: "example_channel_name" } ] ``` The request block is used to specify desired `channels` from the output shader for a creation graph node. The available channels are defined by the `exports` of the output shader and support for individual channels can be queried using the `TM_CHANNEL_AVAILABLE_#` macro syntax. See ‘Walkthrough: Making creation graph nodes` for an example. ## Common ```glsl common: [[ groupshared float local_variable[2]; float example_function(uint group_index, float value) { local_variable[group_index] = value; GroupMemoryBarrierWithGroupSynch(); return local_variable[0] + local_variable[1]; } ]] ``` The common code block allows you to write any HLSL code. This is useful for common functions or definitions. Note that resource definitions should **NOT** be specified in here as the shader system has no way to bind them, use the `imports` block for this. Shader local definitions can however be specified. When generating the final shaders, the shader system will include the common code blocks first allowing them to be used by any other call. See ‘order of code includes’ for more info. ## Function ```json function: [[ output.example_output = a + b; ]] ``` The function node defines the HLSL code associated with a creation graph node. Note that the function signature is generated, so only the function body should be specified. Any inputs (defined in a `creation_graph_node` block) can be accessed as variables and any outputs (also defined in a `creation_graph_node` block) can be accessed through the output struct that’s also accessible like a variable. For more information see ‘Walkthrough: Making creation graph nodes’. ## Shader Stage block ```json hull_shader: { enabled: "true" import_system_semantics: [ "control_point_id" ] export_system_semantics: [ ] attributes: { domain: "triangle" output_topology: "traingle_cw" output_control_points: 3 partitioning: "fractional_odd" } exports: [ { name: "example_export" type: "float3" channel_requested: true } ] patch: [[ return output; ]] code: [[ tm_graph_io_t graph; tm_graph_read(graph, input[control_point_id]); #if defined (TM_CHANNEL_REQUESTED_example_export) graph.example_export = float3(1.0f, 0.0f, 1.0f); #endif tm_graph_evaluatie(graph); output.position = input[control_point_id].position; tm_graph_write(output, graph); return output; ]] } ``` This block defined the shader code and environment for every shader stage. Note that this example shows all available subobjects, but is in no way meant to be a reasonable shader, in this example a hull shader is used because it can use all of the available subobjects. The available rasterization stages are (in pipeline execution order): `vertex_shader`, `hull_shader`, `domain_shader`, `geometry_shader`, and `pixel_shader`. The available ray tracing stages are: `raygen_shader`, `any_hit_shader`, `closest_hit_shader`, `miss_shader`, and `intersection_shader`. The `compute_shader`, `raygen_shader`, and `miss_shader` block should only be used alone in a separate shader file. Note that any other raytracing stages in the same file (`any_hit_shader`, `closest_hit_shader`, and `intersection_shader`) will be build as part of the same hit group. Note as well that the `patch` subobject is only available in the hull shader stage. Note that the example above specifies part of a creation graph output node shader. The `tm_graph_` structure and functions aren’t needed for every shader. These functions do go together, omitting one can cause unwanted behavior from the creation graph. | **Available structs** | **Stage** | **Description** | | --------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | input | `vertex` `geometry` `hull` `domain` `pixel` `compute` | Holds any inputs from previous stages or semantics, for instance the `vertex` stage will have `position` as a default input. | | output | `vertex` `geometry` `hull` `domain` `pixel` `compute` `raygen` | Holds any outputs from this stage, these outputs are defined by the `exports` subobject. | | patch | `domain` | Holds the patch constants from the patch constants function created in the `hull` stage. | | payload | `miss` `any_hit` `closest_hit` `intersection` | Holds the payload specified using the `payload` attribute, this is an input and output struct. | | barycentrics | `any_hit` `closest_hit` `intersection` | Holds the fixed-function triangle intersection attributes, this is of `float2` type. | | **Subobject** | **Description** | | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | enabled | An expression using the shader conditional language to determine whether this stage should participate in compilation. This is useful if you want stages to be dependent on the compilation environment and especially creation graph inputs. | | import_system_semantics | Any HLSL system semantics that are used by the stage. These will be defined as readonly variables. | | export_system_semantics | Any HLSL system semantics that this stage will write to. Currently these are not used. | | attributes | Any HLSL attributes for the shader stage. | | exports | Defines any named exports for the shader stage. These are passed to stages later in the pipeline and can be requested by creation graph nodes. You can have multiple of the same name if an export is passed throughout the pipeline. For instance, a normal might change depending on the executing stage and thusly has different results in a creation graph depending on the stage it’s evaluated in. | | patch | Defines a code block for the patch constants function. Currently no additional information can be passed between patches. | | code | The main code block for this stage. This block is placed in the generated main function for this stage. An `output` struct will be defined if the shader has defined any exports. | | **System Semantic** | **Type** | **Stage** | **Description** | | ------------------- | --------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | position | float4 | `vertex` `geometry` `pixel` | Imported automatically by the vertex shader, which will need to write to it in order to set the vertex’s position. In any other stage it can be read as either the interpolated vertex position or the pixel location. | | dispatch_thread_id | uint3 | `compute` | Defines the global thread offset within the dispatch call. | | group_id | uint3 | `compute` | Defines the group offset within the dispatch call. | | group_index | uint | `compute` | Defines an flattened index version for a given thread within a given group. | | group_thread_id | uint3 | `compute` | Defines the thread offset within a group. | | instance_id | uint | `vertex` | Defines a per-instance identifier. | | primitive_id | uint | `geometry` `pixel` | Defines an automatically generated per-primitive identifier. | | vertex_id | uint | `vertex` | Defines an automatically generated per-vertex identifier. | | is_front_face | bool | `geometry` `pixel` | Specified whether the current triangle is front facing, this is always true for lines and points. | | control_point_id | uint | `hull` | Defines the index of the control point ID being operated on. | | domain_location | float2 / float3 | `domain` | Defines the location of the current domain point. For triangle patches this is float3, otherwise; it’s float2. | | **Attribute** | **Type / Value** | **Description** | | --------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | | instance | uint | Specifies the number of geometry shader instances for each primitive. | | max_vertex_count | uint | specifies the maximum number of vertices to create in a geometry shader. | domain | "triangle”
“quad”
“isoline” | Specifies the path type used in the tessellation shader stages. | | max_tess_factor | uint | Specifies the maximum tessellation factor that will be used to clamp the calculated value in the hull shader. | | output_control_points | uint | Specifies the number of times the hull shader is executed. | | output_topology | “point"
“line"
“triangle_cw"
“triangle_ccw" | Specifies the output topology for the hull shader. | | partitioning | “integer"
“fractional_even"
“fractional_odd"
“pow2" | Specifies the partitioning scheme used in the hull shader | | early_depth_stencil | bool | Specifies whether epth-stencil testing should occur before the pixel shader. | | num_threads | uint3 | Specifies the number of threads to be executed in a single thread group for a compute shader dispatch. | | payload | string | Specifies the identifier for the payload used by the ray tracing shader stage. | ## Creation Graph Node ```json creation_graph_node: { name: "example_node" display_name: "Example Node" category: "Shader/Example" actions: { example_action: { defines: [ "EXAMPLE_ACTION_ACTIVE" ] requests: [ { channel: "example_channel" type_name: "" } ] resource_aspects: [ { resource: "image_resource" aspect "srgb" } ] enable_systems: { example_configuration: [ "example_system" ] } raster_states: { cull_mode: "back" } } empty action: { } } settings: { example_settings: [ { name: "example_setting" display_name: "Example Setting" display_tooltip: "This creates a hover tooltip" type: "dropdown" default: "empty_action" options: [ { display_name: "Option 1" action: "example_action" } { display_name: "Option 2" action: "empty_action" } ] } { name: "second_example_setting" display_name: "Second Example Setting" type: "bool" default: false action: "example_action" condition: "example_setting == example_action" } ] } inputs: [ { name: "a_input" display_name: "A" optional: false } { name: "b_input" display_name: "B" optional: false } { name: "example_input" display_name: "Example Input" display_tooltip: "This is an example input" type: { settings: "example_settings" } evaluation_stage: [ "vertex_shader" ] connector_flag: "HAS_EXAMPLE_INPUT" optional: true target: { name: "example_resource" element: 0 } } ] outputs: [ { name: "a_output" display_name: "A" type: { type_of: { requested_channel: "example_channel" } or: "float3" } optional: false } { name: "b_output" display_name: "B" type: { largest_of: [ "a_input", "b_input" ] } optional: false } { name: "example_output" display_name: "Example Output" display_tooltip: "This is an example output" type: "float" optional: false } ] } ``` The creation graph block allows you to create a single complex creation graph node. The example above is not meant to be a realistic creation graph node, instead it shows all the possibilities. Note that `inputs` and `outputs` share the same format as they are both connectors. Actions can specify many different changes to the shader’s environment. In the example above all are shown. Note that an action can also be empty, this can be used for a default state. - `defined` allow you to add extra macros to the shader if the action is active. These can later be checked on compile time by the shader. - `requests` allow you to ask for additional channels to be set in the parent node. Note that these don’t need to have a HLSL name if they aren’t used in the shader code, but still need to be calculated by the parent shader. This can be used for systems. - `resource_aspects` allow you to change the default aspect of a import resource. The possible values for these aspects are `default`, `srgb`, `depth`, and `stencil`. - `enable_systems` allows you to enable additional systems on top of the systems defined in the `compile` block. This can for instance be used to enable shadows. - Finally you can add pipeline state overrides, these objects have the same name as the pipeline state block defined earlier in this document. | **Subobject** | **Description** | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | name | Specifies the unique identifier for this node. | | display_name | Specifies the name displayed in the graph UI for this node. | | category | Specifies a category path for this node in the graph UI. | | includes | Array with named includes this node requests to be merged into the generated code. Useful for defining structs at a centralized location when more then one node depend on them. | | actions | Actions specify changes to the shader code depending on external factors. These can be activated through the `settings`. Not that these actions themselves are named, this is used as their unique identifier. | | settings | Settings are a way to enable actions based on user input. They either define a dropdown or checkbox type that will be displayed in the UI. Note that these don’t show up on their own. They need to be used in the `inputs` section. | | inputs | The inputs map directly to the input connectors in the creation graph UI. The order of these connectors in the UI is the same as the definition order. | | outputs | The outputs map directly to the output connectors in the creation graph UI. The order of these connectors in the UI is the same as the definition order. | | **Input / Output Parameter** | **Description** | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | Specifies the HLSL name for this connector. | | display_name | Specifies the name displayed in the graph UI for this connector. | | display_tooltip | Specifies a hover tooltip for this connector. | | type | Specifies the type of this connector. Note that input connectors often don’t need a type specified if they map to generic functions. for output connectors it’s often useful to make them dependent on the type of input connectors. You can use the `type_of` and `largest_of` type specifiers for this. | | struct_name | Specified the name of struct when `type: "struct"`. | evaluation_stage | Specifies the pipeline stage(s) at which this connector is evaluated. This means that the creation graph nodes connected to this connector will be evaluated by `tm_graph_evaluate` in the specified shader stage(s). Note that this might mean that inputs (such as vertex color) need to be passed to later stages of the pipeline. | | connector_flag | Specifies an optional flag that can be used as a macro in shader code to determine whether this connector is used by the current creation graph. This should be used to check for optional inputs on compile time. | | optional | Specifies whether this connector is optional. Although not required it’s highly recommended to also add a `connector_flag` is this is set to true. | | target | Specifies a resource that this connector should be bound to. This can be used to allow to user to input resources, or to specify an output render target. The name specified for this target should be in the `imports` section of the shader file. | | **Setting Parameter** | **Description** | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | Specifies a unique identifier for this setting. | | display_name | Specifies the name displayed to the graph UI for this setting. | | display_tooltip | Specifies a hover tooltip for this setting. | | type | Specifies how the setting can be altered, this can be either `bool` or `dropdown`. If `bool` is defined then the `action` parameter should also be specified. If instead `dropdown` is chosen then the `options` parameter should also be specified. | | default | Specifies the default state of this setting. This should be a boolean value if `type` is `bool`, and an action if `type` is `dropdown`. | | options | Should only be declared if `type` is `dropdown`. This specifies the available dropdown options. These subobjects only have a `display_name` and `action` specified. | | action | Should only be declared if `type` is `bool`. This specifies the action to enable if the setting is enabled. | | condition | Specifies an optional condition for this setting to be shown. This allows you to hide settings that are dependent on other settings or values. This condition is written in the shader conditional language. | ## Compile ```json compile: { includes: [ "first_included_shader", "second_included_shader" ] configurations: { example_configuration: [ systems: [ "example_system" ] variations: { compile_variations: [ ["nested_example_system"], [] ] variations: [] } ] } contexts: { context_name: [ { layer: "example_layer" condition: { systems_active: [ "example_system" ] } enable_systems: [ "another_example_system" ] configuration: "example_configuration" } { if: "settings.example_setting == example_action" then: [ { layer: "example_layer" raster_states: { cull_mode: "back" } } ] else: [ { layer: "example_layer" raster_states: { cull_mode: "front" } } ]} ] } } ``` The compile block allows you to specify the compilation environment for the shader. This block **HAS** to be added in order for the shader to be compiled, the shader can still be included without this. There are two things you can do in this block: - Include additional shader files to be appended to this shader file. - Enable systems or configurations based on the shader conditional language or whether a system is active. The contexts defined in the `contexts` block define the compilation environment(s) for this shader. There will always be one ‘default’ instance of this shader compiled if no context is specified so context are optional. The example context shown above affects just one layer (`example_layer`), the first object in the context specified that if the `example_system` is active then it will enable `another_example_system` and enable the configuration `example_configuration`. The second object is a branched configuration. If first checks if `example_setting` in the `settings` creation graph input is set to `example_action`. If that is the case it will set the cull mode for the `example_layer` to back-face culling, otherwise; it will be set to front-face culling. Note that the configuration block can become very complex because of it’s recursive nature. A configuration can have several `systems` that need to be enabled for the configuration to run. But it might also have `variations` on those systems. This can continue recursively. ## System ```json system: { includes: [ "first_included_shader", "second_included_shader" ] } ``` The system block adds the ability to include header files for library type shaders. It works in the same way as the `compile` block, but it won't trigger shader compilation no its own. # Shader Conditional Language The shader conditional language is C subset that allows you to create code that evaluated to a single boolean outcome. This is used exclusively in the shader system as a way to conditionally include or define additional code. The language is also very small and only contains the following operations and functions: | **Function** | **Precedence** | **Description** | | ---------------- | -------------- | --------------------------------------------------------------------------- | | == | 1 | Logical equality | | != | 1 | Logical bi conditional | | ! | 2 | Logical negation | | is_connected | 2 | Returns whether the specified creation graph connector is connected | | is_system_active | 2 | Returns whether the specified system is active in the compile configuration | | && | 3 | Logical and | | `||` | 3 | Logical or | The variables on which these operations function are many of the unique identifiers defined in the shader file. These are: - Action names - System names - Creation graph input names - Creation graph output names - Settings results **Some examples**: ```json hull_shader: { enabled: "is_connected(tessellation_factor)" } ``` This enables the hull_shader stage if the `tessellation_factor` creation graph input is connected. The variable used here is a creation graph input. ```json compile: { contexts: { viewport: [ { if: "settings.face_culling == face_culling_none" then: [ { layer: "transparency" raster_states: { cull_mode: "front" } } { layer: "transparency" raster_sattes: { cull_mode: "back" } } ]} ] } } ``` This adds two passes (one for each side of the geometry) to the `transparency` layer if the `face_culling` setting from the `settings` creation graph input is set to `face_culling_none`. The variables used here are: a creation graph input, a setting result, and an action name. # Order of code inclusion Not all functions and definitions have to come from the same shader file in order to be used. There are several ways of sharing code in the shader system. Some on a global basis and some on a more local basis. They layout of the code blocks in a shader file is as follows: - Shader system definitions (created by the shader system) - I/O linkage (created by the shader system) - Resource declarations and I/O functions (created by the shader system) - Common code blocks - Creation graph I/O - Auxiliary code (currently only the patch constants function) - Shader stage code It’s important to note that shader includes happen in the order that they are found. So if one include depends on the other the it should be included first or have an include itself. Note as well that the shader stage code and the patch constants functions have access to the common code block, but not vice versa. ```json common: [[ void func() { } ]] hull_stage: { code: [[ return output; ]] patch: [[ return output; ]] } compile: { includes: [ "included_code" ] configurations: { shadows: [ systems: [ "shadow_system" ] ] } } ``` The order of inclusion is as follows: - The common code block in `included code`. - The common code block from the `shadow system`. - The common code block from the example shader. - The patch constants function. - The hull stage code # Predefined Macros | **Macro** | **Description** | | ---------- | -------------------------------------------------------------------------------- | | DXC | Defined if this shader was compiled using the DXC compiler. | | STAGE_VS | Defined if the current shader stage is **Vertex**. | | STAGE_HS | Defined if the current shader stage is **Hull** / **Tessellation Control**. | | STAGE_DS | Defined if the current shader stage is **Domain** / **Tessellation Evaluation**. | | STAGE_GS | Defined if the current shader stage is **Geomtry**. | | STAGE_PS | Defined if the current shader stage is **Pixel** / **Fragment**. | | STAGE_CS | Defined if the current shader stage is **Compute**. | | STAGE_RG | Defined if the current shader stage is **Ray Generation**. | | STAGE_AH | Defined if the current shader stage is **Any-Hit**. | | STAGE_CH | Defined if the current shader stage is **Closest Hit** | | STAGE_MS | Defined if the current shader stage is **Miss**. | | STAGE_IS | Defined if the current shader stage is **Intersection**. | # Resources mapping | **Type** | **HLSL Type** | **HLSL UAV Type** | **SPIR-V Type** | **SPIR-V UAV Type** | | ---------------------- | ------------------------------- | ------------------- | ----------------------------------------- | ---------------------------------------- | | buffer | ByteAddressBuffer | RWByteAddressBuffer | OpTypeStruct { OpTypeRuntimeArray uint } | OpTypeStruct { OpTypeRuntimeArray uint } | | texture_1d | Texture1D | RWTexture1D | OpTypeImage 1D Sampled ReadOnly | OpTypeImage 1D ReadWrite | | texture_2d | Texture2D | RWTexture2D | OpTypeImage 2D Sampled ReadOnly | OpTypeImage 2D ReadWrite | | texture_3d | Texture3D | RWTexture3D | OpTypeImage 3D Sampled ReadOnly | OpTypeImage 3D ReadWrite | | texture_cube | TextureCube | RWTextureCube | OpTypeImage Cube Sampled ReadOnly | OpTypeImage Cube ReadWrite | | texture_1d_array | Texture1DArray | RWTexture1DArray | OpTypeImage 1D Arrayed Sampled ReadOnly | OpTypeImage 1D Arrayed ReadWrite | | texture_2d_array | Texture2DArray | RWTexture2DArray | OpTypeImage 2D Arrayed Sampled ReadOnly | OpTypeImage 2D Arrayed ReadWrite | | texture_cube_array | TextureCubeArray | RWTextureCubeArray | OpTypeImage Cube Arrayed Sampled ReadOnly | OpTypeImage Cube Arrayed ReadWrite | | sampler | SamplerState | | OpTypeSampler | | | sampler_comparison | SamplerComparisonState | | OpTypeSampler | | | acceleration_structure | RaytracingAccelerationStructure | | OpTypeAccelerationStructureKHR | |