tor-browser

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

DeclareAndInitBuiltinsForInstancedMultiview.cpp (9450B)


      1 //
      2 // Copyright 2017 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 // Applies the necessary AST transformations to support multiview rendering through instancing.
      7 // Check the header file For more information.
      8 //
      9 
     10 #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
     11 
     12 #include "compiler/translator/Compiler.h"
     13 #include "compiler/translator/StaticType.h"
     14 #include "compiler/translator/SymbolTable.h"
     15 #include "compiler/translator/tree_ops/InitializeVariables.h"
     16 #include "compiler/translator/tree_util/BuiltIn.h"
     17 #include "compiler/translator/tree_util/FindMain.h"
     18 #include "compiler/translator/tree_util/IntermNode_util.h"
     19 #include "compiler/translator/tree_util/IntermTraverse.h"
     20 #include "compiler/translator/tree_util/ReplaceVariable.h"
     21 #include "compiler/translator/util.h"
     22 
     23 namespace sh
     24 {
     25 
     26 namespace
     27 {
     28 
     29 constexpr const ImmutableString kViewIDVariableName("ViewID_OVR");
     30 constexpr const ImmutableString kInstanceIDVariableName("InstanceID");
     31 constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName(
     32    "multiviewBaseViewLayerIndex");
     33 
     34 // Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
     35 void InitializeViewIDAndInstanceID(const TVariable *viewID,
     36                                   const TVariable *instanceID,
     37                                   unsigned numberOfViews,
     38                                   const TSymbolTable &symbolTable,
     39                                   TIntermSequence *initializers)
     40 {
     41    // Create an unsigned numberOfViews node.
     42    TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion();
     43    numberOfViewsUnsignedConstant->setUConst(numberOfViews);
     44    TIntermConstantUnion *numberOfViewsUint =
     45        new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpLow, EvqConst));
     46 
     47    // Create a uint(gl_InstanceID) node.
     48    TIntermSequence glInstanceIDSymbolCastArguments;
     49    glInstanceIDSymbolCastArguments.push_back(new TIntermSymbol(BuiltInVariable::gl_InstanceID()));
     50    TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
     51        TType(EbtUInt, EbpHigh, EvqTemporary), &glInstanceIDSymbolCastArguments);
     52 
     53    // Create a uint(gl_InstanceID) / numberOfViews node.
     54    TIntermBinary *normalizedInstanceID =
     55        new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint);
     56 
     57    // Create an int(uint(gl_InstanceID) / numberOfViews) node.
     58    TIntermSequence normalizedInstanceIDCastArguments;
     59    normalizedInstanceIDCastArguments.push_back(normalizedInstanceID);
     60    TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor(
     61        TType(EbtInt, EbpHigh, EvqTemporary), &normalizedInstanceIDCastArguments);
     62 
     63    // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node.
     64    TIntermBinary *instanceIDInitializer =
     65        new TIntermBinary(EOpAssign, new TIntermSymbol(instanceID), normalizedInstanceIDAsInt);
     66    initializers->push_back(instanceIDInitializer);
     67 
     68    // Create a uint(gl_InstanceID) % numberOfViews node.
     69    TIntermBinary *normalizedViewID =
     70        new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy());
     71 
     72    // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
     73    TIntermBinary *viewIDInitializer =
     74        new TIntermBinary(EOpAssign, new TIntermSymbol(viewID), normalizedViewID);
     75    initializers->push_back(viewIDInitializer);
     76 }
     77 
     78 // Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is
     79 // added to the end of the initializers' sequence.
     80 void SelectViewIndexInVertexShader(const TVariable *viewID,
     81                                   const TVariable *multiviewBaseViewLayerIndex,
     82                                   TIntermSequence *initializers,
     83                                   const TSymbolTable &symbolTable)
     84 {
     85    // Create an int(ViewID_OVR) node.
     86    TIntermSequence viewIDSymbolCastArguments;
     87    viewIDSymbolCastArguments.push_back(new TIntermSymbol(viewID));
     88    TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
     89        TType(EbtInt, EbpHigh, EvqTemporary), &viewIDSymbolCastArguments);
     90 
     91    // Create a gl_ViewportIndex node.
     92    TIntermSymbol *viewportIndexSymbol = new TIntermSymbol(BuiltInVariable::gl_ViewportIndex());
     93 
     94    // Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
     95    TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
     96    viewportIndexInitializerInBlock->appendStatement(
     97        new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
     98 
     99    // Create a gl_Layer node.
    100    TIntermSymbol *layerSymbol = new TIntermSymbol(BuiltInVariable::gl_LayerVS());
    101 
    102    // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
    103    TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
    104        EOpAdd, viewIDAsInt->deepCopy(), new TIntermSymbol(multiviewBaseViewLayerIndex));
    105 
    106    // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node.
    107    TIntermBlock *layerInitializerInBlock = new TIntermBlock();
    108    layerInitializerInBlock->appendStatement(
    109        new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex));
    110 
    111    // Create a node to compare whether the base view index uniform is less than zero.
    112    TIntermBinary *multiviewBaseViewLayerIndexZeroComparison =
    113        new TIntermBinary(EOpLessThan, new TIntermSymbol(multiviewBaseViewLayerIndex),
    114                          CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst)));
    115 
    116    // Create an if-else statement to select the code path.
    117    TIntermIfElse *multiviewBranch =
    118        new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison,
    119                          viewportIndexInitializerInBlock, layerInitializerInBlock);
    120 
    121    initializers->push_back(multiviewBranch);
    122 }
    123 
    124 }  // namespace
    125 
    126 bool DeclareAndInitBuiltinsForInstancedMultiview(TCompiler *compiler,
    127                                                 TIntermBlock *root,
    128                                                 unsigned numberOfViews,
    129                                                 GLenum shaderType,
    130                                                 const ShCompileOptions &compileOptions,
    131                                                 ShShaderOutput shaderOutput,
    132                                                 TSymbolTable *symbolTable)
    133 {
    134    ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
    135 
    136    TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
    137    const TVariable *viewID =
    138        new TVariable(symbolTable, kViewIDVariableName,
    139                      new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal);
    140 
    141    DeclareGlobalVariable(root, viewID);
    142    if (!ReplaceVariable(compiler, root, BuiltInVariable::gl_ViewID_OVR(), viewID))
    143    {
    144        return false;
    145    }
    146    if (shaderType == GL_VERTEX_SHADER)
    147    {
    148        // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
    149        // InstanceID and ViewID.
    150        const TType *instanceIDVariableType = StaticType::Get<EbtInt, EbpHigh, EvqGlobal, 1, 1>();
    151        const TVariable *instanceID =
    152            new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType,
    153                          SymbolType::AngleInternal);
    154        DeclareGlobalVariable(root, instanceID);
    155        if (!ReplaceVariable(compiler, root, BuiltInVariable::gl_InstanceID(), instanceID))
    156        {
    157            return false;
    158        }
    159 
    160        TIntermSequence initializers;
    161        InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
    162                                      &initializers);
    163 
    164        // The AST transformation which adds the expression to select the viewport index should
    165        // be done only for the GLSL and ESSL output.
    166        const bool selectView = compileOptions.selectViewInNvGLSLVertexShader;
    167        // Assert that if the view is selected in the vertex shader, then the output is
    168        // either GLSL or ESSL.
    169        ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput));
    170        if (selectView)
    171        {
    172            // Add a uniform to switch between side-by-side and layered rendering.
    173            const TType *baseLayerIndexVariableType =
    174                StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
    175            const TVariable *multiviewBaseViewLayerIndex =
    176                new TVariable(symbolTable, kMultiviewBaseViewLayerIndexVariableName,
    177                              baseLayerIndexVariableType, SymbolType::AngleInternal);
    178            DeclareGlobalVariable(root, multiviewBaseViewLayerIndex);
    179 
    180            // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
    181            // initialization.
    182            SelectViewIndexInVertexShader(viewID, multiviewBaseViewLayerIndex, &initializers,
    183                                          *symbolTable);
    184        }
    185 
    186        // Insert initializers at the beginning of main().
    187        TIntermBlock *initializersBlock = new TIntermBlock();
    188        initializersBlock->getSequence()->swap(initializers);
    189        TIntermBlock *mainBody = FindMainBody(root);
    190        mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock);
    191    }
    192 
    193    return compiler->validateAST(root);
    194 }
    195 
    196 }  // namespace sh