//
// Copyright (c) 2012-2014 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.
//

// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.

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

#include <EGL/eglext.h>
#include <versionhelpers.h>
#include <sstream>

#include "common/tls.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Display.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Program.h"
#include "libANGLE/State.h"
#include "libANGLE/Surface.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/d3d/CompilerD3D.h"
#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Image11.h"
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/renderer_utils.h"
#include "third_party/trace_event/trace_event.h"

#ifdef ANGLE_ENABLE_WINDOWS_STORE
#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
#else
#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
#endif

// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
#ifdef ANGLE_ENABLE_D3D9
#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
#endif

// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
#ifndef ANGLE_SKIP_DXGI_1_2_CHECK
#define ANGLE_SKIP_DXGI_1_2_CHECK 0
#endif

#ifdef _DEBUG
// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
// and conformance tests. to enable all warnings, remove this define.
#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
#endif

namespace rx
{

namespace
{

enum
{
    MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
};

enum ANGLEFeatureLevel
{
    ANGLE_FEATURE_LEVEL_INVALID,
    ANGLE_FEATURE_LEVEL_9_3,
    ANGLE_FEATURE_LEVEL_10_0,
    ANGLE_FEATURE_LEVEL_10_1,
    ANGLE_FEATURE_LEVEL_11_0,
    ANGLE_FEATURE_LEVEL_11_1,
    NUM_ANGLE_FEATURE_LEVELS
};

ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
{
    switch (d3dFeatureLevel)
    {
        case D3D_FEATURE_LEVEL_9_3:
            return ANGLE_FEATURE_LEVEL_9_3;
        case D3D_FEATURE_LEVEL_10_0:
            return ANGLE_FEATURE_LEVEL_10_0;
        case D3D_FEATURE_LEVEL_10_1:
            return ANGLE_FEATURE_LEVEL_10_1;
        case D3D_FEATURE_LEVEL_11_0:
            return ANGLE_FEATURE_LEVEL_11_0;
        // Note: we don't ever request a 11_1 device, because this gives
        // an E_INVALIDARG error on systems that don't have the platform update.
        case D3D_FEATURE_LEVEL_11_1:
            return ANGLE_FEATURE_LEVEL_11_1;
        default:
            return ANGLE_FEATURE_LEVEL_INVALID;
    }
}

void SetLineLoopIndices(GLuint *dest, size_t count)
{
    for (size_t i = 0; i < count; i++)
    {
        dest[i] = static_cast<GLuint>(i);
    }
    dest[count] = 0;
}

template <typename T>
void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
{
    const T *srcPtr = static_cast<const T *>(indices);
    for (size_t i = 0; i < count; ++i)
    {
        dest[i] = static_cast<GLuint>(srcPtr[i]);
    }
    dest[count] = static_cast<GLuint>(srcPtr[0]);
}

void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
{
    for (size_t i = 0; i < numTris; i++)
    {
        destPtr[i * 3 + 0] = 0;
        destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
        destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
    }
}

template <typename T>
void CopyLineLoopIndicesWithRestart(const void *indices,
                                    size_t count,
                                    GLenum indexType,
                                    std::vector<GLuint> *bufferOut)
{
    GLuint restartIndex    = gl::GetPrimitiveRestartIndex(indexType);
    GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
    const T *srcPtr        = static_cast<const T *>(indices);
    Optional<GLuint> currentLoopStart;

    bufferOut->clear();

    for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
    {
        GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);

        if (value == restartIndex)
        {
            if (currentLoopStart.valid())
            {
                bufferOut->push_back(currentLoopStart.value());
                bufferOut->push_back(d3dRestartIndex);
                currentLoopStart.reset();
            }
        }
        else
        {
            bufferOut->push_back(value);
            if (!currentLoopStart.valid())
            {
                currentLoopStart = value;
            }
        }
    }

    if (currentLoopStart.valid())
    {
        bufferOut->push_back(currentLoopStart.value());
    }
}

void GetLineLoopIndices(const void *indices,
                        GLenum indexType,
                        GLuint count,
                        bool usePrimitiveRestartFixedIndex,
                        std::vector<GLuint> *bufferOut)
{
    if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
    {
        switch (indexType)
        {
            case GL_UNSIGNED_BYTE:
                CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
                break;
            case GL_UNSIGNED_SHORT:
                CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
                break;
            case GL_UNSIGNED_INT:
                CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
                break;
            default:
                UNREACHABLE();
                break;
        }
        return;
    }

    // For non-primitive-restart draws, the index count is static.
    bufferOut->resize(static_cast<size_t>(count) + 1);

    switch (indexType)
    {
        // Non-indexed draw
        case GL_NONE:
            SetLineLoopIndices(&(*bufferOut)[0], count);
            break;
        case GL_UNSIGNED_BYTE:
            CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
            break;
        case GL_UNSIGNED_SHORT:
            CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
            break;
        case GL_UNSIGNED_INT:
            CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

template <typename T>
void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
{
    const T *srcPtr = static_cast<const T *>(indices);

    for (size_t i = 0; i < numTris; i++)
    {
        destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
        destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
        destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
    }
}

template <typename T>
void CopyTriangleFanIndicesWithRestart(const void *indices,
                                       GLuint indexCount,
                                       GLenum indexType,
                                       std::vector<GLuint> *bufferOut)
{
    GLuint restartIndex    = gl::GetPrimitiveRestartIndex(indexType);
    GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
    const T *srcPtr        = static_cast<const T *>(indices);
    Optional<GLuint> vertexA;
    Optional<GLuint> vertexB;

    bufferOut->clear();

    for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
    {
        GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);

        if (value == restartIndex)
        {
            bufferOut->push_back(d3dRestartIndex);
            vertexA.reset();
            vertexB.reset();
        }
        else
        {
            if (!vertexA.valid())
            {
                vertexA = value;
            }
            else if (!vertexB.valid())
            {
                vertexB = value;
            }
            else
            {
                bufferOut->push_back(vertexA.value());
                bufferOut->push_back(vertexB.value());
                bufferOut->push_back(value);
                vertexB = value;
            }
        }
    }
}

void GetTriFanIndices(const void *indices,
                      GLenum indexType,
                      GLuint count,
                      bool usePrimitiveRestartFixedIndex,
                      std::vector<GLuint> *bufferOut)
{
    if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
    {
        switch (indexType)
        {
            case GL_UNSIGNED_BYTE:
                CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
                break;
            case GL_UNSIGNED_SHORT:
                CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
                break;
            case GL_UNSIGNED_INT:
                CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
                break;
            default:
                UNREACHABLE();
                break;
        }
        return;
    }

    // For non-primitive-restart draws, the index count is static.
    GLuint numTris = count - 2;
    bufferOut->resize(numTris * 3);

    switch (indexType)
    {
        // Non-indexed draw
        case GL_NONE:
            SetTriangleFanIndices(&(*bufferOut)[0], numTris);
            break;
        case GL_UNSIGNED_BYTE:
            CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
            break;
        case GL_UNSIGNED_SHORT:
            CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
            break;
        case GL_UNSIGNED_INT:
            CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

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

const uint32_t ScratchMemoryBufferLifetime = 1000;

}  // anonymous namespace

Renderer11::Renderer11(egl::Display *display)
    : RendererD3D(display),
      mStateCache(this),
      mStateManager(this),
      mLastHistogramUpdateTime(
          ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
      mDebug(nullptr),
      mScratchMemoryBuffer(ScratchMemoryBufferLifetime),
      mAnnotator(nullptr)
{
    mVertexDataManager = nullptr;
    mIndexDataManager  = nullptr;

    mLineLoopIB       = nullptr;
    mTriangleFanIB    = nullptr;
    mAppliedIBChanged = false;

    mBlit          = nullptr;
    mPixelTransfer = nullptr;

    mClear = nullptr;

    mTrim = nullptr;

    mSyncQuery = nullptr;

    mRenderer11DeviceCaps.supportsClearView             = false;
    mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
    mRenderer11DeviceCaps.supportsDXGI1_2               = false;
    mRenderer11DeviceCaps.B5G6R5support                 = 0;
    mRenderer11DeviceCaps.B4G4R4A4support               = 0;
    mRenderer11DeviceCaps.B5G5R5A1support               = 0;

    mD3d11Module          = nullptr;
    mDxgiModule           = nullptr;
    mDCompModule          = nullptr;
    mCreatedWithDeviceEXT = false;
    mEGLDevice            = nullptr;

    mDevice         = nullptr;
    mDeviceContext  = nullptr;
    mDeviceContext1 = nullptr;
    mDxgiAdapter    = nullptr;
    mDxgiFactory    = nullptr;

    mDriverConstantBufferVS = nullptr;
    mDriverConstantBufferPS = nullptr;
    mDriverConstantBufferCS = nullptr;

    mAppliedVertexShader   = angle::DirtyPointer;
    mAppliedGeometryShader = angle::DirtyPointer;
    mAppliedPixelShader    = angle::DirtyPointer;
    mAppliedComputeShader  = angle::DirtyPointer;

    mAppliedTFObject = angle::DirtyPointer;

    ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));

    if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
    {
        const auto &attributes = mDisplay->getAttributeMap();

        EGLint requestedMajorVersion = static_cast<EGLint>(
            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
        EGLint requestedMinorVersion = static_cast<EGLint>(
            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));

// Only allow feature level 10 on starboard.
#if defined(STARBOARD)
        mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
#else
        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
        {
            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
            {
                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
            }
        }

        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
        {
            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
            {
                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
            }
            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
            {
                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
            }
        }

        if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
        {
            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
        }
#endif  // STARBOARD

        EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
            EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
        switch (requestedDeviceType)
        {
            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
                mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
                break;

            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
                mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
                break;

            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
                mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
                break;

            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
                mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
                break;

            default:
                UNREACHABLE();
        }

        const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
            EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
        mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
    }
    else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
    {
        mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
        ASSERT(mEGLDevice != nullptr);
        mCreatedWithDeviceEXT = true;

        // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
        // mAvailableFeatureLevels defaults to empty
        mRequestedDriverType    = D3D_DRIVER_TYPE_UNKNOWN;
        mPresentPathFastEnabled = false;
    }

// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
// Diagnostics tools in Visual Studio 2013.
// The D3D9 annotator works properly for both D3D11 and D3D9.
// Incorrect status reporting can cause ANGLE to log unnecessary debug events.
#ifdef ANGLE_ENABLE_D3D9
    mAnnotator = new DebugAnnotator9();
#else
    mAnnotator = new DebugAnnotator11();
#endif
    ASSERT(mAnnotator);
    gl::InitializeDebugAnnotations(mAnnotator);
}

Renderer11::~Renderer11()
{
    release();
}

#ifndef __d3d11_1_h__
#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
#endif

egl::Error Renderer11::initialize()
{
    HRESULT result = S_OK;

    ANGLE_TRY(initializeD3DDevice());

#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#if !ANGLE_SKIP_DXGI_1_2_CHECK
    {
        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
        // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
        // required.
        // The easiest way to check is to query for a IDXGIDevice2.
        bool requireDXGI1_2 = false;
        HWND hwnd           = WindowFromDC(mDisplay->getNativeDisplayId());
        if (hwnd)
        {
            DWORD currentProcessId = GetCurrentProcessId();
            DWORD wndProcessId;
            GetWindowThreadProcessId(hwnd, &wndProcessId);
            requireDXGI1_2 = (currentProcessId != wndProcessId);
        }
        else
        {
            requireDXGI1_2 = true;
        }

        if (requireDXGI1_2)
        {
            IDXGIDevice2 *dxgiDevice2 = nullptr;
            result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
            if (FAILED(result))
            {
                return egl::Error(
                    EGL_NOT_INITIALIZED, D3D11_INIT_INCOMPATIBLE_DXGI,
                    "DXGI 1.2 required to present to HWNDs owned by another process.");
            }
            SafeRelease(dxgiDevice2);
        }
    }
#endif
#endif

    {
        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
        // Cast the DeviceContext to a DeviceContext1.
        // This could fail on Windows 7 without the Platform Update.
        // Don't error in this case- just don't use mDeviceContext1.
        mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);

        IDXGIDevice *dxgiDevice = nullptr;
        result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);

        if (FAILED(result))
        {
            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
                              "Could not query DXGI device.");
        }

        result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);

        if (FAILED(result))
        {
            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
                              "Could not retrieve DXGI adapter");
        }

        SafeRelease(dxgiDevice);

        IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);

        // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
        // description string.
        // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
        // hardware values.
        if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
        {
            DXGI_ADAPTER_DESC2 adapterDesc2 = {};
            result                          = dxgiAdapter2->GetDesc2(&adapterDesc2);
            if (SUCCEEDED(result))
            {
                // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
                // DXGI_ADAPTER_DESC).
                memcpy(mAdapterDescription.Description, adapterDesc2.Description,
                       sizeof(mAdapterDescription.Description));
                mAdapterDescription.VendorId              = adapterDesc2.VendorId;
                mAdapterDescription.DeviceId              = adapterDesc2.DeviceId;
                mAdapterDescription.SubSysId              = adapterDesc2.SubSysId;
                mAdapterDescription.Revision              = adapterDesc2.Revision;
                mAdapterDescription.DedicatedVideoMemory  = adapterDesc2.DedicatedVideoMemory;
                mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
                mAdapterDescription.SharedSystemMemory    = adapterDesc2.SharedSystemMemory;
                mAdapterDescription.AdapterLuid           = adapterDesc2.AdapterLuid;
            }
        }
        else
        {
            result = mDxgiAdapter->GetDesc(&mAdapterDescription);
        }

        SafeRelease(dxgiAdapter2);

        if (FAILED(result))
        {
            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
                              "Could not read DXGI adaptor description.");
        }

        memset(mDescription, 0, sizeof(mDescription));
        wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);

        result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);

        if (!mDxgiFactory || FAILED(result))
        {
            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
                              "Could not create DXGI factory.");
        }
    }

// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
    {
        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
        ID3D11InfoQueue *infoQueue;
        result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);

        if (SUCCEEDED(result))
        {
            D3D11_MESSAGE_ID hideMessages[] = {
                D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};

            D3D11_INFO_QUEUE_FILTER filter = {};
            filter.DenyList.NumIDs         = static_cast<unsigned int>(ArraySize(hideMessages));
            filter.DenyList.pIDList        = hideMessages;

            infoQueue->AddStorageFilterEntries(&filter);
            SafeRelease(infoQueue);
        }
    }
#endif

#if !defined(NDEBUG)
    mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
#endif

    initializeDevice();

    return egl::Error(EGL_SUCCESS);
}

egl::Error Renderer11::initializeD3DDevice()
{
    HRESULT result = S_OK;

    if (!mCreatedWithDeviceEXT)
    {
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
        PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
        {
            SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
            TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
            mDxgiModule  = LoadLibrary(TEXT("dxgi.dll"));
            mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
            mDCompModule = LoadLibrary(TEXT("dcomp.dll"));

            if (mD3d11Module == nullptr || mDxgiModule == nullptr)
            {
                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
                                  "Could not load D3D11 or DXGI library.");
            }

            // create the D3D11 device
            ASSERT(mDevice == nullptr);
            D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
                GetProcAddress(mD3d11Module, "D3D11CreateDevice"));

            if (D3D11CreateDevice == nullptr)
            {
                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
                                  "Could not retrieve D3D11CreateDevice address.");
            }
        }
#endif

#ifdef _DEBUG
        {
            TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
            result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr,
                                       D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
                                       static_cast<unsigned int>(mAvailableFeatureLevels.size()),
                                       D3D11_SDK_VERSION, &mDevice,
                                       &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
        }

        if (!mDevice || FAILED(result))
        {
            WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
        }

        if (!mDevice || FAILED(result))
