//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// StateManager11.cpp: Defines a class for caching D3D11 state

#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"

#include "common/angleutils.h"
#include "common/bitset_utils.h"
#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/Query.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"

namespace rx
{

namespace
{
bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
{
    unsigned mipLevel           = index.getLevelIndex();
    gl::TextureType textureType = index.getType();

    switch (desc.ViewDimension)
    {
        case D3D11_SRV_DIMENSION_TEXTURE2D:
        {
            bool allLevels         = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
            unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;

            unsigned mipMin = index.getLevelIndex();
            unsigned mipMax = INT_MAX;

            return textureType == gl::TextureType::_2D &&
                   gl::RangeUI(mipMin, mipMax)
                       .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
        }

        case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
        {
            GLint layerIndex = index.getLayerIndex();

            bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
            unsigned int maxSrvMip =
                desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
            maxSrvMip = allLevels ? INT_MAX : maxSrvMip;

            unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;

            // Cube maps can be mapped to Texture2DArray SRVs
            return (textureType == gl::TextureType::_2DArray ||
                    textureType == gl::TextureType::CubeMap) &&
                   desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
                   desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
                   static_cast<UINT>(layerIndex) < maxSlice;
        }

        case D3D11_SRV_DIMENSION_TEXTURECUBE:
        {
            bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
            unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;

            return textureType == gl::TextureType::CubeMap &&
                   desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
        }

        case D3D11_SRV_DIMENSION_TEXTURE3D:
        {
            bool allLevels         = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
            unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;

            return textureType == gl::TextureType::_3D &&
                   desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
        }
        default:
            // We only handle the cases corresponding to valid image indexes
            UNIMPLEMENTED();
    }

    return false;
}

bool ImageIndexConflictsWithUAV(const gl::ImageIndex &index, D3D11_UNORDERED_ACCESS_VIEW_DESC desc)
{
    unsigned mipLevel           = index.getLevelIndex();
    gl::TextureType textureType = index.getType();

    switch (desc.ViewDimension)
    {
        case D3D11_UAV_DIMENSION_TEXTURE2D:
        {
            return textureType == gl::TextureType::_2D && mipLevel == desc.Texture2D.MipSlice;
        }

        case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
        {
            GLint layerIndex         = index.getLayerIndex();
            unsigned mipSlice        = desc.Texture2DArray.MipSlice;
            unsigned firstArraySlice = desc.Texture2DArray.FirstArraySlice;
            unsigned lastArraySlice  = firstArraySlice + desc.Texture2DArray.ArraySize;

            return (textureType == gl::TextureType::_2DArray ||
                    textureType == gl::TextureType::CubeMap) &&
                   (mipLevel == mipSlice && gl::RangeUI(firstArraySlice, lastArraySlice)
                                                .contains(static_cast<UINT>(layerIndex)));
        }

        case D3D11_UAV_DIMENSION_TEXTURE3D:
        {
            GLint layerIndex     = index.getLayerIndex();
            unsigned mipSlice    = desc.Texture3D.MipSlice;
            unsigned firstWSlice = desc.Texture3D.FirstWSlice;
            unsigned lastWSlice  = firstWSlice + desc.Texture3D.WSize;

            return textureType == gl::TextureType::_3D &&
                   (mipLevel == mipSlice &&
                    gl::RangeUI(firstWSlice, lastWSlice).contains(static_cast<UINT>(layerIndex)));
        }
        default:
            return false;
    }
}

// Does *not* increment the resource ref count!!
ID3D11Resource *GetViewResource(ID3D11View *view)
{
    ID3D11Resource *resource = nullptr;
    ASSERT(view);
    view->GetResource(&resource);
    resource->Release();
    return resource;
}

int GetWrapBits(GLenum wrap)
{
    switch (wrap)
    {
        case GL_CLAMP_TO_EDGE:
            return 0x0;
        case GL_REPEAT:
            return 0x1;
        case GL_MIRRORED_REPEAT:
            return 0x2;
        case GL_CLAMP_TO_BORDER:
            return 0x3;
        default:
            UNREACHABLE();
            return 0;
    }
}

Optional<size_t> FindFirstNonInstanced(
    const std::vector<const TranslatedAttribute *> &currentAttributes)
{
    for (size_t index = 0; index < currentAttributes.size(); ++index)
    {
        if (currentAttributes[index]->divisor == 0)
        {
            return Optional<size_t>(index);
        }
    }

    return Optional<size_t>::Invalid();
}

void SortAttributesByLayout(const ProgramD3D &programD3D,
                            const std::vector<TranslatedAttribute> &vertexArrayAttribs,
                            const std::vector<TranslatedAttribute> &currentValueAttribs,
                            AttribIndexArray *sortedD3DSemanticsOut,
                            std::vector<const TranslatedAttribute *> *sortedAttributesOut)
{
    sortedAttributesOut->clear();

    const AttribIndexArray &locationToSemantic = programD3D.getAttribLocationToD3DSemantics();

    for (auto locationIndex : programD3D.getState().getActiveAttribLocationsMask())
    {
        int d3dSemantic = locationToSemantic[locationIndex];
        if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
        {
            sortedAttributesOut->resize(d3dSemantic + 1);
        }

        (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;

        const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
        if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
        {
            (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
        }
        else
        {
            ASSERT(currentValueAttribs[locationIndex].attribute);
            (*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
        }
    }
}

void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext,
                         UniformStorage11 *storage,
                         const d3d11::Buffer *buffer)
{
    deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0,
                                     0);
}

size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
{
    return usesPointSpriteEmulation ? 1 : 0;
}

bool CullsEverything(const gl::State &glState)
{
    return (glState.getRasterizerState().cullFace &&
            glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
}
}  // anonymous namespace

// StateManager11::ViewCache Implementation.
template <typename ViewType, typename DescType>
StateManager11::ViewCache<ViewType, DescType>::ViewCache() : mHighestUsedView(0)
{}

template <typename ViewType, typename DescType>
StateManager11::ViewCache<ViewType, DescType>::~ViewCache()
{}

template <typename ViewType, typename DescType>
void StateManager11::ViewCache<ViewType, DescType>::update(size_t resourceIndex, ViewType *view)
{
    ASSERT(resourceIndex < mCurrentViews.size());
    ViewRecord<DescType> *record = &mCurrentViews[resourceIndex];

    record->view = reinterpret_cast<uintptr_t>(view);
    if (view)
    {
        record->resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
        view->GetDesc(&record->desc);
        mHighestUsedView = std::max(resourceIndex + 1, mHighestUsedView);
    }
    else
    {
        record->resource = 0;

        if (resourceIndex + 1 == mHighestUsedView)
        {
            do
            {
                --mHighestUsedView;
            } while (mHighestUsedView > 0 && mCurrentViews[mHighestUsedView].view == 0);
        }
    }
}

template <typename ViewType, typename DescType>
void StateManager11::ViewCache<ViewType, DescType>::clear()
{
    if (mCurrentViews.empty())
    {
        return;
    }

    memset(&mCurrentViews[0], 0, sizeof(ViewRecord<DescType>) * mCurrentViews.size());
    mHighestUsedView = 0;
}

StateManager11::SRVCache *StateManager11::getSRVCache(gl::ShaderType shaderType)
{
    ASSERT(shaderType != gl::ShaderType::InvalidEnum);
    return &mCurShaderSRVs[shaderType];
}

// ShaderConstants11 implementation
ShaderConstants11::ShaderConstants11() : mNumActiveShaderSamplers({})
{
    mShaderConstantsDirty.set();
}

ShaderConstants11::~ShaderConstants11() {}

void ShaderConstants11::init(const gl::Caps &caps)
{
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]);
        mShaderReadonlyImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
        mShaderImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
    }
}

size_t ShaderConstants11::GetShaderConstantsStructSize(gl::ShaderType shaderType)
{
    switch (shaderType)
    {
        case gl::ShaderType::Vertex:
            return sizeof(Vertex);
        case gl::ShaderType::Fragment:
            return sizeof(Pixel);
        case gl::ShaderType::Compute:
            return sizeof(Compute);

        // TODO(jiawei.shao@intel.com): return geometry shader constant struct size
        case gl::ShaderType::Geometry:
            return 0u;

        default:
            UNREACHABLE();
            return 0u;
    }
}

size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
{
    ASSERT(shaderType != gl::ShaderType::InvalidEnum);
    return GetShaderConstantsStructSize(shaderType) +
           mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) +
           mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) +
           mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata);
}

void ShaderConstants11::markDirty()
{
    mShaderConstantsDirty.set();
    mNumActiveShaderSamplers.fill(0);
}

bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data,
                                              const gl::Texture &texture,
                                              const gl::SamplerState &samplerState)
{
    bool dirty               = false;
    unsigned int baseLevel   = texture.getTextureState().getEffectiveBaseLevel();
    gl::TextureTarget target = (texture.getType() == gl::TextureType::CubeMap)
                                   ? gl::kCubeMapTextureTargetMin
                                   : gl::NonCubeTextureTypeToTarget(texture.getType());
    GLenum sizedFormat = texture.getFormat(target, baseLevel).info->sizedInternalFormat;
    if (data->baseLevel != static_cast<int>(baseLevel))
    {
        data->baseLevel = static_cast<int>(baseLevel);
        dirty           = true;
    }

    // Some metadata is needed only for integer textures. We avoid updating the constant buffer
    // unnecessarily by changing the data only in case the texture is an integer texture and
    // the values have changed.
    bool needIntegerTextureMetadata = false;
    // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
    int internalFormatBits = 0;
    switch (sizedFormat)
    {
        case GL_RGBA32I:
        case GL_RGBA32UI:
        case GL_RGB32I:
        case GL_RGB32UI:
        case GL_RG32I:
        case GL_RG32UI:
        case GL_R32I:
        case GL_R32UI:
            needIntegerTextureMetadata = true;
            break;
        case GL_RGBA16I:
        case GL_RGBA16UI:
        case GL_RGB16I:
        case GL_RGB16UI:
        case GL_RG16I:
        case GL_RG16UI:
        case GL_R16I:
        case GL_R16UI:
            needIntegerTextureMetadata = true;
            internalFormatBits         = 16;
            break;
        case GL_RGBA8I:
        case GL_RGBA8UI:
        case GL_RGB8I:
        case GL_RGB8UI:
        case GL_RG8I:
        case GL_RG8UI:
        case GL_R8I:
        case GL_R8UI:
            needIntegerTextureMetadata = true;
            internalFormatBits         = 8;
            break;
        case GL_RGB10_A2UI:
            needIntegerTextureMetadata = true;
            internalFormatBits         = 10;
            break;
        default:
            break;
    }
    if (needIntegerTextureMetadata)
    {
        if (data->internalFormatBits != internalFormatBits)
        {
            data->internalFormatBits = internalFormatBits;
            dirty                    = true;
        }
        // Pack the wrap values into one integer so we can fit all the metadata in two 4-integer
        // vectors.
        GLenum wrapS  = samplerState.getWrapS();
        GLenum wrapT  = samplerState.getWrapT();
        GLenum wrapR  = samplerState.getWrapR();
        int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
        if (data->wrapModes != wrapModes)
        {
            data->wrapModes = wrapModes;
            dirty           = true;
        }

        const angle::ColorGeneric &borderColor(samplerState.getBorderColor());
        constexpr int kBlack[4]          = {0};
        const void *const intBorderColor = (borderColor.type == angle::ColorGeneric::Type::Float)
                                               ? kBlack
                                               : borderColor.colorI.data();
        ASSERT(static_cast<const void *>(borderColor.colorI.data()) ==
               static_cast<const void *>(borderColor.colorUI.data()));
        if (memcmp(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor)) != 0)
        {
            memcpy(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor));
            dirty = true;
        }
    }

    return dirty;
}

bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit)
{
    bool dirty = false;

    if (data->layer != static_cast<int>(imageUnit.layer))
    {
        data->layer = static_cast<int>(imageUnit.layer);
        dirty       = true;
    }

    if (data->level != static_cast<unsigned int>(imageUnit.level))
    {
        data->level = static_cast<unsigned int>(imageUnit.level);
        dirty       = true;
    }

    return dirty;
}

void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
                                             GLuint numGroupsY,
                                             GLuint numGroupsZ)
{
    mCompute.numWorkGroups[0] = numGroupsX;
    mCompute.numWorkGroups[1] = numGroupsY;
    mCompute.numWorkGroups[2] = numGroupsZ;
    mShaderConstantsDirty.set(gl::ShaderType::Compute);
}

void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index)
{
    mVertex.multiviewWriteToViewportIndex = index;
    mPixel.multiviewWriteToViewportIndex  = index;
    mShaderConstantsDirty.set(gl::ShaderType::Vertex);
    mShaderConstantsDirty.set(gl::ShaderType::Fragment);
}

