tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SeparateStructFromUniformDeclarations.cpp (4226B)


      1 //
      2 // Copyright 2018 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 // SeparateStructFromUniformDeclarations: Separate struct declarations from uniform declarations.
      7 //
      8 
      9 #include "compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h"
     10 #include "compiler/translator/SymbolTable.h"
     11 #include "compiler/translator/tree_util/IntermTraverse.h"
     12 #include "compiler/translator/tree_util/ReplaceVariable.h"
     13 
     14 namespace sh
     15 {
     16 namespace
     17 {
     18 // This traverser translates embedded uniform structs into a specifier and declaration.
     19 // This makes the declarations easier to move into uniform blocks.
     20 class Traverser : public TIntermTraverser
     21 {
     22  public:
     23    explicit Traverser(TSymbolTable *symbolTable)
     24        : TIntermTraverser(true, false, false, symbolTable)
     25    {}
     26 
     27    bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
     28    {
     29        ASSERT(visit == PreVisit);
     30 
     31        if (!mInGlobalScope)
     32        {
     33            return true;
     34        }
     35 
     36        const TIntermSequence &sequence = *(decl->getSequence());
     37        ASSERT(sequence.size() == 1);
     38        TIntermTyped *declarator = sequence.front()->getAsTyped();
     39        const TType &type        = declarator->getType();
     40 
     41        if (type.isStructSpecifier() && type.getQualifier() == EvqUniform)
     42        {
     43            doReplacement(decl, declarator, type);
     44            return false;
     45        }
     46 
     47        return true;
     48    }
     49 
     50    void visitSymbol(TIntermSymbol *symbol) override
     51    {
     52        const TVariable *variable = &symbol->variable();
     53        if (mVariableMap.count(variable) > 0)
     54        {
     55            queueAccessChainReplacement(mVariableMap[variable]->deepCopy());
     56        }
     57    }
     58 
     59  private:
     60    void doReplacement(TIntermDeclaration *decl, TIntermTyped *declarator, const TType &oldType)
     61    {
     62        const TStructure *structure = oldType.getStruct();
     63        if (structure->symbolType() == SymbolType::Empty)
     64        {
     65            // Handle nameless structs: uniform struct { ... } variable;
     66            structure = new TStructure(mSymbolTable, kEmptyImmutableString, &structure->fields(),
     67                                       SymbolType::AngleInternal);
     68        }
     69        TType *namedType = new TType(structure, true);
     70        namedType->setQualifier(EvqGlobal);
     71 
     72        TVariable *structVariable =
     73            new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty);
     74        TIntermSymbol *structDeclarator       = new TIntermSymbol(structVariable);
     75        TIntermDeclaration *structDeclaration = new TIntermDeclaration;
     76        structDeclaration->appendDeclarator(structDeclarator);
     77 
     78        TIntermSequence newSequence;
     79        newSequence.push_back(structDeclaration);
     80 
     81        // Redeclare the uniform with the (potentially) new struct type
     82        TIntermSymbol *asSymbol = declarator->getAsSymbolNode();
     83        ASSERT(asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty);
     84 
     85        TIntermDeclaration *namedDecl = new TIntermDeclaration;
     86        TType *uniformType            = new TType(structure, false);
     87        uniformType->setQualifier(EvqUniform);
     88        uniformType->makeArrays(oldType.getArraySizes());
     89 
     90        TVariable *newVar        = new TVariable(mSymbolTable, asSymbol->getName(), uniformType,
     91                                          asSymbol->variable().symbolType());
     92        TIntermSymbol *newSymbol = new TIntermSymbol(newVar);
     93        namedDecl->appendDeclarator(newSymbol);
     94 
     95        newSequence.push_back(namedDecl);
     96 
     97        mVariableMap[&asSymbol->variable()] = newSymbol;
     98 
     99        mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl,
    100                                        std::move(newSequence));
    101    }
    102 
    103    VariableReplacementMap mVariableMap;
    104 };
    105 }  // anonymous namespace
    106 
    107 bool SeparateStructFromUniformDeclarations(TCompiler *compiler,
    108                                           TIntermBlock *root,
    109                                           TSymbolTable *symbolTable)
    110 {
    111    Traverser separateStructDecls(symbolTable);
    112    root->traverse(&separateStructDecls);
    113    return separateStructDecls.updateTree(compiler, root);
    114 }
    115 }  // namespace sh