tor-browser

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

InputLayoutCache.cpp (12547B)


      1 //
      2 // Copyright 2012 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 
      7 // InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
      8 // D3D11 input layouts.
      9 
     10 #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
     11 
     12 #include "common/bitset_utils.h"
     13 #include "common/utilities.h"
     14 #include "libANGLE/Context.h"
     15 #include "libANGLE/Program.h"
     16 #include "libANGLE/VertexArray.h"
     17 #include "libANGLE/VertexAttribute.h"
     18 #include "libANGLE/renderer/d3d/IndexDataManager.h"
     19 #include "libANGLE/renderer/d3d/ProgramD3D.h"
     20 #include "libANGLE/renderer/d3d/VertexDataManager.h"
     21 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     22 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     23 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
     24 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
     25 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
     26 
     27 namespace rx
     28 {
     29 
     30 namespace
     31 {
     32 
     33 GLenum GetGLSLAttributeType(const std::vector<sh::ShaderVariable> &shaderAttributes, size_t index)
     34 {
     35    // Count matrices differently
     36    for (const sh::ShaderVariable &attrib : shaderAttributes)
     37    {
     38        if (attrib.location == -1)
     39        {
     40            continue;
     41        }
     42 
     43        GLenum transposedType = gl::TransposeMatrixType(attrib.type);
     44        int rows              = gl::VariableRowCount(transposedType);
     45        int intIndex          = static_cast<int>(index);
     46 
     47        if (intIndex >= attrib.location && intIndex < attrib.location + rows)
     48        {
     49            return transposedType;
     50        }
     51    }
     52 
     53    UNREACHABLE();
     54    return GL_NONE;
     55 }
     56 
     57 struct PackedAttribute
     58 {
     59    uint8_t attribType;
     60    uint8_t semanticIndex;
     61    uint8_t vertexFormatType;
     62    uint8_t unusedPadding;
     63    uint32_t divisor;
     64 };
     65 
     66 }  // anonymous namespace
     67 
     68 PackedAttributeLayout::PackedAttributeLayout() : numAttributes(0), flags(0), attributeData({}) {}
     69 
     70 PackedAttributeLayout::PackedAttributeLayout(const PackedAttributeLayout &other) = default;
     71 
     72 void PackedAttributeLayout::addAttributeData(GLenum glType,
     73                                             UINT semanticIndex,
     74                                             angle::FormatID vertexFormatID,
     75                                             unsigned int divisor)
     76 {
     77    gl::AttributeType attribType = gl::GetAttributeType(glType);
     78 
     79    PackedAttribute packedAttrib;
     80    packedAttrib.attribType       = static_cast<uint8_t>(attribType);
     81    packedAttrib.semanticIndex    = static_cast<uint8_t>(semanticIndex);
     82    packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatID);
     83    packedAttrib.unusedPadding    = 0u;
     84    packedAttrib.divisor          = static_cast<uint32_t>(divisor);
     85 
     86    ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType);
     87    ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex);
     88    ASSERT(static_cast<angle::FormatID>(packedAttrib.vertexFormatType) == vertexFormatID);
     89    ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor);
     90 
     91    static_assert(sizeof(uint64_t) == sizeof(PackedAttribute),
     92                  "PackedAttributes must be 64-bits exactly.");
     93 
     94    attributeData[numAttributes++] = gl::bitCast<uint64_t>(packedAttrib);
     95 }
     96 
     97 bool PackedAttributeLayout::operator==(const PackedAttributeLayout &other) const
     98 {
     99    return (numAttributes == other.numAttributes) && (flags == other.flags) &&
    100           (attributeData == other.attributeData);
    101 }
    102 
    103 InputLayoutCache::InputLayoutCache() : mLayoutCache(kDefaultCacheSize * 2) {}
    104 
    105 InputLayoutCache::~InputLayoutCache() {}
    106 
    107 void InputLayoutCache::clear()
    108 {
    109    mLayoutCache.Clear();
    110 }
    111 
    112 angle::Result InputLayoutCache::getInputLayout(
    113    Context11 *context11,
    114    const gl::State &state,
    115    const std::vector<const TranslatedAttribute *> &currentAttributes,
    116    const AttribIndexArray &sortedSemanticIndices,
    117    gl::PrimitiveMode mode,
    118    GLsizei vertexCount,
    119    GLsizei instances,
    120    const d3d11::InputLayout **inputLayoutOut)
    121 {
    122    gl::Program *program         = state.getProgram();
    123    const auto &shaderAttributes = program->getAttributes();
    124    PackedAttributeLayout layout;
    125 
    126    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    127    bool programUsesInstancedPointSprites =
    128        programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
    129    bool instancedPointSpritesActive =
    130        programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);
    131 
    132    if (programUsesInstancedPointSprites)
    133    {
    134        layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES;
    135    }
    136 
    137    if (instancedPointSpritesActive)
    138    {
    139        layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
    140    }
    141 
    142    if (instances > 0)
    143    {
    144        layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
    145    }
    146 
    147    const auto &attribs            = state.getVertexArray()->getVertexAttributes();
    148    const auto &bindings           = state.getVertexArray()->getVertexBindings();
    149    const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
    150    int divisorMultiplier          = program->usesMultiview() ? program->getNumViews() : 1;
    151 
    152    for (size_t attribIndex : state.getProgramExecutable()->getActiveAttribLocationsMask())
    153    {
    154        // Record the type of the associated vertex shader vector in our key
    155        // This will prevent mismatched vertex shaders from using the same input layout
    156        GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex);
    157 
    158        const auto &attrib  = attribs[attribIndex];
    159        const auto &binding = bindings[attrib.bindingIndex];
    160        int d3dSemantic     = locationToSemantic[attribIndex];
    161 
    162        const auto &currentValue =
    163            state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
    164        angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, currentValue.Type);
    165 
    166        layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatID,
    167                                binding.getDivisor() * divisorMultiplier);
    168    }
    169 
    170    if (layout.numAttributes > 0 || layout.flags != 0)
    171    {
    172        auto it = mLayoutCache.Get(layout);
    173        if (it != mLayoutCache.end())
    174        {
    175            *inputLayoutOut = &it->second;
    176        }
    177        else
    178        {
    179            angle::TrimCache(mLayoutCache.max_size() / 2, kGCLimit, "input layout", &mLayoutCache);
    180 
    181            d3d11::InputLayout newInputLayout;
    182            ANGLE_TRY(createInputLayout(context11, sortedSemanticIndices, currentAttributes, mode,
    183                                        vertexCount, instances, &newInputLayout));
    184 
    185            auto insertIt   = mLayoutCache.Put(layout, std::move(newInputLayout));
    186            *inputLayoutOut = &insertIt->second;
    187        }
    188    }
    189 
    190    return angle::Result::Continue;
    191 }
    192 
    193 angle::Result InputLayoutCache::createInputLayout(
    194    Context11 *context11,
    195    const AttribIndexArray &sortedSemanticIndices,
    196    const std::vector<const TranslatedAttribute *> &currentAttributes,
    197    gl::PrimitiveMode mode,
    198    GLsizei vertexCount,
    199    GLsizei instances,
    200    d3d11::InputLayout *inputLayoutOut)
    201 {
    202    Renderer11 *renderer           = context11->getRenderer();
    203    ProgramD3D *programD3D         = renderer->getStateManager()->getProgramD3D();
    204    D3D_FEATURE_LEVEL featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
    205 
    206    bool programUsesInstancedPointSprites =
    207        programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
    208 
    209    unsigned int inputElementCount = 0;
    210    gl::AttribArray<D3D11_INPUT_ELEMENT_DESC> inputElements;
    211 
    212    for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex)
    213    {
    214        const auto &attrib    = *currentAttributes[attribIndex];
    215        const int sortedIndex = sortedSemanticIndices[attribIndex];
    216 
    217        D3D11_INPUT_CLASSIFICATION inputClass =
    218            attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
    219 
    220        angle::FormatID vertexFormatID =
    221            gl::GetVertexFormatID(*attrib.attribute, attrib.currentValueType);
    222        const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatID, featureLevel);
    223 
    224        auto *inputElement = &inputElements[inputElementCount];
    225 
    226        inputElement->SemanticName         = "TEXCOORD";
    227        inputElement->SemanticIndex        = sortedIndex;
    228        inputElement->Format               = vertexFormatInfo.nativeFormat;
    229        inputElement->InputSlot            = static_cast<UINT>(attribIndex);
    230        inputElement->AlignedByteOffset    = 0;
    231        inputElement->InputSlotClass       = inputClass;
    232        inputElement->InstanceDataStepRate = attrib.divisor;
    233 
    234        inputElementCount++;
    235    }
    236 
    237    // Instanced PointSprite emulation requires additional entries in the
    238    // inputlayout to support the vertices that make up the pointsprite quad.
    239    // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the
    240    // input layout must match the shader
    241    if (programUsesInstancedPointSprites)
    242    {
    243        // On 9_3, we must ensure that slot 0 contains non-instanced data.
    244        // If slot 0 currently contains instanced data then we swap it with a non-instanced element.
    245        // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3
    246        // doesn't support OpenGL ES 3.0.
    247        // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced
    248        // simultaneously, so a non-instanced element must exist.
    249 
    250        UINT numIndicesPerInstance = 0;
    251        if (instances > 0)
    252        {
    253            // This requires that the index range is resolved.
    254            // Note: Vertex indexes can be arbitrarily large.
    255            numIndicesPerInstance = gl::clampCast<UINT>(vertexCount);
    256        }
    257 
    258        for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex)
    259        {
    260            // If rendering points and instanced pointsprite emulation is being used, the
    261            // inputClass is required to be configured as per instance data
    262            if (mode == gl::PrimitiveMode::Points)
    263            {
    264                inputElements[elementIndex].InputSlotClass       = D3D11_INPUT_PER_INSTANCE_DATA;
    265                inputElements[elementIndex].InstanceDataStepRate = 1;
    266                if (numIndicesPerInstance > 0 && currentAttributes[elementIndex]->divisor > 0)
    267                {
    268                    inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
    269                }
    270            }
    271            inputElements[elementIndex].InputSlot++;
    272        }
    273 
    274        inputElements[inputElementCount].SemanticName         = "SPRITEPOSITION";
    275        inputElements[inputElementCount].SemanticIndex        = 0;
    276        inputElements[inputElementCount].Format               = DXGI_FORMAT_R32G32B32_FLOAT;
    277        inputElements[inputElementCount].InputSlot            = 0;
    278        inputElements[inputElementCount].AlignedByteOffset    = 0;
    279        inputElements[inputElementCount].InputSlotClass       = D3D11_INPUT_PER_VERTEX_DATA;
    280        inputElements[inputElementCount].InstanceDataStepRate = 0;
    281        inputElementCount++;
    282 
    283        inputElements[inputElementCount].SemanticName         = "SPRITETEXCOORD";
    284        inputElements[inputElementCount].SemanticIndex        = 0;
    285        inputElements[inputElementCount].Format               = DXGI_FORMAT_R32G32_FLOAT;
    286        inputElements[inputElementCount].InputSlot            = 0;
    287        inputElements[inputElementCount].AlignedByteOffset    = sizeof(float) * 3;
    288        inputElements[inputElementCount].InputSlotClass       = D3D11_INPUT_PER_VERTEX_DATA;
    289        inputElements[inputElementCount].InstanceDataStepRate = 0;
    290        inputElementCount++;
    291    }
    292 
    293    ShaderExecutableD3D *shader = nullptr;
    294    ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(context11, &shader, nullptr));
    295 
    296    ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
    297 
    298    InputElementArray inputElementArray(inputElements.data(), inputElementCount);
    299    ShaderData vertexShaderData(shader11->getFunction(), shader11->getLength());
    300 
    301    ANGLE_TRY(renderer->allocateResource(context11, inputElementArray, &vertexShaderData,
    302                                         inputLayoutOut));
    303    return angle::Result::Continue;
    304 }
    305 
    306 void InputLayoutCache::setCacheSize(size_t newCacheSize)
    307 {
    308    // Forces a reset of the cache.
    309    LayoutCache newCache(newCacheSize);
    310    mLayoutCache.Swap(newCache);
    311 }
    312 
    313 }  // namespace rx