//
// 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"

#if defined(STARBOARD)
#include "angle_hdr.h"
#endif  // STARBOARD
#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]          = {};
        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 = {};
    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 = caps.maxViewportWidth;
    int dxMaxViewportBoundsY = 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, gl::AttachmentSampleType::Emulated) != 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 =
            static_cast<GLuint>(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(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 &&
         index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
        (type == gl::ShaderType::Vertex &&
         index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
        (type == gl::ShaderType::Compute &&
         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(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((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((index < mRenderer->getNativeCaps().maxImageUnits));
        setUnorderedAccessViewInternal(type, index, textureUAV);
    }

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

#if defined(STARBOARD)
namespace
{
angle::FormatID GetTextureFormatId(const gl::Context *context, ProgramD3D *programD3D)
{
    gl::ShaderType type      = gl::ShaderType::Fragment;
    const gl::State &glState      = context->getState();
    gl::RangeUI samplerRange  = programD3D->getUsedSamplerRange(type);

    for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
    {
        gl::TextureType textureType = programD3D->getSamplerTextureType(type, i);
        GLint textureUnit           = programD3D->getSamplerMapping(type, i, context->getCaps());
        if (textureUnit != -1)
        {
            gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
            ASSERT(texture);
            rx::TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
            ASSERT(textureD3D);
            TextureStorage *texStorage = nullptr;
            textureD3D->getNativeTexture(context, & texStorage);
            if (texStorage)
            {
                return GetAs<TextureStorage11_2D>(texStorage)->getFormat().id;
            }
        }
    }
    return angle::FormatID::NONE;
}
}  // namespace
#endif  // STARBOARD

// 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;
#if defined(STARBOARD)
    // While 10-bit HDR video is playing we run the pixel shader to apply color space for all UI
    // elements conversion from 8-bit to 10-bit for all draw calls that do not involve the HDR video
    // texture (look at spec ITU - R BT .2100 - 2(07 / 2018) for BT709 to BT2020 transform). This
    // conversion  is applicable only once when we draw to the display - drawFramebuffer->id() is 0.
    const gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
    if (IsHdrAngleModeEnabled() && drawFramebuffer->id().value == 0)
    {
        if (GetTextureFormatId(context, mProgramD3D) == angle::FormatID::R10G10B10A2_UNORM ||
            GetTextureFormatId(context, mProgramD3D) == angle::FormatID::R16_UNORM)
        {
            ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe,
                                                                           nullptr));
        }
        else
        {
            ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedHdrOutputLayout(context11, &pixelExe,
                                                                              nullptr));
        }
    }
    else
    {
        ANGLE_TRY(
            mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
    }
#else
    ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
#endif  // STARBOARD

    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 = {};
        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 = {};
        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
