xref: /aosp_15_r20/external/angle/src/compiler/translator/wgsl/Utils.cpp (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 #include "compiler/translator/wgsl/Utils.h"
8 
9 #include "compiler/translator/Common.h"
10 #include "compiler/translator/Symbol.h"
11 #include "compiler/translator/Types.h"
12 #include "compiler/translator/util.h"
13 
14 namespace sh
15 {
16 
17 template <typename StringStreamType>
WriteWgslBareTypeName(StringStreamType & output,const TType & type)18 void WriteWgslBareTypeName(StringStreamType &output, const TType &type)
19 {
20     const TBasicType basicType = type.getBasicType();
21 
22     switch (basicType)
23     {
24         case TBasicType::EbtVoid:
25         case TBasicType::EbtBool:
26             output << type.getBasicString();
27             break;
28         // TODO(anglebug.com/42267100): is there double precision (f64) in GLSL? It doesn't really
29         // exist in WGSL (i.e. f64 does not exist but AbstractFloat can handle 64 bits???) Metal
30         // does not have 64 bit double precision types. It's being implemented in WGPU:
31         // https://github.com/gpuweb/gpuweb/issues/2805
32         case TBasicType::EbtFloat:
33             output << "f32";
34             break;
35         case TBasicType::EbtInt:
36             output << "i32";
37             break;
38         case TBasicType::EbtUInt:
39             output << "u32";
40             break;
41 
42         case TBasicType::EbtStruct:
43             WriteNameOf(output, *type.getStruct());
44             break;
45 
46         case TBasicType::EbtInterfaceBlock:
47             WriteNameOf(output, *type.getInterfaceBlock());
48             break;
49 
50         default:
51             if (IsSampler(basicType))
52             {
53                 //  TODO(anglebug.com/42267100): possibly emit both a sampler and a texture2d. WGSL
54                 //  has sampler variables for the sampler configuration, whereas GLSL has sampler2d
55                 //  and other sampler* variables for an actual texture.
56                 output << "texture2d<";
57                 switch (type.getBasicType())
58                 {
59                     case EbtSampler2D:
60                         output << "f32";
61                         break;
62                     case EbtISampler2D:
63                         output << "i32";
64                         break;
65                     case EbtUSampler2D:
66                         output << "u32";
67                         break;
68                     default:
69                         // TODO(anglebug.com/42267100): are any of the other sampler types necessary
70                         // to translate?
71                         UNIMPLEMENTED();
72                         break;
73                 }
74                 if (type.getMemoryQualifier().readonly || type.getMemoryQualifier().writeonly)
75                 {
76                     // TODO(anglebug.com/42267100): implement memory qualifiers.
77                     UNIMPLEMENTED();
78                 }
79                 output << ">";
80             }
81             else if (IsImage(basicType))
82             {
83                 // TODO(anglebug.com/42267100): does texture2d also correspond to GLSL's image type?
84                 output << "texture2d<";
85                 switch (type.getBasicType())
86                 {
87                     case EbtImage2D:
88                         output << "f32";
89                         break;
90                     case EbtIImage2D:
91                         output << "i32";
92                         break;
93                     case EbtUImage2D:
94                         output << "u32";
95                         break;
96                     default:
97                         // TODO(anglebug.com/42267100): are any of the other image types necessary
98                         // to translate?
99                         UNIMPLEMENTED();
100                         break;
101                 }
102                 if (type.getMemoryQualifier().readonly || type.getMemoryQualifier().writeonly)
103                 {
104                     // TODO(anglebug.com/42267100): implement memory qualifiers.
105                     UNREACHABLE();
106                 }
107                 output << ">";
108             }
109             else
110             {
111                 UNREACHABLE();
112             }
113             break;
114     }
115 }
116 
117 template <typename StringStreamType>
WriteNameOf(StringStreamType & output,SymbolType symbolType,const ImmutableString & name)118 void WriteNameOf(StringStreamType &output, SymbolType symbolType, const ImmutableString &name)
119 {
120     switch (symbolType)
121     {
122         case SymbolType::BuiltIn:
123             output << name;
124             break;
125         case SymbolType::UserDefined:
126             output << kUserDefinedNamePrefix << name;
127             break;
128         case SymbolType::AngleInternal:
129             output << name;
130             break;
131         case SymbolType::Empty:
132             // TODO(anglebug.com/42267100): support this if necessary
133             UNREACHABLE();
134     }
135 }
136 
137 template <typename StringStreamType>
WriteWgslType(StringStreamType & output,const TType & type)138 void WriteWgslType(StringStreamType &output, const TType &type)
139 {
140     if (type.isArray())
141     {
142         // Examples:
143         // array<f32, 5>
144         // array<array<u32, 5>, 10>
145         output << "array<";
146         TType innerType = type;
147         innerType.toArrayElementType();
148         WriteWgslType(output, innerType);
149         output << ", " << type.getOutermostArraySize() << ">";
150     }
151     else if (type.isVector())
152     {
153         output << "vec" << static_cast<uint32_t>(type.getNominalSize()) << "<";
154         WriteWgslBareTypeName(output, type);
155         output << ">";
156     }
157     else if (type.isMatrix())
158     {
159         output << "mat" << static_cast<uint32_t>(type.getCols()) << "x"
160                << static_cast<uint32_t>(type.getRows()) << "<";
161         WriteWgslBareTypeName(output, type);
162         output << ">";
163     }
164     else
165     {
166         // This type has no dimensions and is equivalent to its bare type.
167         WriteWgslBareTypeName(output, type);
168     }
169 }
170 
171 template void WriteWgslBareTypeName<TInfoSinkBase>(TInfoSinkBase &output, const TType &type);
172 template void WriteNameOf<TInfoSinkBase>(TInfoSinkBase &output,
173                                          SymbolType symbolType,
174                                          const ImmutableString &name);
175 template void WriteWgslType<TInfoSinkBase>(TInfoSinkBase &output, const TType &type);
176 
177 template void WriteWgslBareTypeName<TStringStream>(TStringStream &output, const TType &type);
178 template void WriteNameOf<TStringStream>(TStringStream &output,
179                                          SymbolType symbolType,
180                                          const ImmutableString &name);
181 template void WriteWgslType<TStringStream>(TStringStream &output, const TType &type);
182 
FindGlobalVars(TIntermBlock * root)183 GlobalVars FindGlobalVars(TIntermBlock *root)
184 {
185     GlobalVars globals;
186     for (TIntermNode *node : *root->getSequence())
187     {
188         if (TIntermDeclaration *declNode = node->getAsDeclarationNode())
189         {
190             Declaration decl = ViewDeclaration(*declNode);
191             globals.insert({decl.symbol.variable().name(), declNode});
192         }
193     }
194     return globals;
195 }
196 
197 }  // namespace sh
198