void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
                                         const D3D11_VIEWPORT &dxViewport,
                                         bool is9_3,
                                         bool presentPathFast)
{
    mShaderConstantsDirty.set(gl::ShaderType::Vertex);
    mShaderConstantsDirty.set(gl::ShaderType::Fragment);

    // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
    // using viewAdjust (like the D3D9 renderer).
    if (is9_3)
    {
        mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
                                                   2 * (glViewport.x - dxViewport.TopLeftX)) /
                                dxViewport.Width;
        mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
                                                   2 * (glViewport.y - dxViewport.TopLeftY)) /
                                dxViewport.Height;
        mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
        mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
    }

    mPixel.viewCoords[0] = glViewport.width * 0.5f;
    mPixel.viewCoords[1] = glViewport.height * 0.5f;
    mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
    mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);

    // Instanced pointsprite emulation requires ViewCoords to be defined in the
    // the vertex shader.
    mVertex.viewCoords[0] = mPixel.viewCoords[0];
    mVertex.viewCoords[1] = mPixel.viewCoords[1];
    mVertex.viewCoords[2] = mPixel.viewCoords[2];
    mVertex.viewCoords[3] = mPixel.viewCoords[3];

    const float zNear = dxViewport.MinDepth;
    const float zFar  = dxViewport.MaxDepth;

    mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
    mPixel.depthFront[1] = (zNear + zFar) * 0.5f;

    mVertex.depthRange[0] = zNear;
    mVertex.depthRange[1] = zFar;
    mVertex.depthRange[2] = zFar - zNear;

    mPixel.depthRange[0] = zNear;
    mPixel.depthRange[1] = zFar;
    mPixel.depthRange[2] = zFar - zNear;

    mPixel.viewScale[0] = 1.0f;
    mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
    // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw
    // framebuffer's layout is changed.

    mVertex.viewScale[0] = mPixel.viewScale[0];
    mVertex.viewScale[1] = mPixel.viewScale[1];
}

// Update the ShaderConstants with a new first vertex and return whether the update dirties them.
ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex, GLint baseVertex)
{
    uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex + baseVertex);

    bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex);
    if (firstVertexDirty)
    {
        mVertex.firstVertex = newFirstVertex;
        mShaderConstantsDirty.set(gl::ShaderType::Vertex);
    }
    return firstVertexDirty;
}

void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
                                        unsigned int samplerIndex,
                                        const gl::Texture &texture,
                                        const gl::SamplerState &samplerState)
{
    ASSERT(shaderType != gl::ShaderType::InvalidEnum);
    if (updateSamplerMetadata(&mShaderSamplerMetadata[shaderType][samplerIndex], texture,
                              samplerState))
    {
        mNumActiveShaderSamplers[shaderType] = 0;
    }
}

void ShaderConstants11::onImageChange(gl::ShaderType shaderType,
                                      unsigned int imageIndex,
                                      const gl::ImageUnit &imageUnit)
{
    ASSERT(shaderType != gl::ShaderType::InvalidEnum);
    if (imageUnit.access == GL_READ_ONLY)
    {
        if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit))
        {
            mNumActiveShaderReadonlyImages[shaderType] = 0;
        }
    }
    else
    {
        if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit))
        {
            mNumActiveShaderImages[shaderType] = 0;
        }
    }
}

angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
                                              Renderer11 *renderer,
                                              gl::ShaderType shaderType,
                                              const ProgramD3D &programD3D,
                                              const d3d11::Buffer &driverConstantBuffer)
{
    // Re-upload the sampler meta-data if the current program uses more samplers
    // than we previously uploaded.
    const int numSamplers       = programD3D.getUsedSamplerRange(shaderType).length();
    const int numReadonlyImages = programD3D.getUsedImageRange(shaderType, true).length();
    const int numImages         = programD3D.getUsedImageRange(shaderType, false).length();

    const bool dirty = mShaderConstantsDirty[shaderType] ||
                       (mNumActiveShaderSamplers[shaderType] < numSamplers) ||
                       (mNumActiveShaderReadonlyImages[shaderType] < numReadonlyImages) ||
                       (mNumActiveShaderImages[shaderType] < numImages);

    const size_t dataSize = GetShaderConstantsStructSize(shaderType);
    const uint8_t *samplerData =
        reinterpret_cast<const uint8_t *>(mShaderSamplerMetadata[shaderType].data());
    const size_t samplerDataSize = sizeof(SamplerMetadata) * numSamplers;
    const uint8_t *readonlyImageData =
        reinterpret_cast<const uint8_t *>(mShaderReadonlyImageMetadata[shaderType].data());
    const size_t readonlyImageDataSize = sizeof(ImageMetadata) * numReadonlyImages;
    const uint8_t *imageData =
        reinterpret_cast<const uint8_t *>(mShaderImageMetadata[shaderType].data());
    const size_t imageDataSize = sizeof(ImageMetadata) * numImages;

    mNumActiveShaderSamplers[shaderType]       = numSamplers;
    mNumActiveShaderReadonlyImages[shaderType] = numReadonlyImages;
    mNumActiveShaderImages[shaderType]         = numImages;
    mShaderConstantsDirty.set(shaderType, false);

    const uint8_t *data = nullptr;
    switch (shaderType)
    {
        case gl::ShaderType::Vertex:
            data = reinterpret_cast<const uint8_t *>(&mVertex);
            break;
        case gl::ShaderType::Fragment:
            data = reinterpret_cast<const uint8_t *>(&mPixel);
            break;
        case gl::ShaderType::Compute:
            data = reinterpret_cast<const uint8_t *>(&mCompute);
            break;
        default:
            UNREACHABLE();
            break;
    }

    ASSERT(driverConstantBuffer.valid());

    if (!dirty)
    {
        return angle::Result::Continue;
    }

    // Previous buffer contents are discarded, so we need to refresh the whole buffer.
    D3D11_MAPPED_SUBRESOURCE mapping = {0};
    ANGLE_TRY(renderer->mapResource(context, driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD,
                                    0, &mapping));

    memcpy(mapping.pData, data, dataSize);
    memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize, samplerData,
           sizeof(SamplerMetadata) * numSamplers);

    memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize, readonlyImageData,
           readonlyImageDataSize);
    memcpy(
        static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize + readonlyImageDataSize,
        imageData, imageDataSize);
    renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0);

    return angle::Result::Continue;
}

StateManager11::StateManager11(Renderer11 *renderer)
    : mRenderer(renderer),
      mInternalDirtyBits(),
      mCurBlendColor(0, 0, 0, 0),
      mCurSampleMask(0),
      mCurStencilRef(0),
      mCurStencilBackRef(0),
      mCurStencilSize(0),
      mCurScissorEnabled(false),
      mCurScissorRect(),
      mCurViewport(),
      mCurNear(0.0f),
      mCurFar(0.0f),
      mViewportBounds(),
      mRenderTargetIsDirty(true),
      mCurPresentPathFastEnabled(false),
      mCurPresentPathFastColorBufferHeight(0),
      mDirtyCurrentValueAttribs(),
      mCurrentValueAttribs(),
      mCurrentInputLayout(),
      mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0),
      mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED),
      mLastAppliedDrawMode(gl::PrimitiveMode::InvalidEnum),
      mCullEverything(false),
      mDirtySwizzles(false),
      mAppliedIB(nullptr),
      mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
      mAppliedIBOffset(0),
      mIndexBufferIsDirty(false),
      mVertexDataManager(renderer),
      mIndexDataManager(renderer),
      mIsMultiviewEnabled(false),
      mEmptySerial(mRenderer->generateSerial()),
      mProgramD3D(nullptr),
      mVertexArray11(nullptr),
      mFramebuffer11(nullptr)
{
    mCurBlendState.blend                 = false;
    mCurBlendState.sourceBlendRGB        = GL_ONE;
    mCurBlendState.destBlendRGB          = GL_ZERO;
    mCurBlendState.sourceBlendAlpha      = GL_ONE;
    mCurBlendState.destBlendAlpha        = GL_ZERO;
    mCurBlendState.blendEquationRGB      = GL_FUNC_ADD;
    mCurBlendState.blendEquationAlpha    = GL_FUNC_ADD;
    mCurBlendState.colorMaskRed          = true;
    mCurBlendState.colorMaskBlue         = true;
    mCurBlendState.colorMaskGreen        = true;
    mCurBlendState.colorMaskAlpha        = true;
    mCurBlendState.sampleAlphaToCoverage = false;
    mCurBlendState.dither                = false;

    mCurDepthStencilState.depthTest                = false;
    mCurDepthStencilState.depthFunc                = GL_LESS;
    mCurDepthStencilState.depthMask                = true;
    mCurDepthStencilState.stencilTest              = false;
    mCurDepthStencilState.stencilMask              = true;
    mCurDepthStencilState.stencilFail              = GL_KEEP;
    mCurDepthStencilState.stencilPassDepthFail     = GL_KEEP;
    mCurDepthStencilState.stencilPassDepthPass     = GL_KEEP;
    mCurDepthStencilState.stencilWritemask         = static_cast<GLuint>(-1);
    mCurDepthStencilState.stencilBackFunc          = GL_ALWAYS;
    mCurDepthStencilState.stencilBackMask          = static_cast<GLuint>(-1);
    mCurDepthStencilState.stencilBackFail          = GL_KEEP;
    mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
    mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
    mCurDepthStencilState.stencilBackWritemask     = static_cast<GLuint>(-1);

    mCurRasterState.rasterizerDiscard   = false;
    mCurRasterState.cullFace            = false;
    mCurRasterState.cullMode            = gl::CullFaceMode::Back;
    mCurRasterState.frontFace           = GL_CCW;
    mCurRasterState.polygonOffsetFill   = false;
    mCurRasterState.polygonOffsetFactor = 0.0f;
    mCurRasterState.polygonOffsetUnits  = 0.0f;
    mCurRasterState.pointDrawMode       = false;
    mCurRasterState.multiSample         = false;

    // Start with all internal dirty bits set except DIRTY_BIT_COMPUTE_SRVUAV_STATE and
    // DIRTY_BIT_GRAPHICS_SRVUAV_STATE.
    mInternalDirtyBits.set();
    mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_SRVUAV_STATE);
    mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_SRVUAV_STATE);

    mGraphicsDirtyBitsMask.set();
    mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
    mComputeDirtyBitsMask.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
    mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORMS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_DRIVER_UNIFORMS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_SHADERS);
    mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);

    // Initially all current value attributes must be updated on first use.
    mDirtyCurrentValueAttribs.set();

    mCurrentVertexBuffers.fill(nullptr);
    mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
    mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
}

StateManager11::~StateManager11() {}

template <typename SRVType>
void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType,
                                               UINT resourceSlot,
                                               const SRVType *srv)
{
    auto *currentSRVs = getSRVCache(shaderType);
    ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs->size());
    const ViewRecord<D3D11_SHADER_RESOURCE_VIEW_DESC> &record = (*currentSRVs)[resourceSlot];

    if (record.view != reinterpret_cast<uintptr_t>(srv))
    {
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
        ID3D11ShaderResourceView *srvPtr   = srv ? srv->get() : nullptr;
        if (srvPtr)
        {
            uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
            unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
                                 resource, nullptr);
        }

        switch (shaderType)
        {
            case gl::ShaderType::Vertex:
                deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr);
                break;
            case gl::ShaderType::Fragment:
                deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr);
                break;
            case gl::ShaderType::Compute:
            {
                if (srvPtr)
                {
                    uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
                    unsetConflictingRTVs(resource);
                }
                deviceContext->CSSetShaderResources(resourceSlot, 1, &srvPtr);
                break;
            }
            default:
                UNREACHABLE();
        }

        currentSRVs->update(resourceSlot, srvPtr);
    }
}

template <typename UAVType>
void StateManager11::setUnorderedAccessViewInternal(gl::ShaderType shaderType,
                                                    UINT resourceSlot,
                                                    const UAVType *uav)
{
    ASSERT(shaderType == gl::ShaderType::Compute);
    ASSERT(static_cast<size_t>(resourceSlot) < mCurComputeUAVs.size());
    const ViewRecord<D3D11_UNORDERED_ACCESS_VIEW_DESC> &record = mCurComputeUAVs[resourceSlot];

    if (record.view != reinterpret_cast<uintptr_t>(uav))
    {
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
        ID3D11UnorderedAccessView *uavPtr  = uav ? uav->get() : nullptr;
        // We need to make sure that resource being set to UnorderedAccessView slot |resourceSlot|
        // is not bound on SRV.
        if (uavPtr)
        {
            uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(uavPtr));
            unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Vertex,
                                 resource, nullptr, false);
            unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Fragment,
                                 resource, nullptr, false);
            unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Compute,
                                 resource, nullptr, false);
        }
        deviceContext->CSSetUnorderedAccessViews(resourceSlot, 1, &uavPtr, nullptr);

        mCurComputeUAVs.update(resourceSlot, uavPtr);
    }
}

void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
                                                unsigned int stencilSize)
{
    if (!depthStencilInitialized || stencilSize != mCurStencilSize)
    {
        mCurStencilSize = stencilSize;
        mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
    }
}

void StateManager11::checkPresentPath(const gl::Context *context)
{
    if (!mRenderer->presentPathFastEnabled())
        return;

    const auto *framebuffer          = context->getState().getDrawFramebuffer();
    const auto *firstColorAttachment = framebuffer->getFirstColorAttachment();
    const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment);

    const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0;

    if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
        (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
    {
        mCurPresentPathFastEnabled           = presentPathFastActive;
        mCurPresentPathFastColorBufferHeight = colorBufferHeight;

        // Scissor rect may need to be vertically inverted
        mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);

        // Cull Mode may need to be inverted
        mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);

        // Viewport may need to be vertically inverted
        invalidateViewport(context);
    }
}