#endif
        {
            SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
            TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");

            result = D3D11CreateDevice(
                nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(),
                static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
                &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);

            // Cleanup done by destructor
            if (!mDevice || FAILED(result))
            {
                ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
                                              static_cast<int>(result));
                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
                                  "Could not create D3D11 device.");
            }
        }
    }
    else
    {
        // We should use the inputted D3D11 device instead
        void *device = nullptr;
        ANGLE_TRY(mEGLDevice->getDevice(&device));

        ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
        if (FAILED(d3dDevice->GetDeviceRemovedReason()))
        {
            return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
        }

        if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
        {
            return egl::Error(EGL_NOT_INITIALIZED,
                              "Inputted D3D11 device must be Feature Level 9_3 or greater.");
        }

        // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
        mDevice = d3dDevice;
        mDevice->AddRef();
        mDevice->GetImmediateContext(&mDeviceContext);
        mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
    }

    d3d11::SetDebugName(mDeviceContext, "DeviceContext");

    return egl::Error(EGL_SUCCESS);
}

// do any one-time device initialization
// NOTE: this is also needed after a device lost/reset
// to reset the scene status and ensure the default states are reset.
void Renderer11::initializeDevice()
{
    SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
    TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");

    populateRenderer11DeviceCaps();

    mStateCache.initialize(mDevice);
    mInputLayoutCache.initialize(mDevice, mDeviceContext);

    ASSERT(!mVertexDataManager && !mIndexDataManager);
    mVertexDataManager = new VertexDataManager(this);
    mIndexDataManager  = new IndexDataManager(this, getRendererClass());

    ASSERT(!mBlit);
    mBlit = new Blit11(this);

    ASSERT(!mClear);
    mClear = new Clear11(this);

    const auto &attributes = mDisplay->getAttributeMap();
    // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
    // automatically when an application is suspended by the OS. This feature is currently
    // only supported for Windows Store applications.
    EGLint enableAutoTrim = static_cast<EGLint>(
        attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));

    if (enableAutoTrim == EGL_TRUE)
    {
        ASSERT(!mTrim);
        mTrim = new Trim11(this);
    }

    ASSERT(!mPixelTransfer);
    mPixelTransfer = new PixelTransfer11(this);

    const gl::Caps &rendererCaps = getNativeCaps();

    mStateManager.initialize(rendererCaps);

    mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
    mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
    mSamplerMetadataVS.initData(rendererCaps.maxVertexTextureImageUnits);

    mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
    mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
    mSamplerMetadataPS.initData(rendererCaps.maxTextureImageUnits);

    mForceSetComputeSamplerStates.resize(rendererCaps.maxComputeTextureImageUnits);
    mCurComputeSamplerStates.resize(rendererCaps.maxComputeTextureImageUnits);
    mSamplerMetadataCS.initData(rendererCaps.maxComputeTextureImageUnits);

    mStateManager.initialize(rendererCaps);

    markAllStateDirty();

    // Gather stats on DXGI and D3D feature level
    ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);

    ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);

    // We don't actually request a 11_1 device, because of complications with the platform
    // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
    // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
    // because the app can specify a lower version (such as 9_3) on Display creation.
    if (mDeviceContext1 != nullptr)
    {
        angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
    }

    ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
                                NUM_ANGLE_FEATURE_LEVELS);
}

void Renderer11::populateRenderer11DeviceCaps()
{
    HRESULT hr = S_OK;

    LARGE_INTEGER version;
    hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
    if (FAILED(hr))
    {
        mRenderer11DeviceCaps.driverVersion.reset();
        ERR() << "Error querying driver version from DXGI Adapter.";
    }
    else
    {
        mRenderer11DeviceCaps.driverVersion = version;
    }

    if (mDeviceContext1)
    {
        D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
        HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
                                                      sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
        if (SUCCEEDED(result))
        {
            mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
            mRenderer11DeviceCaps.supportsConstantBufferOffsets =
                (d3d11Options.ConstantBufferOffsetting != FALSE);
        }
    }

    if (getWorkarounds().disableB5G6R5Support)
    {
        mRenderer11DeviceCaps.B5G6R5support = 0;
    }
    else
    {
        hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM,
                                         &(mRenderer11DeviceCaps.B5G6R5support));
        if (FAILED(hr))
        {
            mRenderer11DeviceCaps.B5G6R5support = 0;
        }
    }

    hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM,
                                     &(mRenderer11DeviceCaps.B4G4R4A4support));
    if (FAILED(hr))
    {
        mRenderer11DeviceCaps.B4G4R4A4support = 0;
    }

    hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM,
                                     &(mRenderer11DeviceCaps.B5G5R5A1support));
    if (FAILED(hr))
    {
        mRenderer11DeviceCaps.B5G5R5A1support = 0;
    }

    IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
    mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
    SafeRelease(dxgiAdapter2);
}

gl::SupportedSampleSet Renderer11::generateSampleSetFromCaps(
    const gl::TextureCaps &colorBufferFormatCaps,
    const gl::TextureCaps &depthStencilBufferFormatCaps) const
{
    gl::SupportedSampleSet sampleCounts;

    // Generate a new set from the set intersection of sample counts between the color and depth
    // format caps.
    std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
                          colorBufferFormatCaps.sampleCounts.end(),
                          depthStencilBufferFormatCaps.sampleCounts.begin(),
                          depthStencilBufferFormatCaps.sampleCounts.end(),
                          std::inserter(sampleCounts, sampleCounts.begin()));

    // Format of GL_NONE results in no supported sample counts.
    // Add back the color sample counts to the supported sample set.
    if (depthStencilBufferFormatCaps.sampleCounts.empty())
    {
        sampleCounts = colorBufferFormatCaps.sampleCounts;
    }
    else if (colorBufferFormatCaps.sampleCounts.empty())
    {
        // Likewise, add back the depth sample counts to the supported sample set.
        sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
    }

    // In EGL, no multisampling is 0, in D3D its 1, so if 1 exists, insert 0 for EGL to match.
    if (sampleCounts.find(1) != sampleCounts.end())
    {
        sampleCounts.insert(0);
    }

    return sampleCounts;
}

egl::ConfigSet Renderer11::generateConfigs()
{
    std::vector<GLenum> colorBufferFormats;

    // 32-bit supported formats
    colorBufferFormats.push_back(GL_BGRA8_EXT);
    colorBufferFormats.push_back(GL_RGBA8_OES);

    // 24-bit supported formats
    colorBufferFormats.push_back(GL_RGB8_OES);

    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
    {
        // Additional high bit depth formats added in D3D 10.0
        // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
        colorBufferFormats.push_back(GL_RGBA16F);
        colorBufferFormats.push_back(GL_RGB10_A2);
    }

    if (!mPresentPathFastEnabled)
    {
        // 16-bit supported formats
        // These aren't valid D3D11 swapchain formats, so don't expose them as configs
        // if present path fast is active
        colorBufferFormats.push_back(GL_RGBA4);
        colorBufferFormats.push_back(GL_RGB5_A1);
        colorBufferFormats.push_back(GL_RGB565);
    }

    static const GLenum depthStencilBufferFormats[] = {
        GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT16,
    };

    const gl::Caps &rendererCaps                  = getNativeCaps();
    const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();

    const EGLint optimalSurfaceOrientation =
        mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;

    egl::ConfigSet configs;
    for (GLenum colorBufferInternalFormat : colorBufferFormats)
    {
        const gl::TextureCaps &colorBufferFormatCaps =
            rendererTextureCaps.get(colorBufferInternalFormat);
        if (!colorBufferFormatCaps.renderable)
        {
            continue;
        }

        for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
        {
            const gl::TextureCaps &depthStencilBufferFormatCaps =
                rendererTextureCaps.get(depthStencilBufferInternalFormat);
            if (!depthStencilBufferFormatCaps.renderable &&
                depthStencilBufferInternalFormat != GL_NONE)
            {
                continue;
            }

            const gl::InternalFormat &colorBufferFormatInfo =
                gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
            const gl::InternalFormat &depthStencilBufferFormatInfo =
                gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
            const gl::Version &maxVersion = getMaxSupportedESVersion();

            const gl::SupportedSampleSet sampleCounts =
                generateSampleSetFromCaps(colorBufferFormatCaps, depthStencilBufferFormatCaps);

            for (GLuint sampleCount : sampleCounts)
            {
                egl::Config config;
                config.renderTargetFormat = colorBufferInternalFormat;
                config.depthStencilFormat = depthStencilBufferInternalFormat;
                config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
                config.redSize            = colorBufferFormatInfo.redBits;
                config.greenSize          = colorBufferFormatInfo.greenBits;
                config.blueSize           = colorBufferFormatInfo.blueBits;
                config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
                config.alphaSize          = colorBufferFormatInfo.alphaBits;
                config.alphaMaskSize      = 0;
                config.bindToTextureRGB =
                    ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
                config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
                                             (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
                                            (sampleCount <= 1));
                config.colorBufferType = EGL_RGB_BUFFER;
                config.configCaveat    = EGL_NONE;
                config.configID        = static_cast<EGLint>(configs.size() + 1);

                // PresentPathFast may not be conformant
                config.conformant = 0;
                if (!mPresentPathFastEnabled)
                {
                    // Can only support a conformant ES2 with feature level greater than 10.0.
                    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
                    {
                        config.conformant |= EGL_OPENGL_ES2_BIT;
                    }

                    // We can only support conformant ES3 on FL 10.1+
                    if (maxVersion.major >= 3)
                    {
                        config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
                    }
                }

                config.depthSize         = depthStencilBufferFormatInfo.depthBits;
                config.level             = 0;
                config.matchNativePixmap = EGL_NONE;
                config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
                config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
                config.maxPBufferPixels =
                    rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
                config.maxSwapInterval  = 4;
                config.minSwapInterval  = 0;
                config.nativeRenderable = EGL_FALSE;
                config.nativeVisualID   = 0;
                config.nativeVisualType = EGL_NONE;

                // Can't support ES3 at all without feature level 10.1
                config.renderableType = EGL_OPENGL_ES2_BIT;
                if (maxVersion.major >= 3)
                {
                    config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
                }

                config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
                config.samples       = sampleCount;
                config.stencilSize   = depthStencilBufferFormatInfo.stencilBits;
                config.surfaceType =
                    EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
                config.transparentType       = EGL_NONE;
                config.transparentRedValue   = 0;
                config.transparentGreenValue = 0;
                config.transparentBlueValue  = 0;
                config.optimalOrientation    = optimalSurfaceOrientation;
                config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
                    colorBufferFormatInfo.componentType);

                configs.add(config);
            }
        }
    }

    ASSERT(configs.size() > 0);
    return configs;
}

void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
{
    outExtensions->createContextRobustness = true;

    if (getShareHandleSupport())
    {
        outExtensions->d3dShareHandleClientBuffer     = true;
        outExtensions->surfaceD3DTexture2DShareHandle = true;
    }
    outExtensions->d3dTextureClientBuffer = true;

    outExtensions->keyedMutex          = true;
    outExtensions->querySurfacePointer = true;
    outExtensions->windowFixedSize     = true;

    // If present path fast is active then the surface orientation extension isn't supported
    outExtensions->surfaceOrientation = !mPresentPathFastEnabled;

    // D3D11 does not support present with dirty rectangles until DXGI 1.2.
    outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;

    outExtensions->deviceQuery = true;

    outExtensions->image                 = true;
    outExtensions->imageBase             = true;
    outExtensions->glTexture2DImage      = true;
    outExtensions->glTextureCubemapImage = true;
    outExtensions->glRenderbufferImage   = true;

    outExtensions->stream                     = true;
    outExtensions->streamConsumerGLTexture    = true;
    outExtensions->streamConsumerGLTextureYUV = true;
    // Not all D3D11 devices support NV12 textures
    if (getNV12TextureSupport())
    {
        outExtensions->streamProducerD3DTextureNV12 = true;
    }

    outExtensions->flexibleSurfaceCompatibility = true;
    outExtensions->directComposition            = !!mDCompModule;

    // Contexts are virtualized so textures can be shared globally
    outExtensions->displayTextureShareGroup = true;

    outExtensions->createContextRobustResourceInitialization = true;

    // getSyncValues requires direct composition.
    outExtensions->getSyncValues = outExtensions->directComposition;
}

gl::Error Renderer11::flush()
{
    mDeviceContext->Flush();
    return gl::NoError();
}

gl::Error Renderer11::finish()
{
    HRESULT result;

    if (!mSyncQuery)
    {
        D3D11_QUERY_DESC queryDesc;
        queryDesc.Query     = D3D11_QUERY_EVENT;
        queryDesc.MiscFlags = 0;

        result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
        ASSERT(SUCCEEDED(result));
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.",
                             result);
        }
    }

    mDeviceContext->End(mSyncQuery);

    unsigned int attempt = 0;
    do
    {
        unsigned int flushFrequency = 100;
        UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
        attempt++;

        result = mDeviceContext->GetData(mSyncQuery, nullptr, 0, flags);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.",
                             result);
        }

        if (result == S_FALSE)
        {
            // Keep polling, but allow other threads to do something useful first
            ScheduleYield();
        }

        if (testDeviceLost())
        {
            mDisplay->notifyDeviceLost();
            return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
        }
    } while (result == S_FALSE);

    return gl::NoError();
}

bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
{
#ifdef ANGLE_ENABLE_WINDOWS_STORE
    return NativeWindow11WinRT::IsValidNativeWindow(window);
#else
    return NativeWindow11Win32::IsValidNativeWindow(window);
#endif
}

NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
                                                const egl::Config *config,
                                                const egl::AttributeMap &attribs) const
{
#ifdef ANGLE_ENABLE_WINDOWS_STORE
    UNUSED_VARIABLE(attribs);
    return new NativeWindow11WinRT(window, config->alphaSize > 0);
#else
    return new NativeWindow11Win32(
        window, config->alphaSize > 0,
        attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
#endif
}

egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
                                         IUnknown *d3dTexture,
                                         EGLint *width,
                                         EGLint *height,
                                         GLenum *fboFormat) const
{
    ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
    if (texture == nullptr)
    {
        return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a ID3D11Texture2D");
    }

    ID3D11Device *textureDevice = nullptr;
    texture->GetDevice(&textureDevice);
    if (textureDevice != mDevice)
    {
        SafeRelease(texture);
        return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
    }
    SafeRelease(textureDevice);

    D3D11_TEXTURE2D_DESC desc = {0};
    texture->GetDesc(&desc);
    SafeRelease(texture);

    if (width)
    {
        *width = static_cast<EGLint>(desc.Width);
    }
    if (height)
    {
        *height = static_cast<EGLint>(desc.Height);
    }
    if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
    {
        // Both the texture and EGL config sample count may not be the same when multi-sampling
        // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
        // we must only check for a invalid match when the EGL config is non-zero or the texture is
        // not one.
        if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
        {
            return egl::Error(EGL_BAD_PARAMETER, "Texture's sample count does not match.");
        }
    }
    // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
    switch (desc.Format)
    {
        case DXGI_FORMAT_R8G8B8A8_UNORM:
        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
        case DXGI_FORMAT_B8G8R8A8_UNORM:
        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
        case DXGI_FORMAT_R16G16B16A16_FLOAT:
        case DXGI_FORMAT_R32G32B32A32_FLOAT:
            break;

        default:
            return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
                              desc.Format);
    }

    if (fboFormat)
    {
        const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
        *fboFormat                       = angleFormat.fboImplementationInternalFormat;
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error Renderer11::validateShareHandle(const egl::Config *config,
                                           HANDLE shareHandle,
                                           const egl::AttributeMap &attribs) const
{
    if (shareHandle == nullptr)
    {
        return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
    }

    ID3D11Resource *tempResource11 = nullptr;
    HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
                                                 (void **)&tempResource11);
    if (FAILED(result))
    {
        return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
    }

    ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
    SafeRelease(tempResource11);

    if (texture2D == nullptr)
    {
        return egl::Error(EGL_BAD_PARAMETER,
                          "Failed to query ID3D11Texture2D object from share handle.");
    }

    D3D11_TEXTURE2D_DESC desc = {0};
    texture2D->GetDesc(&desc);
    SafeRelease(texture2D);

    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
    ASSERT(width != 0 && height != 0);

    const d3d11::Format &backbufferFormatInfo =
        d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());

    if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
        desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
    {
        return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
    }

    return egl::Error(EGL_SUCCESS);
}

SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
                                          HANDLE shareHandle,
                                          IUnknown *d3dTexture,
                                          GLenum backBufferFormat,
                                          GLenum depthBufferFormat,
                                          EGLint orientation,
                                          EGLint samples)
{
    return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
                           backBufferFormat, depthBufferFormat, orientation, samples);
}

void *Renderer11::getD3DDevice()
{
    return reinterpret_cast<void *>(mDevice);
}

gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
{
    if (texture)
    {
        TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
        ASSERT(textureD3D);

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

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

    return gl::NoError();
}

gl::Error Renderer11::generateSwizzles(const gl::ContextState &data, gl::SamplerType type)
{
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());

    unsigned int samplerRange = programD3D->getUsedSamplerRange(type);

    for (unsigned int i = 0; i < samplerRange; i++)
    {
        GLenum textureType = programD3D->getSamplerTextureType(type, i);
        GLint textureUnit  = programD3D->getSamplerMapping(type, i, data.getCaps());
        if (textureUnit != -1)
        {
            gl::Texture *texture = data.getState().getSamplerTexture(textureUnit, textureType);
            ASSERT(texture);
            if (texture->getTextureState().swizzleRequired())
            {
                ANGLE_TRY(generateSwizzle(texture));
            }
        }
    }

    return gl::NoError();
}

gl::Error Renderer11::generateSwizzles(const gl::ContextState &data)
{
    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_VERTEX));
    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_PIXEL));
    return gl::NoError();
}
gl::Error Renderer11::setSamplerState(gl::SamplerType type,
                                      int index,
                                      gl::Texture *texture,
                                      const gl::SamplerState &samplerState)
{
#if !defined(NDEBUG)
    // Make sure to add the level offset for our tiny compressed texture workaround
    TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);

    TextureStorage *storage = nullptr;
    ANGLE_TRY(textureD3D->getNativeTexture(&storage));

    // Storage should exist, texture should be complete
    ASSERT(storage);
#endif  // !defined(NDEBUG)

    // 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.
    SamplerMetadataD3D11 *metadata = nullptr;

    if (type == gl::SAMPLER_PIXEL)
    {
        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits);

        if (mForceSetPixelSamplerStates[index] ||
            memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
        {
            ID3D11SamplerState *dxSamplerState = nullptr;
            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));

            ASSERT(dxSamplerState != nullptr);
            mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);

            mCurPixelSamplerStates[index] = samplerState;
        }

        mForceSetPixelSamplerStates[index] = false;

        metadata = &mSamplerMetadataPS;
    }
    else if (type == gl::SAMPLER_VERTEX)
    {
        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits);

        if (mForceSetVertexSamplerStates[index] ||
            memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
        {
            ID3D11SamplerState *dxSamplerState = nullptr;
            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));

            ASSERT(dxSamplerState != nullptr);
            mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);

            mCurVertexSamplerStates[index] = samplerState;
        }

        mForceSetVertexSamplerStates[index] = false;

        metadata = &mSamplerMetadataVS;
    }
    else if (type == gl::SAMPLER_COMPUTE)
    {
        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxComputeTextureImageUnits);

        if (mForceSetComputeSamplerStates[index] ||
            memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0)
        {
            ID3D11SamplerState *dxSamplerState = nullptr;
            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));

            ASSERT(dxSamplerState != nullptr);
            mDeviceContext->CSSetSamplers(index, 1, &dxSamplerState);

            mCurComputeSamplerStates[index] = samplerState;
        }

        mForceSetComputeSamplerStates[index] = false;

        metadata = &mSamplerMetadataCS;
    }
    else
        UNREACHABLE();

    ASSERT(metadata != nullptr);
    metadata->update(index, *texture);

    return gl::NoError();
}

gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
{
    ID3D11ShaderResourceView *textureSRV = nullptr;

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

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

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

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

        ANGLE_TRY(storage11->getSRV(texture->getTextureState(), &textureSRV));

        // If we get NULL back from getSRV here, something went wrong in the texture class and we're
        // unexpectedly missing the shader resource view
        ASSERT(textureSRV != nullptr);

        textureImpl->resetDirty();
    }

    ASSERT((type == gl::SAMPLER_PIXEL &&
            static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits) ||
           (type == gl::SAMPLER_VERTEX &&
            static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits));

    mStateManager.setShaderResource(type, index, textureSRV);

    return gl::NoError();
}

gl::Error Renderer11::setUniformBuffers(const gl::ContextState &data,
                                        const std::vector<GLint> &vertexUniformBuffers,
                                        const std::vector<GLint> &fragmentUniformBuffers)
{
    for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size();
         uniformBufferIndex++)
    {
        GLint binding = vertexUniformBuffers[uniformBufferIndex];

        if (binding == -1)
        {
            continue;
        }

        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
            data.getState().getIndexedUniformBuffer(binding);
        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();

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

        Buffer11 *bufferStorage      = GetImplAs<Buffer11>(uniformBuffer.get());
        ID3D11Buffer *constantBuffer = nullptr;
        UINT firstConstant           = 0;
        UINT numConstants            = 0;

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

        if (!constantBuffer)
        {
            return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
        }

        if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() ||
            mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
            mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
        {
            if (firstConstant != 0 && uniformBufferSize != 0)
            {
                ASSERT(numConstants != 0);
                mDeviceContext1->VSSetConstantBuffers1(
                    getReservedVertexUniformBuffers() +
                        static_cast<unsigned int>(uniformBufferIndex),
                    1, &constantBuffer, &firstConstant, &numConstants);
            }
            else
            {
                mDeviceContext->VSSetConstantBuffers(
                    getReservedVertexUniformBuffers() +
                        static_cast<unsigned int>(uniformBufferIndex),
                    1, &constantBuffer);
            }

            mCurrentConstantBufferVS[uniformBufferIndex]       = bufferStorage->getSerial();
            mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset;
            mCurrentConstantBufferVSSize[uniformBufferIndex]   = uniformBufferSize;
        }
    }

    for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size();
         uniformBufferIndex++)
    {
        GLint binding = fragmentUniformBuffers[uniformBufferIndex];

        if (binding == -1)
        {
            continue;
        }

        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
            data.getState().getIndexedUniformBuffer(binding);
        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();

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

        Buffer11 *bufferStorage      = GetImplAs<Buffer11>(uniformBuffer.get());
        ID3D11Buffer *constantBuffer = nullptr;
        UINT firstConstant           = 0;
        UINT numConstants            = 0;

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

        if (!constantBuffer)
        {
            return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
        }

        if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() ||
            mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
            mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
        {
            if (firstConstant != 0 && uniformBufferSize != 0)
            {
                mDeviceContext1->PSSetConstantBuffers1(
                    getReservedFragmentUniformBuffers() +
                        static_cast<unsigned int>(uniformBufferIndex),
                    1, &constantBuffer, &firstConstant, &numConstants);
            }
            else
            {
                mDeviceContext->PSSetConstantBuffers(
                    getReservedFragmentUniformBuffers() +
                        static_cast<unsigned int>(uniformBufferIndex),
                    1, &constantBuffer);
            }

            mCurrentConstantBufferPS[uniformBufferIndex]       = bufferStorage->getSerial();
            mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset;
            mCurrentConstantBufferPSSize[uniformBufferIndex]   = uniformBufferSize;
        }
    }

    return gl::NoError();
}

gl::Error Renderer11::updateState(ContextImpl *contextImpl, GLenum drawMode)
{
    const auto &data    = contextImpl->getContextState();
    const auto &glState = data.getState();

    // Applies the render target surface, depth stencil surface, viewport rectangle and
    // scissor rectangle to the renderer
    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
    ANGLE_TRY(mStateManager.syncFramebuffer(contextImpl, framebuffer));

    // Set the present path state
    auto firstColorAttachment        = framebuffer->getFirstColorbuffer();
    const bool presentPathFastActive = UsePresentPathFast(this, firstColorAttachment);
    mStateManager.updatePresentPath(presentPathFastActive, firstColorAttachment);

    // Setting viewport state
    mStateManager.setViewport(&data.getCaps(), glState.getViewport(), glState.getNearPlane(),
                              glState.getFarPlane());

    // Setting scissor state
    mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());

    // Applying rasterizer state to D3D11 device
    // Since framebuffer->getSamples will return the original samples which may be different with
    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
    // get the actual samples.
    GLsizei samples = 0;
    if (firstColorAttachment)
    {
        ASSERT(firstColorAttachment->isAttached());
        RenderTarget11 *renderTarget = nullptr;
        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
        samples = renderTarget->getSamples();
    }
    gl::RasterizerState rasterizer = glState.getRasterizerState();
    rasterizer.pointDrawMode       = (drawMode == GL_POINTS);
    rasterizer.multiSample         = (samples != 0);

    ANGLE_TRY(mStateManager.setRasterizerState(rasterizer));

    // Setting blend state
    unsigned int mask = GetBlendSampleMask(data, samples);
    ANGLE_TRY(mStateManager.setBlendState(framebuffer, glState.getBlendState(),
                                          glState.getBlendColor(), mask));

    // Setting depth stencil state
    ANGLE_TRY(mStateManager.setDepthStencilState(glState));

    return gl::NoError();
}

bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
{
    D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;

    GLsizei minCount = 0;

    switch (mode)
    {
        case GL_POINTS:
            primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
            minCount          = 1;
            break;
        case GL_LINES:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
            minCount          = 2;
            break;
        case GL_LINE_LOOP:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
            minCount          = 2;
            break;
        case GL_LINE_STRIP:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
            minCount          = 2;
            break;
        case GL_TRIANGLES:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
            minCount          = 3;
            break;
        case GL_TRIANGLE_STRIP:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
            minCount          = 3;
            break;
        // emulate fans via rewriting index buffer
        case GL_TRIANGLE_FAN:
            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
            minCount          = 3;
            break;
        default:
            UNREACHABLE();
            return false;
    }

    // If instanced pointsprite emulation is being used and  If gl_PointSize is used in the shader,
    // GL_POINTS mode is expected to render pointsprites.
    // Instanced PointSprite emulation requires that the topology to be
    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
    if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
    {
        primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    }

    if (primitiveTopology != mCurrentPrimitiveTopology)
    {
        mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
        mCurrentPrimitiveTopology = primitiveTopology;
    }

    return count >= minCount;
}

gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
                                        GLenum mode,
                                        GLint first,
                                        GLsizei count,
                                        GLsizei instances,
                                        TranslatedIndexData *indexInfo)
{
    const auto &vertexArray = state.getVertexArray();
    auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);

    ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first, count,
                                                          instances));

    ANGLE_TRY(mStateManager.updateCurrentValueAttribs(state, mVertexDataManager));

    // If index information is passed, mark it with the current changed status.
    if (indexInfo)
    {
        indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged;
    }

    GLsizei numIndicesPerInstance = 0;
    if (instances > 0)
    {
        numIndicesPerInstance = count;
    }
    const auto &vertexArrayAttribs  = vertexArray11->getTranslatedAttribs();
    const auto &currentValueAttribs = mStateManager.getCurrentValueAttribs();
    ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs,
                                                   mode, first, indexInfo, numIndicesPerInstance));

    // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
    // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
    // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
    // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
    // update on the second draw call.
    // Hence we clear the flags here, after we've applied vertex data, since we know everything
    // is clean. This is a bit of a hack.
    vertexArray11->clearDirtyAndPromoteDynamicAttribs(state, count);

    return gl::NoError();
}

gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data,
                                       const void *indices,
                                       GLsizei count,
                                       GLenum mode,
                                       GLenum type,
                                       TranslatedIndexData *indexInfo)
{
    const auto &glState            = data.getState();
    gl::VertexArray *vao           = glState.getVertexArray();
    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
    ANGLE_TRY(mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
                                                  indexInfo, glState.isPrimitiveRestartEnabled()));

    ID3D11Buffer *buffer = nullptr;
    DXGI_FORMAT bufferFormat =
        (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;

    if (indexInfo->storage)
    {
        Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDEX), buffer);
    }
    else
    {
        IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
        buffer                     = indexBuffer->getBuffer();
    }

    mAppliedIBChanged = false;
    if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat ||
        indexInfo->startOffset != mAppliedIBOffset)
    {
        mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);

        mAppliedIB        = buffer;
        mAppliedIBFormat  = bufferFormat;
        mAppliedIBOffset  = indexInfo->startOffset;
        mAppliedIBChanged = true;
    }

    return gl::NoError();
}

gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::ContextState &data)
{
    const auto &state = data.getState();

    // If transform feedback is not active, unbind all buffers
    if (!state.isTransformFeedbackActiveUnpaused())
    {
        if (mAppliedTFObject != 0)
        {
            mDeviceContext->SOSetTargets(0, nullptr, nullptr);
            mAppliedTFObject = 0;
        }
        return gl::NoError();
    }

    gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
    TransformFeedback11 *transformFeedback11 = GetImplAs<TransformFeedback11>(transformFeedback);
    uintptr_t transformFeedbackId            = reinterpret_cast<uintptr_t>(transformFeedback11);
    if (mAppliedTFObject == transformFeedbackId && !transformFeedback11->isDirty())
    {
        return gl::NoError();
    }

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

    mDeviceContext->SOSetTargets(transformFeedback11->getNumSOBuffers(), soBuffers->data(),
                                 soOffsets.data());

    mAppliedTFObject = transformFeedbackId;
    transformFeedback11->onApply();

    return gl::NoError();
}

gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data,
                                     GLenum mode,
                                     GLint startVertex,
                                     GLsizei count,
                                     GLsizei instances)
{
    const auto &glState    = data.getState();
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());

    if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
    {
        // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
        // won't get the correct output. To work around this, draw with *only* the stream out
        // first (no pixel shader) to feed the stream out buffers and then draw again with the
        // geometry shader + pixel shader to rasterize the primitives.
        mDeviceContext->PSSetShader(nullptr, nullptr, 0);

        if (instances > 0)
        {
            mDeviceContext->DrawInstanced(count, instances, 0, 0);
        }
        else
        {
            mDeviceContext->Draw(count, 0);
        }

        rx::ShaderExecutableD3D *pixelExe = nullptr;
        ANGLE_TRY(
            programD3D->getPixelExecutableForFramebuffer(glState.getDrawFramebuffer(), &pixelExe));

        // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
        if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
        {
            return gl::NoError();
        }

        ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
        ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
        mDeviceContext->PSSetShader(pixelShader, nullptr, 0);

        // Retrieve the geometry shader.
        rx::ShaderExecutableD3D *geometryExe = nullptr;
        ANGLE_TRY(
            programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr));

        ID3D11GeometryShader *geometryShader =
            (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
        mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
        ASSERT(geometryShader);
        mDeviceContext->GSSetShader(geometryShader, nullptr, 0);

        if (instances > 0)
        {
            mDeviceContext->DrawInstanced(count, instances, 0, 0);
        }
        else
        {
            mDeviceContext->Draw(count, 0);
        }
        return gl::NoError();
    }

    if (mode == GL_LINE_LOOP)
    {
        return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
    }

    if (mode == GL_TRIANGLE_FAN)
    {
        return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
    }

    bool useInstancedPointSpriteEmulation =
        programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;

    if (instances > 0)
    {
        if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
        {
            // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a
            // less efficent code path.
            // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
            // points. An offset into the instanced data buffer is calculated and applied on each
            // iteration to ensure all instances are rendered correctly.

            // Each instance being rendered requires the inputlayout cache to reapply buffers and
            // offsets.
            for (GLsizei i = 0; i < instances; i++)
            {
                ANGLE_TRY(
                    mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
                mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
            }
        }
        else
        {
            mDeviceContext->DrawInstanced(count, instances, 0, 0);
        }
        return gl::NoError();
    }

    // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
    // Emulating instanced point sprites for FL9_3 requires the topology to be
    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
    if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
    {
        mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
    }
    else
    {
        mDeviceContext->Draw(count, 0);
    }
    return gl::NoError();
}

gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data,
                                       const TranslatedIndexData &indexInfo,
                                       GLenum mode,
                                       GLsizei count,
                                       GLenum type,
                                       const void *indices,
                                       GLsizei instances)
{
    int startVertex = static_cast<int>(indexInfo.indexRange.start);
    int baseVertex  = -startVertex;

    if (mode == GL_LINE_LOOP)
    {
        return drawLineLoop(data, count, type, indices, baseVertex, instances);
    }

    if (mode == GL_TRIANGLE_FAN)
    {
        return drawTriangleFan(data, count, type, indices, baseVertex, instances);
    }

    const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
    if (instances > 0)
    {
        if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
        {
            // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a
            // less efficent code path.
            // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
            // points. An offset into the instanced data buffer is calculated and applied on each
            // iteration to ensure all instances are rendered correctly.
            GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount());

            // Each instance being rendered requires the inputlayout cache to reapply buffers and
            // offsets.
            for (GLsizei i = 0; i < instances; i++)
            {
                ANGLE_TRY(
                    mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
                mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
            }
        }
        else
        {
            mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertex, 0);
        }
        return gl::NoError();
    }

    // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
    // Emulating instanced point sprites for FL9_3 requires the topology to be
    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
    if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
    {
        // The count parameter passed to drawElements represents the total number of instances
        // to be rendered. Each instance is referenced by the bound index buffer from the
        // the caller.
        //
        // Indexed pointsprite emulation replicates data for duplicate entries found
        // in the index buffer.
        // This is not an efficent rendering mechanism and is only used on downlevel renderers
        // that do not support geometry shaders.
        mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
    }
    else
    {
        mDeviceContext->DrawIndexed(count, 0, baseVertex);
    }
    return gl::NoError();
}

bool Renderer11::supportsFastIndirectDraw(const gl::State &state, GLenum mode, GLenum type)
{
    const auto &vertexArray = state.getVertexArray();
    auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);
    // Indirect drawing doesn't support dynamic attribute storage since it needs the first and count
    // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
    // either since we need to simulate them in D3D.
    if (vertexArray11->hasDynamicAttrib(state) || mode == GL_LINE_LOOP || mode == GL_TRIANGLE_FAN)
    {
        return false;
    }

    if (type != GL_NONE)
    {
        gl::Buffer *elementArrayBuffer = vertexArray->getElementArrayBuffer().get();
        ASSERT(elementArrayBuffer);
        // Only non-streaming index data can be directly used to do indirect draw since they don't
        // need the indices and count informations. Here we don't check whether it really has
        // primitive restart index in it since it also needs to know the index range and count.
        // So, for all other situations, we fall back to normal draw instead of indirect draw.
        bool primitiveRestartWorkaround = mIndexDataManager->usePrimitiveRestartWorkaround(
            state.isPrimitiveRestartEnabled(), type);
        return !mIndexDataManager->isStreamingIndexData(primitiveRestartWorkaround, type,
                                                        elementArrayBuffer);
    }
    return true;
}

gl::Error Renderer11::drawArraysIndirectImpl(const gl::ContextState &data,
                                             GLenum mode,
                                             const void *indirect)
{
    if (skipDraw(data, mode))
    {
        return gl::NoError();
    }

    const auto &glState            = data.getState();
    gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
    ASSERT(drawIndirectBuffer);
    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);

    if (supportsFastIndirectDraw(glState, mode, GL_NONE))
    {
        applyVertexBuffer(glState, mode, 0, 0, 0, nullptr);
        ID3D11Buffer *buffer = nullptr;
        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
        mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
        return gl::NoError();
    }

    const uint8_t *bufferData = nullptr;
    ANGLE_TRY(storage->getData(&bufferData));
    ASSERT(bufferData);
    const gl::DrawArraysIndirectCommand *args =
        reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
    GLuint count     = args->count;
    GLuint instances = args->instanceCount;
    GLuint first     = args->first;

    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));

    if (mode == GL_LINE_LOOP)
    {
        return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
    }
    if (mode == GL_TRIANGLE_FAN)
    {
        return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
    }

    mDeviceContext->DrawInstanced(count, instances, 0, 0);
    return gl::NoError();
}

gl::Error Renderer11::drawElementsIndirectImpl(const gl::ContextState &data,
                                               GLenum mode,
                                               GLenum type,
                                               const void *indirect)
{
    if (skipDraw(data, mode))
    {
        return gl::NoError();
    }

    const auto &glState            = data.getState();
    gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
    ASSERT(drawIndirectBuffer);
    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);

    TranslatedIndexData indexInfo;
    if (supportsFastIndirectDraw(glState, mode, type))
    {
        ANGLE_TRY(applyIndexBuffer(data, nullptr, 0, mode, type, &indexInfo));
        ANGLE_TRY(applyVertexBuffer(glState, mode, 0, 0, 0, &indexInfo));
        ID3D11Buffer *buffer = nullptr;
        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
        mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
        return gl::NoError();
    }

    const uint8_t *bufferData = nullptr;
    ANGLE_TRY(storage->getData(&bufferData));
    ASSERT(bufferData);

    const gl::DrawElementsIndirectCommand *cmd =
        reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset);
    GLuint count      = cmd->count;
    GLuint instances  = cmd->primCount;
    GLuint firstIndex = cmd->firstIndex;
    GLint baseVertex  = cmd->baseVertex;

    const gl::Type &typeInfo = gl::GetTypeInfo(type);
    uint8_t *indices         = static_cast<uint8_t *>(0) + firstIndex * typeInfo.bytes;

    gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer().get();
    ASSERT(elementArrayBuffer);
    gl::IndexRange indexRange;
    ANGLE_TRY(elementArrayBuffer->getIndexRange(type, reinterpret_cast<size_t>(indices), count,
                                                glState.isPrimitiveRestartEnabled(), &indexRange));

    indexInfo.indexRange = indexRange;
    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
    size_t vertexCount = indexRange.vertexCount();
    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexRange.start) + baseVertex,
                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));

    int baseVertexLocation = -static_cast<int>(indexRange.start);
    if (mode == GL_LINE_LOOP)
    {
        return drawLineLoop(data, count, type, indices, baseVertexLocation, instances);
    }

    if (mode == GL_TRIANGLE_FAN)
    {
        return drawTriangleFan(data, count, type, indices, baseVertexLocation, instances);
    }

    mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
    return gl::NoError();
}

gl::Error Renderer11::drawLineLoop(const gl::ContextState &data,
                                   GLsizei count,
                                   GLenum type,
                                   const void *indexPointer,
                                   int baseVertex,
                                   int instances)
{
    const auto &glState            = data.getState();
    gl::VertexArray *vao           = glState.getVertexArray();
    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();

    const void *indices = indexPointer;

    // Get the raw indices for an indexed draw
    if (type != GL_NONE && elementArrayBuffer)
    {
        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
        intptr_t offset    = reinterpret_cast<intptr_t>(indices);

        const uint8_t *bufferData = nullptr;
        ANGLE_TRY(storage->getData(&bufferData));

        indices = bufferData + offset;
    }

    if (!mLineLoopIB)
    {
        mLineLoopIB = new StreamingIndexBufferInterface(this);
        gl::Error error =
            mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
        if (error.isError())
        {
            SafeDelete(mLineLoopIB);
            return error;
        }
    }

    // Checked by Renderer11::applyPrimitiveType
    ASSERT(count >= 0);

    if (static_cast<unsigned int>(count) + 1 >
        (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
    {
        return gl::Error(GL_OUT_OF_MEMORY,
                         "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too "
                         "many indices required.");
    }

    GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
                       glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);

    unsigned int spaceNeeded =
        static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
    ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));

    void *mappedMemory = nullptr;
    unsigned int offset;
    ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));

    // Copy over the converted index data.
    memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
           sizeof(GLuint) * mScratchIndexDataBuffer.size());

    ANGLE_TRY(mLineLoopIB->unmapBuffer());

    IndexBuffer11 *indexBuffer   = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
    ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
    DXGI_FORMAT indexFormat      = indexBuffer->getIndexFormat();

    if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
        mAppliedIBOffset != offset)
    {
        mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
        mAppliedIB       = d3dIndexBuffer;
        mAppliedIBFormat = indexFormat;
        mAppliedIBOffset = offset;
    }

    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());

    if (instances > 0)
    {
        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
    }
    else
    {
        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
    }

    return gl::NoError();
}

gl::Error Renderer11::drawTriangleFan(const gl::ContextState &data,
                                      GLsizei count,
                                      GLenum type,
                                      const void *indices,
                                      int baseVertex,
                                      int instances)
{
    gl::VertexArray *vao           = data.getState().getVertexArray();
    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();

    const void *indexPointer = indices;

    // Get the raw indices for an indexed draw
    if (type != GL_NONE && elementArrayBuffer)
    {
        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
        intptr_t offset    = reinterpret_cast<intptr_t>(indices);

        const uint8_t *bufferData = nullptr;
        ANGLE_TRY(storage->getData(&bufferData));

        indexPointer = bufferData + offset;
    }

    if (!mTriangleFanIB)
    {
        mTriangleFanIB = new StreamingIndexBufferInterface(this);
        gl::Error error =
            mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
        if (error.isError())
        {
            SafeDelete(mTriangleFanIB);
            return error;
        }
    }

    // Checked by Renderer11::applyPrimitiveType
    ASSERT(count >= 3);

    const GLuint numTris = count - 2;

    if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
    {
        return gl::Error(GL_OUT_OF_MEMORY,
                         "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many "
                         "indices required.");
    }

    GetTriFanIndices(indexPointer, type, count, data.getState().isPrimitiveRestartEnabled(),
                     &mScratchIndexDataBuffer);

    const unsigned int spaceNeeded =
        static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
    ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));

    void *mappedMemory = nullptr;
    unsigned int offset;
    ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));

    memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);

    ANGLE_TRY(mTriangleFanIB->unmapBuffer());

    IndexBuffer11 *indexBuffer   = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
    ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
    DXGI_FORMAT indexFormat      = indexBuffer->getIndexFormat();

    if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
        mAppliedIBOffset != offset)
    {
        mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
        mAppliedIB       = d3dIndexBuffer;
        mAppliedIBFormat = indexFormat;
        mAppliedIBOffset = offset;
    }

    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());

    if (instances > 0)
    {
        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
    }
    else
    {
        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
    }

    return gl::NoError();
}

gl::Error Renderer11::applyShaders(const gl::ContextState &data, GLenum drawMode)
{
    // This method is called single-threaded.
    ANGLE_TRY(ensureHLSLCompilerInitialized());

    const auto &glState    = data.getState();
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
    programD3D->updateCachedInputLayout(glState);

    const auto &inputLayout = programD3D->getCachedInputLayout();

    ShaderExecutableD3D *vertexExe = nullptr;
    ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr));

    const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
    ShaderExecutableD3D *pixelExe          = nullptr;
    ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe));

    ShaderExecutableD3D *geometryExe = nullptr;
    ANGLE_TRY(
        programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr));

    ID3D11VertexShader *vertexShader =
        (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);

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

    ID3D11GeometryShader *geometryShader = nullptr;
    bool transformFeedbackActive         = glState.isTransformFeedbackActiveUnpaused();
    if (transformFeedbackActive)
    {
        geometryShader =
            (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
    }
    else
    {
        geometryShader =
            (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
    }

    bool dirtyUniforms = false;

    if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader)
    {
        mDeviceContext->VSSetShader(vertexShader, nullptr, 0);
        mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader);
        dirtyUniforms        = true;
    }

    if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader)
    {
        mDeviceContext->GSSetShader(geometryShader, nullptr, 0);
        mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
        dirtyUniforms          = true;
    }

    if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader)
    {
        mDeviceContext->PSSetShader(pixelShader, nullptr, 0);
        mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader);
        dirtyUniforms       = true;
    }

    if (dirtyUniforms)
    {
        programD3D->dirtyAllUniforms();
    }

    return programD3D->applyUniforms(drawMode);
}

gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
                                    GLenum drawMode,
                                    const std::vector<D3DUniform *> &uniformArray)
{
    unsigned int totalRegisterCountVS = 0;
    unsigned int totalRegisterCountPS = 0;

    bool vertexUniformsDirty = false;
    bool pixelUniformsDirty  = false;

    for (const D3DUniform *uniform : uniformArray)
    {
        if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
        {
            totalRegisterCountVS += uniform->registerCount;
            vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
        }

        if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
        {
            totalRegisterCountPS += uniform->registerCount;
            pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
        }
    }

    const UniformStorage11 *vertexUniformStorage =
        GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
    const UniformStorage11 *fragmentUniformStorage =
        GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
    ASSERT(vertexUniformStorage);
    ASSERT(fragmentUniformStorage);

    ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer();
    ID3D11Buffer *pixelConstantBuffer  = fragmentUniformStorage->getConstantBuffer();

    float(*mapVS)[4] = nullptr;
    float(*mapPS)[4] = nullptr;

    if (totalRegisterCountVS > 0 && vertexUniformsDirty)
    {
        D3D11_MAPPED_SUBRESOURCE map = {0};
        HRESULT result =
            mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
        ASSERT(SUCCEEDED(result));
        mapVS = (float(*)[4])map.pData;
    }

    if (totalRegisterCountPS > 0 && pixelUniformsDirty)
    {
        D3D11_MAPPED_SUBRESOURCE map = {0};
        HRESULT result =
            mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
        ASSERT(SUCCEEDED(result));
        mapPS = (float(*)[4])map.pData;
    }

    for (const D3DUniform *uniform : uniformArray)
    {
        if (uniform->isSampler())
            continue;

        unsigned int componentCount = (4 - uniform->registerElement);

        // we assume that uniforms from structs are arranged in struct order in our uniforms list.
        // otherwise we would overwrite previously written regions of memory.

        if (uniform->isReferencedByVertexShader() && mapVS)
        {
            memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
                   uniform->registerCount * sizeof(float) * componentCount);
        }

        if (uniform->isReferencedByFragmentShader() && mapPS)
        {
            memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
                   uniform->registerCount * sizeof(float) * componentCount);
        }
    }

    if (mapVS)
    {
        mDeviceContext->Unmap(vertexConstantBuffer, 0);
    }

    if (mapPS)
    {
        mDeviceContext->Unmap(pixelConstantBuffer, 0);
    }

    if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
    {
        mDeviceContext->VSSetConstantBuffers(
            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &vertexConstantBuffer);
        mCurrentVertexConstantBuffer = vertexConstantBuffer;
    }

    if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
    {
        mDeviceContext->PSSetConstantBuffers(
            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &pixelConstantBuffer);
        mCurrentPixelConstantBuffer = pixelConstantBuffer;
    }

    if (!mDriverConstantBufferVS)
    {
        D3D11_BUFFER_DESC constantBufferDescription = {0};
        d3d11::InitConstantBufferDesc(
            &constantBufferDescription,
            sizeof(dx_VertexConstants11) + mSamplerMetadataVS.sizeBytes());
        HRESULT result =
            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferVS);
        ASSERT(SUCCEEDED(result));
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to create vertex shader constant buffer, result: 0x%X.",
                             result);
        }
        mDeviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                             &mDriverConstantBufferVS);
    }
    if (!mDriverConstantBufferPS)
    {
        D3D11_BUFFER_DESC constantBufferDescription = {0};
        d3d11::InitConstantBufferDesc(&constantBufferDescription,
                                      sizeof(dx_PixelConstants11) + mSamplerMetadataPS.sizeBytes());
        HRESULT result =
            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferPS);
        ASSERT(SUCCEEDED(result));
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to create pixel shader constant buffer, result: 0x%X.",
                             result);
        }
        mDeviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                             &mDriverConstantBufferPS);
    }

    // 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.
    const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants();
    size_t samplerMetadataReferencedBytesVS     = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
                                              programD3D.getUsedSamplerRange(gl::SAMPLER_VERTEX);
    applyDriverConstantsIfNeeded(&mAppliedVertexConstants, vertexConstants, &mSamplerMetadataVS,
                                 samplerMetadataReferencedBytesVS, mDriverConstantBufferVS);

    const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants();
    size_t samplerMetadataReferencedBytesPS   = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
                                              programD3D.getUsedSamplerRange(gl::SAMPLER_PIXEL);
    applyDriverConstantsIfNeeded(&mAppliedPixelConstants, pixelConstants, &mSamplerMetadataPS,
                                 samplerMetadataReferencedBytesPS, mDriverConstantBufferPS);

    // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
    if (programD3D.usesGeometryShader(drawMode))
    {
        // needed for the point sprite geometry shader
        if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
        {
            ASSERT(mDriverConstantBufferPS != nullptr);
            mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
            mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
        }
    }

    return gl::NoError();
}

