xref: /aosp_15_r20/external/angle/doc/WritingShaderASTTransformations.md (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker# How to write ANGLE shader translator AST transformations
2*8975f5c5SAndroid Build Coastguard Worker
3*8975f5c5SAndroid Build Coastguard WorkerUsually, a shader AST transformation is structured as such:
4*8975f5c5SAndroid Build Coastguard Worker
5*8975f5c5SAndroid Build Coastguard Worker**.h file**: one function taking a node to transform, often the root node. If the transformation needs to create new variables or functions, you need to pass a pointer to the TSymbolTable as well (all functions and variables need an id number that's based on a counter in TSymbolTable).
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker    class TIntermBlock;
8*8975f5c5SAndroid Build Coastguard Worker    TransformAST(TIntermBlock *root)
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker**.cpp file**: implementation of the transformation, with all the implementation code in an anonymous namespace.
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker## Utilities to implement a transformation
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard WorkerThe utilities for implementing AST transformations are in **src/compiler/translator/tree_util/**
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Worker**TIntermTraverser**: This traverses the tree recursively, visiting all nodes. Override the visit* functions you need.
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker**TLValueTrackingTraverser**: If you need to know if the node that is being visited is a target of a write (used as an l-value), use TLValueTrackingTraverser and its isLValueRequiredHere() function.
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard WorkerIf you're only interested in function declarations or global variables, they're all in the global scope, so you can get away with just iterating over the root block instead of using a traverser.
21*8975f5c5SAndroid Build Coastguard Worker
22*8975f5c5SAndroid Build Coastguard WorkerTIntermTraverser has member functions to insert and replace nodes. To remove a node, replace it with an empty list. Usually visit functions queue replacements and then updateTree() is called after the traversal is complete - this way the replacement doesn't affect the current traversal. For some transformations of nested AST structures you may need to do multiple traversals.
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker**BuiltIn.h**: With the helpers here you can easily and cheaply create references to built-in variables that are stored as constexpr.
25*8975f5c5SAndroid Build Coastguard Worker
26*8975f5c5SAndroid Build Coastguard Worker**IntermNode_utils.h**: These utilities can do things like create a zero node with an arbitrary type, create bool nodes, index nodes, or operations on temporary variables.
27*8975f5c5SAndroid Build Coastguard Worker
28*8975f5c5SAndroid Build Coastguard Worker**RunAtTheEndOfShader.h**: Use this when you need to run code at the end of the shader so you don't need to worry about corner cases like return statements in main().
29*8975f5c5SAndroid Build Coastguard Worker
30*8975f5c5SAndroid Build Coastguard Worker**ReplaceVariable.h**: Replace all references to a specific variable in the AST. Useful if a type of a variable needs to be changed, for example.
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker**FindMain.h**: Find the main() function in the AST.
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker**FindSymbolNode.h**: Find a particular symbol in the AST.
35*8975f5c5SAndroid Build Coastguard Worker
36*8975f5c5SAndroid Build Coastguard Worker**IntermNodePatternMatcher.h**: This helper matches certain AST patterns that are needed in more than one different transformation, such as expressions returning an array.
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Worker**StaticType.h**: Create TType objects that are initialized at compile time.
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard WorkerSome member functions of AST nodes can also be useful:
41*8975f5c5SAndroid Build Coastguard Worker* **deepCopy()** creates a copy of any typed node, including its children.
42*8975f5c5SAndroid Build Coastguard Worker* **hasSideEffects()** determines whether an expression might have side effects. Usually we want to avoid removing nodes with side effects unless there's certainty they would never be executed.
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard Worker## Checklist
45*8975f5c5SAndroid Build Coastguard Worker
46*8975f5c5SAndroid Build Coastguard WorkerWhen implementing traversers, be careful that:
47*8975f5c5SAndroid Build Coastguard Worker* Each node will only have one parent (multiple parents could mess up further AST transformations)
48*8975f5c5SAndroid Build Coastguard Worker* You take into account some less common AST structures, such as declarations inside a loop header.
49*8975f5c5SAndroid Build Coastguard Worker* You run the transformation at the right stage of compilation. You don't want to reintroduce AST structures that have already been pruned away for example, and on the other hand you can depend on earlier transformations to clean up some inconvenient structures from the AST, like empty declarations or multiple variables declared on the same line.
50*8975f5c5SAndroid Build Coastguard Worker* Make sure that any functions you add are marked with SymbolType::AngleInternal so they exist in a separate namespace from user-defined names and can't conflict with them.
51