angle::Result StateManager11::updateStateForCompute(const gl::Context *context,
                                                    GLuint numGroupsX,
                                                    GLuint numGroupsY,
                                                    GLuint numGroupsZ)
{
    mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);

    if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
    {
        invalidateTexturesAndSamplers();
    }

    if (mDirtySwizzles)
    {
        ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
        mDirtySwizzles = false;
    }

    if (mProgramD3D->anyShaderUniformsDirty())
    {
        mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
    }

    auto dirtyBitsCopy = mInternalDirtyBits & mComputeDirtyBitsMask;
    mInternalDirtyBits &= ~mComputeDirtyBitsMask;

    for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
    {
        switch (*iter)
        {
            case DIRTY_BIT_COMPUTE_SRVUAV_STATE:
                // Avoid to call syncTexturesForCompute function two times.
                iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
                ANGLE_TRY(syncTexturesForCompute(context));
                break;
            case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
                ANGLE_TRY(syncTexturesForCompute(context));
                break;
            case DIRTY_BIT_PROGRAM_UNIFORMS:
            case DIRTY_BIT_DRIVER_UNIFORMS:
                ANGLE_TRY(applyComputeUniforms(context, mProgramD3D));
                break;
            case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
                ANGLE_TRY(syncUniformBuffers(context));
                break;
            case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
                ANGLE_TRY(syncAtomicCounterBuffers(context));
                break;
            case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
                ANGLE_TRY(syncShaderStorageBuffers(context));
                break;
            case DIRTY_BIT_SHADERS:
                ANGLE_TRY(syncProgramForCompute(context));
                break;
            default:
                UNREACHABLE();
                break;
        }
    }

    return angle::Result::Continue;
}

void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
{
    if (!dirtyBits.any())
    {
        return;
    }

    const gl::State &state = context->getState();

    for (size_t dirtyBit : dirtyBits)
    {
        switch (dirtyBit)
        {
            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
                    blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            }
            case gl::State::DIRTY_BIT_BLEND_FUNCS:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
                    blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
                    blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
                    blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            }
            case gl::State::DIRTY_BIT_BLEND_ENABLED:
                if (state.getBlendState().blend != mCurBlendState.blend)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
                if (state.getBlendState().sampleAlphaToCoverage !=
                    mCurBlendState.sampleAlphaToCoverage)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_DITHER_ENABLED:
                if (state.getBlendState().dither != mCurBlendState.dither)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_COLOR_MASK:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
                    blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
                    blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
                    blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            }
            case gl::State::DIRTY_BIT_BLEND_COLOR:
                if (state.getBlendColor() != mCurBlendColor)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
                }
                break;
            // Depth and stencil redundant state changes are guarded in the
            // frontend so for related cases here just set the dirty bit.
            case gl::State::DIRTY_BIT_DEPTH_MASK:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_DEPTH_FUNC:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;
            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
                mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
                break;

            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
                if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                    mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
                }
                break;
            case gl::State::DIRTY_BIT_CULL_FACE:
                if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                    mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
                }
                break;
            case gl::State::DIRTY_BIT_FRONT_FACE:
                if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                    mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
                }
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
                if (state.getRasterizerState().polygonOffsetFill !=
                    mCurRasterState.polygonOffsetFill)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
            {
                const gl::RasterizerState &rasterState = state.getRasterizerState();
                if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
                    rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                }
                break;
            }
            case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
                if (state.getRasterizerState().rasterizerDiscard !=
                    mCurRasterState.rasterizerDiscard)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);

                    // Enabling/disabling rasterizer discard affects the pixel shader.
                    invalidateShaders();
                }
                break;
            case gl::State::DIRTY_BIT_SCISSOR:
                if (state.getScissor() != mCurScissorRect)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
                if (state.isScissorTestEnabled() != mCurScissorEnabled)
                {
                    mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
                    // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
                    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
                }
                break;
            case gl::State::DIRTY_BIT_DEPTH_RANGE:
                invalidateViewport(context);
                break;
            case gl::State::DIRTY_BIT_VIEWPORT:
                if (state.getViewport() != mCurViewport)
                {
                    invalidateViewport(context);
                }
                break;
            case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
                invalidateRenderTarget();
                if (mIsMultiviewEnabled)
                {
                    handleMultiviewDrawFramebufferChange(context);
                }
                mFramebuffer11 = GetImplAs<Framebuffer11>(state.getDrawFramebuffer());
                break;
            case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
                invalidateVertexBuffer();
                // Force invalidate the current value attributes, since the VertexArray11 keeps an
                // internal cache of TranslatedAttributes, and they CurrentValue attributes are
                // owned by the StateManager11/Context.
                mDirtyCurrentValueAttribs.set();
                // Invalidate the cached index buffer.
                invalidateIndexBuffer();
                mVertexArray11 = GetImplAs<VertexArray11>(state.getVertexArray());
                break;
            case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
                invalidateProgramUniformBuffers();
                break;
            case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
                invalidateProgramAtomicCounterBuffers();
                break;
            case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
                invalidateProgramShaderStorageBuffers();
                break;
            case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
                invalidateTexturesAndSamplers();
                break;
            case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
                invalidateTexturesAndSamplers();
                break;
            case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
                // TODO(jie.a.chen@intel.com): More fine-grained update.
                // Currently images are updated together with textures and samplers. It would be
                // better to update them separately.
                // http://anglebug.com/2814
                invalidateTexturesAndSamplers();
                break;
            case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
                invalidateTransformFeedback();
                break;
            case gl::State::DIRTY_BIT_PROGRAM_BINDING:
                mProgramD3D = GetImplAs<ProgramD3D>(state.getProgram());
                break;
            case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
            {
                invalidateShaders();
                invalidateTexturesAndSamplers();
                invalidateProgramUniforms();
                invalidateProgramUniformBuffers();
                invalidateProgramAtomicCounterBuffers();
                invalidateProgramShaderStorageBuffers();
                invalidateDriverUniforms();
                const gl::Program *program = state.getProgram();
                if (!program || !program->hasLinkedShaderStage(gl::ShaderType::Compute))
                {
                    mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
                    invalidateVertexBuffer();
                    invalidateRenderTarget();
                    // If OVR_multiview2 is enabled, the attribute divisor has to be updated for
                    // each binding. When using compute, there could be no vertex array.
                    if (mIsMultiviewEnabled && mVertexArray11)
                    {
                        ASSERT(mProgramD3D);
                        ASSERT(mVertexArray11 == GetImplAs<VertexArray11>(state.getVertexArray()));
                        const gl::ProgramState &programState = mProgramD3D->getState();
                        int numViews =
                            programState.usesMultiview() ? programState.getNumViews() : 1;
                        mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews);
                    }
                }
                break;
            }
            case gl::State::DIRTY_BIT_CURRENT_VALUES:
            {
                for (auto attribIndex : state.getAndResetDirtyCurrentValues())
                {
                    invalidateCurrentValueAttrib(attribIndex);
                }
                break;
            }
            case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
                invalidateShaders();
                break;
            default:
                break;
        }
    }

    // TODO(jmadill): Input layout and vertex buffer state.
}

void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context)
{
    const auto &glState                    = context->getState();
    const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
    ASSERT(drawFramebuffer != nullptr);

    if (drawFramebuffer->isMultiview())
    {
        // Because the base view index is applied as an offset to the 2D texture array when the
        // RTV is created, we just have to pass a boolean to select which code path is to be
        // used.
        mShaderConstants.setMultiviewWriteToViewportIndex(0.0f);
    }
}

angle::Result StateManager11::syncBlendState(const gl::Context *context,
                                             const gl::BlendState &blendState,
                                             const gl::ColorF &blendColor,
                                             unsigned int sampleMask)
{
    const d3d11::BlendState *dxBlendState = nullptr;
    const d3d11::BlendStateKey &key =
        RenderStateCache::GetBlendStateKey(context, mFramebuffer11, blendState);

    ANGLE_TRY(mRenderer->getBlendState(context, key, &dxBlendState));

    ASSERT(dxBlendState != nullptr);

    float blendColors[4] = {0.0f};
    if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
        blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
        blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
        blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
    {
        blendColors[0] = blendColor.red;
        blendColors[1] = blendColor.green;
        blendColors[2] = blendColor.blue;
        blendColors[3] = blendColor.alpha;
    }
    else
    {
        blendColors[0] = blendColor.alpha;
        blendColors[1] = blendColor.alpha;
        blendColors[2] = blendColor.alpha;
        blendColors[3] = blendColor.alpha;
    }

    mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask);

    mCurBlendState = blendState;
    mCurBlendColor = blendColor;
    mCurSampleMask = sampleMask;

    return angle::Result::Continue;
}

angle::Result StateManager11::syncDepthStencilState(const gl::Context *context)
{
    const gl::State &glState = context->getState();

    mCurDepthStencilState = glState.getDepthStencilState();
    mCurStencilRef        = glState.getStencilRef();
    mCurStencilBackRef    = glState.getStencilBackRef();

    // get the maximum size of the stencil ref
    unsigned int maxStencil = 0;
    if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
    {
        maxStencil = (1 << mCurStencilSize) - 1;
    }
    ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
           (mCurDepthStencilState.stencilBackWritemask & maxStencil));
    ASSERT(gl::clamp(mCurStencilRef, 0, static_cast<int>(maxStencil)) ==
           gl::clamp(mCurStencilBackRef, 0, static_cast<int>(maxStencil)));
    ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
           (mCurDepthStencilState.stencilBackMask & maxStencil));

    gl::DepthStencilState modifiedGLState = glState.getDepthStencilState();

    ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid());

    if (mCurDisableDepth.value())
    {
        modifiedGLState.depthTest = false;
        modifiedGLState.depthMask = false;
    }

    if (mCurDisableStencil.value())
    {
        modifiedGLState.stencilTest = false;
    }
    if (!modifiedGLState.stencilTest)
    {
        modifiedGLState.stencilWritemask     = 0;
        modifiedGLState.stencilBackWritemask = 0;
    }

    // If STENCIL_TEST is disabled in glState, stencil testing and writing should be disabled.
    // Verify that's true in the modifiedGLState so it is propagated to d3dState.
    ASSERT(glState.getDepthStencilState().stencilTest ||
           (!modifiedGLState.stencilTest && modifiedGLState.stencilWritemask == 0 &&
            modifiedGLState.stencilBackWritemask == 0));

    const d3d11::DepthStencilState *d3dState = nullptr;
    ANGLE_TRY(mRenderer->getDepthStencilState(context, modifiedGLState, &d3dState));
    ASSERT(d3dState);

    // Max D3D11 stencil reference value is 0xFF,
    // corresponding to the max 8 bits in a stencil buffer
    // GL specifies we should clamp the ref value to the
    // nearest bit depth when doing stencil ops
    static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
                  "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
    static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
                  "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
    UINT dxStencilRef = static_cast<UINT>(gl::clamp(mCurStencilRef, 0, 0xFF));

    mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef);

    return angle::Result::Continue;
}

angle::Result StateManager11::syncRasterizerState(const gl::Context *context,
                                                  gl::PrimitiveMode mode)
{
    // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
    gl::RasterizerState rasterState = context->getState().getRasterizerState();
    rasterState.pointDrawMode       = (mode == gl::PrimitiveMode::Points);
    rasterState.multiSample         = mCurRasterState.multiSample;

    ID3D11RasterizerState *dxRasterState = nullptr;

    if (mCurPresentPathFastEnabled)
    {
        gl::RasterizerState modifiedRasterState = rasterState;

        // If prseent path fast is active then we need invert the front face state.
        // This ensures that both gl_FrontFacing is correct, and front/back culling
        // is performed correctly.
        if (modifiedRasterState.frontFace == GL_CCW)
        {
            modifiedRasterState.frontFace = GL_CW;
        }
        else
        {
            ASSERT(modifiedRasterState.frontFace == GL_CW);
            modifiedRasterState.frontFace = GL_CCW;
        }

        ANGLE_TRY(mRenderer->getRasterizerState(context, modifiedRasterState, mCurScissorEnabled,
                                                &dxRasterState));
    }
    else
    {
        ANGLE_TRY(mRenderer->getRasterizerState(context, rasterState, mCurScissorEnabled,
                                                &dxRasterState));
    }

    mRenderer->getDeviceContext()->RSSetState(dxRasterState);

    mCurRasterState = rasterState;

    return angle::Result::Continue;
}

void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled)
{
    int modifiedScissorY = scissor.y;
    if (mCurPresentPathFastEnabled)
    {
        modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
    }

    if (enabled)
    {
        D3D11_RECT rect;
        int x       = scissor.x;
        int y       = modifiedScissorY;
        rect.left   = std::max(0, x);
        rect.top    = std::max(0, y);
        rect.right  = x + std::max(0, scissor.width);
        rect.bottom = y + std::max(0, scissor.height);
        mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
    }

    mCurScissorRect    = scissor;
    mCurScissorEnabled = enabled;
}

