xref: /aosp_15_r20/external/angle/src/compiler/translator/msl/TranslatorMSL.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 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_TRANSLATOR_MSL_H_
8 #define COMPILER_TRANSLATOR_MSL_H_
9 
10 #include "compiler/translator/Compiler.h"
11 
12 namespace sh
13 {
14 
15 constexpr const char kUniformsVar[]                    = "angleUniforms";
16 constexpr const char kUnassignedAttributeString[]      = " __unassigned_attribute__";
17 constexpr const char kUnassignedFragmentOutputString[] = "__unassigned_output__";
18 
19 class DriverUniform;
20 class DriverUniformMetal;
21 class SpecConst;
22 class TOutputMSL;
23 class TranslatorMetalReflection;
24 typedef std::unordered_map<size_t, std::string> originalNamesMap;
25 typedef std::unordered_map<std::string, size_t> samplerBindingMap;
26 typedef std::unordered_map<std::string, size_t> textureBindingMap;
27 typedef std::unordered_map<int, int> rwTextureBindingMap;  // GLSL image -> mtl read_write texture.
28 typedef std::unordered_map<std::string, size_t> userUniformBufferBindingMap;
29 typedef std::pair<size_t, size_t> uboBindingInfo;
30 struct UBOBindingInfo
31 {
32     size_t bindIndex = 0;
33     size_t arraySize = 0;
34 };
35 typedef std::unordered_map<std::string, UBOBindingInfo> uniformBufferBindingMap;
36 
37 namespace mtl
38 {
39 TranslatorMetalReflection *getTranslatorMetalReflection(const TCompiler *compiler);
40 }
41 
42 class TranslatorMetalReflection
43 {
44   public:
TranslatorMetalReflection()45     TranslatorMetalReflection() : hasUBOs(false), hasFlatInput(false) {}
~TranslatorMetalReflection()46     ~TranslatorMetalReflection() {}
47 
addOriginalName(const size_t id,const std::string & name)48     void addOriginalName(const size_t id, const std::string &name)
49     {
50         originalNames.insert({id, name});
51     }
addSamplerBinding(const std::string & name,size_t samplerBinding)52     void addSamplerBinding(const std::string &name, size_t samplerBinding)
53     {
54         samplerBindings.insert({name, samplerBinding});
55     }
addTextureBinding(const std::string & name,size_t textureBinding)56     void addTextureBinding(const std::string &name, size_t textureBinding)
57     {
58         textureBindings.insert({name, textureBinding});
59     }
addRWTextureBinding(int glslImageBinding,int mtlRWTextureBinding)60     void addRWTextureBinding(int glslImageBinding, int mtlRWTextureBinding)
61     {
62         bool inserted = rwTextureBindings.insert({glslImageBinding, mtlRWTextureBinding}).second;
63         if (!inserted)
64         {
65             // Shader images are currently only implemented enough to support pixel local storage,
66             // which does not allow more than one image to be bound to the same index.
67             //
68             // NOTE: Pixel local storage also does not allow image bindings to change via
69             // glUniform1i, which we do not currently account for in this backend.
70             UNIMPLEMENTED();
71         }
72     }
addUserUniformBufferBinding(const std::string & name,size_t userUniformBufferBinding)73     void addUserUniformBufferBinding(const std::string &name, size_t userUniformBufferBinding)
74     {
75         userUniformBufferBindings.insert({name, userUniformBufferBinding});
76     }
addUniformBufferBinding(const std::string & name,UBOBindingInfo bindingInfo)77     void addUniformBufferBinding(const std::string &name, UBOBindingInfo bindingInfo)
78     {
79         uniformBufferBindings.insert({name, bindingInfo});
80     }
getOriginalName(const size_t id)81     std::string getOriginalName(const size_t id) { return originalNames.at(id); }
getSamplerBindings()82     samplerBindingMap getSamplerBindings() const { return samplerBindings; }
getTextureBindings()83     textureBindingMap getTextureBindings() const { return textureBindings; }
getUserUniformBufferBindings()84     userUniformBufferBindingMap getUserUniformBufferBindings() const
85     {
86         return userUniformBufferBindings;
87     }
getUniformBufferBindings()88     uniformBufferBindingMap getUniformBufferBindings() const { return uniformBufferBindings; }
getSamplerBinding(const std::string & name)89     size_t getSamplerBinding(const std::string &name) const
90     {
91         auto it = samplerBindings.find(name);
92         if (it != samplerBindings.end())
93         {
94             return it->second;
95         }
96         // If we can't find a matching sampler, assert out on Debug, and return an invalid value on
97         // release.
98         ASSERT(0);
99         return std::numeric_limits<size_t>::max();
100     }
getTextureBinding(const std::string & name)101     size_t getTextureBinding(const std::string &name) const
102     {
103         auto it = textureBindings.find(name);
104         if (it != textureBindings.end())
105         {
106             return it->second;
107         }
108         // If we can't find a matching texture, assert out on Debug, and return an invalid value on
109         // release.
110         ASSERT(0);
111         return std::numeric_limits<size_t>::max();
112     }
getRWTextureBinding(int glslImageBinding)113     int getRWTextureBinding(int glslImageBinding) const
114     {
115         auto it = rwTextureBindings.find(glslImageBinding);
116         if (it != rwTextureBindings.end())
117         {
118             return it->second;
119         }
120         // If there isn't a shader image bound to this slot, return -1. This signals to the program
121         // that there is nothing here to bind.
122         return -1;
123     }
getUserUniformBufferBinding(const std::string & name)124     size_t getUserUniformBufferBinding(const std::string &name) const
125     {
126         auto it = userUniformBufferBindings.find(name);
127         if (it != userUniformBufferBindings.end())
128         {
129             return it->second;
130         }
131         // If we can't find a matching Uniform binding, assert out on Debug, and return an invalid
132         // value.
133         ASSERT(0);
134         return std::numeric_limits<size_t>::max();
135     }
getUniformBufferBinding(const std::string & name)136     UBOBindingInfo getUniformBufferBinding(const std::string &name) const
137     {
138         auto it = uniformBufferBindings.find(name);
139         if (it != uniformBufferBindings.end())
140         {
141             return it->second;
142         }
143         // If we can't find a matching UBO binding by name, assert out on Debug, and return an
144         // invalid value.
145         ASSERT(0);
146         return {.bindIndex = std::numeric_limits<size_t>::max(),
147                 .arraySize = std::numeric_limits<size_t>::max()};
148     }
reset()149     void reset()
150     {
151         hasUBOs              = false;
152         hasFlatInput         = false;
153         hasInvariance        = false;
154         hasIsnanOrIsinf      = false;
155         hasAttributeAliasing = false;
156         originalNames.clear();
157         samplerBindings.clear();
158         textureBindings.clear();
159         rwTextureBindings.clear();
160         userUniformBufferBindings.clear();
161         uniformBufferBindings.clear();
162     }
163 
164     bool hasUBOs              = false;
165     bool hasFlatInput         = false;
166     bool hasInvariance        = false;
167     bool hasIsnanOrIsinf      = false;
168     bool hasAttributeAliasing = false;
169 
170   private:
171     originalNamesMap originalNames;
172     samplerBindingMap samplerBindings;
173     textureBindingMap textureBindings;
174     rwTextureBindingMap rwTextureBindings;
175     userUniformBufferBindingMap userUniformBufferBindings;
176     uniformBufferBindingMap uniformBufferBindings;
177 };
178 
179 class TranslatorMSL : public TCompiler
180 {
181   public:
182     TranslatorMSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
183 
184 #ifdef ANGLE_ENABLE_METAL
getAsTranslatorMSL()185     TranslatorMSL *getAsTranslatorMSL() override { return this; }
186 #endif
187 
getTranslatorMetalReflection()188     TranslatorMetalReflection *getTranslatorMetalReflection() { return &translatorMetalReflection; }
189 
190   protected:
191     bool translate(TIntermBlock *root,
192                    const ShCompileOptions &compileOptions,
193                    PerformanceDiagnostics *perfDiagnostics) override;
194 
195     [[nodiscard]] bool translateImpl(TInfoSinkBase &sink,
196                                      TIntermBlock *root,
197                                      const ShCompileOptions &compileOptions,
198                                      PerformanceDiagnostics *perfDiagnostics,
199                                      SpecConst *specConst,
200                                      DriverUniformMetal *driverUniforms);
201 
202     [[nodiscard]] bool shouldFlattenPragmaStdglInvariantAll() override;
203 
204     [[nodiscard]] bool transformDepthBeforeCorrection(TIntermBlock *root,
205                                                       const DriverUniformMetal *driverUniforms);
206 
207     [[nodiscard]] bool appendVertexShaderDepthCorrectionToMain(
208         TIntermBlock *root,
209         const DriverUniformMetal *driverUniforms);
210 
211     [[nodiscard]] bool insertSampleMaskWritingLogic(TIntermBlock &root,
212                                                     DriverUniformMetal &driverUniforms);
213     [[nodiscard]] bool insertRasterizationDiscardLogic(TIntermBlock &root);
214 
215     TranslatorMetalReflection translatorMetalReflection = {};
216 };
217 
218 }  // namespace sh
219 
220 #endif  // COMPILER_TRANSLATOR_MSL_H_
221