gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/InputLayoutCache.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,202 @@
     1.4 +#include "precompiled.h"
     1.5 +//
     1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
     1.7 +// Use of this source code is governed by a BSD-style license that can be
     1.8 +// found in the LICENSE file.
     1.9 +//
    1.10 +
    1.11 +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
    1.12 +// D3D11 input layouts.
    1.13 +
    1.14 +#include "libGLESv2/renderer/InputLayoutCache.h"
    1.15 +#include "libGLESv2/renderer/VertexBuffer11.h"
    1.16 +#include "libGLESv2/renderer/BufferStorage11.h"
    1.17 +#include "libGLESv2/renderer/ShaderExecutable11.h"
    1.18 +#include "libGLESv2/ProgramBinary.h"
    1.19 +#include "libGLESv2/Context.h"
    1.20 +#include "libGLESv2/renderer/VertexDataManager.h"
    1.21 +
    1.22 +#include "third_party/murmurhash/MurmurHash3.h"
    1.23 +
    1.24 +namespace rx
    1.25 +{
    1.26 +
    1.27 +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
    1.28 +
    1.29 +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
    1.30 +{
    1.31 +    mCounter = 0;
    1.32 +    mDevice = NULL;
    1.33 +    mDeviceContext = NULL;
    1.34 +    mCurrentIL = NULL;
    1.35 +    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    1.36 +    {
    1.37 +        mCurrentBuffers[i] = -1;
    1.38 +        mCurrentVertexStrides[i] = -1;
    1.39 +        mCurrentVertexOffsets[i] = -1;
    1.40 +    }
    1.41 +}
    1.42 +
    1.43 +InputLayoutCache::~InputLayoutCache()
    1.44 +{
    1.45 +    clear();
    1.46 +}
    1.47 +
    1.48 +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
    1.49 +{
    1.50 +    clear();
    1.51 +    mDevice = device;
    1.52 +    mDeviceContext = context;
    1.53 +}
    1.54 +
    1.55 +void InputLayoutCache::clear()
    1.56 +{
    1.57 +    for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
    1.58 +    {
    1.59 +        i->second.inputLayout->Release();
    1.60 +    }
    1.61 +    mInputLayoutMap.clear();
    1.62 +    markDirty();
    1.63 +}
    1.64 +
    1.65 +void InputLayoutCache::markDirty()
    1.66 +{
    1.67 +    mCurrentIL = NULL;
    1.68 +    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    1.69 +    {
    1.70 +        mCurrentBuffers[i] = -1;
    1.71 +        mCurrentVertexStrides[i] = -1;
    1.72 +        mCurrentVertexOffsets[i] = -1;
    1.73 +    }
    1.74 +}
    1.75 +
    1.76 +GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
    1.77 +                                            gl::ProgramBinary *programBinary)
    1.78 +{
    1.79 +    int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
    1.80 +    programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices);
    1.81 +
    1.82 +    if (!mDevice || !mDeviceContext)
    1.83 +    {
    1.84 +        ERR("InputLayoutCache is not initialized.");
    1.85 +        return GL_INVALID_OPERATION;
    1.86 +    }
    1.87 +
    1.88 +    InputLayoutKey ilKey = { 0 };
    1.89 +
    1.90 +    ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
    1.91 +    unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
    1.92 +    UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
    1.93 +    UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
    1.94 +
    1.95 +    static const char* semanticName = "TEXCOORD";
    1.96 +
    1.97 +    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    1.98 +    {
    1.99 +        if (attributes[i].active)
   1.100 +        {
   1.101 +            VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
   1.102 +            BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL;
   1.103 +
   1.104 +            D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
   1.105 +
   1.106 +            // Record the type of the associated vertex shader vector in our key
   1.107 +            // This will prevent mismatched vertex shaders from using the same input layout
   1.108 +            GLint attributeSize;
   1.109 +            programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL);
   1.110 +
   1.111 +            ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
   1.112 +            ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
   1.113 +            ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
   1.114 +            ilKey.elements[ilKey.elementCount].InputSlot = i;
   1.115 +            ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
   1.116 +            ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
   1.117 +            ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
   1.118 +            ilKey.elementCount++;
   1.119 +
   1.120 +            vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
   1.121 +            vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
   1.122 +            vertexStrides[i] = attributes[i].stride;
   1.123 +            vertexOffsets[i] = attributes[i].offset;
   1.124 +        }
   1.125 +    }
   1.126 +
   1.127 +    ID3D11InputLayout *inputLayout = NULL;
   1.128 +
   1.129 +    InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey);
   1.130 +    if (i != mInputLayoutMap.end())
   1.131 +    {
   1.132 +        inputLayout = i->second.inputLayout;
   1.133 +        i->second.lastUsedTime = mCounter++;
   1.134 +    }
   1.135 +    else
   1.136 +    {
   1.137 +        ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
   1.138 +
   1.139 +        HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
   1.140 +        if (FAILED(result))
   1.141 +        {
   1.142 +            ERR("Failed to crate input layout, result: 0x%08x", result);
   1.143 +            return GL_INVALID_OPERATION;
   1.144 +        }
   1.145 +
   1.146 +        if (mInputLayoutMap.size() >= kMaxInputLayouts)
   1.147 +        {
   1.148 +            TRACE("Overflowed the limit of %u input layouts, removing the least recently used "
   1.149 +                  "to make room.", kMaxInputLayouts);
   1.150 +
   1.151 +            InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin();
   1.152 +            for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
   1.153 +            {
   1.154 +                if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime)
   1.155 +                {
   1.156 +                    leastRecentlyUsed = i;
   1.157 +                }
   1.158 +            }
   1.159 +            leastRecentlyUsed->second.inputLayout->Release();
   1.160 +            mInputLayoutMap.erase(leastRecentlyUsed);
   1.161 +        }
   1.162 +
   1.163 +        InputLayoutCounterPair inputCounterPair;
   1.164 +        inputCounterPair.inputLayout = inputLayout;
   1.165 +        inputCounterPair.lastUsedTime = mCounter++;
   1.166 +
   1.167 +        mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
   1.168 +    }
   1.169 +
   1.170 +    if (inputLayout != mCurrentIL)
   1.171 +    {
   1.172 +        mDeviceContext->IASetInputLayout(inputLayout);
   1.173 +        mCurrentIL = inputLayout;
   1.174 +    }
   1.175 +
   1.176 +    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
   1.177 +    {
   1.178 +        if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
   1.179 +            vertexOffsets[i] != mCurrentVertexOffsets[i])
   1.180 +        {
   1.181 +            mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
   1.182 +            mCurrentBuffers[i] = vertexBufferSerials[i];
   1.183 +            mCurrentVertexStrides[i] = vertexStrides[i];
   1.184 +            mCurrentVertexOffsets[i] = vertexOffsets[i];
   1.185 +        }
   1.186 +    }
   1.187 +
   1.188 +    return GL_NO_ERROR;
   1.189 +}
   1.190 +
   1.191 +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
   1.192 +{
   1.193 +    static const unsigned int seed = 0xDEADBEEF;
   1.194 +
   1.195 +    std::size_t hash = 0;
   1.196 +    MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash);
   1.197 +    return hash;
   1.198 +}
   1.199 +
   1.200 +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
   1.201 +{
   1.202 +    return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0;
   1.203 +}
   1.204 +
   1.205 +}

mercurial