void StateManager11::syncViewport(const gl::Context *context)
{
    const auto &glState          = context->getState();
    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
    float actualZNear            = gl::clamp01(glState.getNearPlane());
    float actualZFar             = gl::clamp01(glState.getFarPlane());

    const auto &caps         = context->getCaps();
    int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
    int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
    int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
    int dxMinViewportBoundsY = -dxMaxViewportBoundsY;

    bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3;

    if (is9_3)
    {
        // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
        dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
        dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
        dxMinViewportBoundsX = 0;
        dxMinViewportBoundsY = 0;
    }

    const auto &viewport = glState.getViewport();

    int dxViewportTopLeftX = 0;
    int dxViewportTopLeftY = 0;
    int dxViewportWidth    = 0;
    int dxViewportHeight   = 0;

    dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
    dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
    dxViewportWidth    = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
    dxViewportHeight   = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);

    D3D11_VIEWPORT dxViewport;
    dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
    if (mCurPresentPathFastEnabled)
    {
        // When present path fast is active and we're rendering to framebuffer 0, we must invert
        // the viewport in Y-axis.
        // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
        // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
        // unaltered dxViewportTopLeftY value.
        dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
                                                 dxViewportTopLeftY - dxViewportHeight);
    }
    else
    {
        dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
    }

    // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering
    // will be limited to a rectangle having a lower left of (0, 0) and an upper right of
    // (width, height), where width and height are the framebuffer object's default width
    // and height." See http://anglebug.com/1594
    // If the Framebuffer has no color attachment and the default width or height is smaller
    // than the current viewport, use the smaller of the two sizes.
    // If framebuffer default width or height is 0, the params should not set.
    if (!framebuffer->getFirstNonNullAttachment() &&
        (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight()))
    {
        dxViewport.Width =
            static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth()));
        dxViewport.Height =
            static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight()));
    }
    else
    {
        dxViewport.Width  = static_cast<float>(dxViewportWidth);
        dxViewport.Height = static_cast<float>(dxViewportHeight);
    }
    dxViewport.MinDepth = actualZNear;
    dxViewport.MaxDepth = actualZFar;

    mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);

    mCurViewport = viewport;
    mCurNear     = actualZNear;
    mCurFar      = actualZFar;

    const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX),
                                           static_cast<FLOAT>(dxViewportTopLeftY),
                                           static_cast<FLOAT>(dxViewportWidth),
                                           static_cast<FLOAT>(dxViewportHeight),
                                           actualZNear,
                                           actualZFar};
    mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled);
}

void StateManager11::invalidateRenderTarget()
{
    mRenderTargetIsDirty = true;
}

void StateManager11::processFramebufferInvalidation(const gl::Context *context)
{
    ASSERT(mRenderTargetIsDirty);
    ASSERT(context);

    mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);

    // The pixel shader is dependent on the output layout.
    invalidateShaders();

    // The D3D11 blend state is heavily dependent on the current render target.
    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);

    gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
    ASSERT(fbo);

    // Disable the depth test/depth write if we are using a stencil-only attachment.
    // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
    // nor write to the unused depth part of this emulated texture.
    bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil());

    // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
    bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil());

    if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() ||
        !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value())
    {
        mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
        mCurDisableDepth   = disableDepth;
        mCurDisableStencil = disableStencil;
    }

    bool multiSample = (fbo->getCachedSamples(context) != 0);
    if (multiSample != mCurRasterState.multiSample)
    {
        mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
        mCurRasterState.multiSample = multiSample;
    }

    checkPresentPath(context);

    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
    {
        const auto *firstAttachment = fbo->getFirstNonNullAttachment();
        if (firstAttachment)
        {
            const auto &size = firstAttachment->getSize();
            if (mViewportBounds.width != size.width || mViewportBounds.height != size.height)
            {
                mViewportBounds = gl::Extents(size.width, size.height, 1);
                invalidateViewport(context);
            }
        }
    }
}

void StateManager11::invalidateBoundViews()
{
    for (SRVCache &curShaderSRV : mCurShaderSRVs)
    {
        curShaderSRV.clear();
    }

    invalidateRenderTarget();
}

void StateManager11::invalidateVertexBuffer()
{
    unsigned int limit      = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
                                                gl::MAX_VERTEX_ATTRIBS);
    mDirtyVertexBufferRange = gl::RangeUI(0, limit);
    invalidateInputLayout();
    invalidateShaders();
    mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
}

void StateManager11::invalidateViewport(const gl::Context *context)
{
    mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);

    // Viewport affects the driver constants.
    invalidateDriverUniforms();
}

void StateManager11::invalidateTexturesAndSamplers()
{
    mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
    invalidateSwizzles();

    // Texture state affects the driver uniforms (base level, etc).
    invalidateDriverUniforms();
}

void StateManager11::invalidateSwizzles()
{
    mDirtySwizzles = true;
}

void StateManager11::invalidateProgramUniforms()
{
    mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
}

void StateManager11::invalidateDriverUniforms()
{
    mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
}

void StateManager11::invalidateProgramUniformBuffers()
{
    mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
}

void StateManager11::invalidateProgramAtomicCounterBuffers()
{
    mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
}

void StateManager11::invalidateProgramShaderStorageBuffers()
{
    mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
}

void StateManager11::invalidateConstantBuffer(unsigned int slot)
{
    if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
    {
        invalidateDriverUniforms();
    }
    else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK)
    {
        invalidateProgramUniforms();
    }
    else
    {
        invalidateProgramUniformBuffers();
    }
}

void StateManager11::invalidateShaders()
{
    mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
}

void StateManager11::invalidateTransformFeedback()
{
    // Transform feedback affects the stream-out geometry shader.
    invalidateShaders();
    mInternalDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK);
    // syncPrimitiveTopology checks the transform feedback state.
    mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
}

void StateManager11::invalidateInputLayout()
{
    mInternalDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT);
}

void StateManager11::invalidateIndexBuffer()
{
    mIndexBufferIsDirty = true;
}

void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv)
{
    if (rtv)
    {
        unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtv, true);
    }

    if (dsv)
    {
        unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
    }

    mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
    mCurRTVs.clear();
    mCurRTVs.update(0, rtv);
    mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
}

void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs,
                                      UINT numRTVs,
                                      ID3D11DepthStencilView *dsv)
{
    for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex)
    {
        unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtvs[rtvIndex], true);
    }

    if (dsv)
    {
        unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
    }

    mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv);
    mCurRTVs.clear();
    for (UINT i = 0; i < numRTVs; i++)
    {
        mCurRTVs.update(i, rtvs[i]);
    }
    mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
}

void StateManager11::onBeginQuery(Query11 *query)
{
    mCurrentQueries.insert(query);
}

void StateManager11::onDeleteQueryObject(Query11 *query)
{
    mCurrentQueries.erase(query);
}

angle::Result StateManager11::onMakeCurrent(const gl::Context *context)
{
    ANGLE_TRY(ensureInitialized(context));

    const gl::State &state = context->getState();

    Context11 *context11 = GetImplAs<Context11>(context);

    for (Query11 *query : mCurrentQueries)
    {
        ANGLE_TRY(query->pause(context11));
    }
    mCurrentQueries.clear();

    for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
    {
        gl::Query *query = state.getActiveQuery(type);
        if (query != nullptr)
        {
            Query11 *query11 = GetImplAs<Query11>(query);
            ANGLE_TRY(query11->resume(context11));
            mCurrentQueries.insert(query11);
        }
    }

    // Reset the cache objects.
    mProgramD3D    = nullptr;
    mVertexArray11 = nullptr;
    mFramebuffer11 = nullptr;

    return angle::Result::Continue;
}

void StateManager11::unsetConflictingView(gl::PipelineType pipeline,
                                          ID3D11View *view,
                                          bool isRenderTarget)
{
    uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));

    unsetConflictingSRVs(pipeline, gl::ShaderType::Vertex, resource, nullptr, isRenderTarget);
    unsetConflictingSRVs(pipeline, gl::ShaderType::Fragment, resource, nullptr, isRenderTarget);
    unsetConflictingSRVs(pipeline, gl::ShaderType::Compute, resource, nullptr, isRenderTarget);
    unsetConflictingUAVs(pipeline, gl::ShaderType::Compute, resource, nullptr);
}

void StateManager11::unsetConflictingSRVs(gl::PipelineType pipeline,
                                          gl::ShaderType shaderType,
                                          uintptr_t resource,
                                          const gl::ImageIndex *index,
                                          bool isRenderTarget)
{
    auto *currentSRVs                 = getSRVCache(shaderType);
    gl::PipelineType conflictPipeline = gl::GetPipelineType(shaderType);
    bool foundOne                     = false;
    size_t count                      = std::min(currentSRVs->size(), currentSRVs->highestUsed());
    for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
    {
        auto &record = (*currentSRVs)[resourceIndex];

        if (record.view && record.resource == resource &&
            (!index || ImageIndexConflictsWithSRV(*index, record.desc)))
        {
            setShaderResourceInternal<d3d11::ShaderResourceView>(
                shaderType, static_cast<UINT>(resourceIndex), nullptr);
            foundOne = true;
        }
    }

    if (foundOne && (pipeline != conflictPipeline || isRenderTarget))
    {
        switch (conflictPipeline)
        {
            case gl::PipelineType::GraphicsPipeline:
                mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRVUAV_STATE);
                break;
            case gl::PipelineType::ComputePipeline:
                mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
                break;
            default:
                UNREACHABLE();
        }
    }
}

void StateManager11::unsetConflictingUAVs(gl::PipelineType pipeline,
                                          gl::ShaderType shaderType,
                                          uintptr_t resource,
                                          const gl::ImageIndex *index)
{
    ASSERT(shaderType == gl::ShaderType::Compute);
    bool foundOne = false;

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    size_t count = std::min(mCurComputeUAVs.size(), mCurComputeUAVs.highestUsed());
    for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
    {
        auto &record = mCurComputeUAVs[resourceIndex];

        if (record.view && record.resource == resource &&
            (!index || ImageIndexConflictsWithUAV(*index, record.desc)))
        {
            deviceContext->CSSetUnorderedAccessViews(static_cast<UINT>(resourceIndex), 1,
                                                     &mNullUAVs[0], nullptr);
            mCurComputeUAVs.update(resourceIndex, nullptr);
            foundOne = true;
        }
    }

    if (foundOne && pipeline == gl::PipelineType::GraphicsPipeline)
    {
        mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
    }
}

void StateManager11::unsetConflictingRTVs(uintptr_t resource)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    size_t count                       = std::min(mCurRTVs.size(), mCurRTVs.highestUsed());
    for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
    {
        auto &record = mCurRTVs[resourceIndex];

        if (record.view && record.resource == resource)
        {
            deviceContext->OMSetRenderTargets(0, nullptr, nullptr);
            mCurRTVs.clear();
            mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
            return;
        }
    }
}

void StateManager11::unsetConflictingAttachmentResources(
    const gl::FramebufferAttachment &attachment,
    ID3D11Resource *resource)
{
    // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
    if (attachment.type() == GL_TEXTURE)
    {
        uintptr_t resourcePtr       = reinterpret_cast<uintptr_t>(resource);
        const gl::ImageIndex &index = attachment.getTextureImageIndex();
        // The index doesn't need to be corrected for the small compressed texture workaround
        // because a rendertarget is never compressed.
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
                             resourcePtr, &index, false);
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
                             resourcePtr, &index, false);
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
                             resourcePtr, &index, false);
        unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
                             resourcePtr, &index);
    }
    else if (attachment.type() == GL_FRAMEBUFFER_DEFAULT)
    {
        uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
                             resourcePtr, nullptr, false);
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
                             resourcePtr, nullptr, false);
        unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
                             resourcePtr, nullptr, false);
        unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
                             resourcePtr, nullptr);
    }
}

angle::Result StateManager11::ensureInitialized(const gl::Context *context)
{
    Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();

    const gl::Caps &caps             = renderer->getNativeCaps();
    const gl::Extensions &extensions = renderer->getNativeExtensions();

    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        const GLuint maxShaderTextureImageUnits = caps.maxShaderTextureImageUnits[shaderType];

        mCurShaderSRVs[shaderType].initialize(maxShaderTextureImageUnits);
        mForceSetShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits, true);
        mCurShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits);
    }
    mCurRTVs.initialize(caps.maxColorAttachments);
    mCurComputeUAVs.initialize(caps.maxImageUnits);

    // Initialize cached NULL SRV block
    mNullSRVs.resize(caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment], nullptr);

    mNullUAVs.resize(caps.maxImageUnits, nullptr);

    mCurrentValueAttribs.resize(caps.maxVertexAttributes);

    mShaderConstants.init(caps);

    mIsMultiviewEnabled = extensions.multiview || extensions.multiview2;

    ANGLE_TRY(mVertexDataManager.initialize(context));

    mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);

    return angle::Result::Continue;
}

void StateManager11::deinitialize()
{
    mCurrentValueAttribs.clear();
    mInputLayoutCache.clear();
    mVertexDataManager.deinitialize();
    mIndexDataManager.deinitialize();

    for (d3d11::Buffer &ShaderDriverConstantBuffer : mShaderDriverConstantBuffers)
    {
        ShaderDriverConstantBuffer.reset();
    }

    mPointSpriteVertexBuffer.reset();
    mPointSpriteIndexBuffer.reset();
}

// Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
angle::Result StateManager11::syncFramebuffer(const gl::Context *context)
{
    // Check for zero-sized default framebuffer, which is a special case.
    // in this case we do not wish to modify any state and just silently return false.
    // this will not report any gl error but will cause the calling method to return.
    if (mFramebuffer11->getState().isDefault())
    {
        RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
        const gl::Extents &size = firstRT->getExtents();
        if (size.empty())
        {
            return angle::Result::Continue;
        }
    }

    RTVArray framebufferRTVs = {{}};
    const auto &colorRTs     = mFramebuffer11->getCachedColorRenderTargets();

    size_t appliedRTIndex                   = 0;
    bool skipInactiveRTs                    = mRenderer->getFeatures().mrtPerfWorkaround.enabled;
    const auto &drawStates                  = mFramebuffer11->getState().getDrawBufferStates();
    gl::DrawBufferMask activeProgramOutputs = mProgramD3D->getState().getActiveOutputVariables();
    UINT maxExistingRT                      = 0;
    const auto &colorAttachments            = mFramebuffer11->getState().getColorAttachments();

    for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
    {
        const RenderTarget11 *renderTarget = colorRTs[rtIndex];

        // Skip inactive rendertargets if the workaround is enabled.
        if (skipInactiveRTs &&
            (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
        {
            continue;
        }

        if (renderTarget)
        {
            framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
            ASSERT(framebufferRTVs[appliedRTIndex]);
            maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;

            // Unset conflicting texture SRVs
            const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
            ASSERT(attachment.isAttached());
            unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
        }

        appliedRTIndex++;
    }

    // Get the depth stencil buffers
    ID3D11DepthStencilView *framebufferDSV = nullptr;
    const auto *depthStencilRenderTarget   = mFramebuffer11->getCachedDepthStencilRenderTarget();
    if (depthStencilRenderTarget)
    {
        framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
        ASSERT(framebufferDSV);

        // Unset conflicting texture SRVs
        const gl::FramebufferAttachment *attachment =
            mFramebuffer11->getState().getDepthOrStencilAttachment();
        ASSERT(attachment);
        unsetConflictingAttachmentResources(*attachment,
                                            depthStencilRenderTarget->getTexture().get());
    }

    ASSERT(maxExistingRT <= static_cast<UINT>(context->getCaps().maxDrawBuffers));

    // Apply the render target and depth stencil
    mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
                                                      framebufferDSV);
    mCurRTVs.clear();
    for (UINT i = 0; i < maxExistingRT; i++)
    {
        mCurRTVs.update(i, framebufferRTVs[i]);
    }
    return angle::Result::Continue;
}

void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
{
    mDirtyCurrentValueAttribs.set(attribIndex);
    mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
    invalidateInputLayout();
    invalidateShaders();
}

angle::Result StateManager11::syncCurrentValueAttribs(
    const gl::Context *context,
    const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
{
    const auto &activeAttribsMask  = mProgramD3D->getState().getActiveAttribLocationsMask();
    const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);

    if (!dirtyActiveAttribs.any())
    {
        return angle::Result::Continue;
    }

    const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
    const auto &vertexBindings   = mVertexArray11->getState().getVertexBindings();
    mDirtyCurrentValueAttribs    = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);

    for (auto attribIndex : dirtyActiveAttribs)
    {
        if (vertexAttributes[attribIndex].enabled)
            continue;

        const auto *attrib                      = &vertexAttributes[attribIndex];
        const auto &currentValue                = currentValues[attribIndex];
        TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
        currentValueAttrib->currentValueType    = currentValue.Type;
        currentValueAttrib->attribute           = attrib;
        currentValueAttrib->binding             = &vertexBindings[attrib->bindingIndex];

        mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));

        ANGLE_TRY(mVertexDataManager.storeCurrentValue(context, currentValue, currentValueAttrib,
                                                       static_cast<size_t>(attribIndex)));
    }

    return angle::Result::Continue;
}

void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
{
    if (setInputLayoutInternal(inputLayout))
    {
        invalidateInputLayout();
    }
}

bool StateManager11::setInputLayoutInternal(const d3d11::InputLayout *inputLayout)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    if (inputLayout == nullptr)
    {
        if (!mCurrentInputLayout.empty())
        {
            deviceContext->IASetInputLayout(nullptr);
            mCurrentInputLayout.clear();
            return true;
        }
    }
    else if (inputLayout->getSerial() != mCurrentInputLayout)
    {
        deviceContext->IASetInputLayout(inputLayout->get());
        mCurrentInputLayout = inputLayout->getSerial();
        return true;
    }

    return false;
}

bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
                                             ID3D11Buffer *buffer,
                                             UINT stride,
                                             UINT offset)
{
    if (buffer != mCurrentVertexBuffers[bufferIndex] ||
        stride != mCurrentVertexStrides[bufferIndex] ||
        offset != mCurrentVertexOffsets[bufferIndex])
    {
        mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));

        mCurrentVertexBuffers[bufferIndex] = buffer;
        mCurrentVertexStrides[bufferIndex] = stride;
        mCurrentVertexOffsets[bufferIndex] = offset;
        return true;
    }

    return false;
}

void StateManager11::applyVertexBufferChanges()
{
    if (mDirtyVertexBufferRange.empty())
    {
        return;
    }

    ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);

    UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
                                      &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
                                      &mCurrentVertexOffsets[start]);

    mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
}

void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
{
    ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
    if (queueVertexBufferChange(0, native, stride, offset))
    {
        invalidateInputLayout();
        applyVertexBufferChanges();
    }
}

angle::Result StateManager11::updateState(const gl::Context *context,
                                          gl::PrimitiveMode mode,
                                          GLint firstVertex,
                                          GLsizei vertexOrIndexCount,
                                          gl::DrawElementsType indexTypeOrInvalid,
                                          const void *indices,
                                          GLsizei instanceCount,
                                          GLint baseVertex)
{
    const gl::State &glState = context->getState();

    // TODO(jmadill): Use dirty bits.
    if (mRenderTargetIsDirty)
    {
        processFramebufferInvalidation(context);
        mRenderTargetIsDirty = false;
    }

    // TODO(jmadill): Use dirty bits.
    if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
    {
        invalidateTexturesAndSamplers();
    }

    // TODO(jmadill): Use dirty bits.
    if (mProgramD3D->anyShaderUniformsDirty())
    {
        mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
    }

    // Swizzling can cause internal state changes with blit shaders.
    if (mDirtySwizzles)
    {
        ANGLE_TRY(generateSwizzles(context));
        mDirtySwizzles = false;
    }

    ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));

    // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
    // state changes.
    RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
    int samples             = (firstRT ? firstRT->getSamples() : 0);
    unsigned int sampleMask = GetBlendSampleMask(glState, samples);
    if (sampleMask != mCurSampleMask)
    {
        mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
    }

    ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
                                               indexTypeOrInvalid, indices, instanceCount,
                                               baseVertex));

    // Changes in the draw call can affect the vertex buffer translations.
    if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
    {
        mLastFirstVertex = firstVertex;
        invalidateInputLayout();
    }

    // The ShaderConstants only need to be updated when the program uses vertexID
    if (mProgramD3D->usesVertexID())
    {
        if (mShaderConstants.onFirstVertexChange(firstVertex, baseVertex))
        {
            mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
        }
    }

    if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
    {
        ANGLE_TRY(applyIndexBuffer(context, vertexOrIndexCount, indexTypeOrInvalid, indices));
    }

    if (mLastAppliedDrawMode != mode)
    {
        mLastAppliedDrawMode = mode;
        mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);

        bool pointDrawMode = (mode == gl::PrimitiveMode::Points);
        if (pointDrawMode != mCurRasterState.pointDrawMode)
        {
            mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);

            // Changing from points to not points (or vice-versa) affects the geometry shader.
            invalidateShaders();
        }
    }

    auto dirtyBitsCopy = mInternalDirtyBits & mGraphicsDirtyBitsMask;
    mInternalDirtyBits &= ~mGraphicsDirtyBitsMask;

    for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
    {
        switch (*iter)
        {
            case DIRTY_BIT_RENDER_TARGET:
                ANGLE_TRY(syncFramebuffer(context));
                break;
            case DIRTY_BIT_VIEWPORT_STATE:
                syncViewport(context);
                break;
            case DIRTY_BIT_SCISSOR_STATE:
                syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
                break;
            case DIRTY_BIT_RASTERIZER_STATE:
                ANGLE_TRY(syncRasterizerState(context, mode));
                break;
            case DIRTY_BIT_BLEND_STATE:
                ANGLE_TRY(syncBlendState(context, glState.getBlendState(), glState.getBlendColor(),
                                         sampleMask));
                break;
            case DIRTY_BIT_DEPTH_STENCIL_STATE:
                ANGLE_TRY(syncDepthStencilState(context));
                break;
            case DIRTY_BIT_GRAPHICS_SRVUAV_STATE:
                iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
                ANGLE_TRY(syncTextures(context));
                break;
            case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
                // TODO(jmadill): More fine-grained update.
                ANGLE_TRY(syncTextures(context));
                break;
            case DIRTY_BIT_PROGRAM_UNIFORMS:
                ANGLE_TRY(applyUniforms(context));
                break;
            case DIRTY_BIT_DRIVER_UNIFORMS:
                // This must happen after viewport sync; the viewport affects builtin uniforms.
                ANGLE_TRY(applyDriverUniforms(context));
                break;
            case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
                ANGLE_TRY(syncUniformBuffers(context));
                break;
            case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
                // TODO(jie.a.chen@intel.com): http://anglebug.com/1729
                break;
            case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
                // TODO(jie.a.chen@intel.com): http://anglebug.com/1951
                break;
            case DIRTY_BIT_SHADERS:
                ANGLE_TRY(syncProgram(context, mode));
                break;
            case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
                ANGLE_TRY(syncCurrentValueAttribs(context, glState.getVertexAttribCurrentValues()));
                break;
            case DIRTY_BIT_TRANSFORM_FEEDBACK:
                ANGLE_TRY(syncTransformFeedbackBuffers(context));
                break;
            case DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT:
                ANGLE_TRY(syncVertexBuffersAndInputLayout(context, mode, firstVertex,
                                                          vertexOrIndexCount, indexTypeOrInvalid,
                                                          instanceCount));
                break;
            case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
                syncPrimitiveTopology(glState, mode);
                break;
            default:
                UNREACHABLE();
                break;
        }
    }

    // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except
    // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit.
    ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none());

    return angle::Result::Continue;
}

void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
                                             UINT resourceSlot,
                                             const d3d11::SharedSRV *srv)
{
    setShaderResourceInternal(shaderType, resourceSlot, srv);

    // TODO(jmadill): Narrower dirty region.
    mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
}

void StateManager11::setShaderResource(gl::ShaderType shaderType,
                                       UINT resourceSlot,
                                       const d3d11::ShaderResourceView *srv)
{
    setShaderResourceInternal(shaderType, resourceSlot, srv);

    // TODO(jmadill): Narrower dirty region.
    mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
}

void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
{
    if (setPrimitiveTopologyInternal(primitiveTopology))
    {
        mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
    }
}

bool StateManager11::setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
{
    if (primitiveTopology != mCurrentPrimitiveTopology)
    {
        mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
        mCurrentPrimitiveTopology = primitiveTopology;
        return true;
    }
    else
    {
        return false;
    }
}

void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
                                    const d3d11::GeometryShader *geometryShader,
                                    const d3d11::PixelShader *pixelShader)
{
    setVertexShader(vertexShader);
    setGeometryShader(geometryShader);
    setPixelShader(pixelShader);
}

void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
{
    ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);

    if (serial != mAppliedShaders[gl::ShaderType::Vertex])
    {
        ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
        mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
        mAppliedShaders[gl::ShaderType::Vertex] = serial;
        invalidateShaders();
    }
}

void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
{
    ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);

    if (serial != mAppliedShaders[gl::ShaderType::Geometry])
    {
        ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
        mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
        mAppliedShaders[gl::ShaderType::Geometry] = serial;
        invalidateShaders();
    }
}

void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
{
    ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);

    if (serial != mAppliedShaders[gl::ShaderType::Fragment])
    {
        ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
        mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
        mAppliedShaders[gl::ShaderType::Fragment] = serial;
        invalidateShaders();
    }
}

void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
{
    ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);

    if (serial != mAppliedShaders[gl::ShaderType::Compute])
    {
        ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
        mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
        mAppliedShaders[gl::ShaderType::Compute] = serial;
        invalidateShaders();
    }
}

void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    auto &currentSerial                = mCurrentConstantBufferVS[slot];

    mCurrentConstantBufferVSOffset[slot] = 0;
    mCurrentConstantBufferVSSize[slot]   = 0;

    if (buffer)
    {
        if (currentSerial != buffer->getSerial())
        {
            deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
            currentSerial = buffer->getSerial();
            invalidateConstantBuffer(slot);
        }
    }
    else
    {
        if (!currentSerial.empty())
        {
            ID3D11Buffer *nullBuffer = nullptr;
            deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
            currentSerial.clear();
            invalidateConstantBuffer(slot);
        }
    }
}

