RewriteSampleMaskVariable.cpp (6909B)
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 // RewriteSampleMaskVariable.cpp: Find any references to gl_SampleMask and gl_SampleMaskIn, and 7 // rewrite it with ANGLESampleMask or ANGLESampleMaskIn. 8 // 9 10 #include "compiler/translator/tree_util/RewriteSampleMaskVariable.h" 11 12 #include "common/bitset_utils.h" 13 #include "common/debug.h" 14 #include "common/utilities.h" 15 #include "compiler/translator/Compiler.h" 16 #include "compiler/translator/SymbolTable.h" 17 #include "compiler/translator/tree_util/BuiltIn.h" 18 #include "compiler/translator/tree_util/IntermNode_util.h" 19 #include "compiler/translator/tree_util/IntermTraverse.h" 20 #include "compiler/translator/tree_util/RunAtTheEndOfShader.h" 21 22 namespace sh 23 { 24 namespace 25 { 26 constexpr int kMaxIndexForSampleMaskVar = 0; 27 constexpr int kFullSampleMask = 0xFFFFFFFF; 28 29 // Traverse the tree and collect the redeclaration and replace all non constant index references of 30 // gl_SampleMask or gl_SampleMaskIn with constant index references 31 class GLSampleMaskRelatedReferenceTraverser : public TIntermTraverser 32 { 33 public: 34 GLSampleMaskRelatedReferenceTraverser(const TIntermSymbol **redeclaredSymOut, 35 const ImmutableString &targetStr) 36 : TIntermTraverser(true, false, false), 37 mRedeclaredSym(redeclaredSymOut), 38 mTargetStr(targetStr) 39 { 40 *mRedeclaredSym = nullptr; 41 } 42 43 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override 44 { 45 // If gl_SampleMask is redeclared, we need to collect its information 46 const TIntermSequence &sequence = *(node->getSequence()); 47 48 if (sequence.size() != 1) 49 { 50 return true; 51 } 52 53 TIntermTyped *variable = sequence.front()->getAsTyped(); 54 TIntermSymbol *symbol = variable->getAsSymbolNode(); 55 if (symbol == nullptr || symbol->getName() != mTargetStr) 56 { 57 return true; 58 } 59 60 *mRedeclaredSym = symbol; 61 62 return true; 63 } 64 65 bool visitBinary(Visit visit, TIntermBinary *node) override 66 { 67 TOperator op = node->getOp(); 68 if (op != EOpIndexDirect && op != EOpIndexIndirect) 69 { 70 return true; 71 } 72 TIntermSymbol *left = node->getLeft()->getAsSymbolNode(); 73 if (!left) 74 { 75 return true; 76 } 77 if (left->getName() != mTargetStr) 78 { 79 return true; 80 } 81 const TConstantUnion *constIdx = node->getRight()->getConstantValue(); 82 if (!constIdx) 83 { 84 if (node->getRight()->hasSideEffects()) 85 { 86 insertStatementInParentBlock(node->getRight()); 87 } 88 89 queueReplacementWithParent(node, node->getRight(), 90 CreateIndexNode(kMaxIndexForSampleMaskVar), 91 OriginalNode::IS_DROPPED); 92 } 93 94 return true; 95 } 96 97 private: 98 const TIntermSymbol **mRedeclaredSym; 99 const ImmutableString mTargetStr; 100 }; 101 102 } // anonymous namespace 103 104 [[nodiscard]] bool RewriteSampleMask(TCompiler *compiler, 105 TIntermBlock *root, 106 TSymbolTable *symbolTable, 107 const TIntermTyped *numSamplesUniform) 108 { 109 const TIntermSymbol *redeclaredGLSampleMask = nullptr; 110 GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMask, 111 ImmutableString("gl_SampleMask")); 112 113 root->traverse(&indexTraverser); 114 if (!indexTraverser.updateTree(compiler, root)) 115 { 116 return false; 117 } 118 119 // Retrieve gl_SampleMask variable reference 120 // Search user redeclared it first 121 const TVariable *glSampleMaskVar = nullptr; 122 if (redeclaredGLSampleMask) 123 { 124 glSampleMaskVar = &redeclaredGLSampleMask->variable(); 125 } 126 else 127 { 128 // User defined not found, find in built-in table 129 glSampleMaskVar = static_cast<const TVariable *>(symbolTable->findBuiltIn( 130 ImmutableString("gl_SampleMask"), compiler->getShaderVersion())); 131 } 132 if (!glSampleMaskVar) 133 { 134 return false; 135 } 136 137 // Current ANGLE assumes that the maximum number of samples is less than or equal to 138 // VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one. 139 const unsigned int arraySizeOfSampleMask = glSampleMaskVar->getType().getOutermostArraySize(); 140 ASSERT(arraySizeOfSampleMask == 1); 141 142 TIntermSymbol *glSampleMaskSymbol = new TIntermSymbol(glSampleMaskVar); 143 144 // if (ANGLEUniforms.numSamples == 1) 145 // { 146 // gl_SampleMask[0] = int(0xFFFFFFFF); 147 // } 148 TIntermConstantUnion *singleSampleCount = CreateUIntNode(1); 149 TIntermBinary *equalTo = 150 new TIntermBinary(EOpEqual, numSamplesUniform->deepCopy(), singleSampleCount); 151 152 TIntermBlock *trueBlock = new TIntermBlock(); 153 154 TIntermBinary *sampleMaskVar = new TIntermBinary(EOpIndexDirect, glSampleMaskSymbol->deepCopy(), 155 CreateIndexNode(kMaxIndexForSampleMaskVar)); 156 TIntermConstantUnion *fullSampleMask = CreateIndexNode(kFullSampleMask); 157 TIntermBinary *assignment = new TIntermBinary(EOpAssign, sampleMaskVar, fullSampleMask); 158 159 trueBlock->appendStatement(assignment); 160 161 TIntermIfElse *multiSampleOrNot = new TIntermIfElse(equalTo, trueBlock, nullptr); 162 163 return RunAtTheEndOfShader(compiler, root, multiSampleOrNot, symbolTable); 164 } 165 166 [[nodiscard]] bool RewriteSampleMaskIn(TCompiler *compiler, 167 TIntermBlock *root, 168 TSymbolTable *symbolTable) 169 { 170 const TIntermSymbol *redeclaredGLSampleMaskIn = nullptr; 171 GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMaskIn, 172 ImmutableString("gl_SampleMaskIn")); 173 174 root->traverse(&indexTraverser); 175 if (!indexTraverser.updateTree(compiler, root)) 176 { 177 return false; 178 } 179 180 // Retrieve gl_SampleMaskIn variable reference 181 const TVariable *glSampleMaskInVar = nullptr; 182 glSampleMaskInVar = static_cast<const TVariable *>( 183 symbolTable->findBuiltIn(ImmutableString("gl_SampleMaskIn"), compiler->getShaderVersion())); 184 if (!glSampleMaskInVar) 185 { 186 return false; 187 } 188 189 // Current ANGLE assumes that the maximum number of samples is less than or equal to 190 // VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one. 191 const unsigned int arraySizeOfSampleMaskIn = 192 glSampleMaskInVar->getType().getOutermostArraySize(); 193 ASSERT(arraySizeOfSampleMaskIn == 1); 194 195 return true; 196 } 197 198 } // namespace sh