// SamplerMetadataD3D11 implementation

Renderer11::SamplerMetadataD3D11::SamplerMetadataD3D11() : mDirty(true)
{
}

Renderer11::SamplerMetadataD3D11::~SamplerMetadataD3D11()
{
}

void Renderer11::SamplerMetadataD3D11::initData(unsigned int samplerCount)
{
    mSamplerMetadata.resize(samplerCount);
}

void Renderer11::SamplerMetadataD3D11::update(unsigned int samplerIndex, const gl::Texture &texture)
{
    unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
    GLenum sizedFormat =
        texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat;
    if (mSamplerMetadata[samplerIndex].baseLevel != static_cast<int>(baseLevel))
    {
        mSamplerMetadata[samplerIndex].baseLevel = static_cast<int>(baseLevel);
        mDirty                                   = 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 (mSamplerMetadata[samplerIndex].internalFormatBits != internalFormatBits)
        {
            mSamplerMetadata[samplerIndex].internalFormatBits = internalFormatBits;
            mDirty                                            = true;
        }
        // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer
        // vector.
        GLenum wrapS  = texture.getWrapS();
        GLenum wrapT  = texture.getWrapT();
        GLenum wrapR  = texture.getWrapR();
        int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
        if (mSamplerMetadata[samplerIndex].wrapModes != wrapModes)
        {
            mSamplerMetadata[samplerIndex].wrapModes = wrapModes;
            mDirty                                   = true;
        }
    }
}

const Renderer11::SamplerMetadataD3D11::dx_SamplerMetadata *
Renderer11::SamplerMetadataD3D11::getData() const
{
    return mSamplerMetadata.data();
}

size_t Renderer11::SamplerMetadataD3D11::sizeBytes() const
{
    return sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * mSamplerMetadata.size();
}

template <class TShaderConstants>
void Renderer11::applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
                                              const TShaderConstants &constants,
                                              SamplerMetadataD3D11 *samplerMetadata,
                                              size_t samplerMetadataReferencedBytes,
                                              ID3D11Buffer *driverConstantBuffer)
{
    ASSERT(driverConstantBuffer != nullptr);
    if (memcmp(appliedConstants, &constants, sizeof(TShaderConstants)) != 0 ||
        samplerMetadata->isDirty())
    {
        memcpy(appliedConstants, &constants, sizeof(TShaderConstants));

        D3D11_MAPPED_SUBRESOURCE mapping = {0};
        HRESULT result =
            mDeviceContext->Map(driverConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping);
        ASSERT(SUCCEEDED(result));
        memcpy(mapping.pData, appliedConstants, sizeof(TShaderConstants));
        // Previous buffer contents were discarded, so we need to refresh also the area of the
        // buffer that isn't used by this program.
        memcpy(&reinterpret_cast<uint8_t *>(mapping.pData)[sizeof(TShaderConstants)],
               samplerMetadata->getData(), samplerMetadata->sizeBytes());
        mDeviceContext->Unmap(driverConstantBuffer, 0);

        samplerMetadata->markClean();
    }
}

template void Renderer11::applyDriverConstantsIfNeeded<dx_VertexConstants11>(
    dx_VertexConstants11 *appliedConstants,
    const dx_VertexConstants11 &constants,
    SamplerMetadataD3D11 *samplerMetadata,
    size_t samplerMetadataReferencedBytes,
    ID3D11Buffer *driverConstantBuffer);
template void Renderer11::applyDriverConstantsIfNeeded<dx_PixelConstants11>(
    dx_PixelConstants11 *appliedConstants,
    const dx_PixelConstants11 &constants,
    SamplerMetadataD3D11 *samplerMetadata,
    size_t samplerMetadataReferencedBytes,
    ID3D11Buffer *driverConstantBuffer);
template void Renderer11::applyDriverConstantsIfNeeded<dx_ComputeConstants11>(
    dx_ComputeConstants11 *appliedConstants,
    const dx_ComputeConstants11 &constants,
    SamplerMetadataD3D11 *samplerMetadata,
    size_t samplerMetadataReferencedBytes,
    ID3D11Buffer *driverConstantBuffer);

void Renderer11::markAllStateDirty()
{
    TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");

    for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
    {
        mForceSetVertexSamplerStates[vsamplerId] = true;
    }

    for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
    {
        mForceSetPixelSamplerStates[fsamplerId] = true;
    }

    for (size_t csamplerId = 0; csamplerId < mForceSetComputeSamplerStates.size(); ++csamplerId)
    {
        mForceSetComputeSamplerStates[csamplerId] = true;
    }

    mStateManager.invalidateEverything();

    mAppliedIB       = nullptr;
    mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
    mAppliedIBOffset = 0;

    mAppliedVertexShader   = angle::DirtyPointer;
    mAppliedGeometryShader = angle::DirtyPointer;
    mAppliedPixelShader    = angle::DirtyPointer;
    mAppliedComputeShader  = angle::DirtyPointer;

    mAppliedTFObject = angle::DirtyPointer;

    memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
    memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));

    mInputLayoutCache.markDirty();

    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
    {
        mCurrentConstantBufferVS[i]       = static_cast<unsigned int>(-1);
        mCurrentConstantBufferVSOffset[i] = 0;
        mCurrentConstantBufferVSSize[i]   = 0;
        mCurrentConstantBufferPS[i]       = static_cast<unsigned int>(-1);
        mCurrentConstantBufferPSOffset[i] = 0;
        mCurrentConstantBufferPSSize[i]   = 0;
    }

    mCurrentVertexConstantBuffer   = nullptr;
    mCurrentPixelConstantBuffer    = nullptr;
    mCurrentGeometryConstantBuffer = nullptr;
    mCurrentComputeConstantBuffer  = nullptr;

    mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}

void Renderer11::releaseDeviceResources()
{
    mStateManager.deinitialize();
    mStateCache.clear();
    mInputLayoutCache.clear();

    SafeDelete(mVertexDataManager);
    SafeDelete(mIndexDataManager);
    SafeDelete(mLineLoopIB);
    SafeDelete(mTriangleFanIB);
    SafeDelete(mBlit);
    SafeDelete(mClear);
    SafeDelete(mTrim);
    SafeDelete(mPixelTransfer);

    SafeRelease(mDriverConstantBufferVS);
    SafeRelease(mDriverConstantBufferPS);
    SafeRelease(mDriverConstantBufferCS);
    SafeRelease(mSyncQuery);
}

// set notify to true to broadcast a message to all contexts of the device loss
bool Renderer11::testDeviceLost()
{
    bool isLost = false;

    if (!mDevice)
    {
        return true;
    }

    // GetRemovedReason is used to test if the device is removed
    HRESULT result = mDevice->GetDeviceRemovedReason();
    isLost         = d3d11::isDeviceLostError(result);

    if (isLost)
    {
        ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
    }

    return isLost;
}

bool Renderer11::testDeviceResettable()
{
    // determine if the device is resettable by creating a dummy device
    PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
        (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");

    if (D3D11CreateDevice == nullptr)
    {
        return false;
    }

    ID3D11Device *dummyDevice;
    D3D_FEATURE_LEVEL dummyFeatureLevel;
    ID3D11DeviceContext *dummyContext;

    ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
    HRESULT result = D3D11CreateDevice(
        nullptr, mRequestedDriverType, nullptr,
#if defined(_DEBUG)
        D3D11_CREATE_DEVICE_DEBUG,
#else
        0,
#endif
        mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
        D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext);

    if (!mDevice || FAILED(result))
    {
        return false;
    }

    SafeRelease(dummyContext);
    SafeRelease(dummyDevice);

    return true;
}

void Renderer11::release()
{
    RendererD3D::cleanup();

    mScratchMemoryBuffer.clear();

    if (mAnnotator != nullptr)
    {
        gl::UninitializeDebugAnnotations();
        SafeDelete(mAnnotator);
    }

    releaseDeviceResources();

    if (!mCreatedWithDeviceEXT)
    {
        // Only delete the device if the Renderer11 owns it
        // Otherwise we should keep it around in case we try to reinitialize the renderer later
        SafeDelete(mEGLDevice);
    }

    SafeRelease(mDxgiFactory);
    SafeRelease(mDxgiAdapter);

    SafeRelease(mDeviceContext1);

    if (mDeviceContext)
    {
        mDeviceContext->ClearState();
        mDeviceContext->Flush();
        SafeRelease(mDeviceContext);
    }

    SafeRelease(mDevice);
    SafeRelease(mDebug);

    if (mD3d11Module)
    {
        FreeLibrary(mD3d11Module);
        mD3d11Module = nullptr;
    }

    if (mDxgiModule)
    {
        FreeLibrary(mDxgiModule);
        mDxgiModule = nullptr;
    }

    if (mDCompModule)
    {
        FreeLibrary(mDCompModule);
        mDCompModule = nullptr;
    }

    mCompiler.release();

    mSupportsShareHandles.reset();
}

bool Renderer11::resetDevice()
{
    // recreate everything
    release();
    egl::Error result = initialize();

    if (result.isError())
    {
        ERR() << "Could not reinitialize D3D11 device: " << result;
        return false;
    }

    return true;
}

std::string Renderer11::getRendererDescription() const
{
    std::ostringstream rendererString;

    rendererString << mDescription;
    rendererString << " Direct3D11";

    rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
                   << getShaderModelSuffix();
    rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
                   << getShaderModelSuffix();

    return rendererString.str();
}

DeviceIdentifier Renderer11::getAdapterIdentifier() const
{
    // Don't use the AdapterLuid here, since that doesn't persist across reboot.
    DeviceIdentifier deviceIdentifier = {0};
    deviceIdentifier.VendorId         = mAdapterDescription.VendorId;
    deviceIdentifier.DeviceId         = mAdapterDescription.DeviceId;
    deviceIdentifier.SubSysId         = mAdapterDescription.SubSysId;
    deviceIdentifier.Revision         = mAdapterDescription.Revision;
    deviceIdentifier.FeatureLevel     = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);

    return deviceIdentifier;
}

unsigned int Renderer11::getReservedVertexUniformVectors() const
{
    // Driver uniforms are stored in a separate constant buffer
    return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
}

unsigned int Renderer11::getReservedFragmentUniformVectors() const
{
    // Driver uniforms are stored in a separate constant buffer
    return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
}

unsigned int Renderer11::getReservedVertexUniformBuffers() const
{
    // we reserve one buffer for the application uniforms, and one for driver uniforms
    return 2;
}

unsigned int Renderer11::getReservedFragmentUniformBuffers() const
{
    // we reserve one buffer for the application uniforms, and one for driver uniforms
    return 2;
}

d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
{
    if (mCreatedWithDeviceEXT)
    {
        return d3d11::GetDeviceType(mDevice);
    }

    if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
        (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
        (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
    {
        return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
    }

    if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
    {
        return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
    }

    return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
}

bool Renderer11::getShareHandleSupport() const
{
    if (mSupportsShareHandles.valid())
    {
        return mSupportsShareHandles.value();
    }

    // We only currently support share handles with BGRA surfaces, because
    // chrome needs BGRA. Once chrome fixes this, we should always support them.
    if (!getNativeExtensions().textureFormatBGRA8888)
    {
        mSupportsShareHandles = false;
        return false;
    }

    // PIX doesn't seem to support using share handles, so disable them.
    if (gl::DebugAnnotationsActive())
    {
        mSupportsShareHandles = false;
        return false;
    }

    // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
    // RGBA8 textures/swapchains.
    if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
    {
        mSupportsShareHandles = false;
        return false;
    }

    // Find out which type of D3D11 device the Renderer11 is using
    d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
    {
        mSupportsShareHandles = false;
        return false;
    }

    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
    {
        // Software/Reference/NULL devices don't support share handles
        mSupportsShareHandles = false;
        return false;
    }

    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
    {
#ifndef ANGLE_ENABLE_WINDOWS_STORE
        if (!IsWindows8OrGreater())
        {
            // WARP on Windows 7 doesn't support shared handles
            mSupportsShareHandles = false;
            return false;
        }
#endif  // ANGLE_ENABLE_WINDOWS_STORE

        // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
        // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
        //       to prevent them trying to use a WARP share handle with an a HW device (or
        //       vice-versa)
        //       e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
        mSupportsShareHandles = true;
        return true;
    }

    ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
    mSupportsShareHandles = true;
    return true;
}

bool Renderer11::getNV12TextureSupport() const
{
    HRESULT result;
    UINT formatSupport;
    result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
    if (result == E_FAIL)
    {
        return false;
    }
    return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
}

int Renderer11::getMajorShaderModel() const
{
    switch (mRenderer11DeviceCaps.featureLevel)
    {
        case D3D_FEATURE_LEVEL_11_0:
            return D3D11_SHADER_MAJOR_VERSION;  // 5
        case D3D_FEATURE_LEVEL_10_1:
            return D3D10_1_SHADER_MAJOR_VERSION;  // 4
        case D3D_FEATURE_LEVEL_10_0:
            return D3D10_SHADER_MAJOR_VERSION;  // 4
        case D3D_FEATURE_LEVEL_9_3:
            return D3D10_SHADER_MAJOR_VERSION;  // 4
        default:
            UNREACHABLE();
            return 0;
    }
}

int Renderer11::getMinorShaderModel() const
{
    switch (mRenderer11DeviceCaps.featureLevel)
    {
        case D3D_FEATURE_LEVEL_11_0:
            return D3D11_SHADER_MINOR_VERSION;  // 0
        case D3D_FEATURE_LEVEL_10_1:
            return D3D10_1_SHADER_MINOR_VERSION;  // 1
        case D3D_FEATURE_LEVEL_10_0:
            return D3D10_SHADER_MINOR_VERSION;  // 0
        case D3D_FEATURE_LEVEL_9_3:
            return D3D10_SHADER_MINOR_VERSION;  // 0
        default:
            UNREACHABLE();
            return 0;
    }
}

std::string Renderer11::getShaderModelSuffix() const
{
    switch (mRenderer11DeviceCaps.featureLevel)
    {
        case D3D_FEATURE_LEVEL_11_0:
            return "";
        case D3D_FEATURE_LEVEL_10_1:
            return "";
        case D3D_FEATURE_LEVEL_10_0:
            return "";
        case D3D_FEATURE_LEVEL_9_3:
            return "_level_9_3";
        default:
            UNREACHABLE();
            return "";
    }
}

const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const
{
    if (!mWorkaroundsInitialized)
    {
        mWorkarounds            = generateWorkarounds();
        mWorkaroundsInitialized = true;
    }

    return mWorkarounds;
}

gl::Error Renderer11::copyImageInternal(const gl::Framebuffer *framebuffer,
                                        const gl::Rectangle &sourceRect,
                                        GLenum destFormat,
                                        const gl::Offset &destOffset,
                                        RenderTargetD3D *destRenderTarget)
{
    const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
    ASSERT(colorAttachment);

    RenderTarget11 *sourceRenderTarget = nullptr;
    ANGLE_TRY(colorAttachment->getRenderTarget(&sourceRenderTarget));
    ASSERT(sourceRenderTarget);

    ID3D11ShaderResourceView *source = sourceRenderTarget->getBlitShaderResourceView();
    ASSERT(source);

    const d3d11::RenderTargetView &dest =
        GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
    ASSERT(dest.valid());

    gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
    gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);

    const bool invertSource = UsePresentPathFast(this, colorAttachment);
    if (invertSource)
    {
        sourceArea.y      = sourceSize.height - sourceRect.y;
        sourceArea.height = -sourceArea.height;
    }

    gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
    gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);

    // Use nearest filtering because source and destination are the same size for the direct copy.
    // Convert to the unsized format before calling copyTexture.
    ANGLE_TRY(mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, nullptr,
                                 gl::GetUnsizedFormat(destFormat), GL_NEAREST, false, false,
                                 false));

    return gl::NoError();
}

gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer,
                                  const gl::Rectangle &sourceRect,
                                  GLenum destFormat,
                                  const gl::Offset &destOffset,
                                  TextureStorage *storage,
                                  GLint level)
{
    TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
    ASSERT(storage11);

    gl::ImageIndex index              = gl::ImageIndex::Make2D(level);
    RenderTargetD3D *destRenderTarget = nullptr;
    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
    ASSERT(destRenderTarget);

    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));

    storage11->markLevelDirty(level);

    return gl::NoError();
}

gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer,
                                    const gl::Rectangle &sourceRect,
                                    GLenum destFormat,
                                    const gl::Offset &destOffset,
                                    TextureStorage *storage,
                                    GLenum target,
                                    GLint level)
{
    TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
    ASSERT(storage11);

    gl::ImageIndex index              = gl::ImageIndex::MakeCube(target, level);
    RenderTargetD3D *destRenderTarget = nullptr;
    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
    ASSERT(destRenderTarget);

    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));

    storage11->markLevelDirty(level);

    return gl::NoError();
}

gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer,
                                  const gl::Rectangle &sourceRect,
                                  GLenum destFormat,
                                  const gl::Offset &destOffset,
                                  TextureStorage *storage,
                                  GLint level)
{
    TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
    ASSERT(storage11);

    gl::ImageIndex index              = gl::ImageIndex::Make3D(level, destOffset.z);
    RenderTargetD3D *destRenderTarget = nullptr;
    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
    ASSERT(destRenderTarget);

    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));

    storage11->markLevelDirty(level);

    return gl::NoError();
}

gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer,
                                       const gl::Rectangle &sourceRect,
                                       GLenum destFormat,
                                       const gl::Offset &destOffset,
                                       TextureStorage *storage,
                                       GLint level)
{
    TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
    ASSERT(storage11);

    gl::ImageIndex index              = gl::ImageIndex::Make2DArray(level, destOffset.z);
    RenderTargetD3D *destRenderTarget = nullptr;
    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
    ASSERT(destRenderTarget);

    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
    storage11->markLevelDirty(level);

    return gl::NoError();
}

gl::Error Renderer11::copyTexture(const gl::Texture *source,
                                  GLint sourceLevel,
                                  const gl::Rectangle &sourceRect,
                                  GLenum destFormat,
                                  const gl::Offset &destOffset,
                                  TextureStorage *storage,
                                  GLenum destTarget,
                                  GLint destLevel,
                                  bool unpackFlipY,
                                  bool unpackPremultiplyAlpha,
                                  bool unpackUnmultiplyAlpha)
{
    const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);

    TextureStorage *sourceStorage = nullptr;
    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));

    ASSERT(destTarget == GL_TEXTURE_2D);
    TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
    ASSERT(sourceStorage11);

    TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
    ASSERT(destStorage11);

    // Check for fast path where a CopySubresourceRegion can be used.
    if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
        sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
    {
        ID3D11Resource *sourceResource = nullptr;
        ANGLE_TRY(sourceStorage11->getResource(&sourceResource));

        gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
        UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);

        ID3D11Resource *destResource = nullptr;
        ANGLE_TRY(destStorage11->getResource(&destResource));

        gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
        UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);

        D3D11_BOX sourceBox{
            static_cast<UINT>(sourceRect.x),
            static_cast<UINT>(sourceRect.y),
            0u,
            static_cast<UINT>(sourceRect.x + sourceRect.width),
            static_cast<UINT>(sourceRect.y + sourceRect.height),
            1u,
        };

        mDeviceContext->CopySubresourceRegion(destResource, destSubresource, destOffset.x,
                                              destOffset.y, destOffset.z, sourceResource,
                                              sourceSubresource, &sourceBox);
    }
    else
    {
        ID3D11ShaderResourceView *sourceSRV = nullptr;
        ANGLE_TRY(sourceStorage11->getSRVLevels(sourceLevel, sourceLevel, &sourceSRV));

        gl::ImageIndex destIndex             = gl::ImageIndex::Make2D(destLevel);
        RenderTargetD3D *destRenderTargetD3D = nullptr;
        ANGLE_TRY(destStorage11->getRenderTarget(destIndex, &destRenderTargetD3D));

        RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);

        const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
        ASSERT(destRTV.valid());

        gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
        gl::Extents sourceSize(
            static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
            static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
        if (unpackFlipY)
        {
            sourceArea.y      = sourceSize.height - sourceRect.y;
            sourceArea.height = -sourceArea.height;
        }

        gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
        gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);

        // Use nearest filtering because source and destination are the same size for the direct
        // copy
        ANGLE_TRY(mBlit->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
                                     nullptr, destFormat, GL_NEAREST, false, unpackPremultiplyAlpha,
                                     unpackUnmultiplyAlpha));
    }

    destStorage11->markLevelDirty(destLevel);

    return gl::NoError();
}

gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source,
                                            GLint sourceLevel,
                                            TextureStorage *storage,
                                            GLint destLevel)
{
    TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
    ASSERT(destStorage11);

    ID3D11Resource *destResource = nullptr;
    ANGLE_TRY(destStorage11->getResource(&destResource));

    gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
    UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);

    TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
    ASSERT(sourceD3D);

    TextureStorage *sourceStorage = nullptr;
    ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage));

    TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
    ASSERT(sourceStorage11);

    ID3D11Resource *sourceResource = nullptr;
    ANGLE_TRY(sourceStorage11->getResource(&sourceResource));

    gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
    UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);

    mDeviceContext->CopySubresourceRegion(destResource, destSubresource, 0, 0, 0, sourceResource,
                                          sourceSubresource, nullptr);

    return gl::NoError();
}

gl::Error Renderer11::createRenderTarget(int width,
                                         int height,
                                         GLenum format,
                                         GLsizei samples,
                                         RenderTargetD3D **outRT)
{
    const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);

    const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
    GLuint supportedSamples            = textureCaps.getNearestSamples(samples);

    if (width > 0 && height > 0)
    {
        // Create texture resource
        D3D11_TEXTURE2D_DESC desc;
        desc.Width              = width;
        desc.Height             = height;
        desc.MipLevels          = 1;
        desc.ArraySize          = 1;
        desc.Format             = formatInfo.texFormat;
        desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
        desc.SampleDesc.Quality = 0;
        desc.Usage              = D3D11_USAGE_DEFAULT;
        desc.CPUAccessFlags     = 0;
        desc.MiscFlags          = 0;

        // If a rendertarget or depthstencil format exists for this texture format,
        // we'll flag it to allow binding that way. Shader resource views are a little
        // more complicated.
        bool bindRTV = false, bindDSV = false, bindSRV = false;
        bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
        bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
        bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);

        // D3D feature level 10.0 no longer allows creation of textures with both the bind SRV and
        // DSV flags when multisampled.  crbug.com/656989
        bool supportsMultisampledDepthStencilSRVs =
            mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
        bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
        if (isMultisampledDepthStencil && !supportsMultisampledDepthStencilSRVs)
        {
            bindSRV = false;
        }

        desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
                         (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
                         (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);

        // The format must be either an RTV or a DSV
        ASSERT(bindRTV != bindDSV);

        ID3D11Texture2D *texture = nullptr;
        HRESULT result           = mDevice->CreateTexture2D(&desc, nullptr, &texture);
        if (FAILED(result))
        {
            ASSERT(result == E_OUTOFMEMORY);
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to create render target texture, result: 0x%X.", result);
        }

        ID3D11ShaderResourceView *srv     = nullptr;
        ID3D11ShaderResourceView *blitSRV = nullptr;
        if (bindSRV)
        {
            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
            srvDesc.Format        = formatInfo.srvFormat;
            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
                                                            : D3D11_SRV_DIMENSION_TEXTURE2DMS;
            srvDesc.Texture2D.MostDetailedMip = 0;
            srvDesc.Texture2D.MipLevels       = 1;

            result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
            if (FAILED(result))
            {
                ASSERT(result == E_OUTOFMEMORY);
                SafeRelease(texture);
                return gl::Error(
                    GL_OUT_OF_MEMORY,
                    "Failed to create render target shader resource view, result: 0x%X.", result);
            }

            if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
            {
                D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
                blitSRVDesc.Format        = formatInfo.blitSRVFormat;
                blitSRVDesc.ViewDimension = (supportedSamples == 0)
                                                ? D3D11_SRV_DIMENSION_TEXTURE2D
                                                : D3D11_SRV_DIMENSION_TEXTURE2DMS;
                blitSRVDesc.Texture2D.MostDetailedMip = 0;
                blitSRVDesc.Texture2D.MipLevels       = 1;

                result = mDevice->CreateShaderResourceView(texture, &blitSRVDesc, &blitSRV);
                if (FAILED(result))
                {
                    ASSERT(result == E_OUTOFMEMORY);
                    SafeRelease(texture);
                    SafeRelease(srv);
                    return gl::Error(GL_OUT_OF_MEMORY,
                                     "Failed to create render target shader resource view for "
                                     "blits, result: 0x%X.",
                                     result);
                }
            }
            else
            {
                blitSRV = srv;
                srv->AddRef();
            }
        }

        if (bindDSV)
        {
            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
            dsvDesc.Format        = formatInfo.dsvFormat;
            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
                                                            : D3D11_DSV_DIMENSION_TEXTURE2DMS;
            dsvDesc.Texture2D.MipSlice = 0;
            dsvDesc.Flags              = 0;

            ID3D11DepthStencilView *dsv = nullptr;
            result                      = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
            if (FAILED(result))
            {
                ASSERT(result == E_OUTOFMEMORY);
                SafeRelease(texture);
                SafeRelease(srv);
                SafeRelease(blitSRV);
                return gl::Error(GL_OUT_OF_MEMORY,
                                 "Failed to create render target depth stencil view, result: 0x%X.",
                                 result);
            }

            *outRT = new TextureRenderTarget11(dsv, texture, srv, format, formatInfo, width, height,
                                               1, supportedSamples);

            SafeRelease(dsv);
        }
        else if (bindRTV)
        {
            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
            rtvDesc.Format        = formatInfo.rtvFormat;
            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
                                                            : D3D11_RTV_DIMENSION_TEXTURE2DMS;
            rtvDesc.Texture2D.MipSlice = 0;

            d3d11::RenderTargetView rtv;
            gl::Error err = allocateResource(rtvDesc, texture, &rtv);
            if (err.isError())
            {
                SafeRelease(texture);
                SafeRelease(srv);
                SafeRelease(blitSRV);
                return err;
            }

            if (formatInfo.dataInitializerFunction != nullptr)
            {
                const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
                mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
            }

            *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
                                               formatInfo, width, height, 1, supportedSamples);
        }
        else
        {
            UNREACHABLE();
        }

        SafeRelease(texture);
        SafeRelease(srv);
        SafeRelease(blitSRV);
    }
    else
    {
        *outRT = new TextureRenderTarget11(
            d3d11::RenderTargetView(), nullptr, nullptr, nullptr, format,
            d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), width, height, 1, supportedSamples);
    }

    return gl::NoError();
}

gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
{
    ASSERT(source != nullptr);

    RenderTargetD3D *newRT = nullptr;
    ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
                                 source->getInternalFormat(), source->getSamples(), &newRT));

    RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
    RenderTarget11 *dest11   = GetAs<RenderTarget11>(newRT);

    mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0,
                                          0, source11->getTexture(),
                                          source11->getSubresourceIndex(), nullptr);
    *outRT = newRT;
    return gl::NoError();
}

gl::Error Renderer11::loadExecutable(const void *function,
                                     size_t length,
                                     ShaderType type,
                                     const std::vector<D3DVarying> &streamOutVaryings,
                                     bool separatedOutputBuffers,
                                     ShaderExecutableD3D **outExecutable)
{
    switch (type)
    {
        case SHADER_VERTEX:
        {
            ID3D11VertexShader *vertexShader      = nullptr;
            ID3D11GeometryShader *streamOutShader = nullptr;

            HRESULT result = mDevice->CreateVertexShader(function, length, nullptr, &vertexShader);
            ASSERT(SUCCEEDED(result));
            if (FAILED(result))
            {
                return gl::OutOfMemory() << "Failed to create vertex shader, " << result;
            }

            if (!streamOutVaryings.empty())
            {
                std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
                soDeclaration.reserve(streamOutVaryings.size());

                for (const auto &streamOutVarying : streamOutVaryings)
                {
                    D3D11_SO_DECLARATION_ENTRY entry = {0};
                    entry.Stream                     = 0;
                    entry.SemanticName               = streamOutVarying.semanticName.c_str();
                    entry.SemanticIndex              = streamOutVarying.semanticIndex;
                    entry.StartComponent             = 0;
                    entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
                    entry.OutputSlot     = static_cast<BYTE>(
                        (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
                    soDeclaration.push_back(entry);
                }

                result = mDevice->CreateGeometryShaderWithStreamOutput(
                    function, static_cast<unsigned int>(length), soDeclaration.data(),
                    static_cast<unsigned int>(soDeclaration.size()), nullptr, 0, 0, nullptr,
                    &streamOutShader);
                ASSERT(SUCCEEDED(result));
                if (FAILED(result))
                {
                    return gl::OutOfMemory() << "Failed to create steam output shader, " << result;
                }
            }

            *outExecutable =
                new ShaderExecutable11(function, length, vertexShader, streamOutShader);
        }
        break;
        case SHADER_PIXEL:
        {
            ID3D11PixelShader *pixelShader = nullptr;

            HRESULT result = mDevice->CreatePixelShader(function, length, nullptr, &pixelShader);
            ASSERT(SUCCEEDED(result));
            if (FAILED(result))
            {
                return gl::OutOfMemory() << "Failed to create pixel shader, " << result;
            }

            *outExecutable = new ShaderExecutable11(function, length, pixelShader);
        }
        break;
        case SHADER_GEOMETRY:
        {
            ID3D11GeometryShader *geometryShader = nullptr;

            HRESULT result =
                mDevice->CreateGeometryShader(function, length, nullptr, &geometryShader);
            ASSERT(SUCCEEDED(result));
            if (FAILED(result))
            {
                return gl::OutOfMemory() << "Failed to create geometry shader, " << result;
            }

            *outExecutable = new ShaderExecutable11(function, length, geometryShader);
        }
        break;
        case SHADER_COMPUTE:
        {
            ID3D11ComputeShader *computeShader = nullptr;

            HRESULT result =
                mDevice->CreateComputeShader(function, length, nullptr, &computeShader);
            ASSERT(SUCCEEDED(result));
            if (FAILED(result))
            {
                return gl::OutOfMemory() << "Failed to create compute shader, " << result;
            }

            *outExecutable = new ShaderExecutable11(function, length, computeShader);
        }
        break;
        default:
            UNREACHABLE();
            return gl::Error(GL_INVALID_OPERATION);
    }

    return gl::NoError();
}

gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
                                          const std::string &shaderHLSL,
                                          ShaderType type,
                                          const std::vector<D3DVarying> &streamOutVaryings,
                                          bool separatedOutputBuffers,
                                          const angle::CompilerWorkaroundsD3D &workarounds,
                                          ShaderExecutableD3D **outExectuable)
{
    std::stringstream profileStream;

    switch (type)
    {
        case SHADER_VERTEX:
            profileStream << "vs";
            break;
        case SHADER_PIXEL:
            profileStream << "ps";
            break;
        case SHADER_GEOMETRY:
            profileStream << "gs";
            break;
        case SHADER_COMPUTE:
            profileStream << "cs";
            break;
        default:
            UNREACHABLE();
            return gl::Error(GL_INVALID_OPERATION);
    }

    profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
                  << getShaderModelSuffix();
    std::string profile = profileStream.str();

    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;

    if (gl::DebugAnnotationsActive())
    {
#ifndef NDEBUG
        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
#endif

        flags |= D3DCOMPILE_DEBUG;
    }

    if (workarounds.enableIEEEStrictness)
        flags |= D3DCOMPILE_IEEE_STRICTNESS;

    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
    // when it would otherwise pass with alternative options.
    // Try the default flags first and if compilation fails, try some alternatives.
    std::vector<CompileConfig> configs;
    configs.push_back(CompileConfig(flags, "default"));
    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));

    if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
    {
        // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
        // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
        // Using the [unroll] directive works around this, as does this D3DCompile flag.
        configs.push_back(
            CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
    }

    D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};

    ID3DBlob *binary = nullptr;
    std::string debugInfo;
    ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary,
                                        &debugInfo));

    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
    // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
    // internal state is still OK.
    if (!binary)
    {
        *outExectuable = nullptr;
        return gl::NoError();
    }

    gl::Error error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
                                     streamOutVaryings, separatedOutputBuffers, outExectuable);

    SafeRelease(binary);
    if (error.isError())
    {
        return error;
    }

    if (!debugInfo.empty())
    {
        (*outExectuable)->appendDebugInfo(debugInfo);
    }

    return gl::NoError();
}