void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    auto &currentSerial                = mCurrentConstantBufferPS[slot];

    mCurrentConstantBufferPSOffset[slot] = 0;
    mCurrentConstantBufferPSSize[slot]   = 0;

    if (buffer)
    {
        if (currentSerial != buffer->getSerial())
        {
            deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
            currentSerial = buffer->getSerial();
            invalidateConstantBuffer(slot);
        }
    }
    else
    {
        if (!currentSerial.empty())
        {
            ID3D11Buffer *nullBuffer = nullptr;
            deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
            currentSerial.clear();
            invalidateConstantBuffer(slot);
        }
    }
}

void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
                                          UINT stencilRef)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    if (depthStencilState)
    {
        deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
    }
    else
    {
        deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
    }

    mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}

void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    if (blendState)
    {
        deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
    }
    else
    {
        deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
    }

    mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}

void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    if (rasterizerState)
    {
        deviceContext->RSSetState(rasterizerState->get());
    }
    else
    {
        deviceContext->RSSetState(nullptr);
    }

    mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}

void StateManager11::setSimpleViewport(const gl::Extents &extents)
{
    setSimpleViewport(extents.width, extents.height);
}

void StateManager11::setSimpleViewport(int width, int height)
{
    D3D11_VIEWPORT viewport;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width    = static_cast<FLOAT>(width);
    viewport.Height   = static_cast<FLOAT>(height);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;

    mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
    mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
}

void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
                                                     const d3d11::SamplerState &samplerState)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    setShaderResourceInternal(gl::ShaderType::Fragment, 0, &srv);
    deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());

    mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
    mForceSetShaderSamplerStates[gl::ShaderType::Fragment][0] = true;
}

void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
{
    D3D11_RECT scissorRect;
    scissorRect.left   = glRect.x;
    scissorRect.right  = glRect.x + glRect.width;
    scissorRect.top    = glRect.y;
    scissorRect.bottom = glRect.y + glRect.height;
    setScissorRectD3D(scissorRect);
}

void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
{
    mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
    mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
}

angle::Result StateManager11::syncTextures(const gl::Context *context)
{
    ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
    ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
    if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
    {
        ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::setSamplerState(const gl::Context *context,
                                              gl::ShaderType type,
                                              int index,
                                              gl::Texture *texture,
                                              const gl::SamplerState &samplerState)
{
#if !defined(NDEBUG)
    // Storage should exist, texture should be complete. Only verified in Debug.
    TextureD3D *textureD3D  = GetImplAs<TextureD3D>(texture);
    TextureStorage *storage = nullptr;
    ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
    ASSERT(storage);
#endif  // !defined(NDEBUG)

    auto *deviceContext = mRenderer->getDeviceContext();

    ASSERT(static_cast<unsigned int>(index) <
           mRenderer->getNativeCaps().maxShaderTextureImageUnits[type]);

    if (mForceSetShaderSamplerStates[type][index] ||
        memcmp(&samplerState, &mCurShaderSamplerStates[type][index], sizeof(gl::SamplerState)) != 0)
    {
        ID3D11SamplerState *dxSamplerState = nullptr;
        ANGLE_TRY(mRenderer->getSamplerState(context, samplerState, &dxSamplerState));

        ASSERT(dxSamplerState != nullptr);

        switch (type)
        {
            case gl::ShaderType::Vertex:
                deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
                break;
            case gl::ShaderType::Fragment:
                deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
                break;
            case gl::ShaderType::Compute:
                deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
                break;
            case gl::ShaderType::Geometry:
                deviceContext->GSSetSamplers(index, 1, &dxSamplerState);
                break;
            default:
                UNREACHABLE();
                break;
        }

        mCurShaderSamplerStates[type][index] = samplerState;
    }

    mForceSetShaderSamplerStates[type][index] = false;

    // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
    // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
    // buffer, and it doesn't affect the state set by
    // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers.
    mShaderConstants.onSamplerChange(type, index, *texture, samplerState);

    return angle::Result::Continue;
}

angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
                                                   gl::ShaderType type,
                                                   int index,
                                                   gl::Texture *texture,
                                                   const gl::SamplerState &sampler)
{
    const d3d11::SharedSRV *textureSRV = nullptr;

    if (texture)
    {
        TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);

        TextureStorage *texStorage = nullptr;
        ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));

        // Texture should be complete and have a storage
        ASSERT(texStorage);

        TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);

        ANGLE_TRY(
            storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));

        // If we get an invalid SRV here, something went wrong in the texture class and we're
        // unexpectedly missing the shader resource view.
        ASSERT(textureSRV->valid());

        textureImpl->resetDirty();
    }

    ASSERT((type == gl::ShaderType::Fragment &&
            static_cast<unsigned int>(index) <
                mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
           (type == gl::ShaderType::Vertex &&
            static_cast<unsigned int>(index) <
                mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
           (type == gl::ShaderType::Compute &&
            static_cast<unsigned int>(index) <
                mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]));

    setShaderResourceInternal(type, index, textureSRV);
    return angle::Result::Continue;
}

angle::Result StateManager11::setImageState(const gl::Context *context,
                                            gl::ShaderType type,
                                            int index,
                                            const gl::ImageUnit &imageUnit)
{
    ASSERT(static_cast<unsigned int>(index) <
           mRenderer->getNativeCaps().maxShaderImageUniforms[type]);

    mShaderConstants.onImageChange(type, index, imageUnit);

    return angle::Result::Continue;
}

// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
// Sampler mapping needs to be up-to-date on the program object before this is called.
angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
                                                   gl::ShaderType shaderType)
{
    const auto &glState = context->getState();
    const auto &caps    = context->getCaps();

    ASSERT(!mProgramD3D->isSamplerMappingDirty());

    // TODO(jmadill): Use the Program's sampler bindings.
    const gl::ActiveTexturePointerArray &completeTextures = glState.getActiveTexturesCache();

    const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
    for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
         samplerIndex++)
    {
        GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
        ASSERT(textureUnit != -1);
        gl::Texture *texture = completeTextures[textureUnit];

        // A nullptr texture indicates incomplete.
        if (texture)
        {
            gl::Sampler *samplerObject = glState.getSampler(textureUnit);

            const gl::SamplerState &samplerState =
                samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();

            ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
            ANGLE_TRY(
                setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
        }
        else
        {
            gl::TextureType textureType =
                mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);

            // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
            // incomplete texture.
            gl::Texture *incompleteTexture = nullptr;
            ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
            ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
                                      incompleteTexture->getSamplerState()));
            ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
                                           incompleteTexture->getSamplerState()));
        }
    }

    const gl::RangeUI readonlyImageRange = mProgramD3D->getUsedImageRange(shaderType, true);
    for (unsigned int readonlyImageIndex = readonlyImageRange.low();
         readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
    {
        GLint imageUnitIndex =
            mProgramD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
        ASSERT(imageUnitIndex != -1);
        const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
        if (!imageUnit.layered)
        {
            ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
                                    readonlyImageIndex - readonlyImageRange.low(), imageUnit));
            invalidateProgramUniforms();
        }
        ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, true, imageUnit));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::applyTexturesForUAVs(const gl::Context *context,
                                                   gl::ShaderType shaderType)
{
    ASSERT(shaderType == gl::ShaderType::Compute);
    const auto &glState = context->getState();
    const auto &caps    = context->getCaps();

    const gl::RangeUI imageRange = mProgramD3D->getUsedImageRange(shaderType, false);
    for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
    {
        GLint imageUnitIndex = mProgramD3D->getImageMapping(shaderType, imageIndex, false, caps);
        ASSERT(imageUnitIndex != -1);
        const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
        if (!imageUnit.layered)
        {
            ANGLE_TRY(setImageState(context, gl::ShaderType::Compute, imageIndex - imageRange.low(),
                                    imageUnit));
            invalidateProgramUniforms();
        }
        ANGLE_TRY(setTextureForImage(context, shaderType, imageIndex, false, imageUnit));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
{
    ANGLE_TRY(applyTexturesForUAVs(context, gl::ShaderType::Compute));
    ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
    return angle::Result::Continue;
}

angle::Result StateManager11::setTextureForImage(const gl::Context *context,
                                                 gl::ShaderType type,
                                                 int index,
                                                 bool readonly,
                                                 const gl::ImageUnit &imageUnit)
{
    TextureD3D *textureImpl = nullptr;
    if (!imageUnit.texture.get())
    {
        // The texture is used in shader. However, there is no resource binding to it. We
        // should clear the corresponding UAV/SRV in case the previous view type is a buffer not a
        // texture. Otherwise, below error will be reported. The Unordered Access View dimension
        // declared in the shader code (TEXTURE2D) does not match the view type bound to slot 0
        // of the Compute Shader unit (BUFFER).
        if (readonly)
        {
            setShaderResourceInternal<d3d11::ShaderResourceView>(type, static_cast<UINT>(index),
                                                                 nullptr);
        }
        else
        {
            setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(
                type, static_cast<UINT>(index), nullptr);
        }
        return angle::Result::Continue;
    }

    textureImpl                = GetImplAs<TextureD3D>(imageUnit.texture.get());
    TextureStorage *texStorage = nullptr;
    ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
    // Texture should be complete and have a storage
    ASSERT(texStorage);
    TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);

    if (readonly)
    {
        const d3d11::SharedSRV *textureSRV = nullptr;
        ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
        // If we get an invalid SRV here, something went wrong in the texture class and we're
        // unexpectedly missing the shader resource view.
        ASSERT(textureSRV->valid());
        ASSERT((static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxImageUnits));
        setShaderResourceInternal(type, index, textureSRV);
    }
    else
    {
        const d3d11::SharedUAV *textureUAV = nullptr;
        ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
        // If we get an invalid UAV here, something went wrong in the texture class and we're
        // unexpectedly missing the unordered access view.
        ASSERT(textureUAV->valid());
        ASSERT((static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxImageUnits));
        setUnorderedAccessViewInternal(type, index, textureUAV);
    }

    textureImpl->resetDirty();
    return angle::Result::Continue;
}

// Things that affect a program's dirtyness:
// 1. Directly changing the program executable -> triggered in StateManager11::syncState.
// 2. The vertex attribute layout              -> triggered in VertexArray11::syncState/signal.
// 3. The fragment shader's rendertargets      -> triggered in Framebuffer11::syncState/signal.
// 4. Enabling/disabling rasterizer discard.   -> triggered in StateManager11::syncState.
// 5. Enabling/disabling transform feedback.   -> checked in StateManager11::updateState.
// 6. An internal shader was used.             -> triggered in StateManager11::set*Shader.
// 7. Drawing with/without point sprites.      -> checked in StateManager11::updateState.
// TODO(jmadill): Use dirty bits for transform feedback.
angle::Result StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode)
{
    Context11 *context11 = GetImplAs<Context11>(context);
    ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));

    const auto &glState = context->getState();

    mProgramD3D->updateCachedInputLayout(mVertexArray11->getCurrentStateSerial(), glState);

    // Binaries must be compiled before the sync.
    ASSERT(mProgramD3D->hasVertexExecutableForCachedInputLayout());
    ASSERT(mProgramD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode));
    ASSERT(mProgramD3D->hasPixelExecutableForCachedOutputLayout());

    ShaderExecutableD3D *vertexExe = nullptr;
    ANGLE_TRY(mProgramD3D->getVertexExecutableForCachedInputLayout(context11, &vertexExe, nullptr));

    ShaderExecutableD3D *pixelExe = nullptr;
    ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));

    ShaderExecutableD3D *geometryExe = nullptr;
    ANGLE_TRY(mProgramD3D->getGeometryExecutableForPrimitiveType(context11, glState, drawMode,
                                                                 &geometryExe, nullptr));

    const d3d11::VertexShader *vertexShader =
        (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);

    // Skip pixel shader if we're doing rasterizer discard.
    const d3d11::PixelShader *pixelShader = nullptr;
    if (!glState.getRasterizerState().rasterizerDiscard)
    {
        pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
    }

    const d3d11::GeometryShader *geometryShader = nullptr;
    if (glState.isTransformFeedbackActiveUnpaused())
    {
        geometryShader =
            (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
    }
    else
    {
        geometryShader =
            (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
    }

    setDrawShaders(vertexShader, geometryShader, pixelShader);

    // Explicitly clear the shaders dirty bit.
    mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);

    return angle::Result::Continue;
}

angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
{
    Context11 *context11 = GetImplAs<Context11>(context);
    ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));

    mProgramD3D->updateCachedComputeImage2DBindLayout(context);

    // Binaries must be compiled before the sync.
    ASSERT(mProgramD3D->hasComputeExecutableForCachedImage2DBindLayout());

    ShaderExecutableD3D *computeExe = nullptr;
    ANGLE_TRY(
        mProgramD3D->getComputeExecutableForImage2DBindLayout(context11, &computeExe, nullptr));

    const d3d11::ComputeShader *computeShader =
        (computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
    setComputeShader(computeShader);
    // Explicitly clear the shaders dirty bit.
    mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);

    return angle::Result::Continue;
}

