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