gl::Error Renderer11::ensureHLSLCompilerInitialized()
{
    return mCompiler.ensureInitialized();
}

UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
{
    return new UniformStorage11(this, storageSize);
}

VertexBuffer *Renderer11::createVertexBuffer()
{
    return new VertexBuffer11(this);
}

IndexBuffer *Renderer11::createIndexBuffer()
{
    return new IndexBuffer11(this);
}

StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
    egl::Stream::ConsumerType consumerType,
    const egl::AttributeMap &attribs)
{
    return new StreamProducerNV12(this);
}

bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
{
    ASSERT(getNativeExtensions().pixelBufferObject);

    const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
    const d3d11::Format &d3d11FormatInfo =
        d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);

    // sRGB formats do not work with D3D11 buffer SRVs
    if (internalFormatInfo.colorEncoding == GL_SRGB)
    {
        return false;
    }

    // We cannot support direct copies to non-color-renderable formats
    if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
    {
        return false;
    }

    // We skip all 3-channel formats since sometimes format support is missing
    if (internalFormatInfo.componentCount == 3)
    {
        return false;
    }

    // We don't support formats which we can't represent without conversion
    if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
    {
        return false;
    }

    // Buffer SRV creation for this format was not working on Windows 10.
    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
    {
        return false;
    }

    // This format is not supported as a buffer SRV.
    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
    {
        return false;
    }

    return true;
}

gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
                                              unsigned int offset,
                                              RenderTargetD3D *destRenderTarget,
                                              GLenum destinationFormat,
                                              GLenum sourcePixelsType,
                                              const gl::Box &destArea)
{
    ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
    return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat,
                                               sourcePixelsType, destArea);
}

ImageD3D *Renderer11::createImage()
{
    return new Image11(this);
}

gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
{
    Image11 *dest11 = GetAs<Image11>(dest);
    Image11 *src11  = GetAs<Image11>(src);
    return Image11::generateMipmap(dest11, src11, mRenderer11DeviceCaps);
}

gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
                                             const gl::TextureState &textureState)
{
    TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);

    ASSERT(storage11->isRenderTarget());
    ASSERT(storage11->supportsNativeMipmapFunction());

    ID3D11ShaderResourceView *srv;
    ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
                                      textureState.getEffectiveMaxLevel(), &srv));

    mDeviceContext->GenerateMips(srv);

    return gl::NoError();
}

TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
{
    SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
    return new TextureStorage11_2D(this, swapChain11);
}

TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
                                                         RenderTargetD3D *renderTargetD3D)
{
    return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
}

TextureStorage *Renderer11::createTextureStorageExternal(
    egl::Stream *stream,
    const egl::Stream::GLTextureDescription &desc)
{
    return new TextureStorage11_External(this, stream, desc);
}

TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
                                                   bool renderTarget,
                                                   GLsizei width,
                                                   GLsizei height,
                                                   int levels,
                                                   bool hintLevelZeroOnly)
{
    return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
                                   hintLevelZeroOnly);
}

TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
                                                     bool renderTarget,
                                                     int size,
                                                     int levels,
                                                     bool hintLevelZeroOnly)
{
    return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
                                     hintLevelZeroOnly);
}

TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
                                                   bool renderTarget,
                                                   GLsizei width,
                                                   GLsizei height,
                                                   GLsizei depth,
                                                   int levels)
{
    return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
                                   levels);
}

TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
                                                        bool renderTarget,
                                                        GLsizei width,
                                                        GLsizei height,
                                                        GLsizei depth,
                                                        int levels)
{
    return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
                                        levels);
}

gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
                                         const gl::Rectangle &sourceArea,
                                         GLenum format,
                                         GLenum type,
                                         GLuint outputPitch,
                                         const gl::PixelPackState &pack,
                                         uint8_t *pixelsOut)
{
    ASSERT(sourceArea.width >= 0);
    ASSERT(sourceArea.height >= 0);

    const bool invertTexture = UsePresentPathFast(this, &srcAttachment);

    RenderTargetD3D *renderTarget = nullptr;
    ANGLE_TRY(srcAttachment.getRenderTarget(&renderTarget));

    RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
    ASSERT(rt11->getTexture());

    TextureHelper11 textureHelper =
        TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet());
    unsigned int sourceSubResource = rt11->getSubresourceIndex();

    const gl::Extents &texSize = textureHelper.getExtents();

    gl::Rectangle actualArea = sourceArea;
    if (invertTexture)
    {
        actualArea.y = texSize.height - actualArea.y - actualArea.height;
    }

    // Clamp read region to the defined texture boundaries, preventing out of bounds reads
    // and reads of uninitialized data.
    gl::Rectangle safeArea;
    safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
    safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
    safeArea.width =
        gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
    safeArea.height =
        gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);

    ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
    ASSERT(safeArea.x + safeArea.width <= texSize.width);
    ASSERT(safeArea.y + safeArea.height <= texSize.height);

    if (safeArea.width == 0 || safeArea.height == 0)
    {
        // no work to do
        return gl::NoError();
    }

    gl::Extents safeSize(safeArea.width, safeArea.height, 1);
    TextureHelper11 stagingHelper;
    ANGLE_TRY_RESULT(
        CreateStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
                             StagingAccess::READ, mDevice),
        stagingHelper);

    TextureHelper11 resolvedTextureHelper;

    // "srcTexture" usually points to the source texture.
    // For 2D multisampled textures, it points to the multisampled resolve texture.
    const TextureHelper11 *srcTexture = &textureHelper;

    if (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1)
    {
        D3D11_TEXTURE2D_DESC resolveDesc;
        resolveDesc.Width              = static_cast<UINT>(texSize.width);
        resolveDesc.Height             = static_cast<UINT>(texSize.height);
        resolveDesc.MipLevels          = 1;
        resolveDesc.ArraySize          = 1;
        resolveDesc.Format             = textureHelper.getFormat();
        resolveDesc.SampleDesc.Count   = 1;
        resolveDesc.SampleDesc.Quality = 0;
        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
        resolveDesc.BindFlags          = 0;
        resolveDesc.CPUAccessFlags     = 0;
        resolveDesc.MiscFlags          = 0;

        ID3D11Texture2D *resolveTex2D = nullptr;
        HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Renderer11::readTextureData failed to create internal resolve "
                             "texture for ReadPixels, HRESULT: 0x%X.",
                             result);
        }

        mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(),
                                           sourceSubResource, textureHelper.getFormat());
        resolvedTextureHelper =
            TextureHelper11::MakeAndReference(resolveTex2D, textureHelper.getFormatSet());

        sourceSubResource = 0;
        srcTexture        = &resolvedTextureHelper;
    }

    D3D11_BOX srcBox;
    srcBox.left   = static_cast<UINT>(safeArea.x);
    srcBox.right  = static_cast<UINT>(safeArea.x + safeArea.width);
    srcBox.top    = static_cast<UINT>(safeArea.y);
    srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);

    // Select the correct layer from a 3D attachment
    srcBox.front = 0;
    if (textureHelper.getTextureType() == GL_TEXTURE_3D)
    {
        srcBox.front = static_cast<UINT>(srcAttachment.layer());
    }
    srcBox.back = srcBox.front + 1;

    mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0,
                                          srcTexture->getResource(), sourceSubResource, &srcBox);

    if (!invertTexture)
    {
        PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
        return packPixels(stagingHelper, packParams, pixelsOut);
    }

    gl::PixelPackState invertTexturePack;

    // Create a new PixelPackState with reversed row order. Note that we can't just assign
    // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
    // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
    // pixelBuffer.set() twice, which performs the addRef/release correctly
    invertTexturePack.alignment = pack.alignment;
    invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get());
    invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;

    PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0);
    gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
    invertTexturePack.pixelBuffer.set(nullptr);
    ANGLE_TRY(error);
    return gl::NoError();
}

gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
                                 const PackPixelsParams &params,
                                 uint8_t *pixelsOut)
{
    ID3D11Resource *readResource = textureHelper.getResource();

    D3D11_MAPPED_SUBRESOURCE mapping;
    HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
    if (FAILED(hr))
    {
        ASSERT(hr == E_OUTOFMEMORY);
        return gl::Error(GL_OUT_OF_MEMORY,
                         "Failed to map internal texture for reading, result: 0x%X.", hr);
    }

    uint8_t *source = static_cast<uint8_t *>(mapping.pData);
    int inputPitch  = static_cast<int>(mapping.RowPitch);

    const auto &formatInfo = textureHelper.getFormatSet();
    ASSERT(formatInfo.format().glInternalFormat != GL_NONE);

    PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);

    mDeviceContext->Unmap(readResource, 0);

    return gl::NoError();
}

gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
                                           const gl::Rectangle &drawRectIn,
                                           RenderTargetD3D *readRenderTarget,
                                           RenderTargetD3D *drawRenderTarget,
                                           GLenum filter,
                                           const gl::Rectangle *scissor,
                                           bool colorBlit,
                                           bool depthBlit,
                                           bool stencilBlit)
{
    // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
    // it should never be the case that both color and depth/stencil need to be blitted at
    // at the same time.
    ASSERT(colorBlit != (depthBlit || stencilBlit));

    RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
    if (!drawRenderTarget11)
    {
        return gl::OutOfMemory()
               << "Failed to retrieve the internal draw render target from the draw framebuffer.";
    }

    TextureHelper11 drawTexture = TextureHelper11::MakeAndReference(
        drawRenderTarget11->getTexture(), drawRenderTarget11->getFormatSet());
    unsigned int drawSubresource    = drawRenderTarget11->getSubresourceIndex();
    ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView();

    RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
    if (!readRenderTarget11)
    {
        return gl::OutOfMemory()
               << "Failed to retrieve the internal read render target from the read framebuffer.";
    }

    TextureHelper11 readTexture;
    unsigned int readSubresource      = 0;
    ID3D11ShaderResourceView *readSRV = nullptr;

    if (readRenderTarget->getSamples() > 1)
    {
        ANGLE_TRY_RESULT(resolveMultisampledTexture(readRenderTarget11, depthBlit, stencilBlit),
                         readTexture);

        if (!stencilBlit)
        {
            const auto &readFormatSet = readTexture.getFormatSet();

            D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
            viewDesc.Format                    = readFormatSet.srvFormat;
            viewDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
            viewDesc.Texture2D.MipLevels       = 1;
            viewDesc.Texture2D.MostDetailedMip = 0;

            HRESULT hresult =
                mDevice->CreateShaderResourceView(readTexture.getResource(), &viewDesc, &readSRV);
            if (FAILED(hresult))
            {
                return gl::OutOfMemory()
                       << "Renderer11::blitRenderbufferRect: Failed to create temporary SRV, "
                       << hresult;
            }
        }
    }
    else
    {
        ASSERT(readRenderTarget11);
        readTexture = TextureHelper11::MakeAndReference(readRenderTarget11->getTexture(),
                                                        readRenderTarget11->getFormatSet());
        readSubresource = readRenderTarget11->getSubresourceIndex();
        readSRV         = readRenderTarget11->getBlitShaderResourceView();
        if (readSRV == nullptr)
        {
            ASSERT(depthBlit || stencilBlit);
            readSRV = readRenderTarget11->getShaderResourceView();
        }
        ASSERT(readSRV);
        readSRV->AddRef();
    }

    // Stencil blits don't use shaders.
    ASSERT(readSRV || stencilBlit);

    const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
    const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);

    // From the spec:
    // "The actual region taken from the read framebuffer is limited to the intersection of the
    // source buffers being transferred, which may include the color buffer selected by the read
    // buffer, the depth buffer, and / or the stencil buffer depending on mask."
    // This means negative x and y are out of bounds, and not to be read from. We handle this here
    // by internally scaling the read and draw rectangles.
    gl::Rectangle readRect = readRectIn;
    gl::Rectangle drawRect = drawRectIn;
    auto readToDrawX       = [&drawRectIn, &readRectIn](int readOffset) {
        double readToDrawScale =
            static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
        return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
    };
    if (readRect.x < 0)
    {
        int readOffset = -readRect.x;
        readRect.x += readOffset;
        readRect.width -= readOffset;

        int drawOffset = readToDrawX(readOffset);
        drawRect.x += drawOffset;
        drawRect.width -= drawOffset;
    }

    auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
        double readToDrawScale =
            static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
        return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
    };
    if (readRect.y < 0)
    {
        int readOffset = -readRect.y;
        readRect.y += readOffset;
        readRect.height -= readOffset;

        int drawOffset = readToDrawY(readOffset);
        drawRect.y += drawOffset;
        drawRect.height -= drawOffset;
    }

    if (readRect.x1() < 0)
    {
        int readOffset = -readRect.x1();
        readRect.width += readOffset;

        int drawOffset = readToDrawX(readOffset);
        drawRect.width += drawOffset;
    }

    if (readRect.y1() < 0)
    {
        int readOffset = -readRect.y1();
        readRect.height += readOffset;

        int drawOffset = readToDrawY(readOffset);
        drawRect.height += drawOffset;
    }

    bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);

    const auto &destFormatInfo =
        gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
    const auto &srcFormatInfo =
        gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
    const auto &formatSet    = drawRenderTarget11->getFormatSet();
    const auto &nativeFormat = formatSet.format();

    // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
    // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.

    gl::Color<bool> colorMask;
    colorMask.red =
        (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
    colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
                      (nativeFormat.greenBits > 0);
    colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
                     (nativeFormat.blueBits > 0);
    colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
                      (nativeFormat.alphaBits > 0);

    // We only currently support masking off the alpha channel.
    bool colorMaskingNeeded = colorMask.alpha;
    ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);

    bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
                           readRect.width == readSize.width && readRect.y == 0 &&
                           readRect.height == readSize.height && drawRect.x == 0 &&
                           drawRect.width == drawSize.width && drawRect.y == 0 &&
                           drawRect.height == drawSize.height;

    bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;

    bool flipRequired =
        readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;

    bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
                       readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
                       drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
                       drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;

    bool partialDSBlit =
        (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);

    if (readRenderTarget11->getFormatSet().formatID ==
            drawRenderTarget11->getFormatSet().formatID &&
        !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
        !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
    {
        UINT dstX = drawRect.x;
        UINT dstY = drawRect.y;

        D3D11_BOX readBox;
        readBox.left   = readRect.x;
        readBox.right  = readRect.x + readRect.width;
        readBox.top    = readRect.y;
        readBox.bottom = readRect.y + readRect.height;
        readBox.front  = 0;
        readBox.back   = 1;

        if (scissorNeeded)
        {
            // drawRect is guaranteed to have positive width and height because stretchRequired is
            // false.
            ASSERT(drawRect.width >= 0 || drawRect.height >= 0);

            if (drawRect.x < scissor->x)
            {
                dstX = scissor->x;
                readBox.left += (scissor->x - drawRect.x);
            }
            if (drawRect.y < scissor->y)
            {
                dstY = scissor->y;
                readBox.top += (scissor->y - drawRect.y);
            }
            if (drawRect.x + drawRect.width > scissor->x + scissor->width)
            {
                readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
            }
            if (drawRect.y + drawRect.height > scissor->y + scissor->height)
            {
                readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
            }
        }

        // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
        // We also require complete framebuffer copies for depth-stencil blit.
        D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox;

        mDeviceContext->CopySubresourceRegion(drawTexture.getResource(), drawSubresource, dstX,
                                              dstY, 0, readTexture.getResource(), readSubresource,
                                              pSrcBox);
    }
    else
    {
        gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
        gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);

        if (depthBlit && stencilBlit)
        {
            ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
                                              drawTexture, drawSubresource, drawArea, drawSize,
                                              scissor));
        }
        else if (depthBlit)
        {
            ASSERT(readSRV);
            ANGLE_TRY(mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
                                       scissor));
        }
        else if (stencilBlit)
        {
            ANGLE_TRY(mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
                                         drawTexture, drawSubresource, drawArea, drawSize,
                                         scissor));
        }
        else
        {
            const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();

            // We don't currently support masking off any other channel than alpha
            bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
            ASSERT(readSRV);
            ANGLE_TRY(mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
                                         scissor, destFormatInfo.format, filter, maskOffAlpha,
                                         false, false));
        }
    }

    SafeRelease(readSRV);

    return gl::NoError();
}