angle::Result StateManager11::syncVertexBuffersAndInputLayout(
    const gl::Context *context,
    gl::PrimitiveMode mode,
    GLint firstVertex,
    GLsizei vertexOrIndexCount,
    gl::DrawElementsType indexTypeOrInvalid,
    GLsizei instanceCount)
{
    const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();

    // Sort the attributes according to ensure we re-use similar input layouts.
    AttribIndexArray sortedSemanticIndices;
    SortAttributesByLayout(*mProgramD3D, vertexArrayAttribs, mCurrentValueAttribs,
                           &sortedSemanticIndices, &mCurrentAttributes);

    D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;

    // If we are using FL 9_3, make sure the first attribute is not instanced
    if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
    {
        if (mCurrentAttributes[0]->divisor > 0)
        {
            Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
            if (firstNonInstancedIndex.valid())
            {
                size_t index = firstNonInstancedIndex.value();
                std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
                std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
            }
        }
    }

    // Update the applied input layout by querying the cache.
    const gl::State &state                = context->getState();
    const d3d11::InputLayout *inputLayout = nullptr;
    ANGLE_TRY(mInputLayoutCache.getInputLayout(GetImplAs<Context11>(context), state,
                                               mCurrentAttributes, sortedSemanticIndices, mode,
                                               vertexOrIndexCount, instanceCount, &inputLayout));
    setInputLayoutInternal(inputLayout);

    // Update the applied vertex buffers.
    ANGLE_TRY(applyVertexBuffers(context, mode, indexTypeOrInvalid, firstVertex));

    return angle::Result::Continue;
}

angle::Result StateManager11::applyVertexBuffers(const gl::Context *context,
                                                 gl::PrimitiveMode mode,
                                                 gl::DrawElementsType indexTypeOrInvalid,
                                                 GLint firstVertex)
{
    bool programUsesInstancedPointSprites =
        mProgramD3D->usesPointSize() && mProgramD3D->usesInstancedPointSpriteEmulation();
    bool instancedPointSpritesActive =
        programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);

    // Note that if we use instance emulation, we reserve the first buffer slot.
    size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);

    for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
         ++attribIndex)
    {
        ID3D11Buffer *buffer = nullptr;
        UINT vertexStride    = 0;
        UINT vertexOffset    = 0;

        if (attribIndex < mCurrentAttributes.size())
        {
            const TranslatedAttribute &attrib = *mCurrentAttributes[attribIndex];
            Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;

            // If indexed pointsprite emulation is active, then we need to take a less efficent code
            // path. Emulated indexed pointsprite rendering requires that the vertex buffers match
            // exactly to the indices passed by the caller.  This could expand or shrink the vertex
            // buffer depending on the number of points indicated by the index list or how many
            // duplicates are found on the index list.
            if (bufferStorage == nullptr)
            {
                ASSERT(attrib.vertexBuffer.get());
                buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
            }
            else if (instancedPointSpritesActive &&
                     indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
            {
                ASSERT(mVertexArray11->isCachedIndexInfoValid());
                TranslatedIndexData indexInfo = mVertexArray11->getCachedIndexInfo();
                if (indexInfo.srcIndexData.srcBuffer != nullptr)
                {
                    const uint8_t *bufferData = nullptr;
                    ANGLE_TRY(indexInfo.srcIndexData.srcBuffer->getData(context, &bufferData));
                    ASSERT(bufferData != nullptr);

                    ptrdiff_t offset =
                        reinterpret_cast<ptrdiff_t>(indexInfo.srcIndexData.srcIndices);
                    indexInfo.srcIndexData.srcBuffer  = nullptr;
                    indexInfo.srcIndexData.srcIndices = bufferData + offset;
                }

                ANGLE_TRY(bufferStorage->getEmulatedIndexedBuffer(context, &indexInfo.srcIndexData,
                                                                  attrib, firstVertex, &buffer));

                mVertexArray11->updateCachedIndexInfo(indexInfo);
            }
            else
            {
                ANGLE_TRY(bufferStorage->getBuffer(
                    context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer));
            }

            vertexStride = attrib.stride;
            ANGLE_TRY(attrib.computeOffset(context, firstVertex, &vertexOffset));
        }

        size_t bufferIndex = reservedBuffers + attribIndex;

        queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
    }

    Context11 *context11 = GetImplAs<Context11>(context);

    // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
    // to be created and added to the list of current buffers, strides and offsets collections.
    // This buffer contains the vertices for a single PointSprite quad.
    // An index buffer also needs to be created and applied because rendering instanced data on
    // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and
    // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot
    // handle missing vertex data and will TDR the system.
    if (programUsesInstancedPointSprites)
    {
        constexpr UINT kPointSpriteVertexStride = sizeof(float) * 5;

        if (!mPointSpriteVertexBuffer.valid())
        {
            static constexpr float kPointSpriteVertices[] = {
                // Position        | TexCoord
                -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v0 */
                -1.0f, 1.0f,  0.0f, 0.0f, 0.0f, /* v1 */
                1.0f,  1.0f,  0.0f, 1.0f, 0.0f, /* v2 */
                1.0f,  -1.0f, 0.0f, 1.0f, 1.0f, /* v3 */
                -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v4 */
                1.0f,  1.0f,  0.0f, 1.0f, 0.0f, /* v5 */
            };

            D3D11_SUBRESOURCE_DATA vertexBufferData = {kPointSpriteVertices, 0, 0};
            D3D11_BUFFER_DESC vertexBufferDesc;
            vertexBufferDesc.ByteWidth           = sizeof(kPointSpriteVertices);
            vertexBufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
            vertexBufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
            vertexBufferDesc.CPUAccessFlags      = 0;
            vertexBufferDesc.MiscFlags           = 0;
            vertexBufferDesc.StructureByteStride = 0;

            ANGLE_TRY(mRenderer->allocateResource(context11, vertexBufferDesc, &vertexBufferData,
                                                  &mPointSpriteVertexBuffer));
        }

        // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
        // indexing into the vertex buffer.
        UINT stride = instancedPointSpritesActive ? kPointSpriteVertexStride : 0;
        queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);

        if (!mPointSpriteIndexBuffer.valid())
        {
            // Create an index buffer and set it for pointsprite rendering
            static constexpr unsigned short kPointSpriteIndices[] = {
                0, 1, 2, 3, 4, 5,
            };

            D3D11_SUBRESOURCE_DATA indexBufferData = {kPointSpriteIndices, 0, 0};
            D3D11_BUFFER_DESC indexBufferDesc;
            indexBufferDesc.ByteWidth           = sizeof(kPointSpriteIndices);
            indexBufferDesc.BindFlags           = D3D11_BIND_INDEX_BUFFER;
            indexBufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
            indexBufferDesc.CPUAccessFlags      = 0;
            indexBufferDesc.MiscFlags           = 0;
            indexBufferDesc.StructureByteStride = 0;

            ANGLE_TRY(mRenderer->allocateResource(context11, indexBufferDesc, &indexBufferData,
                                                  &mPointSpriteIndexBuffer));
        }

        if (instancedPointSpritesActive)
        {
            // The index buffer is applied here because Instanced PointSprite emulation uses the a
            // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
            // on the renderer will not be called and setting this buffer here ensures that the
            // rendering path will contain the correct index buffers.
            syncIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
        }
    }

    applyVertexBufferChanges();
    return angle::Result::Continue;
}

angle::Result StateManager11::applyIndexBuffer(const gl::Context *context,
                                               GLsizei indexCount,
                                               gl::DrawElementsType indexType,
                                               const void *indices)
{
    if (!mIndexBufferIsDirty)
    {
        // No streaming or index buffer application necessary.
        return angle::Result::Continue;
    }

    gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType();
    gl::Buffer *elementArrayBuffer       = mVertexArray11->getState().getElementArrayBuffer();

    TranslatedIndexData indexInfo;
    ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount,
                                                 elementArrayBuffer, indices, &indexInfo));

    ID3D11Buffer *buffer     = nullptr;
    DXGI_FORMAT bufferFormat = (indexInfo.indexType == gl::DrawElementsType::UnsignedInt)
                                   ? DXGI_FORMAT_R32_UINT
                                   : DXGI_FORMAT_R16_UINT;

    if (indexInfo.storage)
    {
        Buffer11 *storage = GetAs<Buffer11>(indexInfo.storage);
        ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer));
    }
    else
    {
        IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo.indexBuffer);
        buffer                     = indexBuffer->getBuffer().get();
    }

    // Track dirty indices in the index range cache.
    indexInfo.srcIndexData.srcIndicesChanged =
        syncIndexBuffer(buffer, bufferFormat, indexInfo.startOffset);

    mIndexBufferIsDirty = false;

    mVertexArray11->updateCachedIndexInfo(indexInfo);
    return angle::Result::Continue;
}

void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
                                    DXGI_FORMAT indexFormat,
                                    unsigned int offset)
{
    if (syncIndexBuffer(buffer, indexFormat, offset))
    {
        invalidateIndexBuffer();
    }
}

bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
                                     DXGI_FORMAT indexFormat,
                                     unsigned int offset)
{
    if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
    {
        mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);

        mAppliedIB       = buffer;
        mAppliedIBFormat = indexFormat;
        mAppliedIBOffset = offset;
        return true;
    }

    return false;
}

// Vertex buffer is invalidated outside this function.
angle::Result StateManager11::updateVertexOffsetsForPointSpritesEmulation(
    const gl::Context *context,
    GLint startVertex,
    GLsizei emulatedInstanceId)
{
    size_t reservedBuffers = GetReservedBufferCount(true);
    for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
    {
        const auto &attrib = *mCurrentAttributes[attribIndex];
        size_t bufferIndex = reservedBuffers + attribIndex;

        if (attrib.divisor > 0)
        {
            unsigned int offset = 0;
            ANGLE_TRY(attrib.computeOffset(context, startVertex, &offset));
            offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
            if (offset != mCurrentVertexOffsets[bufferIndex])
            {
                invalidateInputLayout();
                mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
                mCurrentVertexOffsets[bufferIndex] = offset;
            }
        }
    }

    applyVertexBufferChanges();
    return angle::Result::Continue;
}

angle::Result StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
{
    if (!texture)
    {
        return angle::Result::Continue;
    }

    TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
    ASSERT(textureD3D);

    TextureStorage *texStorage = nullptr;
    ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));

    if (texStorage)
    {
        TextureStorage11 *storage11          = GetAs<TextureStorage11>(texStorage);
        const gl::TextureState &textureState = texture->getTextureState();
        ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState()));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::generateSwizzlesForShader(const gl::Context *context,
                                                        gl::ShaderType type)
{
    const gl::State &glState       = context->getState();
    const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(type);

    for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
    {
        gl::TextureType textureType = mProgramD3D->getSamplerTextureType(type, i);
        GLint textureUnit           = mProgramD3D->getSamplerMapping(type, i, context->getCaps());
        if (textureUnit != -1)
        {
            gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
            ASSERT(texture);
            if (texture->getTextureState().swizzleRequired())
            {
                ANGLE_TRY(generateSwizzle(context, texture));
            }
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::generateSwizzles(const gl::Context *context)
{
    ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Vertex));
    ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Fragment));
    return angle::Result::Continue;
}

angle::Result StateManager11::applyUniformsForShader(const gl::Context *context,
                                                     gl::ShaderType shaderType)
{
    UniformStorage11 *shaderUniformStorage =
        GetAs<UniformStorage11>(mProgramD3D->getShaderUniformStorage(shaderType));
    ASSERT(shaderUniformStorage);

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    const d3d11::Buffer *shaderConstantBuffer = nullptr;
    ANGLE_TRY(shaderUniformStorage->getConstantBuffer(context, mRenderer, &shaderConstantBuffer));

    if (shaderUniformStorage->size() > 0 && mProgramD3D->areShaderUniformsDirty(shaderType))
    {
        UpdateUniformBuffer(deviceContext, shaderUniformStorage, shaderConstantBuffer);
    }

    unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;

    switch (shaderType)
    {
        case gl::ShaderType::Vertex:
            if (mCurrentConstantBufferVS[slot] != shaderConstantBuffer->getSerial())
            {
                deviceContext->VSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
                mCurrentConstantBufferVS[slot]       = shaderConstantBuffer->getSerial();
                mCurrentConstantBufferVSOffset[slot] = 0;
                mCurrentConstantBufferVSSize[slot]   = 0;
            }
            break;

        case gl::ShaderType::Fragment:
            if (mCurrentConstantBufferPS[slot] != shaderConstantBuffer->getSerial())
            {
                deviceContext->PSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
                mCurrentConstantBufferPS[slot]       = shaderConstantBuffer->getSerial();
                mCurrentConstantBufferPSOffset[slot] = 0;
                mCurrentConstantBufferPSSize[slot]   = 0;
            }
            break;

        // TODO(jiawei.shao@intel.com): apply geometry shader uniforms
        case gl::ShaderType::Geometry:
            UNIMPLEMENTED();
            break;

        default:
            UNREACHABLE();
            break;
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::applyUniforms(const gl::Context *context)
{
    ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Vertex));
    ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Fragment));
    if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
    {
        ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Geometry));
    }

    mProgramD3D->markUniformsClean();

    return angle::Result::Continue;
}

