tor-browser

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

DriverUniform.cpp (17128B)


      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 // DriverUniform.cpp: Add code to support driver uniforms
      7 //
      8 
      9 #include "compiler/translator/tree_util/DriverUniform.h"
     10 
     11 #include "compiler/translator/Compiler.h"
     12 #include "compiler/translator/IntermNode.h"
     13 #include "compiler/translator/StaticType.h"
     14 #include "compiler/translator/SymbolTable.h"
     15 #include "compiler/translator/tree_util/FindMain.h"
     16 #include "compiler/translator/tree_util/IntermNode_util.h"
     17 #include "compiler/translator/tree_util/IntermTraverse.h"
     18 #include "compiler/translator/util.h"
     19 
     20 namespace sh
     21 {
     22 
     23 namespace
     24 {
     25 constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams");
     26 
     27 constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets";
     28 constexpr const char kDepthRange[]       = "depthRange";
     29 constexpr const char kRenderArea[]       = "renderArea";
     30 constexpr const char kFlipXY[]           = "flipXY";
     31 constexpr const char kDither[]           = "dither";
     32 constexpr const char kMisc[]             = "misc";
     33 
     34 // Extended uniforms
     35 constexpr const char kXfbBufferOffsets[]       = "xfbBufferOffsets";
     36 constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance";
     37 constexpr const char kUnused[]                 = "unused";
     38 constexpr const char kUnused2[]                = "unused2";
     39 }  // anonymous namespace
     40 
     41 // Class DriverUniform
     42 bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
     43 {
     44    constexpr size_t kNumComputeDriverUniforms                                               = 1;
     45    constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = {
     46        {kAcbBufferOffsets}};
     47 
     48    ASSERT(!mDriverUniforms);
     49    // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp.
     50    TFieldList *driverFieldList = new TFieldList;
     51 
     52    const std::array<TType *, kNumComputeDriverUniforms> kDriverUniformTypes = {{
     53        new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
     54    }};
     55 
     56    for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex)
     57    {
     58        TField *driverUniformField =
     59            new TField(kDriverUniformTypes[uniformIndex],
     60                       ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(),
     61                       SymbolType::AngleInternal);
     62        driverFieldList->push_back(driverUniformField);
     63    }
     64 
     65    // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
     66    TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
     67    layoutQualifier.blockStorage     = EbsStd140;
     68    layoutQualifier.pushConstant     = true;
     69 
     70    mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
     71                                            layoutQualifier, TMemoryQualifier::Create(), 0,
     72                                            ImmutableString(vk::kDriverUniformsBlockName),
     73                                            ImmutableString(vk::kDriverUniformsVarName));
     74    return mDriverUniforms != nullptr;
     75 }
     76 
     77 TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable)
     78 {
     79    constexpr size_t kNumGraphicsDriverUniforms                                                = 6;
     80    constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {{
     81        kAcbBufferOffsets,
     82        kDepthRange,
     83        kRenderArea,
     84        kFlipXY,
     85        kDither,
     86        kMisc,
     87    }};
     88 
     89    // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp.
     90    TFieldList *driverFieldList = new TFieldList;
     91 
     92    const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
     93        // acbBufferOffsets: Packed ubyte8
     94        new TType(EbtUInt, EbpHigh, EvqGlobal, 2),
     95        // depthRange: Near and far depth
     96        new TType(EbtFloat, EbpHigh, EvqGlobal, 2),
     97        // renderArea: Packed ushort2
     98        new TType(EbtUInt, EbpHigh, EvqGlobal),
     99        // flipXY: Packed snorm4
    100        new TType(EbtUInt, EbpHigh, EvqGlobal),
    101        // dither: ushort
    102        new TType(EbtUInt, EbpHigh, EvqGlobal),
    103        // misc: Various bits of state
    104        new TType(EbtUInt, EbpHigh, EvqGlobal),
    105    }};
    106 
    107    for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
    108    {
    109        TField *driverUniformField =
    110            new TField(kDriverUniformTypes[uniformIndex],
    111                       ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(),
    112                       SymbolType::AngleInternal);
    113        driverFieldList->push_back(driverUniformField);
    114    }
    115 
    116    return driverFieldList;
    117 }
    118 
    119 const TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable)
    120 {
    121    // If already defined, return it immediately.
    122    if (mEmulatedDepthRangeType != nullptr)
    123    {
    124        return mEmulatedDepthRangeType;
    125    }
    126 
    127    // Create the depth range type.
    128    TFieldList *depthRangeParamsFields = new TFieldList();
    129    TType *floatType                   = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1);
    130    depthRangeParamsFields->push_back(
    131        new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal));
    132    depthRangeParamsFields->push_back(
    133        new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal));
    134    depthRangeParamsFields->push_back(
    135        new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal));
    136 
    137    TStructure *emulatedDepthRangeParams = new TStructure(
    138        symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
    139 
    140    mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
    141 
    142    return mEmulatedDepthRangeType;
    143 }
    144 
    145 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver
    146 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
    147 // variable.
    148 //
    149 // There are Graphics and Compute variations as they require different uniforms.
    150 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
    151 {
    152    ASSERT(!mDriverUniforms);
    153 
    154    // Declare the depth range struct type.
    155    const TType *emulatedDepthRangeType     = createEmulatedDepthRangeType(symbolTable);
    156    const TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true);
    157 
    158    const TVariable *depthRangeVar =
    159        new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
    160                      TExtension::UNDEFINED, emulatedDepthRangeDeclType);
    161 
    162    DeclareGlobalVariable(root, depthRangeVar);
    163 
    164    TFieldList *driverFieldList = createUniformFields(symbolTable);
    165    if (mMode == DriverUniformMode::InterfaceBlock)
    166    {
    167        // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
    168        TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
    169        layoutQualifier.blockStorage     = EbsStd140;
    170        layoutQualifier.pushConstant     = true;
    171 
    172        mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
    173                                                layoutQualifier, TMemoryQualifier::Create(), 0,
    174                                                ImmutableString(vk::kDriverUniformsBlockName),
    175                                                ImmutableString(vk::kDriverUniformsVarName));
    176    }
    177    else
    178    {
    179        // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms".
    180        // This code path is taken only by the direct-to-Metal backend, and the assumptions
    181        // about the naming conventions of ANGLE-internal variables run too deeply to rename
    182        // this one.
    183        auto varName    = ImmutableString("ANGLE_angleUniforms");
    184        auto result     = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform,
    185                                           TMemoryQualifier::Create(), 0,
    186                                           ImmutableString(vk::kDriverUniformsBlockName), &varName);
    187        mDriverUniforms = result.second;
    188    }
    189 
    190    return mDriverUniforms != nullptr;
    191 }
    192 
    193 TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const
    194 {
    195    size_t fieldIndex = 0;
    196    if (mMode == DriverUniformMode::InterfaceBlock)
    197    {
    198        fieldIndex =
    199            FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName);
    200    }
    201    else
    202    {
    203        fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName);
    204    }
    205 
    206    TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms);
    207    TConstantUnion *uniformIndex    = new TConstantUnion;
    208    uniformIndex->setIConst(static_cast<int>(fieldIndex));
    209    TIntermConstantUnion *indexRef =
    210        new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>());
    211    if (mMode == DriverUniformMode::InterfaceBlock)
    212    {
    213        return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
    214    }
    215    return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef);
    216 }
    217 
    218 TIntermTyped *DriverUniform::getAcbBufferOffsets() const
    219 {
    220    return createDriverUniformRef(kAcbBufferOffsets);
    221 }
    222 
    223 TIntermTyped *DriverUniform::getDepthRange() const
    224 {
    225    ASSERT(mEmulatedDepthRangeType != nullptr);
    226 
    227    TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange);
    228    TIntermTyped *nearRef       = new TIntermSwizzle(depthRangeRef, {0});
    229    TIntermTyped *farRef        = new TIntermSwizzle(depthRangeRef->deepCopy(), {1});
    230    TIntermTyped *diff          = new TIntermBinary(EOpSub, farRef, nearRef);
    231 
    232    TIntermSequence args = {
    233        nearRef->deepCopy(),
    234        farRef->deepCopy(),
    235        diff,
    236    };
    237 
    238    return TIntermAggregate::CreateConstructor(*mEmulatedDepthRangeType, &args);
    239 }
    240 
    241 TIntermTyped *DriverUniform::getViewportZScale() const
    242 {
    243    ASSERT(mEmulatedDepthRangeType != nullptr);
    244 
    245    TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange);
    246    TIntermTyped *nearRef       = new TIntermSwizzle(depthRangeRef, {0});
    247    TIntermTyped *farRef        = new TIntermSwizzle(depthRangeRef->deepCopy(), {1});
    248 
    249    TIntermTyped *isNegative = new TIntermBinary(EOpLessThan, farRef, nearRef);
    250 
    251    return new TIntermTernary(isNegative, CreateFloatNode(-1, EbpMedium),
    252                              CreateFloatNode(1, EbpMedium));
    253 }
    254 
    255 TIntermTyped *DriverUniform::getHalfRenderArea() const
    256 {
    257    TIntermTyped *renderAreaRef = createDriverUniformRef(kRenderArea);
    258    TIntermTyped *width = new TIntermBinary(EOpBitwiseAnd, renderAreaRef, CreateUIntNode(0xFFFF));
    259    TIntermTyped *height =
    260        new TIntermBinary(EOpBitShiftRight, renderAreaRef->deepCopy(), CreateUIntNode(16));
    261 
    262    TIntermSequence widthArgs = {
    263        width,
    264    };
    265    TIntermTyped *widthAsFloat =
    266        TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh>(), &widthArgs);
    267 
    268    TIntermSequence heightArgs = {
    269        height,
    270    };
    271    TIntermTyped *heightAsFloat = TIntermAggregate::CreateConstructor(
    272        *StaticType::GetBasic<EbtFloat, EbpHigh>(), &heightArgs);
    273 
    274    TIntermSequence args = {
    275        widthAsFloat,
    276        heightAsFloat,
    277    };
    278 
    279    TIntermTyped *renderArea =
    280        TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh, 2>(), &args);
    281    return new TIntermBinary(EOpVectorTimesScalar, renderArea, CreateFloatNode(0.5, EbpMedium));
    282 }
    283 
    284 TIntermTyped *DriverUniform::getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const
    285 {
    286    TIntermTyped *flipXY = createDriverUniformRef(kFlipXY);
    287    TIntermTyped *values = CreateBuiltInUnaryFunctionCallNode(
    288        "unpackSnorm4x8", flipXY, *symbolTable,
    289        GetESSLOrGLSLVersion(symbolTable->getShaderSpec(), 310, 400));
    290 
    291    if (stage == DriverUniformFlip::Fragment)
    292    {
    293        return new TIntermSwizzle(values, {0, 1});
    294    }
    295 
    296    return new TIntermSwizzle(values, {2, 3});
    297 }
    298 
    299 TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const
    300 {
    301    TIntermTyped *flipXY = getFlipXY(symbolTable, stage);
    302 
    303    constexpr std::array<float, 2> kMultiplier = {1, -1};
    304    return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow));
    305 }
    306 
    307 TIntermTyped *DriverUniform::getDither() const
    308 {
    309    return createDriverUniformRef(kDither);
    310 }
    311 
    312 TIntermTyped *DriverUniform::getSwapXY() const
    313 {
    314    TIntermTyped *miscRef = createDriverUniformRef(kMisc);
    315    TIntermTyped *swapXY  = new TIntermBinary(EOpBitwiseAnd, miscRef,
    316                                              CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask));
    317 
    318    TIntermSequence args = {
    319        swapXY,
    320    };
    321    return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
    322                                               &args);
    323 }
    324 
    325 TIntermTyped *DriverUniform::getAdvancedBlendEquation() const
    326 {
    327    TIntermTyped *miscRef = createDriverUniformRef(kMisc);
    328    TIntermTyped *equation =
    329        new TIntermBinary(EOpBitShiftRight, miscRef,
    330                          CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset));
    331    equation = new TIntermBinary(EOpBitwiseAnd, equation,
    332                                 CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask));
    333 
    334    return equation;
    335 }
    336 
    337 TIntermTyped *DriverUniform::getNumSamples() const
    338 {
    339    TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
    340    TIntermTyped *sampleCount = new TIntermBinary(
    341        EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset));
    342    sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount,
    343                                    CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask));
    344 
    345    return sampleCount;
    346 }
    347 
    348 TIntermTyped *DriverUniform::getClipDistancesEnabled() const
    349 {
    350    TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
    351    TIntermTyped *enabledMask = new TIntermBinary(
    352        EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset));
    353    enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask,
    354                                    CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask));
    355 
    356    return enabledMask;
    357 }
    358 
    359 TIntermTyped *DriverUniform::getTransformDepth() const
    360 {
    361    TIntermTyped *miscRef        = createDriverUniformRef(kMisc);
    362    TIntermTyped *transformDepth = new TIntermBinary(
    363        EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset));
    364    transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth,
    365                                       CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask));
    366 
    367    TIntermSequence args = {
    368        transformDepth,
    369    };
    370    return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
    371                                               &args);
    372 }
    373 
    374 //
    375 // Class DriverUniformExtended
    376 //
    377 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
    378 {
    379    TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
    380 
    381    constexpr size_t kNumGraphicsDriverUniformsExt = 4;
    382    constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
    383        kGraphicsDriverUniformNamesExt = {
    384            {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}};
    385 
    386    const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
    387        // xfbBufferOffsets: uvec4
    388        new TType(EbtInt, EbpHigh, EvqGlobal, 4),
    389        // xfbVerticesPerInstance: uint
    390        new TType(EbtInt, EbpHigh, EvqGlobal),
    391        // unused: uvec3
    392        new TType(EbtUInt, EbpHigh, EvqGlobal),
    393        new TType(EbtUInt, EbpHigh, EvqGlobal, 2),
    394    }};
    395 
    396    for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
    397    {
    398        TField *driverUniformField =
    399            new TField(kDriverUniformTypesExt[uniformIndex],
    400                       ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
    401                       SymbolType::AngleInternal);
    402        driverFieldList->push_back(driverUniformField);
    403    }
    404 
    405    return driverFieldList;
    406 }
    407 
    408 TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const
    409 {
    410    return createDriverUniformRef(kXfbBufferOffsets);
    411 }
    412 
    413 TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const
    414 {
    415    return createDriverUniformRef(kXfbVerticesPerInstance);
    416 }
    417 
    418 TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped)
    419 {
    420    // float(!swapped)
    421    TIntermSequence args = {
    422        new TIntermUnary(EOpLogicalNot, swapped, nullptr),
    423    };
    424    return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
    425 }
    426 
    427 TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped)
    428 {
    429    // float(swapped)
    430    TIntermSequence args = {
    431        swapped,
    432    };
    433    return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
    434 }
    435 }  // namespace sh