bool Renderer11::isES3Capable() const
{
    return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2);
};

void Renderer11::onSwap()
{
    // Send histogram updates every half hour
    const double kHistogramUpdateInterval = 30 * 60;

    auto *platform                   = ANGLEPlatformCurrent();
    const double currentTime         = platform->monotonicallyIncreasingTime(platform);
    const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;

    if (timeSinceLastUpdate > kHistogramUpdateInterval)
    {
        updateHistograms();
        mLastHistogramUpdateTime = currentTime;
    }
}

void Renderer11::updateHistograms()
{
    // Update the buffer CPU memory histogram
    {
        size_t sizeSum = 0;
        for (auto &buffer : mAliveBuffers)
        {
            sizeSum += buffer->getTotalCPUBufferMemoryBytes();
        }
        const int kOneMegaByte = 1024 * 1024;
        ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
                                  static_cast<int>(sizeSum) / kOneMegaByte);
    }
}

void Renderer11::onBufferCreate(const Buffer11 *created)
{
    mAliveBuffers.insert(created);
}

void Renderer11::onBufferDelete(const Buffer11 *deleted)
{
    mAliveBuffers.erase(deleted);
}

gl::ErrorOrResult<TextureHelper11>
Renderer11::resolveMultisampledTexture(RenderTarget11 *renderTarget, bool depth, bool stencil)
{
    if (depth && !stencil)
    {
        return mBlit->resolveDepth(renderTarget);
    }

    if (stencil)
    {
        return mBlit->resolveStencil(renderTarget, depth);
    }

    const auto &formatSet = renderTarget->getFormatSet();

    ASSERT(renderTarget->getSamples() > 1);

    D3D11_TEXTURE2D_DESC resolveDesc;
    resolveDesc.Width              = renderTarget->getWidth();
    resolveDesc.Height             = renderTarget->getHeight();
    resolveDesc.MipLevels          = 1;
    resolveDesc.ArraySize          = 1;
    resolveDesc.Format             = formatSet.texFormat;
    resolveDesc.SampleDesc.Count   = 1;
    resolveDesc.SampleDesc.Quality = 0;
    resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
    resolveDesc.BindFlags          = D3D11_BIND_SHADER_RESOURCE;
    resolveDesc.CPUAccessFlags     = 0;
    resolveDesc.MiscFlags          = 0;

    ID3D11Texture2D *resolveTexture = nullptr;
    HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTexture);
    if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY,
                         "Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
    }

    mDeviceContext->ResolveSubresource(resolveTexture, 0, renderTarget->getTexture(),
                                       renderTarget->getSubresourceIndex(), formatSet.texFormat);
    return TextureHelper11::MakeAndPossess2D(resolveTexture, renderTarget->getFormatSet());
}

bool Renderer11::getLUID(LUID *adapterLuid) const
{
    adapterLuid->HighPart = 0;
    adapterLuid->LowPart  = 0;

    if (!mDxgiAdapter)
    {
        return false;
    }

    DXGI_ADAPTER_DESC adapterDesc;
    if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
    {
        return false;
    }

    *adapterLuid = adapterDesc.AdapterLuid;
    return true;
}

VertexConversionType Renderer11::getVertexConversionType(
    gl::VertexFormatType vertexFormatType) const
{
    return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
        .conversionType;
}

GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
{
    const auto &format =
        d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
    return d3d11::GetComponentType(format.nativeFormat);
}

gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
    const gl::VertexAttribute &attrib,
    const gl::VertexBinding &binding,
    GLsizei count,
    GLsizei instances) const
{
    if (!attrib.enabled)
    {
        return 16u;
    }

    unsigned int elementCount = 0;
    if (instances == 0 || binding.divisor == 0)
    {
        elementCount = count;
    }
    else
    {
        // Round up to divisor, if possible
        elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), binding.divisor);
    }

    gl::VertexFormatType formatType      = gl::GetVertexFormatType(attrib);
    const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
    const d3d11::VertexFormat &vertexFormatInfo =
        d3d11::GetVertexFormatInfo(formatType, featureLevel);
    const d3d11::DXGIFormatSize &dxgiFormatInfo =
        d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
    unsigned int elementSize = dxgiFormatInfo.pixelBytes;
    if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
    {
        return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
    }

    return elementSize * elementCount;
}

void Renderer11::generateCaps(gl::Caps *outCaps,
                              gl::TextureCapsMap *outTextureCaps,
                              gl::Extensions *outExtensions,
                              gl::Limitations *outLimitations) const
{
    d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
                           outExtensions, outLimitations);
}

angle::WorkaroundsD3D Renderer11::generateWorkarounds() const
{
    return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
}

gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
{
    return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
}

egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
{
    if (mEGLDevice == nullptr)
    {
        ASSERT(mDevice != nullptr);
        mEGLDevice       = new DeviceD3D();
        egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
                                                  EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);

        if (error.isError())
        {
            SafeDelete(mEGLDevice);
            return error;
        }
    }

    *device = static_cast<DeviceImpl *>(mEGLDevice);
    return egl::Error(EGL_SUCCESS);
}

ContextImpl *Renderer11::createContext(const gl::ContextState &state)
{
    return new Context11(state, this);
}

gl::Error Renderer11::genericDrawElements(Context11 *context,
                                          GLenum mode,
                                          GLsizei count,
                                          GLenum type,
                                          const void *indices,
                                          GLsizei instances,
                                          const gl::IndexRange &indexRange)
{
    const auto &data     = context->getContextState();
    const auto &glState  = data.getState();
    gl::Program *program = glState.getProgram();
    ASSERT(program != nullptr);
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    bool usesPointSize     = programD3D->usesPointSize();

    programD3D->updateSamplerMapping();

    ANGLE_TRY(generateSwizzles(data));

    if (!applyPrimitiveType(mode, count, usesPointSize))
    {
        return gl::NoError();
    }

    ANGLE_TRY(updateState(context, mode));

    TranslatedIndexData indexInfo;
    indexInfo.indexRange = indexRange;

    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));

    applyTransformFeedbackBuffers(data);
    // Transform feedback is not allowed for DrawElements, this error should have been caught at the
    // API validation layer.
    ASSERT(!glState.isTransformFeedbackActiveUnpaused());

    size_t vertexCount = indexInfo.indexRange.vertexCount();
    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));
    ANGLE_TRY(applyTextures(context, data));
    ANGLE_TRY(applyShaders(data, mode));
    ANGLE_TRY(programD3D->applyUniformBuffers(data));

    if (!skipDraw(data, mode))
    {
        ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances));
    }

    return gl::NoError();
}

gl::Error Renderer11::genericDrawArrays(Context11 *context,
                                        GLenum mode,
                                        GLint first,
                                        GLsizei count,
                                        GLsizei instances)
{
    const auto &data     = context->getContextState();
    const auto &glState  = data.getState();
    gl::Program *program = glState.getProgram();
    ASSERT(program != nullptr);
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    bool usesPointSize     = programD3D->usesPointSize();

    programD3D->updateSamplerMapping();

    ANGLE_TRY(generateSwizzles(data));
    if (!applyPrimitiveType(mode, count, usesPointSize))
    {
        return gl::NoError();
    }

    ANGLE_TRY(updateState(context, mode));
    ANGLE_TRY(applyTransformFeedbackBuffers(data));
    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
    ANGLE_TRY(applyTextures(context, data));
    ANGLE_TRY(applyShaders(data, mode));
    ANGLE_TRY(programD3D->applyUniformBuffers(data));

    if (!skipDraw(data, mode))
    {
        ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));

        if (glState.isTransformFeedbackActiveUnpaused())
        {
            ANGLE_TRY(markTransformFeedbackUsage(data));
        }
    }

    return gl::NoError();
}

gl::Error Renderer11::genericDrawIndirect(Context11 *context,
                                          GLenum mode,
                                          GLenum type,
                                          const void *indirect)
{
    const auto &data     = context->getContextState();
    const auto &glState  = data.getState();
    gl::Program *program = glState.getProgram();
    ASSERT(program != nullptr);
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    bool usesPointSize     = programD3D->usesPointSize();
    programD3D->updateSamplerMapping();

    ANGLE_TRY(generateSwizzles(data));
    applyPrimitiveType(mode, 0, usesPointSize);
    ANGLE_TRY(updateState(context, mode));
    ANGLE_TRY(applyTransformFeedbackBuffers(data));
    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
    ANGLE_TRY(applyTextures(context, data));
    ANGLE_TRY(applyShaders(data, mode));
    ANGLE_TRY(programD3D->applyUniformBuffers(data));

    if (type == GL_NONE)
    {
        ANGLE_TRY(drawArraysIndirectImpl(data, mode, indirect));
    }
    else
    {
        ANGLE_TRY(drawElementsIndirectImpl(data, mode, type, indirect));
    }

    return gl::NoError();
}

FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
{
    return new Framebuffer11(state, this);
}

gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut)
{
    if (!mScratchMemoryBuffer.get(requestedSize, bufferOut))
    {
        return gl::OutOfMemory() << "Failed to allocate internal buffer.";
    }
    return gl::NoError();
}

gl::Version Renderer11::getMaxSupportedESVersion() const
{
    return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel);
}

gl::DebugAnnotator *Renderer11::getAnnotator()
{
    return mAnnotator;
}

gl::Error Renderer11::applyComputeShader(const gl::ContextState &data)
{
    ANGLE_TRY(ensureHLSLCompilerInitialized());

    const auto &glState    = data.getState();
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());

    ShaderExecutableD3D *computeExe = nullptr;
    ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));

    ASSERT(computeExe != nullptr);
    ID3D11ComputeShader *computeShader = GetAs<ShaderExecutable11>(computeExe)->getComputeShader();

    bool dirtyUniforms = false;

    if (reinterpret_cast<uintptr_t>(computeShader) != mAppliedComputeShader)
    {
        mDeviceContext->CSSetShader(computeShader, nullptr, 0);
        mAppliedComputeShader = reinterpret_cast<uintptr_t>(computeShader);
        dirtyUniforms         = true;
    }

    if (dirtyUniforms)
    {
        programD3D->dirtyAllUniforms();
    }

    return programD3D->applyComputeUniforms();
}

gl::Error Renderer11::dispatchCompute(Context11 *context,
                                      GLuint numGroupsX,
                                      GLuint numGroupsY,
                                      GLuint numGroupsZ)
{
    const auto &data     = context->getContextState();
    gl::Program *program = data.getState().getProgram();
    ASSERT(program != nullptr);
    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);

    mStateManager.setComputeConstants(numGroupsX, numGroupsY, numGroupsZ);

    programD3D->updateSamplerMapping();

    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_COMPUTE));
    ANGLE_TRY(applyTextures(context, data));
    ANGLE_TRY(applyComputeShader(data));
    // TODO(Xinghua): applyUniformBuffers for compute shader.
    mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);

    return gl::NoError();
}

gl::Error Renderer11::applyComputeUniforms(const ProgramD3D &programD3D,
                                           const std::vector<D3DUniform *> &uniformArray)
{
    unsigned int totalRegisterCountCS = 0;
    bool computeUniformsDirty         = false;

    for (const D3DUniform *uniform : uniformArray)
    {
        ASSERT(uniform->isReferencedByComputeShader());

        // TODO(Xinghua): add isImage() and isAtomicCounter().
        if (uniform->isSampler())
        {
            totalRegisterCountCS += uniform->registerCount;
            computeUniformsDirty = (computeUniformsDirty || uniform->dirty);
        }
    }

    const UniformStorage11 *computeUniformStorage =
        GetAs<UniformStorage11>(&programD3D.getComputeUniformStorage());
    ASSERT(computeUniformStorage);

    ID3D11Buffer *computeConstantBuffer = computeUniformStorage->getConstantBuffer();

    if (totalRegisterCountCS > 0 && computeUniformsDirty)
    {
        D3D11_MAPPED_SUBRESOURCE map = {0};
        HRESULT result =
            mDeviceContext->Map(computeConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
        ASSERT(SUCCEEDED(result));
        auto *mapCS = static_cast<float(*)[4]>(map.pData);

        ASSERT(mapCS);
        for (const D3DUniform *uniform : uniformArray)
        {
            ASSERT(uniform->isReferencedByComputeShader());

            if (uniform->isSampler())
            {
                continue;
            }

            unsigned int componentCount = (4 - uniform->registerCount);
            memcpy(&mapCS[uniform->csRegisterIndex][uniform->registerElement], uniform->data,
                   uniform->registerCount * sizeof(float) * componentCount);
        }

        mDeviceContext->Unmap(computeConstantBuffer, 0);
    }

    if (mCurrentComputeConstantBuffer != computeConstantBuffer)
    {
        mDeviceContext->CSSetConstantBuffers(
            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &computeConstantBuffer);
        mCurrentComputeConstantBuffer = computeConstantBuffer;
    }

    if (!mDriverConstantBufferCS)
    {
        D3D11_BUFFER_DESC constantBufferDescription = {0};
        d3d11::InitConstantBufferDesc(
            &constantBufferDescription,
            sizeof(dx_ComputeConstants11) + mSamplerMetadataCS.sizeBytes());
        HRESULT result =
            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferCS);
        ASSERT(SUCCEEDED(result));
        if (FAILED(result))
        {
            return gl::OutOfMemory()
                   << "Failed to create compute shader constant buffer, " << result;
        }
        mDeviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
                                             &mDriverConstantBufferCS);
    }

    const dx_ComputeConstants11 &computeConstants = mStateManager.getComputeConstants();
    size_t samplerMetadataReferencedBytesCS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
                                              programD3D.getUsedSamplerRange(gl::SAMPLER_COMPUTE);
    applyDriverConstantsIfNeeded(&mAppliedComputeConstants, computeConstants, &mSamplerMetadataCS,
                                 samplerMetadataReferencedBytesCS, mDriverConstantBufferCS);

    return gl::NoError();
}

}  // namespace rx