angle::Result StateManager11::applyDriverUniformsForShader(const gl::Context *context,
                                                           gl::ShaderType shaderType)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    d3d11::Buffer &shaderDriverConstantBuffer = mShaderDriverConstantBuffers[shaderType];
    if (!shaderDriverConstantBuffer.valid())
    {
        size_t requiredSize = mShaderConstants.getRequiredBufferSize(shaderType);

        D3D11_BUFFER_DESC constantBufferDescription = {0};
        d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
        ANGLE_TRY(mRenderer->allocateResource(
            GetImplAs<Context11>(context), constantBufferDescription, &shaderDriverConstantBuffer));

        ID3D11Buffer *driverConstants = shaderDriverConstantBuffer.get();
        switch (shaderType)
        {
            case gl::ShaderType::Vertex:
                deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                                    &driverConstants);
                break;

            case gl::ShaderType::Fragment:
                deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                                    &driverConstants);
                break;

            case gl::ShaderType::Geometry:
                deviceContext->GSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                                    &driverConstants);
                break;

            default:
                UNREACHABLE();
                return angle::Result::Continue;
        }
    }

    // Sampler metadata and driver constants need to coexist in the same constant buffer to
    // conserve constant buffer slots. We update both in the constant buffer if needed.
    ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, shaderType, *mProgramD3D,
                                            shaderDriverConstantBuffer));

    return angle::Result::Continue;
}

angle::Result StateManager11::applyDriverUniforms(const gl::Context *context)
{
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Vertex));
    ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Fragment));
    if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
    {
        ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Geometry));
    }

    // needed for the point sprite geometry shader
    // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
    if (mRenderer->isES3Capable())
    {
        d3d11::Buffer &driverConstantBufferPS =
            mShaderDriverConstantBuffers[gl::ShaderType::Fragment];
        if (mCurrentGeometryConstantBuffer != driverConstantBufferPS.getSerial())
        {
            ASSERT(driverConstantBufferPS.valid());
            deviceContext->GSSetConstantBuffers(0, 1, driverConstantBufferPS.getPointer());
            mCurrentGeometryConstantBuffer = driverConstantBufferPS.getSerial();
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::applyComputeUniforms(const gl::Context *context,
                                                   ProgramD3D *programD3D)
{
    UniformStorage11 *computeUniformStorage =
        GetAs<UniformStorage11>(programD3D->getShaderUniformStorage(gl::ShaderType::Compute));
    ASSERT(computeUniformStorage);

    const d3d11::Buffer *constantBuffer = nullptr;
    ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer));

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    if (computeUniformStorage->size() > 0 &&
        programD3D->areShaderUniformsDirty(gl::ShaderType::Compute))
    {
        UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
        programD3D->markUniformsClean();
    }

    if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
    {
        deviceContext->CSSetConstantBuffers(
            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
            constantBuffer->getPointer());
        mCurrentComputeConstantBuffer = constantBuffer->getSerial();
    }

    if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid())
    {
        size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute);

        D3D11_BUFFER_DESC constantBufferDescription = {0};
        d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
        ANGLE_TRY(
            mRenderer->allocateResource(GetImplAs<Context11>(context), constantBufferDescription,
                                        &mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
        ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get();
        deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                            &buffer);
    }

    ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute,
                                            *programD3D,
                                            mShaderDriverConstantBuffers[gl::ShaderType::Compute]));

    return angle::Result::Continue;
}

angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context,
                                                          gl::ShaderType shaderType)
{
    gl::ShaderMap<unsigned int> shaderReservedUBOs = mRenderer->getReservedShaderUniformBuffers();

    const auto &glState                  = context->getState();
    ID3D11DeviceContext *deviceContext   = mRenderer->getDeviceContext();
    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();

    const auto &shaderUniformBuffers = mProgramD3D->getShaderUniformBufferCache(shaderType);
    const unsigned int reservedUBOs  = shaderReservedUBOs[shaderType];

    for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffers.size(); ++bufferIndex)
    {
        const GLint binding = shaderUniformBuffers[bufferIndex];
        if (binding == -1)
        {
            continue;
        }

        const auto &uniformBuffer          = glState.getIndexedUniformBuffer(binding);
        const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
        const GLsizeiptr uniformBufferSize = uniformBuffer.getSize();

        if (uniformBuffer.get() == nullptr)
        {
            continue;
        }

        Buffer11 *bufferStorage             = GetImplAs<Buffer11>(uniformBuffer.get());
        const d3d11::Buffer *constantBuffer = nullptr;
        UINT firstConstant                  = 0;
        UINT numConstants                   = 0;

        ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
                                                        uniformBufferSize, &constantBuffer,
                                                        &firstConstant, &numConstants));
        ASSERT(constantBuffer);

        const unsigned int appliedIndex = reservedUBOs + static_cast<unsigned int>(bufferIndex);
        switch (shaderType)
        {
            case gl::ShaderType::Vertex:
            {
                if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() &&
                    mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset &&
                    mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize)
                {
                    continue;
                }

                if (firstConstant != 0 && uniformBufferSize != 0)
                {
                    ASSERT(numConstants != 0);
                    deviceContext1->VSSetConstantBuffers1(appliedIndex, 1,
                                                          constantBuffer->getPointer(),
                                                          &firstConstant, &numConstants);
                }
                else
                {
                    deviceContext->VSSetConstantBuffers(appliedIndex, 1,
                                                        constantBuffer->getPointer());
                }

                mCurrentConstantBufferVS[appliedIndex]       = constantBuffer->getSerial();
                mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset;
                mCurrentConstantBufferVSSize[appliedIndex]   = uniformBufferSize;
                break;
            }

            case gl::ShaderType::Fragment:
            {
                if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() &&
                    mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset &&
                    mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize)
                {
                    continue;
                }

                if (firstConstant != 0 && uniformBufferSize != 0)
                {
                    deviceContext1->PSSetConstantBuffers1(appliedIndex, 1,
                                                          constantBuffer->getPointer(),
                                                          &firstConstant, &numConstants);
                }
                else
                {
                    deviceContext->PSSetConstantBuffers(appliedIndex, 1,
                                                        constantBuffer->getPointer());
                }

                mCurrentConstantBufferPS[appliedIndex]       = constantBuffer->getSerial();
                mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset;
                mCurrentConstantBufferPSSize[appliedIndex]   = uniformBufferSize;
                break;
            }

            case gl::ShaderType::Compute:
            {
                if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() &&
                    mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset &&
                    mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize)
                {
                    continue;
                }

                if (firstConstant != 0 && uniformBufferSize != 0)
                {
                    deviceContext1->CSSetConstantBuffers1(appliedIndex, 1,
                                                          constantBuffer->getPointer(),
                                                          &firstConstant, &numConstants);
                }
                else
                {
                    deviceContext->CSSetConstantBuffers(appliedIndex, 1,
                                                        constantBuffer->getPointer());
                }

                mCurrentConstantBufferCS[appliedIndex]       = constantBuffer->getSerial();
                mCurrentConstantBufferCSOffset[appliedIndex] = uniformBufferOffset;
                mCurrentConstantBufferCSSize[appliedIndex]   = uniformBufferSize;
                break;
            }

            // TODO(jiawei.shao@intel.com): update geometry shader uniform buffers.
            case gl::ShaderType::Geometry:
                UNIMPLEMENTED();
                break;

            default:
                UNREACHABLE();
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncShaderStorageBuffersForShader(const gl::Context *context,
                                                                gl::ShaderType shaderType)
{
    const gl::State &glState   = context->getState();
    const gl::Program *program = glState.getProgram();
    angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
        previouslyBound;
    for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
         blockIndex++)
    {
        GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
        const unsigned int registerIndex = mProgramD3D->getShaderStorageBufferRegisterIndex(
            static_cast<GLuint>(blockIndex), shaderType);
        // It means this block is active but not statically used.
        if (registerIndex == GL_INVALID_INDEX)
        {
            continue;
        }
        const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
        if (shaderStorageBuffer.get() == nullptr)
        {
            // We didn't see a driver error like atomic buffer did. But theoretically, the same
            // thing should be done.
            setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(shaderType, registerIndex,
                                                                       nullptr);
            continue;
        }

        Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
        if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
            previouslyBound.end())
        {
            // D3D11 doesn't support binding a buffer multiple times
            // http://anglebug.com/3032
            ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
            return angle::Result::Stop;
        }
        previouslyBound.push_back(bufferStorage);

        d3d11::UnorderedAccessView *uavPtr = nullptr;
        GLsizeiptr viewSize                = 0;
        // Bindings only have a valid size if bound using glBindBufferRange
        if (shaderStorageBuffer.getSize() > 0)
        {
            viewSize = shaderStorageBuffer.getSize();
        }
        // We use the buffer size for glBindBufferBase
        else
        {
            viewSize = bufferStorage->getSize();
        }
        ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
                                                &uavPtr));

        switch (shaderType)
        {
            case gl::ShaderType::Compute:
            {
                setUnorderedAccessViewInternal(shaderType, registerIndex, uavPtr);
                break;
            }

            case gl::ShaderType::Vertex:
            case gl::ShaderType::Fragment:
            case gl::ShaderType::Geometry:
                UNIMPLEMENTED();
                break;

            default:
                UNREACHABLE();
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
{
    gl::ShaderMap<unsigned int> shaderReservedUBOs = mRenderer->getReservedShaderUniformBuffers();
    mProgramD3D->updateUniformBufferCache(context->getCaps(), shaderReservedUBOs);

    if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
    {
        ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute));
    }
    else
    {
        ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex));
        ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment));
        if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
        {
            ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry));
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncAtomicCounterBuffers(const gl::Context *context)
{
    if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
    {
        ANGLE_TRY(syncAtomicCounterBuffersForShader(context, gl::ShaderType::Compute));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncAtomicCounterBuffersForShader(const gl::Context *context,
                                                                gl::ShaderType shaderType)
{
    const gl::State &glState   = context->getState();
    const gl::Program *program = glState.getProgram();
    for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
    {
        GLuint binding     = atomicCounterBuffer.binding;
        const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
        const unsigned int registerIndex =
            mProgramD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
        ASSERT(registerIndex != GL_INVALID_INDEX);
        if (buffer.get() == nullptr)
        {
            // The atomic counter is used in shader. However, there is no buffer binding to it. We
            // should clear the corresponding UAV in case the previous view type is a texture not a
            // buffer. Otherwise, below error will be reported. The Unordered Access View dimension
            // declared in the shader code (BUFFER) does not match the view type bound to slot 0
            // of the Compute Shader unit (TEXTURE2D).
            setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(shaderType, registerIndex,
                                                                       nullptr);
            continue;
        }

        Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
        // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer
        // multiple times, as this is unsupported by D3D11. http://anglebug.com/3141

        // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
        // buffer size for glBindBufferBase
        GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
        d3d11::UnorderedAccessView *uavPtr = nullptr;
        ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));

        if (shaderType == gl::ShaderType::Compute)
        {
            setUnorderedAccessViewInternal(shaderType, registerIndex, uavPtr);
        }
        else
        {
            // Atomic Shaders on non-compute shaders are currently unimplemented
            // http://anglebug.com/1729
            UNIMPLEMENTED();
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncShaderStorageBuffers(const gl::Context *context)
{
    if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
    {
        ANGLE_TRY(syncShaderStorageBuffersForShader(context, gl::ShaderType::Compute));
    }

    return angle::Result::Continue;
}

angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
{
    const auto &glState = context->getState();

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    // If transform feedback is not active, unbind all buffers
    if (!glState.isTransformFeedbackActiveUnpaused())
    {
        if (mAppliedTFSerial != mEmptySerial)
        {
            deviceContext->SOSetTargets(0, nullptr, nullptr);
            mAppliedTFSerial = mEmptySerial;
        }
        return angle::Result::Continue;
    }

    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
    TransformFeedback11 *tf11                = GetImplAs<TransformFeedback11>(transformFeedback);
    if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
    {
        return angle::Result::Continue;
    }

    const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
    ANGLE_TRY(tf11->getSOBuffers(context, &soBuffers));
    const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();

    deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());

    mAppliedTFSerial = tf11->getSerial();
    tf11->onApply();

    return angle::Result::Continue;
}

void StateManager11::syncPrimitiveTopology(const gl::State &glState,
                                           gl::PrimitiveMode currentDrawMode)
{
    D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
    // Don't cull everything by default, this also resets if we were previously culling
    mCullEverything = false;

    switch (currentDrawMode)
    {
        case gl::PrimitiveMode::Points:
        {
            bool usesPointSize = mProgramD3D->usesPointSize();

            // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
            // which affects varying interpolation. Since the value of gl_PointSize is
            // undefined when not written, just skip drawing to avoid unexpected results.
            if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
            {
                // Notify developers of risking undefined behavior.
                WARN() << "Point rendering without writing to gl_PointSize.";
                mCullEverything = true;
                return;
            }

            // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
            // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
            if (usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled)
            {
                primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
            }
            else
            {
                primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
            }
            break;
        }
        case gl::PrimitiveMode::Lines:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
            break;
        case gl::PrimitiveMode::LineLoop:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
            break;
        case gl::PrimitiveMode::LineStrip:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
            break;
        case gl::PrimitiveMode::Triangles:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
            mCullEverything   = CullsEverything(glState);
            break;
        case gl::PrimitiveMode::TriangleStrip:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
            mCullEverything   = CullsEverything(glState);
            break;
        // emulate fans via rewriting index buffer
        case gl::PrimitiveMode::TriangleFan:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
            mCullEverything   = CullsEverything(glState);
            break;
        default:
            UNREACHABLE();
            break;
    }

    setPrimitiveTopologyInternal(primitiveTopology);
}

}  // namespace rx
