tor-browser

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

Renderer11.cpp (174895B)


      1 //
      2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
      8 
      9 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     10 
     11 #include <EGL/eglext.h>
     12 #include <versionhelpers.h>
     13 #include <sstream>
     14 
     15 #include "anglebase/no_destructor.h"
     16 #include "common/tls.h"
     17 #include "common/utilities.h"
     18 #include "libANGLE/Buffer.h"
     19 #include "libANGLE/Context.h"
     20 #include "libANGLE/Display.h"
     21 #include "libANGLE/Framebuffer.h"
     22 #include "libANGLE/FramebufferAttachment.h"
     23 #include "libANGLE/Program.h"
     24 #include "libANGLE/State.h"
     25 #include "libANGLE/Surface.h"
     26 #include "libANGLE/formatutils.h"
     27 #include "libANGLE/histogram_macros.h"
     28 #include "libANGLE/renderer/d3d/CompilerD3D.h"
     29 #include "libANGLE/renderer/d3d/DeviceD3D.h"
     30 #include "libANGLE/renderer/d3d/DisplayD3D.h"
     31 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
     32 #include "libANGLE/renderer/d3d/IndexDataManager.h"
     33 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
     34 #include "libANGLE/renderer/d3d/ShaderD3D.h"
     35 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
     36 #include "libANGLE/renderer/d3d/TextureD3D.h"
     37 #include "libANGLE/renderer/d3d/VertexDataManager.h"
     38 #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
     39 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
     40 #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
     41 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     42 #include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
     43 #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
     44 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
     45 #include "libANGLE/renderer/d3d/d3d11/Image11.h"
     46 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
     47 #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
     48 #include "libANGLE/renderer/d3d/d3d11/Program11.h"
     49 #include "libANGLE/renderer/d3d/d3d11/Query11.h"
     50 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
     51 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
     52 #include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h"
     53 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
     54 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
     55 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
     56 #include "libANGLE/renderer/d3d/d3d11/Trim11.h"
     57 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
     58 #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
     59 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
     60 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
     61 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
     62 #include "libANGLE/renderer/d3d/driver_utils_d3d.h"
     63 #include "libANGLE/renderer/driver_utils.h"
     64 #include "libANGLE/renderer/dxgi_support_table.h"
     65 #include "libANGLE/renderer/renderer_utils.h"
     66 #include "libANGLE/trace.h"
     67 
     68 #ifdef ANGLE_ENABLE_WINDOWS_UWP
     69 #    include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
     70 #else
     71 #    include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
     72 #endif
     73 
     74 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
     75 #    include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
     76 #endif
     77 
     78 // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
     79 // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
     80 #ifndef ANGLE_SKIP_DXGI_1_2_CHECK
     81 #    define ANGLE_SKIP_DXGI_1_2_CHECK 0
     82 #endif
     83 
     84 namespace rx
     85 {
     86 
     87 namespace
     88 {
     89 
     90 enum
     91 {
     92    MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
     93 };
     94 
     95 enum ANGLEFeatureLevel
     96 {
     97    ANGLE_FEATURE_LEVEL_INVALID,
     98    ANGLE_FEATURE_LEVEL_9_3,
     99    ANGLE_FEATURE_LEVEL_10_0,
    100    ANGLE_FEATURE_LEVEL_10_1,
    101    ANGLE_FEATURE_LEVEL_11_0,
    102    ANGLE_FEATURE_LEVEL_11_1,
    103    NUM_ANGLE_FEATURE_LEVELS
    104 };
    105 
    106 ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
    107 {
    108    switch (d3dFeatureLevel)
    109    {
    110        case D3D_FEATURE_LEVEL_9_3:
    111            return ANGLE_FEATURE_LEVEL_9_3;
    112        case D3D_FEATURE_LEVEL_10_0:
    113            return ANGLE_FEATURE_LEVEL_10_0;
    114        case D3D_FEATURE_LEVEL_10_1:
    115            return ANGLE_FEATURE_LEVEL_10_1;
    116        case D3D_FEATURE_LEVEL_11_0:
    117            return ANGLE_FEATURE_LEVEL_11_0;
    118        case D3D_FEATURE_LEVEL_11_1:
    119            return ANGLE_FEATURE_LEVEL_11_1;
    120        default:
    121            return ANGLE_FEATURE_LEVEL_INVALID;
    122    }
    123 }
    124 
    125 void SetLineLoopIndices(GLuint *dest, size_t count)
    126 {
    127    for (size_t i = 0; i < count; i++)
    128    {
    129        dest[i] = static_cast<GLuint>(i);
    130    }
    131    dest[count] = 0;
    132 }
    133 
    134 template <typename T>
    135 void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
    136 {
    137    const T *srcPtr = static_cast<const T *>(indices);
    138    for (size_t i = 0; i < count; ++i)
    139    {
    140        dest[i] = static_cast<GLuint>(srcPtr[i]);
    141    }
    142    dest[count] = static_cast<GLuint>(srcPtr[0]);
    143 }
    144 
    145 void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
    146 {
    147    for (size_t i = 0; i < numTris; i++)
    148    {
    149        destPtr[i * 3 + 0] = 0;
    150        destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
    151        destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
    152    }
    153 }
    154 
    155 void GetLineLoopIndices(const void *indices,
    156                        gl::DrawElementsType indexType,
    157                        GLuint count,
    158                        bool usePrimitiveRestartFixedIndex,
    159                        std::vector<GLuint> *bufferOut)
    160 {
    161    if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex)
    162    {
    163        size_t indexCount = GetLineLoopWithRestartIndexCount(indexType, count,
    164                                                             static_cast<const uint8_t *>(indices));
    165        bufferOut->resize(indexCount);
    166        switch (indexType)
    167        {
    168            case gl::DrawElementsType::UnsignedByte:
    169                CopyLineLoopIndicesWithRestart<GLubyte, GLuint>(
    170                    count, static_cast<const uint8_t *>(indices),
    171                    reinterpret_cast<uint8_t *>(bufferOut->data()));
    172                break;
    173            case gl::DrawElementsType::UnsignedShort:
    174                CopyLineLoopIndicesWithRestart<GLushort, GLuint>(
    175                    count, static_cast<const uint8_t *>(indices),
    176                    reinterpret_cast<uint8_t *>(bufferOut->data()));
    177                break;
    178            case gl::DrawElementsType::UnsignedInt:
    179                CopyLineLoopIndicesWithRestart<GLuint, GLuint>(
    180                    count, static_cast<const uint8_t *>(indices),
    181                    reinterpret_cast<uint8_t *>(bufferOut->data()));
    182                break;
    183            default:
    184                UNREACHABLE();
    185                break;
    186        }
    187        return;
    188    }
    189 
    190    // For non-primitive-restart draws, the index count is static.
    191    bufferOut->resize(static_cast<size_t>(count) + 1);
    192 
    193    switch (indexType)
    194    {
    195        // Non-indexed draw
    196        case gl::DrawElementsType::InvalidEnum:
    197            SetLineLoopIndices(&(*bufferOut)[0], count);
    198            break;
    199        case gl::DrawElementsType::UnsignedByte:
    200            CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
    201            break;
    202        case gl::DrawElementsType::UnsignedShort:
    203            CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
    204            break;
    205        case gl::DrawElementsType::UnsignedInt:
    206            CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
    207            break;
    208        default:
    209            UNREACHABLE();
    210            break;
    211    }
    212 }
    213 
    214 template <typename T>
    215 void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
    216 {
    217    const T *srcPtr = static_cast<const T *>(indices);
    218 
    219    for (size_t i = 0; i < numTris; i++)
    220    {
    221        destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
    222        destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
    223        destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
    224    }
    225 }
    226 
    227 template <typename T>
    228 void CopyTriangleFanIndicesWithRestart(const void *indices,
    229                                       GLuint indexCount,
    230                                       gl::DrawElementsType indexType,
    231                                       std::vector<GLuint> *bufferOut)
    232 {
    233    GLuint restartIndex    = gl::GetPrimitiveRestartIndex(indexType);
    234    GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(gl::DrawElementsType::UnsignedInt);
    235    const T *srcPtr        = static_cast<const T *>(indices);
    236    Optional<GLuint> vertexA;
    237    Optional<GLuint> vertexB;
    238 
    239    bufferOut->clear();
    240 
    241    for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
    242    {
    243        GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
    244 
    245        if (value == restartIndex)
    246        {
    247            bufferOut->push_back(d3dRestartIndex);
    248            vertexA.reset();
    249            vertexB.reset();
    250        }
    251        else
    252        {
    253            if (!vertexA.valid())
    254            {
    255                vertexA = value;
    256            }
    257            else if (!vertexB.valid())
    258            {
    259                vertexB = value;
    260            }
    261            else
    262            {
    263                bufferOut->push_back(vertexA.value());
    264                bufferOut->push_back(vertexB.value());
    265                bufferOut->push_back(value);
    266                vertexB = value;
    267            }
    268        }
    269    }
    270 }
    271 
    272 void GetTriFanIndices(const void *indices,
    273                      gl::DrawElementsType indexType,
    274                      GLuint count,
    275                      bool usePrimitiveRestartFixedIndex,
    276                      std::vector<GLuint> *bufferOut)
    277 {
    278    if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex)
    279    {
    280        switch (indexType)
    281        {
    282            case gl::DrawElementsType::UnsignedByte:
    283                CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
    284                break;
    285            case gl::DrawElementsType::UnsignedShort:
    286                CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
    287                break;
    288            case gl::DrawElementsType::UnsignedInt:
    289                CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
    290                break;
    291            default:
    292                UNREACHABLE();
    293                break;
    294        }
    295        return;
    296    }
    297 
    298    // For non-primitive-restart draws, the index count is static.
    299    GLuint numTris = count - 2;
    300    bufferOut->resize(numTris * 3);
    301 
    302    switch (indexType)
    303    {
    304        // Non-indexed draw
    305        case gl::DrawElementsType::InvalidEnum:
    306            SetTriangleFanIndices(&(*bufferOut)[0], numTris);
    307            break;
    308        case gl::DrawElementsType::UnsignedByte:
    309            CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
    310            break;
    311        case gl::DrawElementsType::UnsignedShort:
    312            CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
    313            break;
    314        case gl::DrawElementsType::UnsignedInt:
    315            CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
    316            break;
    317        default:
    318            UNREACHABLE();
    319            break;
    320    }
    321 }
    322 
    323 bool IsArrayRTV(ID3D11RenderTargetView *rtv)
    324 {
    325    D3D11_RENDER_TARGET_VIEW_DESC desc;
    326    rtv->GetDesc(&desc);
    327    if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY &&
    328        desc.Texture1DArray.ArraySize > 1)
    329        return true;
    330    if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY &&
    331        desc.Texture2DArray.ArraySize > 1)
    332        return true;
    333    if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY &&
    334        desc.Texture2DMSArray.ArraySize > 1)
    335        return true;
    336    return false;
    337 }
    338 
    339 GLsizei GetAdjustedInstanceCount(const ProgramD3D *program, GLsizei instanceCount)
    340 {
    341    if (!program->getState().usesMultiview())
    342    {
    343        return instanceCount;
    344    }
    345    if (instanceCount == 0)
    346    {
    347        return program->getState().getNumViews();
    348    }
    349    return program->getState().getNumViews() * instanceCount;
    350 }
    351 
    352 const uint32_t ScratchMemoryBufferLifetime = 1000;
    353 
    354 void PopulateFormatDeviceCaps(ID3D11Device *device,
    355                              DXGI_FORMAT format,
    356                              UINT *outSupport,
    357                              UINT *outMaxSamples)
    358 {
    359    if (FAILED(device->CheckFormatSupport(format, outSupport)))
    360    {
    361        *outSupport = 0;
    362    }
    363 
    364    *outMaxSamples = 0;
    365    for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
    366    {
    367        UINT qualityCount = 0;
    368        if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) ||
    369            qualityCount == 0)
    370        {
    371            break;
    372        }
    373 
    374        *outMaxSamples = sampleCount;
    375    }
    376 }
    377 
    378 angle::Result GetTextureD3DResourceFromStorageOrImage(const gl::Context *context,
    379                                                      TextureD3D *texture,
    380                                                      const gl::ImageIndex &index,
    381                                                      const TextureHelper11 **outResource,
    382                                                      UINT *outSubresource)
    383 {
    384    // If the storage exists, use it. Otherwise, copy directly from the images to avoid
    385    // allocating a new storage.
    386    if (texture->hasStorage())
    387    {
    388        TextureStorage *storage = nullptr;
    389        ANGLE_TRY(texture->getNativeTexture(context, &storage));
    390 
    391        TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
    392        ANGLE_TRY(storage11->getResource(context, outResource));
    393        ANGLE_TRY(storage11->getSubresourceIndex(context, index, outSubresource));
    394    }
    395    else
    396    {
    397        ImageD3D *image  = texture->getImage(index);
    398        Image11 *image11 = GetAs<Image11>(image);
    399        ANGLE_TRY(image11->getStagingTexture(context, outResource, outSubresource));
    400    }
    401 
    402    return angle::Result::Continue;
    403 }
    404 
    405 }  // anonymous namespace
    406 
    407 Renderer11DeviceCaps::Renderer11DeviceCaps() = default;
    408 
    409 Renderer11::Renderer11(egl::Display *display)
    410    : RendererD3D(display),
    411      mCreateDebugDevice(false),
    412      mStateCache(),
    413      mStateManager(this),
    414      mLastHistogramUpdateTime(
    415          ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
    416      mDebug(nullptr),
    417      mScratchMemoryBuffer(ScratchMemoryBufferLifetime)
    418 {
    419    mLineLoopIB    = nullptr;
    420    mTriangleFanIB = nullptr;
    421 
    422    mBlit          = nullptr;
    423    mPixelTransfer = nullptr;
    424 
    425    mClear = nullptr;
    426 
    427    mTrim = nullptr;
    428 
    429    mRenderer11DeviceCaps.supportsClearView                      = false;
    430    mRenderer11DeviceCaps.supportsConstantBufferOffsets          = false;
    431    mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
    432    mRenderer11DeviceCaps.supportsDXGI1_2                        = false;
    433    mRenderer11DeviceCaps.allowES3OnFL10_0                       = false;
    434    mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats  = false;
    435    mRenderer11DeviceCaps.supportsRasterizerOrderViews           = false;
    436    mRenderer11DeviceCaps.B5G6R5support                          = 0;
    437    mRenderer11DeviceCaps.B4G4R4A4support                        = 0;
    438    mRenderer11DeviceCaps.B5G5R5A1support                        = 0;
    439 
    440    mD3d11Module          = nullptr;
    441    mD3d12Module          = nullptr;
    442    mDxgiModule           = nullptr;
    443    mDCompModule          = nullptr;
    444    mCreatedWithDeviceEXT = false;
    445 
    446    mDevice         = nullptr;
    447    mDevice1        = nullptr;
    448    mDeviceContext  = nullptr;
    449    mDeviceContext1 = nullptr;
    450    mDeviceContext3 = nullptr;
    451    mDxgiAdapter    = nullptr;
    452    mDxgiFactory    = nullptr;
    453 
    454    ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
    455 
    456    const auto &attributes = mDisplay->getAttributeMap();
    457 
    458    if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
    459    {
    460        EGLint requestedMajorVersion = static_cast<EGLint>(
    461            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
    462        EGLint requestedMinorVersion = static_cast<EGLint>(
    463            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
    464 
    465        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
    466        {
    467            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
    468            {
    469                // This could potentially lead to failed context creation if done on a system
    470                // without the platform update which installs DXGI 1.2. Currently, for Chrome users
    471                // D3D11 contexts are only created if the platform update is available, so this
    472                // should not cause any issues.
    473                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
    474            }
    475            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
    476            {
    477                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
    478            }
    479        }
    480 
    481        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
    482        {
    483            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
    484            {
    485                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
    486            }
    487            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
    488            {
    489                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
    490            }
    491        }
    492 
    493        if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
    494        {
    495            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
    496        }
    497 
    498        EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
    499            EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
    500        switch (requestedDeviceType)
    501        {
    502            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
    503                mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
    504                break;
    505 
    506            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
    507                mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
    508                break;
    509 
    510            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
    511                mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
    512                break;
    513 
    514            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
    515                mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
    516                break;
    517 
    518            default:
    519                UNREACHABLE();
    520        }
    521 
    522        mCreateDebugDevice = ShouldUseDebugLayers(attributes);
    523    }
    524    else if (mDisplay->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
    525    {
    526        ASSERT(mDisplay->getDevice() != nullptr);
    527        mCreatedWithDeviceEXT = true;
    528 
    529        // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
    530        // mAvailableFeatureLevels defaults to empty
    531        mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
    532    }
    533 
    534    const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
    535        EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
    536    mPresentPathFastEnabled   = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
    537 }
    538 
    539 Renderer11::~Renderer11()
    540 {
    541    release();
    542 }
    543 
    544 #ifndef __d3d11_1_h__
    545 #    define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
    546 #endif
    547 
    548 egl::Error Renderer11::initialize()
    549 {
    550    HRESULT result = S_OK;
    551 
    552    ANGLE_TRY(initializeD3DDevice());
    553 
    554 #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
    555 #    if !ANGLE_SKIP_DXGI_1_2_CHECK
    556    {
    557        ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
    558        // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
    559        // required.
    560        // The easiest way to check is to query for a IDXGIDevice2.
    561        bool requireDXGI1_2 = false;
    562        HWND hwnd           = WindowFromDC(mDisplay->getNativeDisplayId());
    563        if (hwnd)
    564        {
    565            DWORD currentProcessId = GetCurrentProcessId();
    566            DWORD wndProcessId;
    567            GetWindowThreadProcessId(hwnd, &wndProcessId);
    568            requireDXGI1_2 = (currentProcessId != wndProcessId);
    569        }
    570        else
    571        {
    572            requireDXGI1_2 = true;
    573        }
    574 
    575        if (requireDXGI1_2)
    576        {
    577            IDXGIDevice2 *dxgiDevice2 = nullptr;
    578            result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
    579            if (FAILED(result))
    580            {
    581                return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI)
    582                       << "DXGI 1.2 required to present to HWNDs owned by another process.";
    583            }
    584            SafeRelease(dxgiDevice2);
    585        }
    586    }
    587 #    endif
    588 #endif
    589 
    590    {
    591        ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
    592        // Cast the DeviceContext to a DeviceContext1 and DeviceContext3.
    593        // This could fail on Windows 7 without the Platform Update.
    594        // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3.
    595        mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
    596        mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext);
    597 
    598        IDXGIDevice *dxgiDevice = nullptr;
    599        result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
    600 
    601        if (FAILED(result))
    602        {
    603            return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
    604        }
    605 
    606        result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
    607 
    608        if (FAILED(result))
    609        {
    610            return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
    611                   << "Could not retrieve DXGI adapter";
    612        }
    613 
    614        SafeRelease(dxgiDevice);
    615 
    616        IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
    617 
    618        // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
    619        // description string.
    620        // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
    621        // hardware values.
    622        if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
    623        {
    624            DXGI_ADAPTER_DESC2 adapterDesc2 = {};
    625            result                          = dxgiAdapter2->GetDesc2(&adapterDesc2);
    626            if (SUCCEEDED(result))
    627            {
    628                // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
    629                // DXGI_ADAPTER_DESC).
    630                memcpy(mAdapterDescription.Description, adapterDesc2.Description,
    631                       sizeof(mAdapterDescription.Description));
    632                mAdapterDescription.VendorId              = adapterDesc2.VendorId;
    633                mAdapterDescription.DeviceId              = adapterDesc2.DeviceId;
    634                mAdapterDescription.SubSysId              = adapterDesc2.SubSysId;
    635                mAdapterDescription.Revision              = adapterDesc2.Revision;
    636                mAdapterDescription.DedicatedVideoMemory  = adapterDesc2.DedicatedVideoMemory;
    637                mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
    638                mAdapterDescription.SharedSystemMemory    = adapterDesc2.SharedSystemMemory;
    639                mAdapterDescription.AdapterLuid           = adapterDesc2.AdapterLuid;
    640            }
    641        }
    642        else
    643        {
    644            result = mDxgiAdapter->GetDesc(&mAdapterDescription);
    645        }
    646 
    647        SafeRelease(dxgiAdapter2);
    648 
    649        if (FAILED(result))
    650        {
    651            return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
    652                   << "Could not read DXGI adaptor description.";
    653        }
    654 
    655        memset(mDescription, 0, sizeof(mDescription));
    656        wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
    657 
    658        result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
    659 
    660        if (!mDxgiFactory || FAILED(result))
    661        {
    662            return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
    663                   << "Could not create DXGI factory.";
    664        }
    665    }
    666 
    667    // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
    668    if (mCreateDebugDevice)
    669    {
    670        ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
    671        ID3D11InfoQueue *infoQueue;
    672        result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
    673 
    674        if (SUCCEEDED(result))
    675        {
    676            D3D11_MESSAGE_ID hideMessages[] = {
    677                D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET,
    678 
    679                // Robust access behaviour makes out of bounds messages safe
    680                D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL,
    681            };
    682 
    683            D3D11_INFO_QUEUE_FILTER filter = {};
    684            filter.DenyList.NumIDs         = static_cast<unsigned int>(ArraySize(hideMessages));
    685            filter.DenyList.pIDList        = hideMessages;
    686 
    687            infoQueue->AddStorageFilterEntries(&filter);
    688            SafeRelease(infoQueue);
    689        }
    690    }
    691 
    692 #if !defined(NDEBUG)
    693    mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
    694 #endif
    695 
    696    ANGLE_TRY(initializeDevice());
    697 
    698    return egl::NoError();
    699 }
    700 
    701 HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
    702 {
    703    angle::ComPtr<IDXGIAdapter> adapter;
    704 
    705    const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
    706    // Check EGL_ANGLE_platform_angle_d3d_luid
    707    long high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0));
    708    unsigned long low =
    709        static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0));
    710    // Check EGL_ANGLE_platform_angle_device_id
    711    if (high == 0 && low == 0)
    712    {
    713        high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0));
    714        low = static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0));
    715    }
    716    if (high != 0 || low != 0)
    717    {
    718        angle::ComPtr<IDXGIFactory1> factory;
    719        if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
    720        {
    721            angle::ComPtr<IDXGIAdapter> temp;
    722            for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++)
    723            {
    724                DXGI_ADAPTER_DESC desc;
    725                if (SUCCEEDED(temp->GetDesc(&desc)))
    726                {
    727                    // EGL_ANGLE_platform_angle_d3d_luid
    728                    if (desc.AdapterLuid.HighPart == high && desc.AdapterLuid.LowPart == low)
    729                    {
    730                        adapter = temp;
    731                        break;
    732                    }
    733 
    734                    // EGL_ANGLE_platform_angle_device_id
    735                    // NOTE: If there are multiple GPUs with the same PCI
    736                    // vendor and device IDs, this will arbitrarily choose one
    737                    // of them. To select a specific GPU, use the LUID instead.
    738                    if ((high == 0 || desc.VendorId == static_cast<UINT>(high)) &&
    739                        (low == 0 || desc.DeviceId == static_cast<UINT>(low)))
    740                    {
    741                        adapter = temp;
    742                        break;
    743                    }
    744                }
    745            }
    746        }
    747    }
    748 
    749    // If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or
    750    // D3D11CreateDevice will return E_INVALIDARG.
    751    return createDevice(
    752        adapter.Get(), adapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr,
    753        debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
    754        static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
    755        &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
    756 }
    757 
    758 HRESULT Renderer11::callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12,
    759                                              PFN_D3D11ON12_CREATE_DEVICE createDevice11on12,
    760                                              bool debug)
    761 {
    762    angle::ComPtr<IDXGIFactory4> factory;
    763    HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
    764    if (FAILED(result))
    765    {
    766        return result;
    767    }
    768 
    769    if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
    770    {
    771        angle::ComPtr<IDXGIAdapter> warpAdapter;
    772        result = factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter));
    773        if (SUCCEEDED(result))
    774        {
    775            result = createDevice12(warpAdapter.Get(), mAvailableFeatureLevels[0],
    776                                    IID_PPV_ARGS(&mDevice12));
    777        }
    778    }
    779    else
    780    {
    781        // Passing nullptr into pAdapter chooses the default adapter which will be the hardware
    782        // adapter if it exists.
    783        result = createDevice12(nullptr, mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12));
    784    }
    785 
    786    if (SUCCEEDED(result))
    787    {
    788        D3D12_COMMAND_QUEUE_DESC queueDesc = {};
    789        queueDesc.Flags                    = D3D12_COMMAND_QUEUE_FLAG_NONE;
    790        queueDesc.Type                     = D3D12_COMMAND_LIST_TYPE_DIRECT;
    791        result = mDevice12->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
    792    }
    793 
    794    if (SUCCEEDED(result))
    795    {
    796        result = createDevice11on12(
    797            mDevice12.Get(), debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
    798            static_cast<unsigned int>(mAvailableFeatureLevels.size()),
    799            reinterpret_cast<IUnknown **>(mCommandQueue.GetAddressOf()), 1 /* NumQueues */,
    800            0 /* NodeMask */, &mDevice, &mDeviceContext, &(mRenderer11DeviceCaps.featureLevel));
    801    }
    802 
    803    return result;
    804 }
    805 
    806 egl::Error Renderer11::initializeD3DDevice()
    807 {
    808    HRESULT result             = S_OK;
    809    bool createD3D11on12Device = false;
    810 
    811    if (!mCreatedWithDeviceEXT)
    812    {
    813 #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
    814        PFN_D3D11_CREATE_DEVICE D3D11CreateDevice         = nullptr;
    815        PFN_D3D12_CREATE_DEVICE D3D12CreateDevice         = nullptr;
    816        PFN_D3D11ON12_CREATE_DEVICE D3D11On12CreateDevice = nullptr;
    817        {
    818            ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
    819            mDxgiModule  = LoadLibrary(TEXT("dxgi.dll"));
    820            mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
    821            mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
    822 
    823            // create the D3D11 device
    824            ASSERT(mDevice == nullptr);
    825 
    826            const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
    827            createD3D11on12Device =
    828                attributes.get(EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE, EGL_FALSE) == EGL_TRUE;
    829 
    830            if (createD3D11on12Device)
    831            {
    832                mD3d12Module = LoadLibrary(TEXT("d3d12.dll"));
    833                if (mD3d12Module == nullptr)
    834                {
    835                    return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
    836                           << "Could not load D3D12 library.";
    837                }
    838 
    839                D3D12CreateDevice = reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(
    840                    GetProcAddress(mD3d12Module, "D3D12CreateDevice"));
    841                if (D3D12CreateDevice == nullptr)
    842                {
    843                    return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
    844                           << "Could not retrieve D3D12CreateDevice address.";
    845                }
    846 
    847                D3D11On12CreateDevice = reinterpret_cast<PFN_D3D11ON12_CREATE_DEVICE>(
    848                    GetProcAddress(mD3d11Module, "D3D11On12CreateDevice"));
    849                if (D3D11On12CreateDevice == nullptr)
    850                {
    851                    return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
    852                           << "Could not retrieve D3D11On12CreateDevice address.";
    853                }
    854            }
    855            else
    856            {
    857                if (mD3d11Module == nullptr || mDxgiModule == nullptr)
    858                {
    859                    return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
    860                           << "Could not load D3D11 or DXGI library.";
    861                }
    862 
    863                D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
    864                    GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
    865 
    866                if (D3D11CreateDevice == nullptr)
    867                {
    868                    return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
    869                           << "Could not retrieve D3D11CreateDevice address.";
    870                }
    871            }
    872        }
    873 #endif
    874 
    875        if (mCreateDebugDevice)
    876        {
    877            ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
    878            if (createD3D11on12Device)
    879            {
    880                result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true);
    881            }
    882            else
    883            {
    884                result = callD3D11CreateDevice(D3D11CreateDevice, true);
    885            }
    886 
    887            if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
    888                mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
    889            {
    890                // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
    891                // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
    892                // levels to fall back on.
    893                mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
    894                if (createD3D11on12Device)
    895                {
    896                    result =
    897                        callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true);
    898                }
    899                else
    900                {
    901                    result = callD3D11CreateDevice(D3D11CreateDevice, true);
    902                }
    903            }
    904 
    905            if (!mDevice || FAILED(result))
    906            {
    907                WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
    908            }
    909        }
    910 
    911        if (!mDevice || FAILED(result))
    912        {
    913            ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
    914            if (createD3D11on12Device)
    915            {
    916                result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false);
    917            }
    918            else
    919            {
    920                result = callD3D11CreateDevice(D3D11CreateDevice, false);
    921            }
    922 
    923            if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
    924                mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
    925            {
    926                // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
    927                // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
    928                // levels to fall back on.
    929                mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
    930                if (createD3D11on12Device)
    931                {
    932                    result =
    933                        callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false);
    934                }
    935                else
    936                {
    937                    result = callD3D11CreateDevice(D3D11CreateDevice, false);
    938                }
    939            }
    940 
    941            // Cleanup done by destructor
    942            if (!mDevice || FAILED(result))
    943            {
    944                ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
    945                                              static_cast<int>(result));
    946                return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR)
    947                       << "Could not create D3D11 device.";
    948            }
    949        }
    950    }
    951    else
    952    {
    953        DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice());
    954        ASSERT(deviceD3D != nullptr);
    955 
    956        // We should use the inputted D3D11 device instead
    957        void *device = nullptr;
    958        ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device));
    959 
    960        ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device);
    961        if (FAILED(d3dDevice->GetDeviceRemovedReason()))
    962        {
    963            return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
    964        }
    965 
    966        if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
    967        {
    968            return egl::EglNotInitialized()
    969                   << "Inputted D3D11 device must be Feature Level 9_3 or greater.";
    970        }
    971 
    972        // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
    973        mDevice = d3dDevice;
    974        mDevice->AddRef();
    975        mDevice->GetImmediateContext(&mDeviceContext);
    976        mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
    977    }
    978 
    979    mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
    980 
    981    d3d11::SetDebugName(mDeviceContext, "DeviceContext", nullptr);
    982 
    983    mAnnotatorContext.initialize(mDeviceContext);
    984 
    985    mDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void **>(&mDevice1));
    986 
    987    return egl::NoError();
    988 }
    989 
    990 void Renderer11::setGlobalDebugAnnotator()
    991 {
    992    static angle::base::NoDestructor<std::mutex> gMutex;
    993    static angle::base::NoDestructor<DebugAnnotator11> gGlobalAnnotator;
    994 
    995    std::lock_guard<std::mutex> lg(*gMutex);
    996    gl::InitializeDebugAnnotations(gGlobalAnnotator.get());
    997 }
    998 
    999 // do any one-time device initialization
   1000 // NOTE: this is also needed after a device lost/reset
   1001 // to reset the scene status and ensure the default states are reset.
   1002 egl::Error Renderer11::initializeDevice()
   1003 {
   1004    ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
   1005 
   1006    populateRenderer11DeviceCaps();
   1007 
   1008    mStateCache.clear();
   1009 
   1010    ASSERT(!mBlit);
   1011    mBlit = new Blit11(this);
   1012 
   1013    ASSERT(!mClear);
   1014    mClear = new Clear11(this);
   1015 
   1016    const auto &attributes = mDisplay->getAttributeMap();
   1017    // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
   1018    // automatically when an application is suspended by the OS. This feature is currently
   1019    // only supported for Windows Store applications.
   1020    EGLint enableAutoTrim = static_cast<EGLint>(
   1021        attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
   1022 
   1023    if (enableAutoTrim == EGL_TRUE)
   1024    {
   1025        ASSERT(!mTrim);
   1026        mTrim = new Trim11(this);
   1027    }
   1028 
   1029    ASSERT(!mPixelTransfer);
   1030    mPixelTransfer = new PixelTransfer11(this);
   1031 
   1032    // Gather stats on DXGI and D3D feature level
   1033    ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
   1034 
   1035    ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);
   1036 
   1037    // We don't actually request a 11_1 device, because of complications with the platform
   1038    // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
   1039    // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
   1040    // because the app can specify a lower version (such as 9_3) on Display creation.
   1041    if (mDeviceContext1 != nullptr)
   1042    {
   1043        angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
   1044    }
   1045 
   1046    ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
   1047                                NUM_ANGLE_FEATURE_LEVELS);
   1048 
   1049    return egl::NoError();
   1050 }
   1051 
   1052 void Renderer11::populateRenderer11DeviceCaps()
   1053 {
   1054    HRESULT hr = S_OK;
   1055 
   1056    LARGE_INTEGER version;
   1057    hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
   1058    if (FAILED(hr))
   1059    {
   1060        mRenderer11DeviceCaps.driverVersion.reset();
   1061        ERR() << "Error querying driver version from DXGI Adapter.";
   1062    }
   1063    else
   1064    {
   1065        mRenderer11DeviceCaps.driverVersion = version;
   1066    }
   1067 
   1068    if (mDeviceContext1)
   1069    {
   1070        D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
   1071        HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
   1072                                                      sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
   1073        if (SUCCEEDED(result))
   1074        {
   1075            mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
   1076            mRenderer11DeviceCaps.supportsConstantBufferOffsets =
   1077                (d3d11Options.ConstantBufferOffsetting != FALSE);
   1078        }
   1079    }
   1080 
   1081    if (mDeviceContext3)
   1082    {
   1083        D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
   1084        HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
   1085                                                      sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
   1086        if (SUCCEEDED(result))
   1087        {
   1088            mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
   1089                (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
   1090        }
   1091        D3D11_FEATURE_DATA_D3D11_OPTIONS2 d3d11Options2;
   1092        result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &d3d11Options2,
   1093                                              sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS2));
   1094        if (SUCCEEDED(result))
   1095        {
   1096            mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats =
   1097                d3d11Options2.TypedUAVLoadAdditionalFormats;
   1098            if (!getFeatures().disableRasterizerOrderViews.enabled)
   1099            {
   1100                mRenderer11DeviceCaps.supportsRasterizerOrderViews = d3d11Options2.ROVsSupported;
   1101            }
   1102        }
   1103    }
   1104 
   1105    mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs =
   1106        mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
   1107 
   1108    if (getFeatures().disableB5G6R5Support.enabled)
   1109    {
   1110        mRenderer11DeviceCaps.B5G6R5support    = 0;
   1111        mRenderer11DeviceCaps.B5G6R5maxSamples = 0;
   1112    }
   1113    else
   1114    {
   1115        PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM,
   1116                                 &mRenderer11DeviceCaps.B5G6R5support,
   1117                                 &mRenderer11DeviceCaps.B5G6R5maxSamples);
   1118    }
   1119 
   1120    if (getFeatures().allowES3OnFL100.enabled)
   1121    {
   1122        mRenderer11DeviceCaps.allowES3OnFL10_0 = true;
   1123    }
   1124 
   1125    PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM,
   1126                             &mRenderer11DeviceCaps.B4G4R4A4support,
   1127                             &mRenderer11DeviceCaps.B4G4R4A4maxSamples);
   1128    PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM,
   1129                             &mRenderer11DeviceCaps.B5G5R5A1support,
   1130                             &mRenderer11DeviceCaps.B5G5R5A1maxSamples);
   1131 
   1132    IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
   1133    mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
   1134    SafeRelease(dxgiAdapter2);
   1135 }
   1136 
   1137 gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
   1138    const gl::TextureCaps &colorBufferFormatCaps,
   1139    const gl::TextureCaps &depthStencilBufferFormatCaps) const
   1140 {
   1141    gl::SupportedSampleSet sampleCounts;
   1142 
   1143    // Generate a new set from the set intersection of sample counts between the color and depth
   1144    // format caps.
   1145    std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
   1146                          colorBufferFormatCaps.sampleCounts.end(),
   1147                          depthStencilBufferFormatCaps.sampleCounts.begin(),
   1148                          depthStencilBufferFormatCaps.sampleCounts.end(),
   1149                          std::inserter(sampleCounts, sampleCounts.begin()));
   1150 
   1151    // Format of GL_NONE results in no supported sample counts.
   1152    // Add back the color sample counts to the supported sample set.
   1153    if (depthStencilBufferFormatCaps.sampleCounts.empty())
   1154    {
   1155        sampleCounts = colorBufferFormatCaps.sampleCounts;
   1156    }
   1157    else if (colorBufferFormatCaps.sampleCounts.empty())
   1158    {
   1159        // Likewise, add back the depth sample counts to the supported sample set.
   1160        sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
   1161    }
   1162 
   1163    // Always support 0 samples
   1164    sampleCounts.insert(0);
   1165 
   1166    return sampleCounts;
   1167 }
   1168 
   1169 egl::ConfigSet Renderer11::generateConfigs()
   1170 {
   1171    std::vector<GLenum> colorBufferFormats;
   1172 
   1173    // 32-bit supported formats
   1174    colorBufferFormats.push_back(GL_BGRA8_EXT);
   1175    colorBufferFormats.push_back(GL_RGBA8_OES);
   1176 
   1177    // 24-bit supported formats
   1178    colorBufferFormats.push_back(GL_RGB8_OES);
   1179 
   1180    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
   1181    {
   1182        // Additional high bit depth formats added in D3D 10.0
   1183        // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
   1184        colorBufferFormats.push_back(GL_RGBA16F);
   1185        colorBufferFormats.push_back(GL_RGB10_A2);
   1186    }
   1187 
   1188    if (!mPresentPathFastEnabled)
   1189    {
   1190        // 16-bit supported formats
   1191        // These aren't valid D3D11 swapchain formats, so don't expose them as configs
   1192        // if present path fast is active
   1193        colorBufferFormats.push_back(GL_RGBA4);
   1194        colorBufferFormats.push_back(GL_RGB5_A1);
   1195        colorBufferFormats.push_back(GL_RGB565);
   1196    }
   1197 
   1198    static const GLenum depthStencilBufferFormats[] = {
   1199        GL_NONE,           GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
   1200        GL_STENCIL_INDEX8,
   1201    };
   1202 
   1203    const gl::Caps &rendererCaps                  = getNativeCaps();
   1204    const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
   1205 
   1206    const EGLint optimalSurfaceOrientation =
   1207        mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
   1208 
   1209    egl::ConfigSet configs;
   1210    for (GLenum colorBufferInternalFormat : colorBufferFormats)
   1211    {
   1212        const gl::TextureCaps &colorBufferFormatCaps =
   1213            rendererTextureCaps.get(colorBufferInternalFormat);
   1214        if (!colorBufferFormatCaps.renderbuffer)
   1215        {
   1216            ASSERT(!colorBufferFormatCaps.textureAttachment);
   1217            continue;
   1218        }
   1219 
   1220        for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
   1221        {
   1222            const gl::TextureCaps &depthStencilBufferFormatCaps =
   1223                rendererTextureCaps.get(depthStencilBufferInternalFormat);
   1224            if (!depthStencilBufferFormatCaps.renderbuffer &&
   1225                depthStencilBufferInternalFormat != GL_NONE)
   1226            {
   1227                ASSERT(!depthStencilBufferFormatCaps.textureAttachment);
   1228                continue;
   1229            }
   1230 
   1231            const gl::InternalFormat &colorBufferFormatInfo =
   1232                gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
   1233            const gl::InternalFormat &depthStencilBufferFormatInfo =
   1234                gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
   1235            const gl::Version &maxVersion = getMaxSupportedESVersion();
   1236 
   1237            const gl::SupportedSampleSet sampleCounts =
   1238                generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps);
   1239 
   1240            for (GLuint sampleCount : sampleCounts)
   1241            {
   1242                egl::Config config;
   1243                config.renderTargetFormat = colorBufferInternalFormat;
   1244                config.depthStencilFormat = depthStencilBufferInternalFormat;
   1245                config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
   1246                config.redSize            = colorBufferFormatInfo.redBits;
   1247                config.greenSize          = colorBufferFormatInfo.greenBits;
   1248                config.blueSize           = colorBufferFormatInfo.blueBits;
   1249                config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
   1250                config.alphaSize          = colorBufferFormatInfo.alphaBits;
   1251                config.alphaMaskSize      = 0;
   1252                config.bindToTextureRGB =
   1253                    ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
   1254                config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
   1255                                             (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
   1256                                            (sampleCount <= 1));
   1257                config.colorBufferType   = EGL_RGB_BUFFER;
   1258                config.configCaveat      = EGL_NONE;
   1259                config.configID          = static_cast<EGLint>(configs.size() + 1);
   1260 
   1261                // PresentPathFast may not be conformant
   1262                config.conformant = 0;
   1263                if (!mPresentPathFastEnabled)
   1264                {
   1265                    // Can only support a conformant ES2 with feature level greater than 10.0.
   1266                    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
   1267                    {
   1268                        config.conformant |= EGL_OPENGL_ES2_BIT;
   1269                    }
   1270 
   1271                    // We can only support conformant ES3 on FL 10.1+
   1272                    if (maxVersion.major >= 3)
   1273                    {
   1274                        config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
   1275                    }
   1276                }
   1277 
   1278                config.depthSize         = depthStencilBufferFormatInfo.depthBits;
   1279                config.level             = 0;
   1280                config.matchNativePixmap = EGL_NONE;
   1281                config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
   1282                config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
   1283                config.maxPBufferPixels =
   1284                    rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
   1285                config.maxSwapInterval  = 4;
   1286                config.minSwapInterval  = 0;
   1287                config.nativeRenderable = EGL_FALSE;
   1288                config.nativeVisualID   = 0;
   1289                config.nativeVisualType = EGL_NONE;
   1290 
   1291                // Can't support ES3 at all without feature level 10.1
   1292                config.renderableType = EGL_OPENGL_ES2_BIT;
   1293                if (maxVersion.major >= 3)
   1294                {
   1295                    config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
   1296                }
   1297 
   1298                config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
   1299                config.samples       = sampleCount;
   1300                config.stencilSize   = depthStencilBufferFormatInfo.stencilBits;
   1301                config.surfaceType =
   1302                    EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
   1303                config.transparentType       = EGL_NONE;
   1304                config.transparentRedValue   = 0;
   1305                config.transparentGreenValue = 0;
   1306                config.transparentBlueValue  = 0;
   1307                config.optimalOrientation    = optimalSurfaceOrientation;
   1308                config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
   1309                       colorBufferFormatInfo.componentType);
   1310 
   1311                configs.add(config);
   1312            }
   1313        }
   1314    }
   1315 
   1316    ASSERT(configs.size() > 0);
   1317    return configs;
   1318 }
   1319 
   1320 void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
   1321 {
   1322    outExtensions->createContextRobustness = true;
   1323 
   1324    if (getShareHandleSupport())
   1325    {
   1326        outExtensions->d3dShareHandleClientBuffer     = true;
   1327        outExtensions->surfaceD3DTexture2DShareHandle = true;
   1328    }
   1329    outExtensions->d3dTextureClientBuffer = true;
   1330    outExtensions->imageD3D11Texture      = true;
   1331 
   1332    outExtensions->keyedMutex          = true;
   1333    outExtensions->querySurfacePointer = true;
   1334    outExtensions->windowFixedSize     = true;
   1335 
   1336    // If present path fast is active then the surface orientation extension isn't supported
   1337    outExtensions->surfaceOrientation = !mPresentPathFastEnabled;
   1338 
   1339    // D3D11 does not support present with dirty rectangles until DXGI 1.2.
   1340    outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
   1341 
   1342    outExtensions->image                 = true;
   1343    outExtensions->imageBase             = true;
   1344    outExtensions->glTexture2DImage      = true;
   1345    outExtensions->glTextureCubemapImage = true;
   1346    outExtensions->glRenderbufferImage   = true;
   1347 
   1348    outExtensions->stream                     = true;
   1349    outExtensions->streamConsumerGLTexture    = true;
   1350    outExtensions->streamConsumerGLTextureYUV = true;
   1351    outExtensions->streamProducerD3DTexture   = true;
   1352 
   1353    outExtensions->noConfigContext   = true;
   1354    outExtensions->directComposition = !!mDCompModule;
   1355 
   1356    // Contexts are virtualized so textures and semaphores can be shared globally
   1357    outExtensions->displayTextureShareGroup   = true;
   1358    outExtensions->displaySemaphoreShareGroup = true;
   1359 
   1360    // syncControlCHROMIUM requires direct composition.
   1361    outExtensions->syncControlCHROMIUM = outExtensions->directComposition;
   1362 
   1363    // D3D11 can be used without a swap chain
   1364    outExtensions->surfacelessContext = true;
   1365 
   1366    // All D3D feature levels support robust resource init
   1367    outExtensions->robustResourceInitializationANGLE = true;
   1368 
   1369 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
   1370    // Compositor Native Window capabilies require WinVer >= 1803
   1371    if (CompositorNativeWindow11::IsSupportedWinRelease())
   1372    {
   1373        outExtensions->windowsUIComposition = true;
   1374    }
   1375 #endif
   1376 }
   1377 
   1378 angle::Result Renderer11::flush(Context11 *context11)
   1379 {
   1380    mDeviceContext->Flush();
   1381    return angle::Result::Continue;
   1382 }
   1383 
   1384 angle::Result Renderer11::finish(Context11 *context11)
   1385 {
   1386    if (!mSyncQuery.valid())
   1387    {
   1388        D3D11_QUERY_DESC queryDesc;
   1389        queryDesc.Query     = D3D11_QUERY_EVENT;
   1390        queryDesc.MiscFlags = 0;
   1391 
   1392        ANGLE_TRY(allocateResource(context11, queryDesc, &mSyncQuery));
   1393    }
   1394 
   1395    mDeviceContext->End(mSyncQuery.get());
   1396 
   1397    HRESULT result       = S_OK;
   1398    unsigned int attempt = 0;
   1399    do
   1400    {
   1401        unsigned int flushFrequency = 100;
   1402        UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
   1403        attempt++;
   1404 
   1405        result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags);
   1406        ANGLE_TRY_HR(context11, result, "Failed to get event query data");
   1407 
   1408        if (result == S_FALSE)
   1409        {
   1410            // Keep polling, but allow other threads to do something useful first
   1411            ScheduleYield();
   1412        }
   1413 
   1414        // Attempt is incremented before checking if we should test for device loss so that device
   1415        // loss is not checked on the first iteration
   1416        bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0;
   1417        if (checkDeviceLost && testDeviceLost())
   1418        {
   1419            mDisplay->notifyDeviceLost();
   1420            ANGLE_CHECK(context11, false, "Device was lost while waiting for sync.",
   1421                        GL_OUT_OF_MEMORY);
   1422        }
   1423    } while (result == S_FALSE);
   1424 
   1425    return angle::Result::Continue;
   1426 }
   1427 
   1428 bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
   1429 {
   1430 #if defined(ANGLE_ENABLE_WINDOWS_UWP)
   1431    if (NativeWindow11WinRT::IsValidNativeWindow(window))
   1432    {
   1433        return true;
   1434    }
   1435 #else
   1436    if (NativeWindow11Win32::IsValidNativeWindow(window))
   1437    {
   1438        return true;
   1439    }
   1440 #endif
   1441 
   1442 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
   1443    static_assert(sizeof(ABI::Windows::UI::Composition::SpriteVisual *) == sizeof(HWND),
   1444                  "Pointer size must match Window Handle size");
   1445    if (CompositorNativeWindow11::IsValidNativeWindow(window))
   1446    {
   1447        return true;
   1448    }
   1449 #endif
   1450 
   1451    return false;
   1452 }
   1453 
   1454 NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
   1455                                                const egl::Config *config,
   1456                                                const egl::AttributeMap &attribs) const
   1457 {
   1458 #if defined(ANGLE_ENABLE_WINDOWS_UWP)
   1459    if (window == nullptr || NativeWindow11WinRT::IsValidNativeWindow(window))
   1460    {
   1461        return new NativeWindow11WinRT(window, config->alphaSize > 0);
   1462    }
   1463 #else
   1464    if (window == nullptr || NativeWindow11Win32::IsValidNativeWindow(window))
   1465    {
   1466        return new NativeWindow11Win32(
   1467            window, config->alphaSize > 0,
   1468            attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
   1469    }
   1470 #endif
   1471 
   1472 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
   1473    if (CompositorNativeWindow11::IsValidNativeWindow(window))
   1474    {
   1475        return new CompositorNativeWindow11(window, config->alphaSize > 0);
   1476    }
   1477 #endif
   1478 
   1479    UNREACHABLE();
   1480    return nullptr;
   1481 }
   1482 
   1483 egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
   1484                                         IUnknown *texture,
   1485                                         const egl::AttributeMap &attribs,
   1486                                         EGLint *width,
   1487                                         EGLint *height,
   1488                                         GLsizei *samples,
   1489                                         gl::Format *glFormat,
   1490                                         const angle::Format **angleFormat,
   1491                                         UINT *arraySlice) const
   1492 {
   1493    angle::ComPtr<ID3D11Texture2D> d3dTexture =
   1494        d3d11::DynamicCastComObjectToComPtr<ID3D11Texture2D>(texture);
   1495    if (d3dTexture == nullptr)
   1496    {
   1497        return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D";
   1498    }
   1499 
   1500    angle::ComPtr<ID3D11Device> textureDevice;
   1501    d3dTexture->GetDevice(&textureDevice);
   1502    if (textureDevice.Get() != mDevice)
   1503    {
   1504        return egl::EglBadParameter() << "Texture's device does not match.";
   1505    }
   1506 
   1507    D3D11_TEXTURE2D_DESC desc = {};
   1508    d3dTexture->GetDesc(&desc);
   1509 
   1510    EGLint imageWidth  = static_cast<EGLint>(desc.Width);
   1511    EGLint imageHeight = static_cast<EGLint>(desc.Height);
   1512 
   1513    GLsizei sampleCount = static_cast<GLsizei>(desc.SampleDesc.Count);
   1514    if (configuration && (configuration->samples != sampleCount))
   1515    {
   1516        // Both the texture and EGL config sample count may not be the same when multi-sampling
   1517        // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
   1518        // we must only check for a invalid match when the EGL config is non-zero or the texture is
   1519        // not one.
   1520        if (configuration->samples != 0 || sampleCount != 1)
   1521        {
   1522            return egl::EglBadParameter() << "Texture's sample count does not match.";
   1523        }
   1524    }
   1525 
   1526    const angle::Format *textureAngleFormat = nullptr;
   1527    GLenum sizedInternalFormat              = GL_NONE;
   1528 
   1529    // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
   1530    if (desc.Format == DXGI_FORMAT_NV12 || desc.Format == DXGI_FORMAT_P010 ||
   1531        desc.Format == DXGI_FORMAT_P016)
   1532    {
   1533        if (!attribs.contains(EGL_D3D11_TEXTURE_PLANE_ANGLE))
   1534        {
   1535            return egl::EglBadParameter()
   1536                   << "EGL_D3D11_TEXTURE_PLANE_ANGLE must be specified for YUV textures.";
   1537        }
   1538 
   1539        EGLint plane = attribs.getAsInt(EGL_D3D11_TEXTURE_PLANE_ANGLE);
   1540 
   1541        // P010 and P016 have the same memory layout, SRV/RTV format, etc.
   1542        const bool isNV12 = (desc.Format == DXGI_FORMAT_NV12);
   1543        if (plane == 0)
   1544        {
   1545            textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8_UNORM)
   1546                                        : &angle::Format::Get(angle::FormatID::R16_UNORM);
   1547        }
   1548        else if (plane == 1)
   1549        {
   1550            textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8G8_UNORM)
   1551                                        : &angle::Format::Get(angle::FormatID::R16G16_UNORM);
   1552            imageWidth /= 2;
   1553            imageHeight /= 2;
   1554        }
   1555        else
   1556        {
   1557            return egl::EglBadParameter() << "Invalid client buffer texture plane: " << plane;
   1558        }
   1559 
   1560        ASSERT(textureAngleFormat);
   1561        sizedInternalFormat = textureAngleFormat->glInternalFormat;
   1562    }
   1563    else
   1564    {
   1565        switch (desc.Format)
   1566        {
   1567            case DXGI_FORMAT_R8G8B8A8_UNORM:
   1568            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
   1569            case DXGI_FORMAT_R8G8B8A8_TYPELESS:
   1570            case DXGI_FORMAT_B8G8R8A8_UNORM:
   1571            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
   1572            case DXGI_FORMAT_B8G8R8A8_TYPELESS:
   1573            case DXGI_FORMAT_R16G16B16A16_FLOAT:
   1574            case DXGI_FORMAT_R32G32B32A32_FLOAT:
   1575            case DXGI_FORMAT_R10G10B10A2_UNORM:
   1576            case DXGI_FORMAT_R8_UNORM:
   1577            case DXGI_FORMAT_R8G8_UNORM:
   1578            case DXGI_FORMAT_R16_UNORM:
   1579            case DXGI_FORMAT_R16G16_UNORM:
   1580                break;
   1581 
   1582            default:
   1583                return egl::EglBadParameter()
   1584                       << "Invalid client buffer texture format: " << desc.Format;
   1585        }
   1586 
   1587        textureAngleFormat = &d3d11_angle::GetFormat(desc.Format);
   1588        ASSERT(textureAngleFormat);
   1589 
   1590        sizedInternalFormat = textureAngleFormat->glInternalFormat;
   1591 
   1592        if (attribs.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE))
   1593        {
   1594            const GLenum internalFormat =
   1595                static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
   1596            switch (internalFormat)
   1597            {
   1598                case GL_RGBA:
   1599                case GL_BGRA_EXT:
   1600                case GL_RGB:
   1601                case GL_RED_EXT:
   1602                case GL_RG_EXT:
   1603                case GL_RGB10_A2_EXT:
   1604                case GL_R16_EXT:
   1605                case GL_RG16_EXT:
   1606                    break;
   1607                default:
   1608                    return egl::EglBadParameter()
   1609                           << "Invalid client buffer texture internal format: " << std::hex
   1610                           << internalFormat;
   1611            }
   1612 
   1613            const GLenum type = gl::GetSizedInternalFormatInfo(sizedInternalFormat).type;
   1614 
   1615            const auto format = gl::Format(internalFormat, type);
   1616            if (!format.valid())
   1617            {
   1618                return egl::EglBadParameter()
   1619                       << "Invalid client buffer texture internal format: " << std::hex
   1620                       << internalFormat;
   1621            }
   1622 
   1623            sizedInternalFormat = format.info->sizedInternalFormat;
   1624        }
   1625    }
   1626 
   1627    UINT textureArraySlice =
   1628        static_cast<UINT>(attribs.getAsInt(EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, 0));
   1629    if (textureArraySlice >= desc.ArraySize)
   1630    {
   1631        return egl::EglBadParameter()
   1632               << "Invalid client buffer texture array slice: " << textureArraySlice;
   1633    }
   1634 
   1635    if (width)
   1636    {
   1637        *width = imageWidth;
   1638    }
   1639    if (height)
   1640    {
   1641        *height = imageHeight;
   1642    }
   1643 
   1644    if (samples)
   1645    {
   1646        // EGL samples 0 corresponds to D3D11 sample count 1.
   1647        *samples = sampleCount != 1 ? sampleCount : 0;
   1648    }
   1649 
   1650    if (glFormat)
   1651    {
   1652        *glFormat = gl::Format(sizedInternalFormat);
   1653    }
   1654 
   1655    if (angleFormat)
   1656    {
   1657        *angleFormat = textureAngleFormat;
   1658    }
   1659 
   1660    if (arraySlice)
   1661    {
   1662        *arraySlice = textureArraySlice;
   1663    }
   1664 
   1665    return egl::NoError();
   1666 }
   1667 
   1668 egl::Error Renderer11::validateShareHandle(const egl::Config *config,
   1669                                           HANDLE shareHandle,
   1670                                           const egl::AttributeMap &attribs) const
   1671 {
   1672    if (shareHandle == nullptr)
   1673    {
   1674        return egl::EglBadParameter() << "NULL share handle.";
   1675    }
   1676 
   1677    ID3D11Resource *tempResource11 = nullptr;
   1678    HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
   1679                                                 (void **)&tempResource11);
   1680    if (FAILED(result) && mDevice1)
   1681    {
   1682        result = mDevice1->OpenSharedResource1(shareHandle, __uuidof(ID3D11Resource),
   1683                                               (void **)&tempResource11);
   1684    }
   1685 
   1686    if (FAILED(result))
   1687    {
   1688        return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
   1689    }
   1690 
   1691    ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
   1692    SafeRelease(tempResource11);
   1693 
   1694    if (texture2D == nullptr)
   1695    {
   1696        return egl::EglBadParameter()
   1697               << "Failed to query ID3D11Texture2D object from share handle.";
   1698    }
   1699 
   1700    D3D11_TEXTURE2D_DESC desc = {};
   1701    texture2D->GetDesc(&desc);
   1702    SafeRelease(texture2D);
   1703 
   1704    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
   1705    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
   1706    ASSERT(width != 0 && height != 0);
   1707 
   1708    const d3d11::Format &backbufferFormatInfo =
   1709        d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
   1710 
   1711    if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
   1712        desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
   1713    {
   1714        return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
   1715    }
   1716 
   1717    return egl::NoError();
   1718 }
   1719 
   1720 SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
   1721                                          HANDLE shareHandle,
   1722                                          IUnknown *d3dTexture,
   1723                                          GLenum backBufferFormat,
   1724                                          GLenum depthBufferFormat,
   1725                                          EGLint orientation,
   1726                                          EGLint samples)
   1727 {
   1728    return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
   1729                           backBufferFormat, depthBufferFormat, orientation, samples);
   1730 }
   1731 
   1732 void *Renderer11::getD3DDevice()
   1733 {
   1734    return mDevice;
   1735 }
   1736 
   1737 angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 *context11,
   1738                                                                     gl::PrimitiveMode mode,
   1739                                                                     UINT instanceCount,
   1740                                                                     UINT vertexCount)
   1741 {
   1742    const gl::State &glState = context11->getState();
   1743    ProgramD3D *programD3D   = mStateManager.getProgramD3D();
   1744 
   1745    // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
   1746    // won't get the correct output. To work around this, draw with *only* the stream out
   1747    // first (no pixel shader) to feed the stream out buffers and then draw again with the
   1748    // geometry shader + pixel shader to rasterize the primitives.
   1749    mStateManager.setPixelShader(nullptr);
   1750 
   1751    if (instanceCount > 0)
   1752    {
   1753        mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0);
   1754    }
   1755    else
   1756    {
   1757        mDeviceContext->Draw(vertexCount, 0);
   1758    }
   1759 
   1760    rx::ShaderExecutableD3D *pixelExe = nullptr;
   1761    ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
   1762 
   1763    // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
   1764    if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
   1765    {
   1766        return angle::Result::Continue;
   1767    }
   1768 
   1769    mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader());
   1770 
   1771    // Retrieve the geometry shader.
   1772    rx::ShaderExecutableD3D *geometryExe = nullptr;
   1773    ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context11, glState, mode,
   1774                                                                &geometryExe, nullptr));
   1775 
   1776    mStateManager.setGeometryShader(&GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader());
   1777 
   1778    if (instanceCount > 0)
   1779    {
   1780        mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0);
   1781    }
   1782    else
   1783    {
   1784        mDeviceContext->Draw(vertexCount, 0);
   1785    }
   1786 
   1787    return angle::Result::Continue;
   1788 }
   1789 
   1790 angle::Result Renderer11::drawArrays(const gl::Context *context,
   1791                                     gl::PrimitiveMode mode,
   1792                                     GLint firstVertex,
   1793                                     GLsizei vertexCount,
   1794                                     GLsizei instanceCount,
   1795                                     GLuint baseInstance,
   1796                                     bool isInstancedDraw)
   1797 {
   1798    if (mStateManager.getCullEverything())
   1799    {
   1800        return angle::Result::Continue;
   1801    }
   1802 
   1803    ANGLE_TRY(markRawBufferUsage(context));
   1804 
   1805    ProgramD3D *programD3D        = mStateManager.getProgramD3D();
   1806    GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount);
   1807 
   1808    // Note: vertex indexes can be arbitrarily large.
   1809    UINT clampedVertexCount = gl::GetClampedVertexCount<UINT>(vertexCount);
   1810 
   1811    const auto &glState = context->getState();
   1812    if (glState.getCurrentTransformFeedback() && glState.isTransformFeedbackActiveUnpaused())
   1813    {
   1814        ANGLE_TRY(markTransformFeedbackUsage(context));
   1815 
   1816        if (programD3D->usesGeometryShader(glState, mode))
   1817        {
   1818            return drawWithGeometryShaderAndTransformFeedback(
   1819                GetImplAs<Context11>(context), mode, adjustedInstanceCount, clampedVertexCount);
   1820        }
   1821    }
   1822 
   1823    switch (mode)
   1824    {
   1825        case gl::PrimitiveMode::LineLoop:
   1826            return drawLineLoop(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum,
   1827                                nullptr, 0, adjustedInstanceCount);
   1828        case gl::PrimitiveMode::TriangleFan:
   1829            return drawTriangleFan(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum,
   1830                                   nullptr, 0, adjustedInstanceCount);
   1831        case gl::PrimitiveMode::Points:
   1832            if (getFeatures().useInstancedPointSpriteEmulation.enabled)
   1833            {
   1834                // This code should not be reachable by multi-view programs.
   1835                ASSERT(programD3D->getState().usesMultiview() == false);
   1836 
   1837                // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
   1838                // Emulating instanced point sprites for FL9_3 requires the topology to be
   1839                // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
   1840                if (adjustedInstanceCount == 0)
   1841                {
   1842                    mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
   1843                    return angle::Result::Continue;
   1844                }
   1845 
   1846                // If pointsprite emulation is used with glDrawArraysInstanced then we need to take
   1847                // a less efficent code path. Instanced rendering of emulated pointsprites requires
   1848                // a loop to draw each batch of points. An offset into the instanced data buffer is
   1849                // calculated and applied on each iteration to ensure all instances are rendered
   1850                // correctly. Each instance being rendered requires the inputlayout cache to reapply
   1851                // buffers and offsets.
   1852                for (GLsizei i = 0; i < instanceCount; i++)
   1853                {
   1854                    ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(
   1855                        context, firstVertex, i));
   1856                    mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
   1857                }
   1858 
   1859                // This required by updateVertexOffsets... above but is outside of the loop for
   1860                // speed.
   1861                mStateManager.invalidateVertexBuffer();
   1862                return angle::Result::Continue;
   1863            }
   1864            break;
   1865        default:
   1866            break;
   1867    }
   1868 
   1869    // "Normal" draw case.
   1870    if (!isInstancedDraw && adjustedInstanceCount == 0)
   1871    {
   1872        mDeviceContext->Draw(clampedVertexCount, 0);
   1873    }
   1874    else
   1875    {
   1876        mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, baseInstance);
   1877    }
   1878    return angle::Result::Continue;
   1879 }
   1880 
   1881 angle::Result Renderer11::drawElements(const gl::Context *context,
   1882                                       gl::PrimitiveMode mode,
   1883                                       GLint startVertex,
   1884                                       GLsizei indexCount,
   1885                                       gl::DrawElementsType indexType,
   1886                                       const void *indices,
   1887                                       GLsizei instanceCount,
   1888                                       GLint baseVertex,
   1889                                       GLuint baseInstance,
   1890                                       bool isInstancedDraw)
   1891 {
   1892    if (mStateManager.getCullEverything())
   1893    {
   1894        return angle::Result::Continue;
   1895    }
   1896 
   1897    ANGLE_TRY(markRawBufferUsage(context));
   1898 
   1899    // Transform feedback is not allowed for DrawElements, this error should have been caught at the
   1900    // API validation layer.
   1901    const gl::State &glState = context->getState();
   1902    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
   1903 
   1904    // If this draw call is coming from an indirect call, offset by the indirect call's base vertex.
   1905    GLint baseVertexAdjusted = baseVertex - startVertex;
   1906 
   1907    const ProgramD3D *programD3D  = mStateManager.getProgramD3D();
   1908    GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount);
   1909 
   1910    if (mode == gl::PrimitiveMode::LineLoop)
   1911    {
   1912        return drawLineLoop(context, indexCount, indexType, indices, baseVertexAdjusted,
   1913                            adjustedInstanceCount);
   1914    }
   1915 
   1916    if (mode == gl::PrimitiveMode::TriangleFan)
   1917    {
   1918        return drawTriangleFan(context, indexCount, indexType, indices, baseVertexAdjusted,
   1919                               adjustedInstanceCount);
   1920    }
   1921 
   1922    if (mode != gl::PrimitiveMode::Points || !programD3D->usesInstancedPointSpriteEmulation())
   1923    {
   1924        if (!isInstancedDraw && adjustedInstanceCount == 0)
   1925        {
   1926            mDeviceContext->DrawIndexed(indexCount, 0, baseVertexAdjusted);
   1927        }
   1928        else
   1929        {
   1930            mDeviceContext->DrawIndexedInstanced(indexCount, adjustedInstanceCount, 0,
   1931                                                 baseVertexAdjusted, baseInstance);
   1932        }
   1933        return angle::Result::Continue;
   1934    }
   1935 
   1936    // This code should not be reachable by multi-view programs.
   1937    ASSERT(programD3D->getState().usesMultiview() == false);
   1938 
   1939    // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
   1940    // Emulating instanced point sprites for FL9_3 requires the topology to be
   1941    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
   1942    //
   1943    // The count parameter passed to drawElements represents the total number of instances to be
   1944    // rendered. Each instance is referenced by the bound index buffer from the the caller.
   1945    //
   1946    // Indexed pointsprite emulation replicates data for duplicate entries found in the index
   1947    // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers
   1948    // that do not support geometry shaders.
   1949    if (instanceCount == 0)
   1950    {
   1951        mDeviceContext->DrawIndexedInstanced(6, indexCount, 0, baseVertexAdjusted, baseInstance);
   1952        return angle::Result::Continue;
   1953    }
   1954 
   1955    // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less
   1956    // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
   1957    // batch of points. An offset into the instanced data buffer is calculated and applied on each
   1958    // iteration to ensure all instances are rendered correctly.
   1959    gl::IndexRange indexRange;
   1960    ANGLE_TRY(glState.getVertexArray()->getIndexRange(context, indexType, indexCount, indices,
   1961                                                      &indexRange));
   1962 
   1963    UINT clampedVertexCount = gl::clampCast<UINT>(indexRange.vertexCount());
   1964 
   1965    // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets.
   1966    for (GLsizei i = 0; i < instanceCount; i++)
   1967    {
   1968        ANGLE_TRY(
   1969            mStateManager.updateVertexOffsetsForPointSpritesEmulation(context, startVertex, i));
   1970        mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, baseVertexAdjusted,
   1971                                             baseInstance);
   1972    }
   1973    mStateManager.invalidateVertexBuffer();
   1974    return angle::Result::Continue;
   1975 }
   1976 
   1977 angle::Result Renderer11::drawArraysIndirect(const gl::Context *context, const void *indirect)
   1978 {
   1979    if (mStateManager.getCullEverything())
   1980    {
   1981        return angle::Result::Continue;
   1982    }
   1983 
   1984    ANGLE_TRY(markRawBufferUsage(context));
   1985 
   1986    const gl::State &glState = context->getState();
   1987    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
   1988 
   1989    gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
   1990    ASSERT(drawIndirectBuffer);
   1991    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
   1992 
   1993    uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
   1994 
   1995    ID3D11Buffer *buffer = nullptr;
   1996    ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
   1997    mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
   1998    return angle::Result::Continue;
   1999 }
   2000 
   2001 angle::Result Renderer11::drawElementsIndirect(const gl::Context *context, const void *indirect)
   2002 {
   2003    if (mStateManager.getCullEverything())
   2004    {
   2005        return angle::Result::Continue;
   2006    }
   2007 
   2008    ANGLE_TRY(markRawBufferUsage(context));
   2009 
   2010    const gl::State &glState = context->getState();
   2011    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
   2012 
   2013    gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
   2014    ASSERT(drawIndirectBuffer);
   2015    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
   2016    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
   2017 
   2018    ID3D11Buffer *buffer = nullptr;
   2019    ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
   2020    mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
   2021    return angle::Result::Continue;
   2022 }
   2023 
   2024 angle::Result Renderer11::drawLineLoop(const gl::Context *context,
   2025                                       GLuint count,
   2026                                       gl::DrawElementsType type,
   2027                                       const void *indexPointer,
   2028                                       int baseVertex,
   2029                                       int instances)
   2030 {
   2031    const gl::State &glState       = context->getState();
   2032    gl::VertexArray *vao           = glState.getVertexArray();
   2033    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
   2034 
   2035    const void *indices = indexPointer;
   2036 
   2037    // Get the raw indices for an indexed draw
   2038    if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
   2039    {
   2040        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
   2041        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
   2042 
   2043        const uint8_t *bufferData = nullptr;
   2044        ANGLE_TRY(storage->getData(context, &bufferData));
   2045 
   2046        indices = bufferData + offset;
   2047    }
   2048 
   2049    if (!mLineLoopIB)
   2050    {
   2051        mLineLoopIB = new StreamingIndexBufferInterface(this);
   2052        ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
   2053                                                  gl::DrawElementsType::UnsignedInt));
   2054    }
   2055 
   2056    // Checked by Renderer11::applyPrimitiveType
   2057    bool indexCheck = static_cast<unsigned int>(count) + 1 >
   2058                      (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int));
   2059    ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck,
   2060                "Failed to create a 32-bit looping index buffer for "
   2061                "GL_LINE_LOOP, too many indices required.",
   2062                GL_OUT_OF_MEMORY);
   2063 
   2064    GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
   2065                       glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
   2066 
   2067    unsigned int spaceNeeded =
   2068        static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
   2069    ANGLE_TRY(
   2070        mLineLoopIB->reserveBufferSpace(context, spaceNeeded, gl::DrawElementsType::UnsignedInt));
   2071 
   2072    void *mappedMemory = nullptr;
   2073    unsigned int offset;
   2074    ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
   2075 
   2076    // Copy over the converted index data.
   2077    memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
   2078           sizeof(GLuint) * mScratchIndexDataBuffer.size());
   2079 
   2080    ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
   2081 
   2082    IndexBuffer11 *indexBuffer          = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
   2083    const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
   2084    DXGI_FORMAT indexFormat             = indexBuffer->getIndexFormat();
   2085 
   2086    mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
   2087 
   2088    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
   2089 
   2090    if (instances > 0)
   2091    {
   2092        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
   2093    }
   2094    else
   2095    {
   2096        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
   2097    }
   2098 
   2099    return angle::Result::Continue;
   2100 }
   2101 
   2102 angle::Result Renderer11::drawTriangleFan(const gl::Context *context,
   2103                                          GLuint count,
   2104                                          gl::DrawElementsType type,
   2105                                          const void *indices,
   2106                                          int baseVertex,
   2107                                          int instances)
   2108 {
   2109    const gl::State &glState       = context->getState();
   2110    gl::VertexArray *vao           = glState.getVertexArray();
   2111    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
   2112 
   2113    const void *indexPointer = indices;
   2114 
   2115    // Get the raw indices for an indexed draw
   2116    if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
   2117    {
   2118        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
   2119        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
   2120 
   2121        const uint8_t *bufferData = nullptr;
   2122        ANGLE_TRY(storage->getData(context, &bufferData));
   2123 
   2124        indexPointer = bufferData + offset;
   2125    }
   2126 
   2127    if (!mTriangleFanIB)
   2128    {
   2129        mTriangleFanIB = new StreamingIndexBufferInterface(this);
   2130        ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
   2131                                                     gl::DrawElementsType::UnsignedInt));
   2132    }
   2133 
   2134    // Checked by Renderer11::applyPrimitiveType
   2135    ASSERT(count >= 3);
   2136 
   2137    const GLuint numTris = count - 2;
   2138 
   2139    bool indexCheck =
   2140        (numTris > std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3));
   2141    ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck,
   2142                "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, "
   2143                "too many indices required.",
   2144                GL_OUT_OF_MEMORY);
   2145 
   2146    GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(),
   2147                     &mScratchIndexDataBuffer);
   2148 
   2149    const unsigned int spaceNeeded =
   2150        static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
   2151    ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, spaceNeeded,
   2152                                                 gl::DrawElementsType::UnsignedInt));
   2153 
   2154    void *mappedMemory = nullptr;
   2155    unsigned int offset;
   2156    ANGLE_TRY(mTriangleFanIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
   2157 
   2158    memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
   2159 
   2160    ANGLE_TRY(mTriangleFanIB->unmapBuffer(context));
   2161 
   2162    IndexBuffer11 *indexBuffer          = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
   2163    const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
   2164    DXGI_FORMAT indexFormat             = indexBuffer->getIndexFormat();
   2165 
   2166    mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
   2167 
   2168    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
   2169 
   2170    if (instances > 0)
   2171    {
   2172        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
   2173    }
   2174    else
   2175    {
   2176        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
   2177    }
   2178 
   2179    return angle::Result::Continue;
   2180 }
   2181 
   2182 void Renderer11::releaseDeviceResources()
   2183 {
   2184    mStateManager.deinitialize();
   2185    mStateCache.clear();
   2186 
   2187    SafeDelete(mLineLoopIB);
   2188    SafeDelete(mTriangleFanIB);
   2189    SafeDelete(mBlit);
   2190    SafeDelete(mClear);
   2191    SafeDelete(mTrim);
   2192    SafeDelete(mPixelTransfer);
   2193 
   2194    mSyncQuery.reset();
   2195 
   2196    mCachedResolveTexture.reset();
   2197 }
   2198 
   2199 // set notify to true to broadcast a message to all contexts of the device loss
   2200 bool Renderer11::testDeviceLost()
   2201 {
   2202    if (!mDevice)
   2203    {
   2204        return true;
   2205    }
   2206 
   2207    // GetRemovedReason is used to test if the device is removed
   2208    HRESULT result = mDevice->GetDeviceRemovedReason();
   2209    bool isLost    = FAILED(result);
   2210 
   2211    if (isLost)
   2212    {
   2213        ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
   2214    }
   2215 
   2216    return isLost;
   2217 }
   2218 
   2219 bool Renderer11::testDeviceResettable()
   2220 {
   2221    // determine if the device is resettable by creating a mock device
   2222    PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
   2223        (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
   2224 
   2225    if (D3D11CreateDevice == nullptr)
   2226    {
   2227        return false;
   2228    }
   2229 
   2230    ID3D11Device *mockDevice;
   2231    D3D_FEATURE_LEVEL mockFeatureLevel;
   2232    ID3D11DeviceContext *mockContext;
   2233    UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0);
   2234 
   2235    ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
   2236    HRESULT result = D3D11CreateDevice(
   2237        nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(),
   2238        static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mockDevice,
   2239        &mockFeatureLevel, &mockContext);
   2240 
   2241    if (!mDevice || FAILED(result))
   2242    {
   2243        return false;
   2244    }
   2245 
   2246    SafeRelease(mockContext);
   2247    SafeRelease(mockDevice);
   2248 
   2249    return true;
   2250 }
   2251 
   2252 void Renderer11::release()
   2253 {
   2254    mScratchMemoryBuffer.clear();
   2255 
   2256    mAnnotatorContext.release();
   2257    gl::UninitializeDebugAnnotations();
   2258 
   2259    releaseDeviceResources();
   2260 
   2261    SafeRelease(mDxgiFactory);
   2262    SafeRelease(mDxgiAdapter);
   2263 
   2264    SafeRelease(mDeviceContext3);
   2265    SafeRelease(mDeviceContext1);
   2266 
   2267    if (mDeviceContext)
   2268    {
   2269        mDeviceContext->ClearState();
   2270        mDeviceContext->Flush();
   2271        SafeRelease(mDeviceContext);
   2272    }
   2273 
   2274    SafeRelease(mDevice);
   2275    SafeRelease(mDevice1);
   2276    SafeRelease(mDebug);
   2277 
   2278    if (mD3d11Module)
   2279    {
   2280        FreeLibrary(mD3d11Module);
   2281        mD3d11Module = nullptr;
   2282    }
   2283 
   2284    if (mDxgiModule)
   2285    {
   2286        FreeLibrary(mDxgiModule);
   2287        mDxgiModule = nullptr;
   2288    }
   2289 
   2290    if (mDCompModule)
   2291    {
   2292        FreeLibrary(mDCompModule);
   2293        mDCompModule = nullptr;
   2294    }
   2295 
   2296    mDevice12.Reset();
   2297    mCommandQueue.Reset();
   2298 
   2299    if (mD3d12Module)
   2300    {
   2301        FreeLibrary(mD3d12Module);
   2302        mD3d12Module = nullptr;
   2303    }
   2304 
   2305    mCompiler.release();
   2306 
   2307    mSupportsShareHandles.reset();
   2308 }
   2309 
   2310 bool Renderer11::resetDevice()
   2311 {
   2312    // recreate everything
   2313    release();
   2314    egl::Error result = initialize();
   2315 
   2316    if (result.isError())
   2317    {
   2318        ERR() << "Could not reinitialize D3D11 device: " << result;
   2319        return false;
   2320    }
   2321 
   2322    return true;
   2323 }
   2324 
   2325 std::string Renderer11::getRendererDescription() const
   2326 {
   2327    std::ostringstream rendererString;
   2328 
   2329    rendererString << mDescription;
   2330    rendererString << " Direct3D11";
   2331 
   2332    rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
   2333                   << getShaderModelSuffix();
   2334    rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
   2335                   << getShaderModelSuffix();
   2336 
   2337    return rendererString.str();
   2338 }
   2339 
   2340 DeviceIdentifier Renderer11::getAdapterIdentifier() const
   2341 {
   2342    // Don't use the AdapterLuid here, since that doesn't persist across reboot.
   2343    DeviceIdentifier deviceIdentifier = {};
   2344    deviceIdentifier.VendorId         = mAdapterDescription.VendorId;
   2345    deviceIdentifier.DeviceId         = mAdapterDescription.DeviceId;
   2346    deviceIdentifier.SubSysId         = mAdapterDescription.SubSysId;
   2347    deviceIdentifier.Revision         = mAdapterDescription.Revision;
   2348    deviceIdentifier.FeatureLevel     = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
   2349 
   2350    return deviceIdentifier;
   2351 }
   2352 
   2353 unsigned int Renderer11::getReservedVertexUniformVectors() const
   2354 {
   2355    // Driver uniforms are stored in a separate constant buffer
   2356    return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
   2357 }
   2358 
   2359 unsigned int Renderer11::getReservedFragmentUniformVectors() const
   2360 {
   2361    // Driver uniforms are stored in a separate constant buffer
   2362    return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
   2363 }
   2364 
   2365 gl::ShaderMap<unsigned int> Renderer11::getReservedShaderUniformBuffers() const
   2366 {
   2367    gl::ShaderMap<unsigned int> shaderReservedUniformBuffers = {};
   2368 
   2369    // we reserve one buffer for the application uniforms, and one for driver uniforms
   2370    shaderReservedUniformBuffers[gl::ShaderType::Vertex]   = 2;
   2371    shaderReservedUniformBuffers[gl::ShaderType::Fragment] = 2;
   2372 
   2373    return shaderReservedUniformBuffers;
   2374 }
   2375 
   2376 d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
   2377 {
   2378    if (mCreatedWithDeviceEXT)
   2379    {
   2380        return d3d11::GetDeviceType(mDevice);
   2381    }
   2382 
   2383    if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
   2384        (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
   2385        (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
   2386    {
   2387        return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
   2388    }
   2389 
   2390    if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
   2391    {
   2392        return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
   2393    }
   2394 
   2395    return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
   2396 }
   2397 
   2398 bool Renderer11::getShareHandleSupport() const
   2399 {
   2400    if (mSupportsShareHandles.valid())
   2401    {
   2402        return mSupportsShareHandles.value();
   2403    }
   2404 
   2405    // We only currently support share handles with BGRA surfaces, because
   2406    // chrome needs BGRA. Once chrome fixes this, we should always support them.
   2407    if (!getNativeExtensions().textureFormatBGRA8888EXT)
   2408    {
   2409        mSupportsShareHandles = false;
   2410        return false;
   2411    }
   2412 
   2413    // PIX doesn't seem to support using share handles, so disable them.
   2414    if (mAnnotatorContext.getStatus())
   2415    {
   2416        mSupportsShareHandles = false;
   2417        return false;
   2418    }
   2419 
   2420    // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
   2421    // RGBA8 textures/swapchains.
   2422    if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
   2423    {
   2424        mSupportsShareHandles = false;
   2425        return false;
   2426    }
   2427 
   2428    // Find out which type of D3D11 device the Renderer11 is using
   2429    d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
   2430    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
   2431    {
   2432        mSupportsShareHandles = false;
   2433        return false;
   2434    }
   2435 
   2436    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
   2437    {
   2438        // Software/Reference/NULL devices don't support share handles
   2439        mSupportsShareHandles = false;
   2440        return false;
   2441    }
   2442 
   2443    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
   2444    {
   2445 #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
   2446        if (!IsWindows8OrGreater())
   2447        {
   2448            // WARP on Windows 7 doesn't support shared handles
   2449            mSupportsShareHandles = false;
   2450            return false;
   2451        }
   2452 #endif  // !defined(ANGLE_ENABLE_WINDOWS_UWP)
   2453 
   2454        // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
   2455        // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
   2456        //       to prevent them trying to use a WARP share handle with an a HW device (or
   2457        //       vice-versa)
   2458        //       e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
   2459        mSupportsShareHandles = true;
   2460        return true;
   2461    }
   2462 
   2463    ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
   2464    mSupportsShareHandles = true;
   2465    return true;
   2466 }
   2467 
   2468 int Renderer11::getMajorShaderModel() const
   2469 {
   2470    switch (mRenderer11DeviceCaps.featureLevel)
   2471    {
   2472        case D3D_FEATURE_LEVEL_11_1:
   2473        case D3D_FEATURE_LEVEL_11_0:
   2474            return D3D11_SHADER_MAJOR_VERSION;  // 5
   2475        case D3D_FEATURE_LEVEL_10_1:
   2476            return D3D10_1_SHADER_MAJOR_VERSION;  // 4
   2477        case D3D_FEATURE_LEVEL_10_0:
   2478            return D3D10_SHADER_MAJOR_VERSION;  // 4
   2479        case D3D_FEATURE_LEVEL_9_3:
   2480            return D3D10_SHADER_MAJOR_VERSION;  // 4
   2481        default:
   2482            UNREACHABLE();
   2483            return 0;
   2484    }
   2485 }
   2486 
   2487 int Renderer11::getMinorShaderModel() const
   2488 {
   2489    switch (mRenderer11DeviceCaps.featureLevel)
   2490    {
   2491        case D3D_FEATURE_LEVEL_11_1:
   2492        case D3D_FEATURE_LEVEL_11_0:
   2493            return D3D11_SHADER_MINOR_VERSION;  // 0
   2494        case D3D_FEATURE_LEVEL_10_1:
   2495            return D3D10_1_SHADER_MINOR_VERSION;  // 1
   2496        case D3D_FEATURE_LEVEL_10_0:
   2497            return D3D10_SHADER_MINOR_VERSION;  // 0
   2498        case D3D_FEATURE_LEVEL_9_3:
   2499            return D3D10_SHADER_MINOR_VERSION;  // 0
   2500        default:
   2501            UNREACHABLE();
   2502            return 0;
   2503    }
   2504 }
   2505 
   2506 std::string Renderer11::getShaderModelSuffix() const
   2507 {
   2508    switch (mRenderer11DeviceCaps.featureLevel)
   2509    {
   2510        case D3D_FEATURE_LEVEL_11_1:
   2511        case D3D_FEATURE_LEVEL_11_0:
   2512            return "";
   2513        case D3D_FEATURE_LEVEL_10_1:
   2514            return "";
   2515        case D3D_FEATURE_LEVEL_10_0:
   2516            return "";
   2517        case D3D_FEATURE_LEVEL_9_3:
   2518            return "_level_9_3";
   2519        default:
   2520            UNREACHABLE();
   2521            return "";
   2522    }
   2523 }
   2524 
   2525 angle::Result Renderer11::copyImageInternal(const gl::Context *context,
   2526                                            const gl::Framebuffer *framebuffer,
   2527                                            const gl::Rectangle &sourceRect,
   2528                                            GLenum destFormat,
   2529                                            const gl::Offset &destOffset,
   2530                                            RenderTargetD3D *destRenderTarget)
   2531 {
   2532    const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorAttachment();
   2533    ASSERT(colorAttachment);
   2534 
   2535    RenderTarget11 *sourceRenderTarget = nullptr;
   2536    ANGLE_TRY(colorAttachment->getRenderTarget(context, 0, &sourceRenderTarget));
   2537    ASSERT(sourceRenderTarget);
   2538 
   2539    const d3d11::RenderTargetView &dest =
   2540        GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
   2541    ASSERT(dest.valid());
   2542 
   2543    gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
   2544    gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
   2545 
   2546    const bool invertSource = UsePresentPathFast(this, colorAttachment);
   2547    if (invertSource)
   2548    {
   2549        sourceArea.y      = sourceSize.height - sourceRect.y;
   2550        sourceArea.height = -sourceArea.height;
   2551    }
   2552 
   2553    gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
   2554    gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
   2555 
   2556    // Use nearest filtering because source and destination are the same size for the direct copy.
   2557    // Convert to the unsized format before calling copyTexture.
   2558    GLenum sourceFormat = colorAttachment->getFormat().info->format;
   2559    if (sourceRenderTarget->getTexture().is2D() && sourceRenderTarget->isMultisampled())
   2560    {
   2561        TextureHelper11 tex;
   2562        ANGLE_TRY(resolveMultisampledTexture(context, sourceRenderTarget,
   2563                                             colorAttachment->getDepthSize() > 0,
   2564                                             colorAttachment->getStencilSize() > 0, &tex));
   2565 
   2566        D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
   2567        viewDesc.Format                    = sourceRenderTarget->getFormatSet().srvFormat;
   2568        viewDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
   2569        viewDesc.Texture2D.MipLevels       = 1;
   2570        viewDesc.Texture2D.MostDetailedMip = 0;
   2571 
   2572        d3d11::SharedSRV readSRV;
   2573        ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, tex.get(), &readSRV));
   2574        ASSERT(readSRV.valid());
   2575 
   2576        ANGLE_TRY(mBlit->copyTexture(context, readSRV, sourceArea, sourceSize, sourceFormat, dest,
   2577                                     destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
   2578                                     GL_NONE, GL_NEAREST, false, false, false));
   2579 
   2580        return angle::Result::Continue;
   2581    }
   2582 
   2583    ASSERT(!sourceRenderTarget->isMultisampled());
   2584 
   2585    const d3d11::SharedSRV *source;
   2586    ANGLE_TRY(sourceRenderTarget->getBlitShaderResourceView(context, &source));
   2587    ASSERT(source->valid());
   2588 
   2589    ANGLE_TRY(mBlit->copyTexture(context, *source, sourceArea, sourceSize, sourceFormat, dest,
   2590                                 destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
   2591                                 GL_NONE, GL_NEAREST, false, false, false));
   2592 
   2593    return angle::Result::Continue;
   2594 }
   2595 
   2596 angle::Result Renderer11::copyImage2D(const gl::Context *context,
   2597                                      const gl::Framebuffer *framebuffer,
   2598                                      const gl::Rectangle &sourceRect,
   2599                                      GLenum destFormat,
   2600                                      const gl::Offset &destOffset,
   2601                                      TextureStorage *storage,
   2602                                      GLint level)
   2603 {
   2604    TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
   2605    ASSERT(storage11);
   2606 
   2607    gl::ImageIndex index              = gl::ImageIndex::Make2D(level);
   2608    RenderTargetD3D *destRenderTarget = nullptr;
   2609    ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
   2610                                         &destRenderTarget));
   2611    ASSERT(destRenderTarget);
   2612 
   2613    ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
   2614                                destRenderTarget));
   2615 
   2616    storage11->markLevelDirty(level);
   2617 
   2618    return angle::Result::Continue;
   2619 }
   2620 
   2621 angle::Result Renderer11::copyImageCube(const gl::Context *context,
   2622                                        const gl::Framebuffer *framebuffer,
   2623                                        const gl::Rectangle &sourceRect,
   2624                                        GLenum destFormat,
   2625                                        const gl::Offset &destOffset,
   2626                                        TextureStorage *storage,
   2627                                        gl::TextureTarget target,
   2628                                        GLint level)
   2629 {
   2630    TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
   2631    ASSERT(storage11);
   2632 
   2633    gl::ImageIndex index              = gl::ImageIndex::MakeCubeMapFace(target, level);
   2634    RenderTargetD3D *destRenderTarget = nullptr;
   2635    ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
   2636                                         &destRenderTarget));
   2637    ASSERT(destRenderTarget);
   2638 
   2639    ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
   2640                                destRenderTarget));
   2641 
   2642    storage11->markLevelDirty(level);
   2643 
   2644    return angle::Result::Continue;
   2645 }
   2646 
   2647 angle::Result Renderer11::copyImage3D(const gl::Context *context,
   2648                                      const gl::Framebuffer *framebuffer,
   2649                                      const gl::Rectangle &sourceRect,
   2650                                      GLenum destFormat,
   2651                                      const gl::Offset &destOffset,
   2652                                      TextureStorage *storage,
   2653                                      GLint level)
   2654 {
   2655    TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
   2656    ASSERT(storage11);
   2657 
   2658    gl::ImageIndex index              = gl::ImageIndex::Make3D(level, destOffset.z);
   2659    RenderTargetD3D *destRenderTarget = nullptr;
   2660    ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
   2661                                         &destRenderTarget));
   2662    ASSERT(destRenderTarget);
   2663 
   2664    ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
   2665                                destRenderTarget));
   2666 
   2667    storage11->markLevelDirty(level);
   2668 
   2669    return angle::Result::Continue;
   2670 }
   2671 
   2672 angle::Result Renderer11::copyImage2DArray(const gl::Context *context,
   2673                                           const gl::Framebuffer *framebuffer,
   2674                                           const gl::Rectangle &sourceRect,
   2675                                           GLenum destFormat,
   2676                                           const gl::Offset &destOffset,
   2677                                           TextureStorage *storage,
   2678                                           GLint level)
   2679 {
   2680    TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
   2681    ASSERT(storage11);
   2682 
   2683    gl::ImageIndex index              = gl::ImageIndex::Make2DArray(level, destOffset.z);
   2684    RenderTargetD3D *destRenderTarget = nullptr;
   2685    ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
   2686                                         &destRenderTarget));
   2687    ASSERT(destRenderTarget);
   2688 
   2689    ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
   2690                                destRenderTarget));
   2691    storage11->markLevelDirty(level);
   2692 
   2693    return angle::Result::Continue;
   2694 }
   2695 
   2696 angle::Result Renderer11::copyTexture(const gl::Context *context,
   2697                                      const gl::Texture *source,
   2698                                      GLint sourceLevel,
   2699                                      gl::TextureTarget srcTarget,
   2700                                      const gl::Box &sourceBox,
   2701                                      GLenum destFormat,
   2702                                      GLenum destType,
   2703                                      const gl::Offset &destOffset,
   2704                                      TextureStorage *storage,
   2705                                      gl::TextureTarget destTarget,
   2706                                      GLint destLevel,
   2707                                      bool unpackFlipY,
   2708                                      bool unpackPremultiplyAlpha,
   2709                                      bool unpackUnmultiplyAlpha)
   2710 {
   2711 
   2712    TextureD3D *sourceD3D                = GetImplAs<TextureD3D>(source);
   2713    const gl::ImageDesc &sourceImageDesc = source->getTextureState().getImageDesc(
   2714        NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
   2715 
   2716    TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage);
   2717    ASSERT(destStorage11);
   2718 
   2719    // Check for fast path where a CopySubresourceRegion can be used.
   2720    if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
   2721        sourceImageDesc.format.info->sizedInternalFormat ==
   2722            destStorage11->getFormatSet().internalFormat)
   2723    {
   2724        const TextureHelper11 *destResource = nullptr;
   2725        ANGLE_TRY(destStorage11->getResource(context, &destResource));
   2726 
   2727        if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D)
   2728        {
   2729            gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel, 1);
   2730            const TextureHelper11 *sourceResource = nullptr;
   2731            UINT sourceSubresource                = 0;
   2732            ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage(context, sourceD3D, sourceIndex,
   2733                                                              &sourceResource, &sourceSubresource));
   2734 
   2735            gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1);
   2736 
   2737            UINT destSubresource = 0;
   2738            ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
   2739 
   2740            D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
   2741                             static_cast<UINT>(sourceBox.y),
   2742                             static_cast<UINT>(sourceBox.z),
   2743                             static_cast<UINT>(sourceBox.x + sourceBox.width),
   2744                             static_cast<UINT>(sourceBox.y + sourceBox.height),
   2745                             static_cast<UINT>(sourceBox.z + sourceBox.depth)};
   2746 
   2747            mDeviceContext->CopySubresourceRegion(
   2748                destResource->get(), destSubresource, destOffset.x, destOffset.y, destOffset.z,
   2749                sourceResource->get(), sourceSubresource, &d3dBox);
   2750        }
   2751        else if (srcTarget == gl::TextureTarget::_2DArray)
   2752        {
   2753            D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
   2754                             static_cast<UINT>(sourceBox.y),
   2755                             0,
   2756                             static_cast<UINT>(sourceBox.x + sourceBox.width),
   2757                             static_cast<UINT>(sourceBox.y + sourceBox.height),
   2758                             1u};
   2759 
   2760            for (int i = 0; i < sourceBox.depth; i++)
   2761            {
   2762                gl::ImageIndex sourceIndex =
   2763                    gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z);
   2764                const TextureHelper11 *sourceResource = nullptr;
   2765                UINT sourceSubresource                = 0;
   2766                ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage(
   2767                    context, sourceD3D, sourceIndex, &sourceResource, &sourceSubresource));
   2768 
   2769                gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z);
   2770                UINT destSubresource  = 0;
   2771                ANGLE_TRY(destStorage11->getSubresourceIndex(context, dIndex, &destSubresource));
   2772 
   2773                mDeviceContext->CopySubresourceRegion(
   2774                    destResource->get(), destSubresource, destOffset.x, destOffset.y, 0,
   2775                    sourceResource->get(), sourceSubresource, &d3dBox);
   2776            }
   2777        }
   2778        else
   2779        {
   2780            UNREACHABLE();
   2781        }
   2782    }
   2783    else
   2784    {
   2785        TextureStorage *sourceStorage = nullptr;
   2786        ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
   2787 
   2788        TextureStorage11 *sourceStorage11 = GetAs<TextureStorage11>(sourceStorage);
   2789        ASSERT(sourceStorage11);
   2790 
   2791        const d3d11::SharedSRV *sourceSRV = nullptr;
   2792        ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
   2793 
   2794        gl::ImageIndex destIndex;
   2795        if (destTarget == gl::TextureTarget::_2D || destTarget == gl::TextureTarget::_3D ||
   2796            gl::IsCubeMapFaceTarget(destTarget))
   2797        {
   2798            destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1);
   2799        }
   2800        else if (destTarget == gl::TextureTarget::_2DArray)
   2801        {
   2802            destIndex = gl::ImageIndex::Make2DArrayRange(destLevel, 0, sourceImageDesc.size.depth);
   2803        }
   2804        else
   2805        {
   2806            UNREACHABLE();
   2807        }
   2808 
   2809        RenderTargetD3D *destRenderTargetD3D = nullptr;
   2810        ANGLE_TRY(destStorage11->getRenderTarget(
   2811            context, destIndex, destStorage11->getRenderToTextureSamples(), &destRenderTargetD3D));
   2812 
   2813        RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
   2814 
   2815        const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
   2816        ASSERT(destRTV.valid());
   2817 
   2818        gl::Box sourceArea(sourceBox.x, sourceBox.y, sourceBox.z, sourceBox.width, sourceBox.height,
   2819                           sourceBox.depth);
   2820 
   2821        if (unpackFlipY)
   2822        {
   2823            sourceArea.y += sourceArea.height;
   2824            sourceArea.height = -sourceArea.height;
   2825        }
   2826 
   2827        gl::Box destArea(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
   2828                         sourceBox.height, sourceBox.depth);
   2829 
   2830        gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(),
   2831                             sourceBox.depth);
   2832 
   2833        // Use nearest filtering because source and destination are the same size for the direct
   2834        // copy
   2835        GLenum sourceFormat = source->getFormat(srcTarget, sourceLevel).info->format;
   2836        ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceImageDesc.size,
   2837                                     sourceFormat, destRTV, destArea, destSize, nullptr, destFormat,
   2838                                     destType, GL_NEAREST, false, unpackPremultiplyAlpha,
   2839                                     unpackUnmultiplyAlpha));
   2840    }
   2841 
   2842    destStorage11->markLevelDirty(destLevel);
   2843 
   2844    return angle::Result::Continue;
   2845 }
   2846 
   2847 angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
   2848                                                const gl::Texture *source,
   2849                                                GLint sourceLevel,
   2850                                                TextureStorage *storage,
   2851                                                GLint destLevel)
   2852 {
   2853    TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
   2854    ASSERT(destStorage11);
   2855 
   2856    const TextureHelper11 *destResource = nullptr;
   2857    ANGLE_TRY(destStorage11->getResource(context, &destResource));
   2858 
   2859    gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
   2860    UINT destSubresource     = 0;
   2861    ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
   2862 
   2863    TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
   2864    ASSERT(sourceD3D);
   2865 
   2866    TextureStorage *sourceStorage = nullptr;
   2867    ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
   2868 
   2869    TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
   2870    ASSERT(sourceStorage11);
   2871 
   2872    const TextureHelper11 *sourceResource = nullptr;
   2873    ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
   2874 
   2875    gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
   2876    UINT sourceSubresource     = 0;
   2877    ANGLE_TRY(sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
   2878 
   2879    mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
   2880                                          sourceResource->get(), sourceSubresource, nullptr);
   2881 
   2882    return angle::Result::Continue;
   2883 }
   2884 
   2885 angle::Result Renderer11::createRenderTarget(const gl::Context *context,
   2886                                             int width,
   2887                                             int height,
   2888                                             GLenum format,
   2889                                             GLsizei samples,
   2890                                             RenderTargetD3D **outRT)
   2891 {
   2892    const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
   2893 
   2894    const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
   2895    GLuint supportedSamples            = textureCaps.getNearestSamples(samples);
   2896 
   2897    Context11 *context11 = GetImplAs<Context11>(context);
   2898 
   2899    if (width > 0 && height > 0)
   2900    {
   2901        // Create texture resource
   2902        D3D11_TEXTURE2D_DESC desc;
   2903        desc.Width              = width;
   2904        desc.Height             = height;
   2905        desc.MipLevels          = 1;
   2906        desc.ArraySize          = 1;
   2907        desc.Format             = formatInfo.texFormat;
   2908        desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
   2909        desc.SampleDesc.Quality = getSampleDescQuality(supportedSamples);
   2910        desc.Usage              = D3D11_USAGE_DEFAULT;
   2911        desc.CPUAccessFlags     = 0;
   2912        desc.MiscFlags          = 0;
   2913 
   2914        // If a rendertarget or depthstencil format exists for this texture format,
   2915        // we'll flag it to allow binding that way. Shader resource views are a little
   2916        // more complicated.
   2917        bool bindRTV = false, bindDSV = false, bindSRV = false;
   2918        bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
   2919        bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
   2920        bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
   2921 
   2922        bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
   2923        if (isMultisampledDepthStencil &&
   2924            !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs)
   2925        {
   2926            bindSRV = false;
   2927        }
   2928 
   2929        desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
   2930                         (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
   2931                         (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
   2932 
   2933        // The format must be either an RTV or a DSV
   2934        ASSERT(bindRTV != bindDSV);
   2935 
   2936        TextureHelper11 texture;
   2937        ANGLE_TRY(allocateTexture(context11, desc, formatInfo, &texture));
   2938        texture.setInternalName("createRenderTarget.Texture");
   2939 
   2940        d3d11::SharedSRV srv;
   2941        d3d11::SharedSRV blitSRV;
   2942        if (bindSRV)
   2943        {
   2944            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   2945            srvDesc.Format        = formatInfo.srvFormat;
   2946            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
   2947                                                            : D3D11_SRV_DIMENSION_TEXTURE2DMS;
   2948            srvDesc.Texture2D.MostDetailedMip = 0;
   2949            srvDesc.Texture2D.MipLevels       = 1;
   2950 
   2951            ANGLE_TRY(allocateResource(context11, srvDesc, texture.get(), &srv));
   2952            srv.setInternalName("createRenderTarget.SRV");
   2953 
   2954            if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
   2955            {
   2956                D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
   2957                blitSRVDesc.Format                    = formatInfo.blitSRVFormat;
   2958                blitSRVDesc.ViewDimension             = (supportedSamples == 0)
   2959                                                            ? D3D11_SRV_DIMENSION_TEXTURE2D
   2960                                                            : D3D11_SRV_DIMENSION_TEXTURE2DMS;
   2961                blitSRVDesc.Texture2D.MostDetailedMip = 0;
   2962                blitSRVDesc.Texture2D.MipLevels       = 1;
   2963 
   2964                ANGLE_TRY(allocateResource(context11, blitSRVDesc, texture.get(), &blitSRV));
   2965                blitSRV.setInternalName("createRenderTarget.BlitSRV");
   2966            }
   2967            else
   2968            {
   2969                blitSRV = srv.makeCopy();
   2970            }
   2971        }
   2972 
   2973        if (bindDSV)
   2974        {
   2975            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
   2976            dsvDesc.Format             = formatInfo.dsvFormat;
   2977            dsvDesc.ViewDimension      = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
   2978                                                                 : D3D11_DSV_DIMENSION_TEXTURE2DMS;
   2979            dsvDesc.Texture2D.MipSlice = 0;
   2980            dsvDesc.Flags              = 0;
   2981 
   2982            d3d11::DepthStencilView dsv;
   2983            ANGLE_TRY(allocateResource(context11, dsvDesc, texture.get(), &dsv));
   2984            dsv.setInternalName("createRenderTarget.DSV");
   2985 
   2986            *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo,
   2987                                               width, height, 1, supportedSamples);
   2988        }
   2989        else if (bindRTV)
   2990        {
   2991            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   2992            rtvDesc.Format             = formatInfo.rtvFormat;
   2993            rtvDesc.ViewDimension      = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
   2994                                                                 : D3D11_RTV_DIMENSION_TEXTURE2DMS;
   2995            rtvDesc.Texture2D.MipSlice = 0;
   2996 
   2997            d3d11::RenderTargetView rtv;
   2998            ANGLE_TRY(allocateResource(context11, rtvDesc, texture.get(), &rtv));
   2999            rtv.setInternalName("createRenderTarget.RTV");
   3000 
   3001            if (formatInfo.dataInitializerFunction != nullptr)
   3002            {
   3003                const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
   3004                mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
   3005            }
   3006 
   3007            *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
   3008                                               formatInfo, width, height, 1, supportedSamples);
   3009        }
   3010        else
   3011        {
   3012            UNREACHABLE();
   3013        }
   3014    }
   3015    else
   3016    {
   3017        *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(),
   3018                                           d3d11::SharedSRV(), d3d11::SharedSRV(), format,
   3019                                           d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps),
   3020                                           width, height, 1, supportedSamples);
   3021    }
   3022 
   3023    return angle::Result::Continue;
   3024 }
   3025 
   3026 angle::Result Renderer11::createRenderTargetCopy(const gl::Context *context,
   3027                                                 RenderTargetD3D *source,
   3028                                                 RenderTargetD3D **outRT)
   3029 {
   3030    ASSERT(source != nullptr);
   3031 
   3032    RenderTargetD3D *newRT = nullptr;
   3033    ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(),
   3034                                 source->getInternalFormat(), source->getSamples(), &newRT));
   3035 
   3036    RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
   3037    RenderTarget11 *dest11   = GetAs<RenderTarget11>(newRT);
   3038 
   3039    mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(),
   3040                                          0, 0, 0, source11->getTexture().get(),
   3041                                          source11->getSubresourceIndex(), nullptr);
   3042    *outRT = newRT;
   3043    return angle::Result::Continue;
   3044 }
   3045 
   3046 angle::Result Renderer11::loadExecutable(d3d::Context *context,
   3047                                         const uint8_t *function,
   3048                                         size_t length,
   3049                                         gl::ShaderType type,
   3050                                         const std::vector<D3DVarying> &streamOutVaryings,
   3051                                         bool separatedOutputBuffers,
   3052                                         ShaderExecutableD3D **outExecutable)
   3053 {
   3054    ShaderData shaderData(function, length);
   3055 
   3056    switch (type)
   3057    {
   3058        case gl::ShaderType::Vertex:
   3059        {
   3060            d3d11::VertexShader vertexShader;
   3061            d3d11::GeometryShader streamOutShader;
   3062            ANGLE_TRY(allocateResource(context, shaderData, &vertexShader));
   3063 
   3064            if (!streamOutVaryings.empty())
   3065            {
   3066                std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
   3067                soDeclaration.reserve(streamOutVaryings.size());
   3068 
   3069                for (const auto &streamOutVarying : streamOutVaryings)
   3070                {
   3071                    D3D11_SO_DECLARATION_ENTRY entry = {};
   3072                    entry.Stream                     = 0;
   3073                    entry.SemanticName               = streamOutVarying.semanticName.c_str();
   3074                    entry.SemanticIndex              = streamOutVarying.semanticIndex;
   3075                    entry.StartComponent             = 0;
   3076                    entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
   3077                    entry.OutputSlot     = static_cast<BYTE>(
   3078                        (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
   3079                    soDeclaration.push_back(entry);
   3080                }
   3081 
   3082                ANGLE_TRY(allocateResource(context, shaderData, &soDeclaration, &streamOutShader));
   3083            }
   3084 
   3085            *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader),
   3086                                                    std::move(streamOutShader));
   3087        }
   3088        break;
   3089        case gl::ShaderType::Fragment:
   3090        {
   3091            d3d11::PixelShader pixelShader;
   3092            ANGLE_TRY(allocateResource(context, shaderData, &pixelShader));
   3093            *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader));
   3094        }
   3095        break;
   3096        case gl::ShaderType::Geometry:
   3097        {
   3098            d3d11::GeometryShader geometryShader;
   3099            ANGLE_TRY(allocateResource(context, shaderData, &geometryShader));
   3100            *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader));
   3101        }
   3102        break;
   3103        case gl::ShaderType::Compute:
   3104        {
   3105            d3d11::ComputeShader computeShader;
   3106            ANGLE_TRY(allocateResource(context, shaderData, &computeShader));
   3107            *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader));
   3108        }
   3109        break;
   3110        default:
   3111            ANGLE_HR_UNREACHABLE(context);
   3112    }
   3113 
   3114    return angle::Result::Continue;
   3115 }
   3116 
   3117 angle::Result Renderer11::compileToExecutable(d3d::Context *context,
   3118                                              gl::InfoLog &infoLog,
   3119                                              const std::string &shaderHLSL,
   3120                                              gl::ShaderType type,
   3121                                              const std::vector<D3DVarying> &streamOutVaryings,
   3122                                              bool separatedOutputBuffers,
   3123                                              const CompilerWorkaroundsD3D &workarounds,
   3124                                              ShaderExecutableD3D **outExectuable)
   3125 {
   3126    std::stringstream profileStream;
   3127 
   3128    switch (type)
   3129    {
   3130        case gl::ShaderType::Vertex:
   3131            profileStream << "vs";
   3132            break;
   3133        case gl::ShaderType::Fragment:
   3134            profileStream << "ps";
   3135            break;
   3136        case gl::ShaderType::Geometry:
   3137            profileStream << "gs";
   3138            break;
   3139        case gl::ShaderType::Compute:
   3140            profileStream << "cs";
   3141            break;
   3142        default:
   3143            ANGLE_HR_UNREACHABLE(context);
   3144    }
   3145 
   3146    profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
   3147                  << getShaderModelSuffix();
   3148    std::string profile = profileStream.str();
   3149 
   3150    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
   3151 
   3152 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
   3153 #    ifndef NDEBUG
   3154    flags = D3DCOMPILE_SKIP_OPTIMIZATION;
   3155 #    endif  // NDEBUG
   3156    flags |= D3DCOMPILE_DEBUG;
   3157 #endif  // defined(ANGLE_ENABLE_DEBUG_TRACE)
   3158 
   3159    if (workarounds.enableIEEEStrictness)
   3160        flags |= D3DCOMPILE_IEEE_STRICTNESS;
   3161 
   3162    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
   3163    // when it would otherwise pass with alternative options.
   3164    // Try the default flags first and if compilation fails, try some alternatives.
   3165    std::vector<CompileConfig> configs;
   3166    configs.push_back(CompileConfig(flags, "default"));
   3167    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
   3168    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
   3169 
   3170    if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
   3171    {
   3172        // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
   3173        // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
   3174        // Using the [unroll] directive works around this, as does this D3DCompile flag.
   3175        configs.push_back(
   3176            CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
   3177    }
   3178 
   3179    D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
   3180 
   3181    // TODO(jmadill): Use ComPtr?
   3182    ID3DBlob *binary = nullptr;
   3183    std::string debugInfo;
   3184    ANGLE_TRY(mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs, loopMacros,
   3185                                        &binary, &debugInfo));
   3186 
   3187    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
   3188    // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
   3189    // internal state is still OK.
   3190    if (!binary)
   3191    {
   3192        *outExectuable = nullptr;
   3193        return angle::Result::Continue;
   3194    }
   3195 
   3196    angle::Result error = loadExecutable(
   3197        context, static_cast<const uint8_t *>(binary->GetBufferPointer()), binary->GetBufferSize(),
   3198        type, streamOutVaryings, separatedOutputBuffers, outExectuable);
   3199 
   3200    SafeRelease(binary);
   3201    if (error == angle::Result::Stop)
   3202    {
   3203        return error;
   3204    }
   3205 
   3206    if (!debugInfo.empty())
   3207    {
   3208        (*outExectuable)->appendDebugInfo(debugInfo);
   3209    }
   3210 
   3211    return angle::Result::Continue;
   3212 }
   3213 
   3214 angle::Result Renderer11::ensureHLSLCompilerInitialized(d3d::Context *context)
   3215 {
   3216    return mCompiler.ensureInitialized(context);
   3217 }
   3218 
   3219 UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
   3220 {
   3221    return new UniformStorage11(storageSize);
   3222 }
   3223 
   3224 VertexBuffer *Renderer11::createVertexBuffer()
   3225 {
   3226    return new VertexBuffer11(this);
   3227 }
   3228 
   3229 IndexBuffer *Renderer11::createIndexBuffer()
   3230 {
   3231    return new IndexBuffer11(this);
   3232 }
   3233 
   3234 StreamProducerImpl *Renderer11::createStreamProducerD3DTexture(
   3235    egl::Stream::ConsumerType consumerType,
   3236    const egl::AttributeMap &attribs)
   3237 {
   3238    return new StreamProducerD3DTexture(this);
   3239 }
   3240 
   3241 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
   3242 {
   3243    ASSERT(getNativeExtensions().pixelBufferObjectNV);
   3244 
   3245    const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
   3246    const d3d11::Format &d3d11FormatInfo =
   3247        d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
   3248 
   3249    // sRGB formats do not work with D3D11 buffer SRVs
   3250    if (internalFormatInfo.colorEncoding == GL_SRGB)
   3251    {
   3252        return false;
   3253    }
   3254 
   3255    // We cannot support direct copies to non-color-renderable formats
   3256    if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
   3257    {
   3258        return false;
   3259    }
   3260 
   3261    // We skip all 3-channel formats since sometimes format support is missing
   3262    if (internalFormatInfo.componentCount == 3)
   3263    {
   3264        return false;
   3265    }
   3266 
   3267    // We don't support formats which we can't represent without conversion
   3268    if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
   3269    {
   3270        return false;
   3271    }
   3272 
   3273    // Buffer SRV creation for this format was not working on Windows 10.
   3274    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
   3275    {
   3276        return false;
   3277    }
   3278 
   3279    // This format is not supported as a buffer SRV.
   3280    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
   3281    {
   3282        return false;
   3283    }
   3284 
   3285    return true;
   3286 }
   3287 
   3288 angle::Result Renderer11::fastCopyBufferToTexture(const gl::Context *context,
   3289                                                  const gl::PixelUnpackState &unpack,
   3290                                                  gl::Buffer *unpackBuffer,
   3291                                                  unsigned int offset,
   3292                                                  RenderTargetD3D *destRenderTarget,
   3293                                                  GLenum destinationFormat,
   3294                                                  GLenum sourcePixelsType,
   3295                                                  const gl::Box &destArea)
   3296 {
   3297    ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
   3298    return mPixelTransfer->copyBufferToTexture(context, unpack, unpackBuffer, offset,
   3299                                               destRenderTarget, destinationFormat,
   3300                                               sourcePixelsType, destArea);
   3301 }
   3302 
   3303 ImageD3D *Renderer11::createImage()
   3304 {
   3305    return new Image11(this);
   3306 }
   3307 
   3308 ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Context *context,
   3309                                                                 EGLenum target,
   3310                                                                 EGLClientBuffer buffer,
   3311                                                                 const egl::AttributeMap &attribs)
   3312 {
   3313    switch (target)
   3314    {
   3315        case EGL_D3D11_TEXTURE_ANGLE:
   3316            return new ExternalImageSiblingImpl11(this, buffer, attribs);
   3317 
   3318        default:
   3319            UNREACHABLE();
   3320            return nullptr;
   3321    }
   3322 }
   3323 
   3324 angle::Result Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
   3325 {
   3326    Image11 *dest11 = GetAs<Image11>(dest);
   3327    Image11 *src11  = GetAs<Image11>(src);
   3328    return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
   3329 }
   3330 
   3331 angle::Result Renderer11::generateMipmapUsingD3D(const gl::Context *context,
   3332                                                 TextureStorage *storage,
   3333                                                 const gl::TextureState &textureState)
   3334 {
   3335    TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
   3336 
   3337    ASSERT(storage11->isRenderTarget());
   3338    ASSERT(storage11->supportsNativeMipmapFunction());
   3339 
   3340    const d3d11::SharedSRV *srv = nullptr;
   3341    ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
   3342                                      textureState.getEffectiveMaxLevel(), &srv));
   3343 
   3344    mDeviceContext->GenerateMips(srv->get());
   3345 
   3346    return angle::Result::Continue;
   3347 }
   3348 
   3349 angle::Result Renderer11::copyImage(const gl::Context *context,
   3350                                    ImageD3D *dest,
   3351                                    ImageD3D *source,
   3352                                    const gl::Box &sourceBox,
   3353                                    const gl::Offset &destOffset,
   3354                                    bool unpackFlipY,
   3355                                    bool unpackPremultiplyAlpha,
   3356                                    bool unpackUnmultiplyAlpha)
   3357 {
   3358    Image11 *dest11 = GetAs<Image11>(dest);
   3359    Image11 *src11  = GetAs<Image11>(source);
   3360    return Image11::CopyImage(context, dest11, src11, sourceBox, destOffset, unpackFlipY,
   3361                              unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
   3362 }
   3363 
   3364 TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain,
   3365                                                   const std::string &label)
   3366 {
   3367    SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
   3368    return new TextureStorage11_2D(this, swapChain11, label);
   3369 }
   3370 
   3371 TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
   3372                                                         RenderTargetD3D *renderTargetD3D,
   3373                                                         const std::string &label)
   3374 {
   3375    return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D),
   3376                                         label);
   3377 }
   3378 
   3379 TextureStorage *Renderer11::createTextureStorageExternal(
   3380    egl::Stream *stream,
   3381    const egl::Stream::GLTextureDescription &desc,
   3382    const std::string &label)
   3383 {
   3384    return new TextureStorage11_External(this, stream, desc, label);
   3385 }
   3386 
   3387 TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
   3388                                                   BindFlags bindFlags,
   3389                                                   GLsizei width,
   3390                                                   GLsizei height,
   3391                                                   int levels,
   3392                                                   const std::string &label,
   3393                                                   bool hintLevelZeroOnly)
   3394 {
   3395    return new TextureStorage11_2D(this, internalformat, bindFlags, width, height, levels, label,
   3396                                   hintLevelZeroOnly);
   3397 }
   3398 
   3399 TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
   3400                                                     BindFlags bindFlags,
   3401                                                     int size,
   3402                                                     int levels,
   3403                                                     bool hintLevelZeroOnly,
   3404                                                     const std::string &label)
   3405 {
   3406    return new TextureStorage11_Cube(this, internalformat, bindFlags, size, levels,
   3407                                     hintLevelZeroOnly, label);
   3408 }
   3409 
   3410 TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
   3411                                                   BindFlags bindFlags,
   3412                                                   GLsizei width,
   3413                                                   GLsizei height,
   3414                                                   GLsizei depth,
   3415                                                   int levels,
   3416                                                   const std::string &label)
   3417 {
   3418    return new TextureStorage11_3D(this, internalformat, bindFlags, width, height, depth, levels,
   3419                                   label);
   3420 }
   3421 
   3422 TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
   3423                                                        BindFlags bindFlags,
   3424                                                        GLsizei width,
   3425                                                        GLsizei height,
   3426                                                        GLsizei depth,
   3427                                                        int levels,
   3428                                                        const std::string &label)
   3429 {
   3430    return new TextureStorage11_2DArray(this, internalformat, bindFlags, width, height, depth,
   3431                                        levels, label);
   3432 }
   3433 
   3434 TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat,
   3435                                                              GLsizei width,
   3436                                                              GLsizei height,
   3437                                                              int levels,
   3438                                                              int samples,
   3439                                                              bool fixedSampleLocations,
   3440                                                              const std::string &label)
   3441 {
   3442    return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples,
   3443                                              fixedSampleLocations, label);
   3444 }
   3445 
   3446 TextureStorage *Renderer11::createTextureStorageBuffer(
   3447    const gl::OffsetBindingPointer<gl::Buffer> &buffer,
   3448    GLenum internalFormat,
   3449    const std::string &label)
   3450 {
   3451    return new TextureStorage11_Buffer(this, buffer, internalFormat, label);
   3452 }
   3453 
   3454 TextureStorage *Renderer11::createTextureStorage2DMultisampleArray(GLenum internalformat,
   3455                                                                   GLsizei width,
   3456                                                                   GLsizei height,
   3457                                                                   GLsizei depth,
   3458                                                                   int levels,
   3459                                                                   int samples,
   3460                                                                   bool fixedSampleLocations,
   3461                                                                   const std::string &label)
   3462 {
   3463    return new TextureStorage11_2DMultisampleArray(this, internalformat, width, height, depth,
   3464                                                   levels, samples, fixedSampleLocations, label);
   3465 }
   3466 
   3467 angle::Result Renderer11::readFromAttachment(const gl::Context *context,
   3468                                             const gl::FramebufferAttachment &srcAttachment,
   3469                                             const gl::Rectangle &sourceArea,
   3470                                             GLenum format,
   3471                                             GLenum type,
   3472                                             GLuint outputPitch,
   3473                                             const gl::PixelPackState &pack,
   3474                                             uint8_t *pixelsOut)
   3475 {
   3476    ASSERT(sourceArea.width >= 0);
   3477    ASSERT(sourceArea.height >= 0);
   3478 
   3479    const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
   3480 
   3481    RenderTarget11 *rt11 = nullptr;
   3482    ANGLE_TRY(srcAttachment.getRenderTarget(context, 0, &rt11));
   3483    ASSERT(rt11->getTexture().valid());
   3484 
   3485    const TextureHelper11 &textureHelper = rt11->getTexture();
   3486    unsigned int sourceSubResource       = rt11->getSubresourceIndex();
   3487 
   3488    const gl::Extents &texSize = textureHelper.getExtents();
   3489 
   3490    gl::Rectangle actualArea = sourceArea;
   3491    bool reverseRowOrder     = pack.reverseRowOrder;
   3492    if (invertTexture)
   3493    {
   3494        actualArea.y    = texSize.height - actualArea.y - actualArea.height;
   3495        reverseRowOrder = !reverseRowOrder;
   3496    }
   3497 
   3498    // Clamp read region to the defined texture boundaries, preventing out of bounds reads
   3499    // and reads of uninitialized data.
   3500    gl::Rectangle safeArea;
   3501    safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
   3502    safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
   3503    safeArea.width =
   3504        gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
   3505    safeArea.height =
   3506        gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);
   3507 
   3508    ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
   3509    ASSERT(safeArea.x + safeArea.width <= texSize.width);
   3510    ASSERT(safeArea.y + safeArea.height <= texSize.height);
   3511 
   3512    if (safeArea.width == 0 || safeArea.height == 0)
   3513    {
   3514        // no work to do
   3515        return angle::Result::Continue;
   3516    }
   3517 
   3518    gl::Extents safeSize(safeArea.width, safeArea.height, 1);
   3519    TextureHelper11 stagingHelper;
   3520    ANGLE_TRY(createStagingTexture(context, textureHelper.getTextureType(),
   3521                                   textureHelper.getFormatSet(), safeSize, StagingAccess::READ,
   3522                                   &stagingHelper));
   3523    stagingHelper.setInternalName("readFromAttachment::stagingHelper");
   3524 
   3525    TextureHelper11 resolvedTextureHelper;
   3526 
   3527    // "srcTexture" usually points to the source texture.
   3528    // For 2D multisampled textures, it points to the multisampled resolve texture.
   3529    const TextureHelper11 *srcTexture = &textureHelper;
   3530 
   3531    if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
   3532    {
   3533        D3D11_TEXTURE2D_DESC resolveDesc;
   3534        resolveDesc.Width              = static_cast<UINT>(texSize.width);
   3535        resolveDesc.Height             = static_cast<UINT>(texSize.height);
   3536        resolveDesc.MipLevels          = 1;
   3537        resolveDesc.ArraySize          = 1;
   3538        resolveDesc.Format             = textureHelper.getFormat();
   3539        resolveDesc.SampleDesc.Count   = 1;
   3540        resolveDesc.SampleDesc.Quality = 0;
   3541        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
   3542        resolveDesc.BindFlags          = 0;
   3543        resolveDesc.CPUAccessFlags     = 0;
   3544        resolveDesc.MiscFlags          = 0;
   3545 
   3546        ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc,
   3547                                  textureHelper.getFormatSet(), &resolvedTextureHelper));
   3548        resolvedTextureHelper.setInternalName("readFromAttachment::resolvedTextureHelper");
   3549 
   3550        mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(),
   3551                                           sourceSubResource, textureHelper.getFormat());
   3552 
   3553        sourceSubResource = 0;
   3554        srcTexture        = &resolvedTextureHelper;
   3555    }
   3556 
   3557    D3D11_BOX srcBox;
   3558    srcBox.left   = static_cast<UINT>(safeArea.x);
   3559    srcBox.right  = static_cast<UINT>(safeArea.x + safeArea.width);
   3560    srcBox.top    = static_cast<UINT>(safeArea.y);
   3561    srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);
   3562 
   3563    // Select the correct layer from a 3D attachment
   3564    srcBox.front = 0;
   3565    if (textureHelper.is3D())
   3566    {
   3567        srcBox.front = static_cast<UINT>(srcAttachment.layer());
   3568    }
   3569    srcBox.back = srcBox.front + 1;
   3570 
   3571    mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(),
   3572                                          sourceSubResource, &srcBox);
   3573 
   3574    const angle::Format &angleFormat = GetFormatFromFormatType(format, type);
   3575    gl::Buffer *packBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelPack);
   3576 
   3577    PackPixelsParams packParams(safeArea, angleFormat, outputPitch, reverseRowOrder, packBuffer, 0);
   3578    return packPixels(context, stagingHelper, packParams, pixelsOut);
   3579 }
   3580 
   3581 angle::Result Renderer11::packPixels(const gl::Context *context,
   3582                                     const TextureHelper11 &textureHelper,
   3583                                     const PackPixelsParams &params,
   3584                                     uint8_t *pixelsOut)
   3585 {
   3586    ID3D11Resource *readResource = textureHelper.get();
   3587 
   3588    D3D11_MAPPED_SUBRESOURCE mapping;
   3589    ANGLE_TRY(mapResource(context, readResource, 0, D3D11_MAP_READ, 0, &mapping));
   3590 
   3591    uint8_t *source = static_cast<uint8_t *>(mapping.pData);
   3592    int inputPitch  = static_cast<int>(mapping.RowPitch);
   3593 
   3594    const auto &formatInfo = textureHelper.getFormatSet();
   3595    ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
   3596 
   3597    PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
   3598 
   3599    mDeviceContext->Unmap(readResource, 0);
   3600 
   3601    return angle::Result::Continue;
   3602 }
   3603 
   3604 angle::Result Renderer11::blitRenderbufferRect(const gl::Context *context,
   3605                                               const gl::Rectangle &readRectIn,
   3606                                               const gl::Rectangle &drawRectIn,
   3607                                               UINT readLayer,
   3608                                               UINT drawLayer,
   3609                                               RenderTargetD3D *readRenderTarget,
   3610                                               RenderTargetD3D *drawRenderTarget,
   3611                                               GLenum filter,
   3612                                               const gl::Rectangle *scissor,
   3613                                               bool colorBlit,
   3614                                               bool depthBlit,
   3615                                               bool stencilBlit)
   3616 {
   3617    // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
   3618    // it should never be the case that both color and depth/stencil need to be blitted at
   3619    // at the same time.
   3620    ASSERT(colorBlit != (depthBlit || stencilBlit));
   3621 
   3622    RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
   3623    ASSERT(drawRenderTarget11);
   3624 
   3625    const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture();
   3626    unsigned int drawSubresource       = drawRenderTarget11->getSubresourceIndex();
   3627 
   3628    RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
   3629    ASSERT(readRenderTarget11);
   3630 
   3631    const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
   3632    const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
   3633 
   3634    // From the spec:
   3635    // "The actual region taken from the read framebuffer is limited to the intersection of the
   3636    // source buffers being transferred, which may include the color buffer selected by the read
   3637    // buffer, the depth buffer, and / or the stencil buffer depending on mask."
   3638    // This means negative x and y are out of bounds, and not to be read from. We handle this here
   3639    // by internally scaling the read and draw rectangles.
   3640 
   3641    // Remove reversal from readRect to simplify further operations.
   3642    gl::Rectangle readRect = readRectIn;
   3643    gl::Rectangle drawRect = drawRectIn;
   3644    if (readRect.isReversedX())
   3645    {
   3646        readRect.x     = readRect.x + readRect.width;
   3647        readRect.width = -readRect.width;
   3648        drawRect.x     = drawRect.x + drawRect.width;
   3649        drawRect.width = -drawRect.width;
   3650    }
   3651    if (readRect.isReversedY())
   3652    {
   3653        readRect.y      = readRect.y + readRect.height;
   3654        readRect.height = -readRect.height;
   3655        drawRect.y      = drawRect.y + drawRect.height;
   3656        drawRect.height = -drawRect.height;
   3657    }
   3658 
   3659    gl::Rectangle readBounds(0, 0, readSize.width, readSize.height);
   3660    gl::Rectangle inBoundsReadRect;
   3661    if (!gl::ClipRectangle(readRect, readBounds, &inBoundsReadRect))
   3662    {
   3663        return angle::Result::Continue;
   3664    }
   3665 
   3666    {
   3667        // Calculate the drawRect that corresponds to inBoundsReadRect.
   3668        auto readToDrawX = [&drawRect, &readRect](int readOffset) {
   3669            double readToDrawScale =
   3670                static_cast<double>(drawRect.width) / static_cast<double>(readRect.width);
   3671            return static_cast<int>(
   3672                round(static_cast<double>(readOffset - readRect.x) * readToDrawScale) + drawRect.x);
   3673        };
   3674        auto readToDrawY = [&drawRect, &readRect](int readOffset) {
   3675            double readToDrawScale =
   3676                static_cast<double>(drawRect.height) / static_cast<double>(readRect.height);
   3677            return static_cast<int>(
   3678                round(static_cast<double>(readOffset - readRect.y) * readToDrawScale) + drawRect.y);
   3679        };
   3680 
   3681        gl::Rectangle drawRectMatchingInBoundsReadRect;
   3682        drawRectMatchingInBoundsReadRect.x = readToDrawX(inBoundsReadRect.x);
   3683        drawRectMatchingInBoundsReadRect.y = readToDrawY(inBoundsReadRect.y);
   3684        drawRectMatchingInBoundsReadRect.width =
   3685            readToDrawX(inBoundsReadRect.x1()) - drawRectMatchingInBoundsReadRect.x;
   3686        drawRectMatchingInBoundsReadRect.height =
   3687            readToDrawY(inBoundsReadRect.y1()) - drawRectMatchingInBoundsReadRect.y;
   3688        drawRect = drawRectMatchingInBoundsReadRect;
   3689        readRect = inBoundsReadRect;
   3690    }
   3691 
   3692    bool scissorNeeded = false;
   3693    if (scissor)
   3694    {
   3695        gl::Rectangle scissoredDrawRect;
   3696        if (!gl::ClipRectangle(drawRect, *scissor, &scissoredDrawRect))
   3697        {
   3698            return angle::Result::Continue;
   3699        }
   3700        scissorNeeded = scissoredDrawRect != drawRect;
   3701    }
   3702 
   3703    const auto &destFormatInfo =
   3704        gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
   3705    const auto &srcFormatInfo =
   3706        gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
   3707    const auto &formatSet    = drawRenderTarget11->getFormatSet();
   3708    const auto &nativeFormat = formatSet.format();
   3709 
   3710    // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
   3711    // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
   3712 
   3713    gl::Color<bool> colorMask;
   3714    colorMask.red =
   3715        (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
   3716    colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
   3717                      (nativeFormat.greenBits > 0);
   3718    colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
   3719                     (nativeFormat.blueBits > 0);
   3720    colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
   3721                      (nativeFormat.alphaBits > 0);
   3722 
   3723    // We only currently support masking off the alpha channel.
   3724    bool colorMaskingNeeded = colorMask.alpha;
   3725    ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
   3726 
   3727    bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
   3728                           readRect.width == readSize.width && readRect.y == 0 &&
   3729                           readRect.height == readSize.height && drawRect.x == 0 &&
   3730                           drawRect.width == drawSize.width && drawRect.y == 0 &&
   3731                           drawRect.height == drawSize.height;
   3732 
   3733    bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
   3734 
   3735    ASSERT(!readRect.isReversedX() && !readRect.isReversedY());
   3736    bool reversalRequired = drawRect.isReversedX() || drawRect.isReversedY();
   3737 
   3738    bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
   3739                       readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
   3740                       drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
   3741                       drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
   3742 
   3743    bool partialDSBlit =
   3744        (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
   3745 
   3746    const bool canCopySubresource =
   3747        drawRenderTarget->getSamples() == readRenderTarget->getSamples() &&
   3748        readRenderTarget11->getFormatSet().formatID ==
   3749            drawRenderTarget11->getFormatSet().formatID &&
   3750        !stretchRequired && !outOfBounds && !reversalRequired && !partialDSBlit &&
   3751        !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy);
   3752 
   3753    TextureHelper11 readTexture;
   3754    unsigned int readSubresource = 0;
   3755    d3d11::SharedSRV readSRV;
   3756 
   3757    if (readRenderTarget->isMultisampled())
   3758    {
   3759        ANGLE_TRY(resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit,
   3760                                             &readTexture));
   3761 
   3762        if (!stencilBlit && !canCopySubresource)
   3763        {
   3764            const auto &readFormatSet = readTexture.getFormatSet();
   3765 
   3766            D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
   3767            viewDesc.Format                    = readFormatSet.srvFormat;
   3768            viewDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
   3769            viewDesc.Texture2D.MipLevels       = 1;
   3770            viewDesc.Texture2D.MostDetailedMip = 0;
   3771 
   3772            ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, readTexture.get(),
   3773                                       &readSRV));
   3774        }
   3775    }
   3776    else
   3777    {
   3778        ASSERT(readRenderTarget11);
   3779        readTexture     = readRenderTarget11->getTexture();
   3780        readSubresource = readRenderTarget11->getSubresourceIndex();
   3781        if (!canCopySubresource)
   3782        {
   3783            const d3d11::SharedSRV *blitSRV;
   3784            ANGLE_TRY(readRenderTarget11->getBlitShaderResourceView(context, &blitSRV));
   3785            readSRV = blitSRV->makeCopy();
   3786            if (!readSRV.valid())
   3787            {
   3788                ASSERT(depthBlit || stencilBlit);
   3789                const d3d11::SharedSRV *srv;
   3790                ANGLE_TRY(readRenderTarget11->getShaderResourceView(context, &srv));
   3791                readSRV = srv->makeCopy();
   3792            }
   3793            ASSERT(readSRV.valid());
   3794        }
   3795    }
   3796 
   3797    if (canCopySubresource)
   3798    {
   3799        UINT dstX = drawRect.x;
   3800        UINT dstY = drawRect.y;
   3801        UINT dstZ = drawLayer;
   3802 
   3803        D3D11_BOX readBox;
   3804        readBox.left   = readRect.x;
   3805        readBox.right  = readRect.x + readRect.width;
   3806        readBox.top    = readRect.y;
   3807        readBox.bottom = readRect.y + readRect.height;
   3808        readBox.front  = readLayer;
   3809        readBox.back   = readLayer + 1;
   3810 
   3811        if (scissorNeeded)
   3812        {
   3813            // drawRect is guaranteed to have positive width and height because stretchRequired is
   3814            // false.
   3815            ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
   3816 
   3817            if (drawRect.x < scissor->x)
   3818            {
   3819                dstX = scissor->x;
   3820                readBox.left += (scissor->x - drawRect.x);
   3821            }
   3822            if (drawRect.y < scissor->y)
   3823            {
   3824                dstY = scissor->y;
   3825                readBox.top += (scissor->y - drawRect.y);
   3826            }
   3827            if (drawRect.x + drawRect.width > scissor->x + scissor->width)
   3828            {
   3829                readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
   3830            }
   3831            if (drawRect.y + drawRect.height > scissor->y + scissor->height)
   3832            {
   3833                readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
   3834            }
   3835        }
   3836 
   3837        // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
   3838        // We also require complete framebuffer copies for depth-stencil blit.
   3839        D3D11_BOX *pSrcBox = wholeBufferCopy && readLayer == 0 ? nullptr : &readBox;
   3840 
   3841        mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, dstZ,
   3842                                              readTexture.get(), readSubresource, pSrcBox);
   3843    }
   3844    else
   3845    {
   3846        gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
   3847        gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
   3848 
   3849        if (depthBlit && stencilBlit)
   3850        {
   3851            ANGLE_TRY(mBlit->copyDepthStencil(context, readTexture, readSubresource, readArea,
   3852                                              readSize, drawTexture, drawSubresource, drawArea,
   3853                                              drawSize, scissor));
   3854        }
   3855        else if (depthBlit)
   3856        {
   3857            const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView();
   3858            ASSERT(readSRV.valid());
   3859            ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea,
   3860                                       drawSize, scissor));
   3861        }
   3862        else if (stencilBlit)
   3863        {
   3864            ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize,
   3865                                         drawTexture, drawSubresource, drawArea, drawSize,
   3866                                         scissor));
   3867        }
   3868        else
   3869        {
   3870            const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
   3871 
   3872            // We don't currently support masking off any other channel than alpha
   3873            bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
   3874            ASSERT(readSRV.valid());
   3875            ANGLE_TRY(mBlit->copyTexture(context, readSRV, readArea, readSize, srcFormatInfo.format,
   3876                                         drawRTV, drawArea, drawSize, scissor,
   3877                                         destFormatInfo.format, GL_NONE, filter, maskOffAlpha,
   3878                                         false, false));
   3879        }
   3880    }
   3881 
   3882    return angle::Result::Continue;
   3883 }
   3884 
   3885 bool Renderer11::isES3Capable() const
   3886 {
   3887    return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps).major > 2);
   3888 }
   3889 
   3890 RendererClass Renderer11::getRendererClass() const
   3891 {
   3892    return RENDERER_D3D11;
   3893 }
   3894 
   3895 void Renderer11::onSwap()
   3896 {
   3897    // Send histogram updates every half hour
   3898    const double kHistogramUpdateInterval = 30 * 60;
   3899 
   3900    auto *platform                   = ANGLEPlatformCurrent();
   3901    const double currentTime         = platform->monotonicallyIncreasingTime(platform);
   3902    const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
   3903 
   3904    if (timeSinceLastUpdate > kHistogramUpdateInterval)
   3905    {
   3906        updateHistograms();
   3907        mLastHistogramUpdateTime = currentTime;
   3908    }
   3909 }
   3910 
   3911 void Renderer11::updateHistograms()
   3912 {
   3913    // Update the buffer CPU memory histogram
   3914    {
   3915        size_t sizeSum = 0;
   3916        for (const Buffer11 *buffer : mAliveBuffers)
   3917        {
   3918            sizeSum += buffer->getTotalCPUBufferMemoryBytes();
   3919        }
   3920        const int kOneMegaByte = 1024 * 1024;
   3921        ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
   3922                                  static_cast<int>(sizeSum) / kOneMegaByte);
   3923    }
   3924 }
   3925 
   3926 void Renderer11::onBufferCreate(const Buffer11 *created)
   3927 {
   3928    mAliveBuffers.insert(created);
   3929 }
   3930 
   3931 void Renderer11::onBufferDelete(const Buffer11 *deleted)
   3932 {
   3933    mAliveBuffers.erase(deleted);
   3934 }
   3935 
   3936 angle::Result Renderer11::resolveMultisampledTexture(const gl::Context *context,
   3937                                                     RenderTarget11 *renderTarget,
   3938                                                     bool depth,
   3939                                                     bool stencil,
   3940                                                     TextureHelper11 *textureOut)
   3941 {
   3942    if (depth && !stencil)
   3943    {
   3944        return mBlit->resolveDepth(context, renderTarget, textureOut);
   3945    }
   3946 
   3947    if (stencil)
   3948    {
   3949        return mBlit->resolveStencil(context, renderTarget, depth, textureOut);
   3950    }
   3951 
   3952    const auto &formatSet = renderTarget->getFormatSet();
   3953 
   3954    ASSERT(renderTarget->isMultisampled());
   3955    const d3d11::SharedSRV *sourceSRV;
   3956    ANGLE_TRY(renderTarget->getShaderResourceView(context, &sourceSRV));
   3957    D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
   3958    sourceSRV->get()->GetDesc(&sourceSRVDesc);
   3959    ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS ||
   3960           sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMSARRAY);
   3961 
   3962    if (!mCachedResolveTexture.valid() ||
   3963        mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
   3964        mCachedResolveTexture.getExtents().height != renderTarget->getHeight() ||
   3965        mCachedResolveTexture.getFormat() != formatSet.texFormat)
   3966    {
   3967        D3D11_TEXTURE2D_DESC resolveDesc;
   3968        resolveDesc.Width              = renderTarget->getWidth();
   3969        resolveDesc.Height             = renderTarget->getHeight();
   3970        resolveDesc.MipLevels          = 1;
   3971        resolveDesc.ArraySize          = 1;
   3972        resolveDesc.Format             = formatSet.texFormat;
   3973        resolveDesc.SampleDesc.Count   = 1;
   3974        resolveDesc.SampleDesc.Quality = 0;
   3975        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
   3976        resolveDesc.BindFlags          = D3D11_BIND_SHADER_RESOURCE;
   3977        resolveDesc.CPUAccessFlags     = 0;
   3978        resolveDesc.MiscFlags          = 0;
   3979 
   3980        ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc, formatSet,
   3981                                  &mCachedResolveTexture));
   3982    }
   3983 
   3984    mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0,
   3985                                       renderTarget->getTexture().get(),
   3986                                       renderTarget->getSubresourceIndex(), formatSet.texFormat);
   3987    *textureOut = mCachedResolveTexture;
   3988    return angle::Result::Continue;
   3989 }
   3990 
   3991 bool Renderer11::getLUID(LUID *adapterLuid) const
   3992 {
   3993    adapterLuid->HighPart = 0;
   3994    adapterLuid->LowPart  = 0;
   3995 
   3996    if (!mDxgiAdapter)
   3997    {
   3998        return false;
   3999    }
   4000 
   4001    DXGI_ADAPTER_DESC adapterDesc;
   4002    if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
   4003    {
   4004        return false;
   4005    }
   4006 
   4007    *adapterLuid = adapterDesc.AdapterLuid;
   4008    return true;
   4009 }
   4010 
   4011 VertexConversionType Renderer11::getVertexConversionType(angle::FormatID vertexFormatID) const
   4012 {
   4013    return d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel)
   4014        .conversionType;
   4015 }
   4016 
   4017 GLenum Renderer11::getVertexComponentType(angle::FormatID vertexFormatID) const
   4018 {
   4019    const auto &format =
   4020        d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel);
   4021    return d3d11::GetComponentType(format.nativeFormat);
   4022 }
   4023 
   4024 angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context,
   4025                                                 const gl::VertexAttribute &attrib,
   4026                                                 const gl::VertexBinding &binding,
   4027                                                 size_t count,
   4028                                                 GLsizei instances,
   4029                                                 GLuint baseInstance,
   4030                                                 unsigned int *bytesRequiredOut) const
   4031 {
   4032    if (!attrib.enabled)
   4033    {
   4034        *bytesRequiredOut = 16u;
   4035        return angle::Result::Continue;
   4036    }
   4037 
   4038    unsigned int elementCount  = 0;
   4039    const unsigned int divisor = binding.getDivisor();
   4040    if (instances == 0 || divisor == 0)
   4041    {
   4042        // This could be a clipped cast.
   4043        elementCount = gl::clampCast<unsigned int>(count);
   4044    }
   4045    else
   4046    {
   4047        // Round up to divisor, if possible
   4048        elementCount =
   4049            UnsignedCeilDivide(static_cast<unsigned int>(instances + baseInstance), divisor);
   4050    }
   4051 
   4052    ASSERT(elementCount > 0);
   4053 
   4054    const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
   4055    const d3d11::VertexFormat &vertexFormatInfo =
   4056        d3d11::GetVertexFormatInfo(attrib.format->id, featureLevel);
   4057    const d3d11::DXGIFormatSize &dxgiFormatInfo =
   4058        d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
   4059    unsigned int elementSize = dxgiFormatInfo.pixelBytes;
   4060    bool check = (elementSize > std::numeric_limits<unsigned int>::max() / elementCount);
   4061    ANGLE_CHECK(GetImplAs<Context11>(context), !check,
   4062                "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
   4063 
   4064    *bytesRequiredOut = elementSize * elementCount;
   4065    return angle::Result::Continue;
   4066 }
   4067 
   4068 void Renderer11::generateCaps(gl::Caps *outCaps,
   4069                              gl::TextureCapsMap *outTextureCaps,
   4070                              gl::Extensions *outExtensions,
   4071                              gl::Limitations *outLimitations) const
   4072 {
   4073    d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, getFeatures(),
   4074                           mDescription, outCaps, outTextureCaps, outExtensions, outLimitations);
   4075 }
   4076 
   4077 void Renderer11::initializeFeatures(angle::FeaturesD3D *features) const
   4078 {
   4079    if (!mDisplay->getState().featuresAllDisabled)
   4080    {
   4081        d3d11::InitializeFeatures(mRenderer11DeviceCaps, mAdapterDescription, features);
   4082    }
   4083    ApplyFeatureOverrides(features, mDisplay->getState());
   4084 }
   4085 
   4086 void Renderer11::initializeFrontendFeatures(angle::FrontendFeatures *features) const
   4087 {
   4088    if (!mDisplay->getState().featuresAllDisabled)
   4089    {
   4090        d3d11::InitializeFrontendFeatures(mAdapterDescription, features);
   4091    }
   4092    ApplyFeatureOverrides(features, mDisplay->getState());
   4093 }
   4094 
   4095 DeviceImpl *Renderer11::createEGLDevice()
   4096 {
   4097    return new DeviceD3D(EGL_D3D11_DEVICE_ANGLE, mDevice);
   4098 }
   4099 
   4100 ContextImpl *Renderer11::createContext(const gl::State &state, gl::ErrorSet *errorSet)
   4101 {
   4102    return new Context11(state, errorSet, this);
   4103 }
   4104 
   4105 FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
   4106 {
   4107    return new Framebuffer11(state, this);
   4108 }
   4109 
   4110 angle::Result Renderer11::getScratchMemoryBuffer(Context11 *context11,
   4111                                                 size_t requestedSize,
   4112                                                 angle::MemoryBuffer **bufferOut)
   4113 {
   4114    ANGLE_CHECK_GL_ALLOC(context11, mScratchMemoryBuffer.get(requestedSize, bufferOut));
   4115    return angle::Result::Continue;
   4116 }
   4117 
   4118 gl::Version Renderer11::getMaxSupportedESVersion() const
   4119 {
   4120    return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps);
   4121 }
   4122 
   4123 gl::Version Renderer11::getMaxConformantESVersion() const
   4124 {
   4125    // 3.1 support is in progress.
   4126    return std::min(getMaxSupportedESVersion(), gl::Version(3, 0));
   4127 }
   4128 
   4129 DebugAnnotatorContext11 *Renderer11::getDebugAnnotatorContext()
   4130 {
   4131    return &mAnnotatorContext;
   4132 }
   4133 
   4134 angle::Result Renderer11::dispatchCompute(const gl::Context *context,
   4135                                          GLuint numGroupsX,
   4136                                          GLuint numGroupsY,
   4137                                          GLuint numGroupsZ)
   4138 {
   4139    const gl::State &glState   = context->getState();
   4140    const gl::Program *program = glState.getProgram();
   4141    if (program->getActiveShaderStorageBlockCount() > 0 ||
   4142        program->getActiveAtomicCounterBufferCount() > 0)
   4143    {
   4144        ANGLE_TRY(markRawBufferUsage(context));
   4145    }
   4146    ANGLE_TRY(markTypedBufferUsage(context));
   4147    ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
   4148    mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
   4149 
   4150    return angle::Result::Continue;
   4151 }
   4152 angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
   4153 {
   4154    const auto &glState        = context->getState();
   4155    const gl::Program *program = glState.getProgram();
   4156    if (program->getActiveShaderStorageBlockCount() > 0 ||
   4157        program->getActiveAtomicCounterBufferCount() > 0)
   4158    {
   4159        ANGLE_TRY(markRawBufferUsage(context));
   4160    }
   4161 
   4162    auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect);
   4163    ASSERT(dispatchIndirectBuffer);
   4164 
   4165    Buffer11 *storage         = GetImplAs<Buffer11>(dispatchIndirectBuffer);
   4166    const uint8_t *bufferData = nullptr;
   4167    // TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant
   4168    // buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization
   4169    // to use GPU->GPU copy instead.
   4170    // http://anglebug.com/2807
   4171    ANGLE_TRY(storage->getData(context, &bufferData));
   4172    const GLuint *groups = reinterpret_cast<const GLuint *>(bufferData + indirect);
   4173    ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2]));
   4174 
   4175    ID3D11Buffer *buffer = nullptr;
   4176    ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
   4177 
   4178    mDeviceContext->DispatchIndirect(buffer, static_cast<UINT>(indirect));
   4179    return angle::Result::Continue;
   4180 }
   4181 
   4182 angle::Result Renderer11::createStagingTexture(const gl::Context *context,
   4183                                               ResourceType textureType,
   4184                                               const d3d11::Format &formatSet,
   4185                                               const gl::Extents &size,
   4186                                               StagingAccess readAndWriteAccess,
   4187                                               TextureHelper11 *textureOut)
   4188 {
   4189    Context11 *context11 = GetImplAs<Context11>(context);
   4190 
   4191    if (textureType == ResourceType::Texture2D)
   4192    {
   4193        D3D11_TEXTURE2D_DESC stagingDesc;
   4194        stagingDesc.Width              = size.width;
   4195        stagingDesc.Height             = size.height;
   4196        stagingDesc.MipLevels          = 1;
   4197        stagingDesc.ArraySize          = 1;
   4198        stagingDesc.Format             = formatSet.texFormat;
   4199        stagingDesc.SampleDesc.Count   = 1;
   4200        stagingDesc.SampleDesc.Quality = 0;
   4201        stagingDesc.Usage              = D3D11_USAGE_STAGING;
   4202        stagingDesc.BindFlags          = 0;
   4203        stagingDesc.CPUAccessFlags     = D3D11_CPU_ACCESS_READ;
   4204        stagingDesc.MiscFlags          = 0;
   4205 
   4206        if (readAndWriteAccess == StagingAccess::READ_WRITE)
   4207        {
   4208            stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
   4209        }
   4210 
   4211        ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut));
   4212        return angle::Result::Continue;
   4213    }
   4214    ASSERT(textureType == ResourceType::Texture3D);
   4215 
   4216    D3D11_TEXTURE3D_DESC stagingDesc;
   4217    stagingDesc.Width          = size.width;
   4218    stagingDesc.Height         = size.height;
   4219    stagingDesc.Depth          = 1;
   4220    stagingDesc.MipLevels      = 1;
   4221    stagingDesc.Format         = formatSet.texFormat;
   4222    stagingDesc.Usage          = D3D11_USAGE_STAGING;
   4223    stagingDesc.BindFlags      = 0;
   4224    stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
   4225    stagingDesc.MiscFlags      = 0;
   4226 
   4227    ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut));
   4228    return angle::Result::Continue;
   4229 }
   4230 
   4231 angle::Result Renderer11::allocateTexture(d3d::Context *context,
   4232                                          const D3D11_TEXTURE2D_DESC &desc,
   4233                                          const d3d11::Format &format,
   4234                                          const D3D11_SUBRESOURCE_DATA *initData,
   4235                                          TextureHelper11 *textureOut)
   4236 {
   4237    d3d11::Texture2D texture;
   4238    ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture));
   4239    textureOut->init(std::move(texture), desc, format);
   4240    return angle::Result::Continue;
   4241 }
   4242 
   4243 angle::Result Renderer11::allocateTexture(d3d::Context *context,
   4244                                          const D3D11_TEXTURE3D_DESC &desc,
   4245                                          const d3d11::Format &format,
   4246                                          const D3D11_SUBRESOURCE_DATA *initData,
   4247                                          TextureHelper11 *textureOut)
   4248 {
   4249    d3d11::Texture3D texture;
   4250    ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture));
   4251    textureOut->init(std::move(texture), desc, format);
   4252    return angle::Result::Continue;
   4253 }
   4254 
   4255 angle::Result Renderer11::getBlendState(const gl::Context *context,
   4256                                        const d3d11::BlendStateKey &key,
   4257                                        const d3d11::BlendState **outBlendState)
   4258 {
   4259    return mStateCache.getBlendState(context, this, key, outBlendState);
   4260 }
   4261 
   4262 angle::Result Renderer11::getRasterizerState(const gl::Context *context,
   4263                                             const gl::RasterizerState &rasterState,
   4264                                             bool scissorEnabled,
   4265                                             ID3D11RasterizerState **outRasterizerState)
   4266 {
   4267    return mStateCache.getRasterizerState(context, this, rasterState, scissorEnabled,
   4268                                          outRasterizerState);
   4269 }
   4270 
   4271 angle::Result Renderer11::getDepthStencilState(const gl::Context *context,
   4272                                               const gl::DepthStencilState &dsState,
   4273                                               const d3d11::DepthStencilState **outDSState)
   4274 {
   4275    return mStateCache.getDepthStencilState(context, this, dsState, outDSState);
   4276 }
   4277 
   4278 angle::Result Renderer11::getSamplerState(const gl::Context *context,
   4279                                          const gl::SamplerState &samplerState,
   4280                                          ID3D11SamplerState **outSamplerState)
   4281 {
   4282    return mStateCache.getSamplerState(context, this, samplerState, outSamplerState);
   4283 }
   4284 
   4285 UINT Renderer11::getSampleDescQuality(GLuint supportedSamples) const
   4286 {
   4287    // Per the documentation on
   4288    // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
   4289    // applications can only request the standard multisample pattern on
   4290    // feature levels 10_1 and above.
   4291    if (supportedSamples > 0 && mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_1)
   4292    {
   4293        return D3D11_STANDARD_MULTISAMPLE_PATTERN;
   4294    }
   4295    return 0;
   4296 }
   4297 
   4298 angle::Result Renderer11::clearRenderTarget(const gl::Context *context,
   4299                                            RenderTargetD3D *renderTarget,
   4300                                            const gl::ColorF &clearColorValue,
   4301                                            const float clearDepthValue,
   4302                                            const unsigned int clearStencilValue)
   4303 {
   4304    RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
   4305 
   4306    if (rt11->getFormatSet().dsvFormat != DXGI_FORMAT_UNKNOWN)
   4307    {
   4308        ASSERT(rt11->getDepthStencilView().valid());
   4309 
   4310        const auto &format    = rt11->getFormatSet();
   4311        const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
   4312                                (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0);
   4313        mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags,
   4314                                              clearDepthValue,
   4315                                              static_cast<UINT8>(clearStencilValue));
   4316        return angle::Result::Continue;
   4317    }
   4318 
   4319    ASSERT(rt11->getRenderTargetView().valid());
   4320    ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get();
   4321 
   4322    // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView.
   4323    // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx
   4324    ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv));
   4325 
   4326    const auto &d3d11Format = rt11->getFormatSet();
   4327    const auto &glFormat    = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
   4328 
   4329    gl::ColorF safeClearColor = clearColorValue;
   4330 
   4331    if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0)
   4332    {
   4333        safeClearColor.alpha = 1.0f;
   4334    }
   4335 
   4336    mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red);
   4337    return angle::Result::Continue;
   4338 }
   4339 
   4340 bool Renderer11::canSelectViewInVertexShader() const
   4341 {
   4342    return !getFeatures().selectViewInGeometryShader.enabled &&
   4343           getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
   4344 }
   4345 
   4346 angle::Result Renderer11::mapResource(const gl::Context *context,
   4347                                      ID3D11Resource *resource,
   4348                                      UINT subResource,
   4349                                      D3D11_MAP mapType,
   4350                                      UINT mapFlags,
   4351                                      D3D11_MAPPED_SUBRESOURCE *mappedResource)
   4352 {
   4353    HRESULT hr = mDeviceContext->Map(resource, subResource, mapType, mapFlags, mappedResource);
   4354    ANGLE_TRY_HR(GetImplAs<Context11>(context), hr, "Failed to map D3D11 resource.");
   4355    return angle::Result::Continue;
   4356 }
   4357 
   4358 angle::Result Renderer11::markTypedBufferUsage(const gl::Context *context)
   4359 {
   4360    const gl::State &glState = context->getState();
   4361    ProgramD3D *programD3D   = GetImplAs<ProgramD3D>(glState.getProgram());
   4362    gl::RangeUI imageRange   = programD3D->getUsedImageRange(gl::ShaderType::Compute, false);
   4363    for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
   4364    {
   4365        GLint imageUnitIndex = programD3D->getImageMapping(gl::ShaderType::Compute, imageIndex,
   4366                                                           false, context->getCaps());
   4367        ASSERT(imageUnitIndex != -1);
   4368        const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
   4369        if (imageUnit.texture.get()->getType() == gl::TextureType::Buffer)
   4370        {
   4371            Buffer11 *buffer11 = GetImplAs<Buffer11>(imageUnit.texture.get()->getBuffer().get());
   4372            ANGLE_TRY(buffer11->markTypedBufferUsage(context));
   4373        }
   4374    }
   4375    return angle::Result::Continue;
   4376 }
   4377 
   4378 angle::Result Renderer11::markRawBufferUsage(const gl::Context *context)
   4379 {
   4380    const gl::State &glState   = context->getState();
   4381    const gl::Program *program = glState.getProgram();
   4382    for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
   4383         blockIndex++)
   4384    {
   4385        GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
   4386        const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
   4387        if (shaderStorageBuffer.get() != nullptr)
   4388        {
   4389            Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
   4390            ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
   4391        }
   4392    }
   4393 
   4394    for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
   4395    {
   4396        GLuint binding     = atomicCounterBuffer.binding;
   4397        const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
   4398 
   4399        if (buffer.get() != nullptr)
   4400        {
   4401            Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
   4402            ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
   4403        }
   4404    }
   4405    return angle::Result::Continue;
   4406 }
   4407 
   4408 angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context)
   4409 {
   4410    const gl::State &glState                       = context->getState();
   4411    const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
   4412    for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
   4413    {
   4414        const gl::OffsetBindingPointer<gl::Buffer> &binding =
   4415            transformFeedback->getIndexedBuffer(i);
   4416        if (binding.get() != nullptr)
   4417        {
   4418            BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
   4419            ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context));
   4420        }
   4421    }
   4422 
   4423    return angle::Result::Continue;
   4424 }
   4425 
   4426 angle::Result Renderer11::getIncompleteTexture(const gl::Context *context,
   4427                                               gl::TextureType type,
   4428                                               gl::Texture **textureOut)
   4429 {
   4430    return GetImplAs<Context11>(context)->getIncompleteTexture(context, type, textureOut);
   4431 }
   4432 
   4433 std::string Renderer11::getVendorString() const
   4434 {
   4435    return GetVendorString(mAdapterDescription.VendorId);
   4436 }
   4437 
   4438 std::string Renderer11::getVersionString(bool includeFullVersion) const
   4439 {
   4440    std::ostringstream versionString;
   4441    versionString << "D3D11";
   4442    if (includeFullVersion && mRenderer11DeviceCaps.driverVersion.valid())
   4443    {
   4444        versionString << "-" << GetDriverVersionString(mRenderer11DeviceCaps.driverVersion.value());
   4445    }
   4446    return versionString.str();
   4447 }
   4448 
   4449 RendererD3D *CreateRenderer11(egl::Display *display)
   4450 {
   4451    return new Renderer11(display);
   4452 }
   4453 
   4454 }  // namespace rx