xref: /aosp_15_r20/external/angle/src/compiler/translator/wgsl/RewritePipelineVariables.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #ifndef COMPILER_REWRITE_BUILTIN_VARIABLES_H_
8 #define COMPILER_REWRITE_BUILTIN_VARIABLES_H_
9 
10 #include <variant>
11 
12 #include "compiler/translator/Common.h"
13 #include "compiler/translator/Compiler.h"
14 #include "compiler/translator/ImmutableString.h"
15 #include "compiler/translator/InfoSink.h"
16 #include "compiler/translator/IntermNode.h"
17 #include "compiler/translator/SymbolUniqueId.h"
18 #include "compiler/translator/wgsl/Utils.h"
19 
20 namespace sh
21 {
22 
23 // In WGSL, all input values are parameters to the shader's main function and all output values are
24 // return values of the shader's main functions (the input/output values can be embedded within
25 // struct types). So this rewrites all accesses of GLSL's input/output variables (including
26 // builtins) to be accesses of a global struct, and writes a new main function (called wgslMain())
27 // that populates the global input struct with parameters of the wgslMain function, and populates
28 // wgslMain's return value with the fields of the global output struct.
29 //
30 // TODO(anglebug.com/42267100): some of these WGSL builtins do not correspond exactly to GLSL
31 // builtin values and will need modification at the beginning (resp. end) of the main function for
32 // input values (resp. output values). E.g. normalized device coordinates in GLSL have -1.0 <= z
33 // <= 1.0, whereas NDC in WGSL have 0.0 <= z <= 1.0.
34 // See e.g. bool TranslatorMSL::appendVertexShaderDepthCorrectionToMain().
35 //
36 // Example GLSL:
37 //
38 // attribute vec2 xy_position;
39 // void setPosition() {
40 //   gl_Position = vec4(xy_position.x, xy_position.y, 0.0, 1.0);
41 // }
42 // void main()
43 // {
44 //   setPosition();
45 // }
46 //
47 // The resulting WGSL:
48 // struct ANGLE_Input_Global {
49 //   xy_position : vec2<f32>,
50 // };
51 //
52 // var<private> ANGLE_input_global : ANGLE_Input_Global;
53 //
54 // struct ANGLE_Input_Annotated {
55 //   @location(@@@@@@) xy_position : vec2<f32>,
56 // };
57 //
58 // struct ANGLE_Output_Global {
59 //   gl_Position_ : vec4<f32>,
60 // };
61 //
62 // var<private> ANGLE_output_global : ANGLE_Output_Global;
63 //
64 // struct ANGLE_Output_Annotated {
65 //   @builtin(position) gl_Position_ : vec4<f32>,
66 // };
67 //
68 // // Generated versions of _umain() and _usetPosition() go here.
69 //
70 // @vertex
71 // fn wgslMain(ANGLE_input_annotated : ANGLE_Input_Annotated) -> ANGLE_Output_Annotated
72 // {
73 //   ANGLE_input_global.xy_position = ANGLE_input_annotated.xy_position;
74 //   _umain();
75 //   var ANGLE_output_annotated : ANGLE_Output_Annotated;
76 //   ANGLE_output_annotated.gl_Position_ = ANGLE_output_global.gl_Position_;
77 //   return ANGLE_output_annotated;
78 // }
79 //
80 // Note the WGSL outputter should not output any declarations of global in/out variables, nor any
81 // redeclarations of builtin variables. And all accesses to global in/out variables should be
82 // rewritten as struct accesses of the global structs.
83 
84 const char kBuiltinInputStructType[]           = "ANGLE_Input_Global";
85 const char kBuiltinOutputStructType[]          = "ANGLE_Output_Global";
86 const char kBuiltinInputAnnotatedStructType[]  = "ANGLE_Input_Annotated";
87 const char kBuiltinOutputAnnotatedStructType[] = "ANGLE_Output_Annotated";
88 const char kBuiltinInputStructName[]           = "ANGLE_input_global";
89 const char kBuiltinOutputStructName[]          = "ANGLE_output_global";
90 const char kBuiltinInputAnnotatedStructName[]  = "ANGLE_input_annotated";
91 const char kBuiltinOutputAnnotatedStructName[] = "ANGLE_output_annotated";
92 
93 class RewritePipelineVarOutputBuilder;
94 
95 struct RewritePipelineVarOutput
96 {
97   public:
98     RewritePipelineVarOutput(sh::GLenum shaderType);
99 
100     // Every time the translator goes to output a TVariable/TSymbol it checks these functions to see
101     // if it should generate a struct access instead.
102     bool IsInputVar(TSymbolUniqueId angleInputVar);
103     bool IsOutputVar(TSymbolUniqueId angleOutputVar);
104 
105     bool OutputStructs(TInfoSinkBase &output);
106     bool OutputMainFunction(TInfoSinkBase &output);
107 
108   private:
109     friend RewritePipelineVarOutputBuilder;
110 
111     // The key is TSymbolUniqueId::get().
112     using RewrittenVarSet = TUnorderedSet<int>;
113 
114     struct WgslIOBlock
115     {
116         TVector<ImmutableString> angleGlobalMembers;
117         TVector<ImmutableString> angleAnnotatedMembers;
118         TVector<ImmutableString> angleConversionFuncs;
119     };
120 
121     static bool OutputIOStruct(TInfoSinkBase &output,
122                                WgslIOBlock &block,
123                                ImmutableString builtinStructType,
124                                ImmutableString builtinStructName,
125                                ImmutableString builtinAnnotatedStructType);
126 
127     // Represents the input and output structs for the WGSL main function.
128     WgslIOBlock mInputBlock;
129     WgslIOBlock mOutputBlock;
130 
131     // Tracks all symbols (attributes, output vars, builtins) that need to be rewritten into struct
132     // accesses by the WGSL outputter. Used in `IsInputVar()` and `IsOutputVar()`.
133     RewrittenVarSet mAngleInputVars;
134     RewrittenVarSet mAngleOutputVars;
135 
136     sh::GLenum mShaderType;
137 };
138 
139 // `outVarReplacements` is a RewritePipelineVarOutput that can output the WGSL main function and the
140 // input/output structs that represent the input and output variables of the GLSL shader,
141 [[nodiscard]] bool GenerateMainFunctionAndIOStructs(TCompiler &compiler,
142                                                     TIntermBlock &root,
143                                                     RewritePipelineVarOutput &outVarReplacements);
144 
145 }  // namespace sh
146 
147 #endif  // COMPILER_REWRITE_BUILTIN_VARIABLES_H_
148