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