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_TRANSLATORMETALDIRECT_H_ 8 #define COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_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 18 class DriverUniform; 19 class DriverUniformMetal; 20 class SpecConst; 21 class TOutputMSL; 22 class TranslatorMetalReflection; 23 typedef std::unordered_map<size_t, std::string> originalNamesMap; 24 typedef std::unordered_map<std::string, size_t> samplerBindingMap; 25 typedef std::unordered_map<std::string, size_t> textureBindingMap; 26 typedef std::unordered_map<std::string, size_t> userUniformBufferBindingMap; 27 typedef std::pair<size_t, size_t> uboBindingInfo; 28 struct UBOBindingInfo 29 { 30 size_t bindIndex = 0; 31 size_t arraySize = 0; 32 }; 33 typedef std::unordered_map<std::string, UBOBindingInfo> uniformBufferBindingMap; 34 35 namespace mtl 36 { 37 TranslatorMetalReflection *getTranslatorMetalReflection(const TCompiler *compiler); 38 } 39 40 class TranslatorMetalReflection 41 { 42 public: TranslatorMetalReflection()43 TranslatorMetalReflection() : hasUBOs(false), hasFlatInput(false) {} ~TranslatorMetalReflection()44 ~TranslatorMetalReflection() {} 45 addOriginalName(const size_t id,const std::string & name)46 void addOriginalName(const size_t id, const std::string &name) 47 { 48 originalNames.insert({id, name}); 49 } addSamplerBinding(const std::string & name,size_t samplerBinding)50 void addSamplerBinding(const std::string &name, size_t samplerBinding) 51 { 52 samplerBindings.insert({name, samplerBinding}); 53 } addTextureBinding(const std::string & name,size_t textureBinding)54 void addTextureBinding(const std::string &name, size_t textureBinding) 55 { 56 textureBindings.insert({name, textureBinding}); 57 } addUserUniformBufferBinding(const std::string & name,size_t userUniformBufferBinding)58 void addUserUniformBufferBinding(const std::string &name, size_t userUniformBufferBinding) 59 { 60 userUniformBufferBindings.insert({name, userUniformBufferBinding}); 61 } addUniformBufferBinding(const std::string & name,UBOBindingInfo bindingInfo)62 void addUniformBufferBinding(const std::string &name, UBOBindingInfo bindingInfo) 63 { 64 uniformBufferBindings.insert({name, bindingInfo}); 65 } getOriginalName(const size_t id)66 std::string getOriginalName(const size_t id) { return originalNames.at(id); } getSamplerBindings()67 samplerBindingMap getSamplerBindings() const { return samplerBindings; } getTextureBindings()68 textureBindingMap getTextureBindings() const { return textureBindings; } getUserUniformBufferBindings()69 userUniformBufferBindingMap getUserUniformBufferBindings() const 70 { 71 return userUniformBufferBindings; 72 } getUniformBufferBindings()73 uniformBufferBindingMap getUniformBufferBindings() const { return uniformBufferBindings; } getSamplerBinding(const std::string & name)74 size_t getSamplerBinding(const std::string &name) const 75 { 76 auto it = samplerBindings.find(name); 77 if (it != samplerBindings.end()) 78 { 79 return it->second; 80 } 81 // If we can't find a matching sampler, assert out on Debug, and return an invalid value on 82 // release. 83 ASSERT(0); 84 return std::numeric_limits<size_t>::max(); 85 } getTextureBinding(const std::string & name)86 size_t getTextureBinding(const std::string &name) const 87 { 88 auto it = textureBindings.find(name); 89 if (it != textureBindings.end()) 90 { 91 return it->second; 92 } 93 // If we can't find a matching texture, assert out on Debug, and return an invalid value on 94 // release. 95 ASSERT(0); 96 return std::numeric_limits<size_t>::max(); 97 } getUserUniformBufferBinding(const std::string & name)98 size_t getUserUniformBufferBinding(const std::string &name) const 99 { 100 auto it = userUniformBufferBindings.find(name); 101 if (it != userUniformBufferBindings.end()) 102 { 103 return it->second; 104 } 105 // If we can't find a matching Uniform binding, assert out on Debug, and return an invalid 106 // value. 107 ASSERT(0); 108 return std::numeric_limits<size_t>::max(); 109 } getUniformBufferBinding(const std::string & name)110 UBOBindingInfo getUniformBufferBinding(const std::string &name) const 111 { 112 auto it = uniformBufferBindings.find(name); 113 if (it != uniformBufferBindings.end()) 114 { 115 return it->second; 116 } 117 // If we can't find a matching UBO binding by name, assert out on Debug, and return an 118 // invalid value. 119 ASSERT(0); 120 return {.bindIndex = std::numeric_limits<size_t>::max(), 121 .arraySize = std::numeric_limits<size_t>::max()}; 122 } reset()123 void reset() 124 { 125 hasUBOs = false; 126 hasFlatInput = false; 127 hasAtan = false; 128 hasInvariance = false; 129 originalNames.clear(); 130 samplerBindings.clear(); 131 textureBindings.clear(); 132 userUniformBufferBindings.clear(); 133 uniformBufferBindings.clear(); 134 } 135 136 bool hasUBOs = false; 137 bool hasFlatInput = false; 138 bool hasAtan = false; 139 bool hasInvariance = false; 140 141 private: 142 originalNamesMap originalNames; 143 samplerBindingMap samplerBindings; 144 textureBindingMap textureBindings; 145 userUniformBufferBindingMap userUniformBufferBindings; 146 uniformBufferBindingMap uniformBufferBindings; 147 }; 148 149 class TranslatorMetalDirect : public TCompiler 150 { 151 public: 152 TranslatorMetalDirect(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 153 154 #ifdef ANGLE_ENABLE_METAL getAsTranslatorMetalDirect()155 TranslatorMetalDirect *getAsTranslatorMetalDirect() override { return this; } 156 #endif 157 getTranslatorMetalReflection()158 TranslatorMetalReflection *getTranslatorMetalReflection() { return &translatorMetalReflection; } 159 160 protected: 161 bool translate(TIntermBlock *root, 162 ShCompileOptions compileOptions, 163 PerformanceDiagnostics *perfDiagnostics) override; 164 165 // Need to collect variables so that RemoveInactiveInterfaceVariables works. shouldCollectVariables(ShCompileOptions compileOptions)166 bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; } 167 168 ANGLE_NO_DISCARD bool translateImpl(TInfoSinkBase &sink, 169 TIntermBlock *root, 170 ShCompileOptions compileOptions, 171 PerformanceDiagnostics *perfDiagnostics, 172 SpecConst *specConst, 173 DriverUniformMetal *driverUniforms); 174 175 ANGLE_NO_DISCARD bool shouldFlattenPragmaStdglInvariantAll() override; 176 177 ANGLE_NO_DISCARD bool transformDepthBeforeCorrection(TIntermBlock *root, 178 const DriverUniformMetal *driverUniforms); 179 180 ANGLE_NO_DISCARD bool appendVertexShaderDepthCorrectionToMain(TIntermBlock *root); 181 182 ANGLE_NO_DISCARD bool insertSampleMaskWritingLogic(TIntermBlock &root, 183 DriverUniformMetal &driverUniforms); 184 ANGLE_NO_DISCARD bool insertRasterizationDiscardLogic(TIntermBlock &root); 185 186 ANGLE_NO_DISCARD TIntermSwizzle *getDriverUniformNegFlipYRef( 187 DriverUniform &driverUniforms) const; 188 189 TranslatorMetalReflection translatorMetalReflection = {}; 190 }; 191 192 } // namespace sh 193 194 #endif // COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_H_ 195