tor-browser

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

NameNamelessUniformBuffers.cpp (4717B)


      1 //
      2 // Copyright 2019 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 // NameNamelessUniformBuffers: Gives nameless uniform buffer variables internal names.
      7 //
      8 
      9 #include "compiler/translator/tree_ops/NameNamelessUniformBuffers.h"
     10 
     11 #include "compiler/translator/SymbolTable.h"
     12 #include "compiler/translator/tree_util/IntermNode_util.h"
     13 #include "compiler/translator/tree_util/IntermTraverse.h"
     14 
     15 namespace sh
     16 {
     17 namespace
     18 {
     19 // Traverse uniform buffer declarations and give name to nameless declarations.  Keeps track of
     20 // the interface fields which will be used in the source without the interface block variable name
     21 // and replaces them with name.field.
     22 class NameUniformBufferVariablesTraverser : public TIntermTraverser
     23 {
     24  public:
     25    explicit NameUniformBufferVariablesTraverser(TSymbolTable *symbolTable)
     26        : TIntermTraverser(true, false, false, symbolTable)
     27    {}
     28 
     29    bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
     30    {
     31        ASSERT(visit == PreVisit);
     32 
     33        const TIntermSequence &sequence = *(decl->getSequence());
     34 
     35        TIntermTyped *variableNode = sequence.front()->getAsTyped();
     36        const TType &type          = variableNode->getType();
     37 
     38        // If it's an interface block, it may have to be converted if it contains any row-major
     39        // fields.
     40        if (!type.isInterfaceBlock())
     41        {
     42            return true;
     43        }
     44 
     45        // Multi declaration statements are already separated, so there can only be one variable
     46        // here.
     47        ASSERT(sequence.size() == 1);
     48        const TVariable *variable = &variableNode->getAsSymbolNode()->variable();
     49        if (variable->symbolType() != SymbolType::Empty)
     50        {
     51            return false;
     52        }
     53 
     54        TIntermDeclaration *newDeclaration = new TIntermDeclaration;
     55        TVariable *newVariable = new TVariable(mSymbolTable, kEmptyImmutableString, &type,
     56                                               SymbolType::AngleInternal, variable->extensions());
     57        newDeclaration->appendDeclarator(new TIntermSymbol(newVariable));
     58 
     59        queueReplacement(newDeclaration, OriginalNode::IS_DROPPED);
     60 
     61        // It's safe to key the map with the interface block, as there couldn't have been multiple
     62        // declarations with this interface block (as the variable is nameless), so for nameless
     63        // uniform buffers, the interface block is unique.
     64        mNamelessUniformBuffersMap[type.getInterfaceBlock()] = newVariable;
     65 
     66        return false;
     67    }
     68 
     69    void visitSymbol(TIntermSymbol *symbol) override
     70    {
     71        const TType &type = symbol->getType();
     72 
     73        // The symbols we are looking for have the interface block pointer set, but are not
     74        // interface blocks.  These are references to fields of nameless uniform buffers.
     75        if (type.isInterfaceBlock() || type.getInterfaceBlock() == nullptr)
     76        {
     77            return;
     78        }
     79 
     80        const TInterfaceBlock *block = type.getInterfaceBlock();
     81 
     82        // If block variable is not nameless, there's nothing to do.
     83        if (mNamelessUniformBuffersMap.count(block) == 0)
     84        {
     85            return;
     86        }
     87 
     88        const ImmutableString symbolName = symbol->getName();
     89 
     90        // Find which field it is
     91        const TVector<TField *> fields = block->fields();
     92        for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
     93        {
     94            const TField *field = fields[fieldIndex];
     95            if (field->name() != symbolName)
     96            {
     97                continue;
     98            }
     99 
    100            // Replace this node with a binary node that indexes the named uniform buffer.
    101            TIntermSymbol *namedUniformBuffer =
    102                new TIntermSymbol(mNamelessUniformBuffersMap[block]);
    103            TIntermBinary *replacement =
    104                new TIntermBinary(EOpIndexDirectInterfaceBlock, namedUniformBuffer,
    105                                  CreateIndexNode(static_cast<uint32_t>(fieldIndex)));
    106 
    107            queueReplacement(replacement, OriginalNode::IS_DROPPED);
    108 
    109            return;
    110        }
    111 
    112        UNREACHABLE();
    113    }
    114 
    115  private:
    116    // A map from nameless uniform buffers to their named replacements.
    117    std::unordered_map<const TInterfaceBlock *, const TVariable *> mNamelessUniformBuffersMap;
    118 };
    119 }  // anonymous namespace
    120 
    121 bool NameNamelessUniformBuffers(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable)
    122 {
    123    NameUniformBufferVariablesTraverser nameUniformBufferVariables(symbolTable);
    124    root->traverse(&nameUniformBufferVariables);
    125    return nameUniformBufferVariables.updateTree(compiler, root);
    126 }
    127 }  // namespace sh