tor-browser

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

Context11.cpp (43321B)


      1 //
      2 // Copyright 2016 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 // Context11:
      7 //   D3D11-specific functionality associated with a GL Context.
      8 //
      9 
     10 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     11 
     12 #include "common/entry_points_enum_autogen.h"
     13 #include "common/string_utils.h"
     14 #include "libANGLE/Context.h"
     15 #include "libANGLE/Context.inl.h"
     16 #include "libANGLE/MemoryProgramCache.h"
     17 #include "libANGLE/renderer/OverlayImpl.h"
     18 #include "libANGLE/renderer/d3d/CompilerD3D.h"
     19 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
     20 #include "libANGLE/renderer/d3d/SamplerD3D.h"
     21 #include "libANGLE/renderer/d3d/ShaderD3D.h"
     22 #include "libANGLE/renderer/d3d/TextureD3D.h"
     23 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
     24 #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
     25 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
     26 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
     27 #include "libANGLE/renderer/d3d/d3d11/Program11.h"
     28 #include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
     29 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     30 #include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
     31 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
     32 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
     33 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
     34 
     35 namespace rx
     36 {
     37 
     38 namespace
     39 {
     40 ANGLE_INLINE bool DrawCallHasDynamicAttribs(const gl::Context *context)
     41 {
     42    VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(context->getState().getVertexArray());
     43    return vertexArray11->hasActiveDynamicAttrib(context);
     44 }
     45 
     46 bool DrawCallHasStreamingVertexArrays(const gl::Context *context, gl::PrimitiveMode mode)
     47 {
     48    // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
     49    // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
     50    // either since we need to simulate them in D3D.
     51    if (DrawCallHasDynamicAttribs(context) || mode == gl::PrimitiveMode::LineLoop ||
     52        mode == gl::PrimitiveMode::TriangleFan)
     53    {
     54        return true;
     55    }
     56 
     57    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(context->getState().getProgram());
     58    if (InstancedPointSpritesActive(programD3D, mode))
     59    {
     60        return true;
     61    }
     62 
     63    return false;
     64 }
     65 
     66 bool DrawCallHasStreamingElementArray(const gl::Context *context, gl::DrawElementsType srcType)
     67 {
     68    const gl::State &glState       = context->getState();
     69    gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer();
     70 
     71    bool primitiveRestartWorkaround =
     72        UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
     73    const gl::DrawElementsType dstType =
     74        (srcType == gl::DrawElementsType::UnsignedInt || primitiveRestartWorkaround)
     75            ? gl::DrawElementsType::UnsignedInt
     76            : gl::DrawElementsType::UnsignedShort;
     77 
     78    // Not clear where the offset comes from here.
     79    switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0))
     80    {
     81        case IndexStorageType::Dynamic:
     82            return true;
     83        case IndexStorageType::Direct:
     84            return false;
     85        case IndexStorageType::Static:
     86        {
     87            BufferD3D *bufferD3D                     = GetImplAs<BufferD3D>(elementArrayBuffer);
     88            StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
     89            return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType);
     90        }
     91        default:
     92            UNREACHABLE();
     93            return true;
     94    }
     95 }
     96 
     97 template <typename IndirectBufferT>
     98 angle::Result ReadbackIndirectBuffer(const gl::Context *context,
     99                                     const void *indirect,
    100                                     const IndirectBufferT **bufferPtrOut)
    101 {
    102    const gl::State &glState       = context->getState();
    103    gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
    104    ASSERT(drawIndirectBuffer);
    105    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
    106    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
    107 
    108    const uint8_t *bufferData = nullptr;
    109    ANGLE_TRY(storage->getData(context, &bufferData));
    110    ASSERT(bufferData);
    111 
    112    *bufferPtrOut = reinterpret_cast<const IndirectBufferT *>(bufferData + offset);
    113    return angle::Result::Continue;
    114 }
    115 }  // anonymous namespace
    116 
    117 Context11::Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer)
    118    : ContextD3D(state, errorSet), mRenderer(renderer)
    119 {}
    120 
    121 Context11::~Context11() {}
    122 
    123 angle::Result Context11::initialize()
    124 {
    125    return angle::Result::Continue;
    126 }
    127 
    128 void Context11::onDestroy(const gl::Context *context)
    129 {
    130    mIncompleteTextures.onDestroy(context);
    131 }
    132 
    133 CompilerImpl *Context11::createCompiler()
    134 {
    135    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
    136    {
    137        return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
    138    }
    139    else
    140    {
    141        return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
    142    }
    143 }
    144 
    145 ShaderImpl *Context11::createShader(const gl::ShaderState &data)
    146 {
    147    return new ShaderD3D(data, mRenderer);
    148 }
    149 
    150 ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
    151 {
    152    return new Program11(data, mRenderer);
    153 }
    154 
    155 FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
    156 {
    157    return new Framebuffer11(data, mRenderer);
    158 }
    159 
    160 TextureImpl *Context11::createTexture(const gl::TextureState &state)
    161 {
    162    switch (state.getType())
    163    {
    164        case gl::TextureType::_2D:
    165        // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to native 2D texture on Windows platform
    166        case gl::TextureType::VideoImage:
    167            return new TextureD3D_2D(state, mRenderer);
    168        case gl::TextureType::CubeMap:
    169            return new TextureD3D_Cube(state, mRenderer);
    170        case gl::TextureType::_3D:
    171            return new TextureD3D_3D(state, mRenderer);
    172        case gl::TextureType::_2DArray:
    173            return new TextureD3D_2DArray(state, mRenderer);
    174        case gl::TextureType::External:
    175            return new TextureD3D_External(state, mRenderer);
    176        case gl::TextureType::_2DMultisample:
    177            return new TextureD3D_2DMultisample(state, mRenderer);
    178        case gl::TextureType::_2DMultisampleArray:
    179            return new TextureD3D_2DMultisampleArray(state, mRenderer);
    180        case gl::TextureType::Buffer:
    181            return new TextureD3D_Buffer(state, mRenderer);
    182        default:
    183            UNREACHABLE();
    184    }
    185 
    186    return nullptr;
    187 }
    188 
    189 RenderbufferImpl *Context11::createRenderbuffer(const gl::RenderbufferState &state)
    190 {
    191    return new RenderbufferD3D(state, mRenderer);
    192 }
    193 
    194 BufferImpl *Context11::createBuffer(const gl::BufferState &state)
    195 {
    196    Buffer11 *buffer = new Buffer11(state, mRenderer);
    197    mRenderer->onBufferCreate(buffer);
    198    return buffer;
    199 }
    200 
    201 VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
    202 {
    203    return new VertexArray11(data);
    204 }
    205 
    206 QueryImpl *Context11::createQuery(gl::QueryType type)
    207 {
    208    return new Query11(mRenderer, type);
    209 }
    210 
    211 FenceNVImpl *Context11::createFenceNV()
    212 {
    213    return new FenceNV11(mRenderer);
    214 }
    215 
    216 SyncImpl *Context11::createSync()
    217 {
    218    return new Sync11(mRenderer);
    219 }
    220 
    221 TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
    222 {
    223    return new TransformFeedback11(state, mRenderer);
    224 }
    225 
    226 SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
    227 {
    228    return new SamplerD3D(state);
    229 }
    230 
    231 ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data)
    232 {
    233    return new ProgramPipeline11(data);
    234 }
    235 
    236 MemoryObjectImpl *Context11::createMemoryObject()
    237 {
    238    UNREACHABLE();
    239    return nullptr;
    240 }
    241 
    242 SemaphoreImpl *Context11::createSemaphore()
    243 {
    244    UNREACHABLE();
    245    return nullptr;
    246 }
    247 
    248 OverlayImpl *Context11::createOverlay(const gl::OverlayState &state)
    249 {
    250    // Not implemented.
    251    return new OverlayImpl(state);
    252 }
    253 
    254 angle::Result Context11::flush(const gl::Context *context)
    255 {
    256    return mRenderer->flush(this);
    257 }
    258 
    259 angle::Result Context11::finish(const gl::Context *context)
    260 {
    261    return mRenderer->finish(this);
    262 }
    263 
    264 angle::Result Context11::drawArrays(const gl::Context *context,
    265                                    gl::PrimitiveMode mode,
    266                                    GLint first,
    267                                    GLsizei count)
    268 {
    269    ASSERT(count > 0);
    270    ANGLE_TRY(mRenderer->getStateManager()->updateState(
    271        context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
    272    return mRenderer->drawArrays(context, mode, first, count, 0, 0, false);
    273 }
    274 
    275 angle::Result Context11::drawArraysInstanced(const gl::Context *context,
    276                                             gl::PrimitiveMode mode,
    277                                             GLint first,
    278                                             GLsizei count,
    279                                             GLsizei instanceCount)
    280 {
    281    ASSERT(count > 0);
    282    ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
    283                                                        gl::DrawElementsType::InvalidEnum, nullptr,
    284                                                        instanceCount, 0, 0, true));
    285    return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0, true);
    286 }
    287 
    288 angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
    289                                                         gl::PrimitiveMode mode,
    290                                                         GLint first,
    291                                                         GLsizei count,
    292                                                         GLsizei instanceCount,
    293                                                         GLuint baseInstance)
    294 {
    295    ASSERT(count > 0);
    296    ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
    297                                                        gl::DrawElementsType::InvalidEnum, nullptr,
    298                                                        instanceCount, 0, baseInstance, true));
    299    return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance, true);
    300 }
    301 
    302 ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context,
    303                                                       gl::PrimitiveMode mode,
    304                                                       GLsizei indexCount,
    305                                                       gl::DrawElementsType indexType,
    306                                                       const void *indices,
    307                                                       GLsizei instanceCount,
    308                                                       GLint baseVertex,
    309                                                       GLuint baseInstance,
    310                                                       bool promoteDynamic,
    311                                                       bool isInstancedDraw)
    312 {
    313    ASSERT(indexCount > 0);
    314 
    315    if (DrawCallHasDynamicAttribs(context))
    316    {
    317        gl::IndexRange indexRange;
    318        ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
    319            context, indexType, indexCount, indices, &indexRange));
    320        GLint startVertex;
    321        ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex,
    322                                     &startVertex));
    323        ANGLE_TRY(mRenderer->getStateManager()->updateState(
    324            context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex,
    325            baseInstance, promoteDynamic));
    326        return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices,
    327                                       instanceCount, baseVertex, baseInstance, isInstancedDraw);
    328    }
    329    else
    330    {
    331        ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
    332                                                            indices, instanceCount, baseVertex,
    333                                                            baseInstance, promoteDynamic));
    334        return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
    335                                       instanceCount, baseVertex, baseInstance, isInstancedDraw);
    336    }
    337 }
    338 
    339 angle::Result Context11::drawElements(const gl::Context *context,
    340                                      gl::PrimitiveMode mode,
    341                                      GLsizei count,
    342                                      gl::DrawElementsType type,
    343                                      const void *indices)
    344 {
    345    return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
    346 }
    347 
    348 angle::Result Context11::drawElementsBaseVertex(const gl::Context *context,
    349                                                gl::PrimitiveMode mode,
    350                                                GLsizei count,
    351                                                gl::DrawElementsType type,
    352                                                const void *indices,
    353                                                GLint baseVertex)
    354 {
    355    return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
    356 }
    357 
    358 angle::Result Context11::drawElementsInstanced(const gl::Context *context,
    359                                               gl::PrimitiveMode mode,
    360                                               GLsizei count,
    361                                               gl::DrawElementsType type,
    362                                               const void *indices,
    363                                               GLsizei instances)
    364 {
    365    return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0, true, true);
    366 }
    367 
    368 angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context,
    369                                                         gl::PrimitiveMode mode,
    370                                                         GLsizei count,
    371                                                         gl::DrawElementsType type,
    372                                                         const void *indices,
    373                                                         GLsizei instances,
    374                                                         GLint baseVertex)
    375 {
    376    return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0, true,
    377                            true);
    378 }
    379 
    380 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
    381                                                                     gl::PrimitiveMode mode,
    382                                                                     GLsizei count,
    383                                                                     gl::DrawElementsType type,
    384                                                                     const void *indices,
    385                                                                     GLsizei instances,
    386                                                                     GLint baseVertex,
    387                                                                     GLuint baseInstance)
    388 {
    389    return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex,
    390                            baseInstance, true, true);
    391 }
    392 
    393 angle::Result Context11::drawRangeElements(const gl::Context *context,
    394                                           gl::PrimitiveMode mode,
    395                                           GLuint start,
    396                                           GLuint end,
    397                                           GLsizei count,
    398                                           gl::DrawElementsType type,
    399                                           const void *indices)
    400 {
    401    return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
    402 }
    403 
    404 angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context,
    405                                                     gl::PrimitiveMode mode,
    406                                                     GLuint start,
    407                                                     GLuint end,
    408                                                     GLsizei count,
    409                                                     gl::DrawElementsType type,
    410                                                     const void *indices,
    411                                                     GLint baseVertex)
    412 {
    413    return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
    414 }
    415 
    416 angle::Result Context11::drawArraysIndirect(const gl::Context *context,
    417                                            gl::PrimitiveMode mode,
    418                                            const void *indirect)
    419 {
    420    if (DrawCallHasStreamingVertexArrays(context, mode))
    421    {
    422        const gl::DrawArraysIndirectCommand *cmd = nullptr;
    423        ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
    424 
    425        ANGLE_TRY(mRenderer->getStateManager()->updateState(
    426            context, mode, cmd->first, cmd->count, gl::DrawElementsType::InvalidEnum, nullptr,
    427            cmd->instanceCount, 0, 0, true));
    428        return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
    429                                     cmd->baseInstance, true);
    430    }
    431    else
    432    {
    433        ANGLE_TRY(mRenderer->getStateManager()->updateState(
    434            context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
    435        return mRenderer->drawArraysIndirect(context, indirect);
    436    }
    437 }
    438 
    439 angle::Result Context11::drawElementsIndirect(const gl::Context *context,
    440                                              gl::PrimitiveMode mode,
    441                                              gl::DrawElementsType type,
    442                                              const void *indirect)
    443 {
    444    if (DrawCallHasStreamingVertexArrays(context, mode) ||
    445        DrawCallHasStreamingElementArray(context, type))
    446    {
    447        const gl::DrawElementsIndirectCommand *cmd = nullptr;
    448        ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
    449 
    450        const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
    451        const void *indices =
    452            reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes));
    453 
    454        // We must explicitly resolve the index range for the slow-path indirect drawElements to
    455        // make sure we are using the correct 'baseVertex'. This parameter does not exist for the
    456        // direct drawElements.
    457        gl::IndexRange indexRange;
    458        ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count,
    459                                                                      indices, &indexRange));
    460 
    461        GLint startVertex;
    462        ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex,
    463                                     &startVertex));
    464 
    465        ANGLE_TRY(mRenderer->getStateManager()->updateState(
    466            context, mode, startVertex, cmd->count, type, indices, cmd->primCount, cmd->baseVertex,
    467            cmd->baseInstance, true));
    468        return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
    469                                       cmd->count, type, indices, cmd->primCount, 0, 0, true);
    470    }
    471    else
    472    {
    473        ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0,
    474                                                            0, 0, true));
    475        return mRenderer->drawElementsIndirect(context, indirect);
    476    }
    477 }
    478 
    479 #define DRAW_ARRAYS__                                                                           \
    480    {                                                                                           \
    481        ANGLE_TRY(mRenderer->getStateManager()->updateState(                                    \
    482            context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum,   \
    483            nullptr, 0, 0, 0, false));                                                          \
    484        ANGLE_TRY(                                                                              \
    485            mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], 0, 0, false)); \
    486    }
    487 #define DRAW_ARRAYS_INSTANCED_                                                                \
    488    {                                                                                         \
    489        ANGLE_TRY(mRenderer->getStateManager()->updateState(                                  \
    490            context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \
    491            nullptr, instanceCounts[drawID], 0, 0, false));                                   \
    492        ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID],        \
    493                                        instanceCounts[drawID], 0, true));                    \
    494    }
    495 #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE                                                    \
    496    {                                                                                          \
    497        ANGLE_TRY(mRenderer->getStateManager()->updateState(                                   \
    498            context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum,  \
    499            nullptr, instanceCounts[drawID], 0, baseInstances[drawID], false));                \
    500        ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID],         \
    501                                        instanceCounts[drawID], baseInstances[drawID], true)); \
    502    }
    503 #define DRAW_ELEMENTS__                                                                           \
    504    {                                                                                             \
    505        ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], 0, 0, 0, \
    506                                   false, false));                                                \
    507    }
    508 #define DRAW_ELEMENTS_INSTANCED_                                                         \
    509    {                                                                                    \
    510        ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
    511                                   instanceCounts[drawID], 0, 0, false, true));          \
    512    }
    513 #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE                                \
    514    {                                                                                    \
    515        ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
    516                                   instanceCounts[drawID], baseVertices[drawID],         \
    517                                   baseInstances[drawID], false, true));                 \
    518    }
    519 
    520 #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
    521 
    522 #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
    523    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)                                     \
    524    {                                                                                          \
    525        if (ANGLE_NOOP_DRAW(instanced))                                                        \
    526        {                                                                                      \
    527            continue;                                                                          \
    528        }                                                                                      \
    529        ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID);                                          \
    530        ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]);                    \
    531        ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]);               \
    532        ASSERT(counts[drawID] > 0);                                                            \
    533        DRAW_CALL(drawType, instanced, bvbi);                                                  \
    534        ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced);                                        \
    535        gl::MarkShaderStorageUsage(context);                                                   \
    536    }
    537 
    538 angle::Result Context11::multiDrawArrays(const gl::Context *context,
    539                                         gl::PrimitiveMode mode,
    540                                         const GLint *firsts,
    541                                         const GLsizei *counts,
    542                                         GLsizei drawcount)
    543 {
    544    gl::Program *programObject = context->getState().getLinkedProgram(context);
    545    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    546    if (hasDrawID)
    547    {
    548        MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0)
    549    }
    550    else
    551    {
    552        MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0)
    553    }
    554 
    555    return angle::Result::Continue;
    556 }
    557 
    558 angle::Result Context11::multiDrawArraysInstanced(const gl::Context *context,
    559                                                  gl::PrimitiveMode mode,
    560                                                  const GLint *firsts,
    561                                                  const GLsizei *counts,
    562                                                  const GLsizei *instanceCounts,
    563                                                  GLsizei drawcount)
    564 {
    565    gl::Program *programObject = context->getState().getLinkedProgram(context);
    566    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    567    if (hasDrawID)
    568    {
    569        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0)
    570    }
    571    else
    572    {
    573        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0)
    574    }
    575 
    576    return angle::Result::Continue;
    577 }
    578 
    579 angle::Result Context11::multiDrawArraysIndirect(const gl::Context *context,
    580                                                 gl::PrimitiveMode mode,
    581                                                 const void *indirect,
    582                                                 GLsizei drawcount,
    583                                                 GLsizei stride)
    584 {
    585    return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
    586 }
    587 
    588 angle::Result Context11::multiDrawElements(const gl::Context *context,
    589                                           gl::PrimitiveMode mode,
    590                                           const GLsizei *counts,
    591                                           gl::DrawElementsType type,
    592                                           const GLvoid *const *indices,
    593                                           GLsizei drawcount)
    594 {
    595    gl::Program *programObject = context->getState().getLinkedProgram(context);
    596    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    597    if (hasDrawID)
    598    {
    599        MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0)
    600    }
    601    else
    602    {
    603        MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0)
    604    }
    605 
    606    return angle::Result::Continue;
    607 }
    608 
    609 angle::Result Context11::multiDrawElementsInstanced(const gl::Context *context,
    610                                                    gl::PrimitiveMode mode,
    611                                                    const GLsizei *counts,
    612                                                    gl::DrawElementsType type,
    613                                                    const GLvoid *const *indices,
    614                                                    const GLsizei *instanceCounts,
    615                                                    GLsizei drawcount)
    616 {
    617    gl::Program *programObject = context->getState().getLinkedProgram(context);
    618    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    619    if (hasDrawID)
    620    {
    621        MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0)
    622    }
    623    else
    624    {
    625        MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0)
    626    }
    627 
    628    return angle::Result::Continue;
    629 }
    630 
    631 angle::Result Context11::multiDrawElementsIndirect(const gl::Context *context,
    632                                                   gl::PrimitiveMode mode,
    633                                                   gl::DrawElementsType type,
    634                                                   const void *indirect,
    635                                                   GLsizei drawcount,
    636                                                   GLsizei stride)
    637 {
    638    return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
    639                                                stride);
    640 }
    641 
    642 angle::Result Context11::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
    643                                                              gl::PrimitiveMode mode,
    644                                                              const GLint *firsts,
    645                                                              const GLsizei *counts,
    646                                                              const GLsizei *instanceCounts,
    647                                                              const GLuint *baseInstances,
    648                                                              GLsizei drawcount)
    649 {
    650    gl::Program *programObject = context->getState().getLinkedProgram(context);
    651    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    652    const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
    653    ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
    654 
    655    if (hasDrawID && hasBaseInstance)
    656    {
    657        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1)
    658    }
    659    else if (hasDrawID)
    660    {
    661        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0)
    662    }
    663    else if (hasBaseInstance)
    664    {
    665        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1)
    666    }
    667    else
    668    {
    669        MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0)
    670    }
    671 
    672    return angle::Result::Continue;
    673 }
    674 
    675 angle::Result Context11::multiDrawElementsInstancedBaseVertexBaseInstance(
    676    const gl::Context *context,
    677    gl::PrimitiveMode mode,
    678    const GLsizei *counts,
    679    gl::DrawElementsType type,
    680    const GLvoid *const *indices,
    681    const GLsizei *instanceCounts,
    682    const GLint *baseVertices,
    683    const GLuint *baseInstances,
    684    GLsizei drawcount)
    685 {
    686    gl::Program *programObject = context->getState().getLinkedProgram(context);
    687    const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
    688    const bool hasBaseVertex   = programObject && programObject->hasBaseVertexUniform();
    689    const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
    690    ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
    691 
    692    if (hasDrawID)
    693    {
    694        if (hasBaseVertex)
    695        {
    696            if (hasBaseInstance)
    697            {
    698                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1)
    699            }
    700            else
    701            {
    702                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0)
    703            }
    704        }
    705        else
    706        {
    707            if (hasBaseInstance)
    708            {
    709                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1)
    710            }
    711            else
    712            {
    713                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0)
    714            }
    715        }
    716    }
    717    else
    718    {
    719        if (hasBaseVertex)
    720        {
    721            if (hasBaseInstance)
    722            {
    723                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1)
    724            }
    725            else
    726            {
    727                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0)
    728            }
    729        }
    730        else
    731        {
    732            if (hasBaseInstance)
    733            {
    734                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1)
    735            }
    736            else
    737            {
    738                MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0)
    739            }
    740        }
    741    }
    742 
    743    return angle::Result::Continue;
    744 }
    745 
    746 gl::GraphicsResetStatus Context11::getResetStatus()
    747 {
    748    return mRenderer->getResetStatus();
    749 }
    750 
    751 angle::Result Context11::insertEventMarker(GLsizei length, const char *marker)
    752 {
    753    mRenderer->getDebugAnnotatorContext()->setMarker(marker);
    754    return angle::Result::Continue;
    755 }
    756 
    757 angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker)
    758 {
    759    mRenderer->getDebugAnnotatorContext()->beginEvent(angle::EntryPoint::GLPushGroupMarkerEXT,
    760                                                      marker, marker);
    761    mMarkerStack.push(std::string(marker));
    762    return angle::Result::Continue;
    763 }
    764 
    765 angle::Result Context11::popGroupMarker()
    766 {
    767    const char *marker = nullptr;
    768    if (!mMarkerStack.empty())
    769    {
    770        marker = mMarkerStack.top().c_str();
    771        mMarkerStack.pop();
    772        mRenderer->getDebugAnnotatorContext()->endEvent(marker,
    773                                                        angle::EntryPoint::GLPopGroupMarkerEXT);
    774    }
    775    return angle::Result::Continue;
    776 }
    777 
    778 angle::Result Context11::pushDebugGroup(const gl::Context *context,
    779                                        GLenum source,
    780                                        GLuint id,
    781                                        const std::string &message)
    782 {
    783    // Fall through to the EXT_debug_marker functions
    784    return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
    785 }
    786 
    787 angle::Result Context11::popDebugGroup(const gl::Context *context)
    788 {
    789    // Fall through to the EXT_debug_marker functions
    790    return popGroupMarker();
    791 }
    792 
    793 angle::Result Context11::syncState(const gl::Context *context,
    794                                   const gl::State::DirtyBits &dirtyBits,
    795                                   const gl::State::DirtyBits &bitMask,
    796                                   gl::Command command)
    797 {
    798    mRenderer->getStateManager()->syncState(context, dirtyBits, command);
    799    return angle::Result::Continue;
    800 }
    801 
    802 GLint Context11::getGPUDisjoint()
    803 {
    804    return mRenderer->getGPUDisjoint();
    805 }
    806 
    807 GLint64 Context11::getTimestamp()
    808 {
    809    return mRenderer->getTimestamp();
    810 }
    811 
    812 angle::Result Context11::onMakeCurrent(const gl::Context *context)
    813 {
    814    // Immediately return if the device has been lost.
    815    if (!mRenderer->getDevice())
    816    {
    817        return angle::Result::Continue;
    818    }
    819 
    820    return mRenderer->getStateManager()->onMakeCurrent(context);
    821 }
    822 
    823 gl::Caps Context11::getNativeCaps() const
    824 {
    825    gl::Caps caps = mRenderer->getNativeCaps();
    826 
    827    // For pixel shaders, the render targets and unordered access views share the same resource
    828    // slots, so the maximum number of fragment shader outputs depends on the current context
    829    // version:
    830    // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8)
    831    //   as the value of max draw buffers because UAVs are not used.
    832    // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8
    833    //   slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value
    834    //   of max combined shader output resources is limited to 7, thus only 7 RTV slots can be
    835    //   used simultaneously.
    836    // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64
    837    //   slots. Currently we allocate 60 slots for combined shader output resources, so we can use
    838    //   at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously.
    839    if (mState.getClientVersion() >= gl::ES_3_1 &&
    840        mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0)
    841    {
    842        caps.maxDrawBuffers      = caps.maxCombinedShaderOutputResources;
    843        caps.maxColorAttachments = caps.maxCombinedShaderOutputResources;
    844    }
    845 
    846    return caps;
    847 }
    848 
    849 const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
    850 {
    851    return mRenderer->getNativeTextureCaps();
    852 }
    853 
    854 const gl::Extensions &Context11::getNativeExtensions() const
    855 {
    856    return mRenderer->getNativeExtensions();
    857 }
    858 
    859 const gl::Limitations &Context11::getNativeLimitations() const
    860 {
    861    return mRenderer->getNativeLimitations();
    862 }
    863 
    864 ShPixelLocalStorageType Context11::getNativePixelLocalStorageType() const
    865 {
    866    return mRenderer->getNativePixelLocalStorageType();
    867 }
    868 
    869 angle::Result Context11::dispatchCompute(const gl::Context *context,
    870                                         GLuint numGroupsX,
    871                                         GLuint numGroupsY,
    872                                         GLuint numGroupsZ)
    873 {
    874    return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
    875 }
    876 
    877 angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
    878 {
    879    return mRenderer->dispatchComputeIndirect(context, indirect);
    880 }
    881 
    882 angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
    883                                                             gl::PrimitiveMode drawMode)
    884 {
    885    const auto &glState    = context->getState();
    886    const auto *va11       = GetImplAs<VertexArray11>(glState.getVertexArray());
    887    const auto *drawFBO    = glState.getDrawFramebuffer();
    888    gl::Program *program   = glState.getProgram();
    889    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    890 
    891    programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
    892    programD3D->updateCachedOutputLayout(context, drawFBO);
    893 
    894    bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout();
    895    bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode);
    896    bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout();
    897 
    898    if (!recompileVS && !recompileGS && !recompilePS)
    899    {
    900        return angle::Result::Continue;
    901    }
    902 
    903    // Load the compiler if necessary and recompile the programs.
    904    ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
    905 
    906    gl::InfoLog infoLog;
    907 
    908    if (recompileVS)
    909    {
    910        ShaderExecutableD3D *vertexExe = nullptr;
    911        ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(this, &vertexExe, &infoLog));
    912        if (!programD3D->hasVertexExecutableForCachedInputLayout())
    913        {
    914            ASSERT(infoLog.getLength() > 0);
    915            ERR() << "Error compiling dynamic vertex executable: " << infoLog.str();
    916            ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable");
    917        }
    918    }
    919 
    920    if (recompileGS)
    921    {
    922        ShaderExecutableD3D *geometryExe = nullptr;
    923        ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(this, glState, drawMode,
    924                                                                    &geometryExe, &infoLog));
    925        if (!programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode))
    926        {
    927            ASSERT(infoLog.getLength() > 0);
    928            ERR() << "Error compiling dynamic geometry executable: " << infoLog.str();
    929            ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable");
    930        }
    931    }
    932 
    933    if (recompilePS)
    934    {
    935        ShaderExecutableD3D *pixelExe = nullptr;
    936        ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(this, &pixelExe, &infoLog));
    937        if (!programD3D->hasPixelExecutableForCachedOutputLayout())
    938        {
    939            ASSERT(infoLog.getLength() > 0);
    940            ERR() << "Error compiling dynamic pixel executable: " << infoLog.str();
    941            ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable");
    942        }
    943    }
    944 
    945    // Refresh the program cache entry.
    946    if (mMemoryProgramCache)
    947    {
    948        ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
    949    }
    950 
    951    return angle::Result::Continue;
    952 }
    953 
    954 angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
    955 {
    956    const auto &glState    = context->getState();
    957    gl::Program *program   = glState.getProgram();
    958    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
    959 
    960    programD3D->updateCachedComputeImage2DBindLayout(context);
    961 
    962    bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout();
    963 
    964    if (!recompileCS)
    965    {
    966        return angle::Result::Continue;
    967    }
    968 
    969    // Load the compiler if necessary and recompile the programs.
    970    ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
    971 
    972    gl::InfoLog infoLog;
    973 
    974    ShaderExecutableD3D *computeExe = nullptr;
    975    ANGLE_TRY(
    976        programD3D->getComputeExecutableForImage2DBindLayout(context, this, &computeExe, &infoLog));
    977    if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout())
    978    {
    979        ASSERT(infoLog.getLength() > 0);
    980        ERR() << "Dynamic recompilation error log: " << infoLog.str();
    981        ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
    982    }
    983 
    984    // Refresh the program cache entry.
    985    if (mMemoryProgramCache)
    986    {
    987        ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
    988    }
    989 
    990    return angle::Result::Continue;
    991 }
    992 
    993 angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
    994 {
    995    return angle::Result::Continue;
    996 }
    997 
    998 angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
    999 {
   1000    return angle::Result::Continue;
   1001 }
   1002 
   1003 angle::Result Context11::getIncompleteTexture(const gl::Context *context,
   1004                                              gl::TextureType type,
   1005                                              gl::Texture **textureOut)
   1006 {
   1007    return mIncompleteTextures.getIncompleteTexture(context, type, gl::SamplerFormat::Float, this,
   1008                                                    textureOut);
   1009 }
   1010 
   1011 angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context,
   1012                                                             gl::Texture *glTexture)
   1013 {
   1014    ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
   1015    TextureD3D *textureD3D        = GetImplAs<TextureD3D>(glTexture);
   1016    gl::ImageIndex index          = gl::ImageIndex::Make2DMultisample();
   1017    RenderTargetD3D *renderTarget = nullptr;
   1018    GLsizei texSamples            = textureD3D->getRenderToTextureSamples();
   1019    ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget));
   1020    return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f),
   1021                                        1.0f, 0);
   1022 }
   1023 
   1024 void Context11::handleResult(HRESULT hr,
   1025                             const char *message,
   1026                             const char *file,
   1027                             const char *function,
   1028                             unsigned int line)
   1029 {
   1030    ASSERT(FAILED(hr));
   1031 
   1032    GLenum glErrorCode = DefaultGLErrorCode(hr);
   1033 
   1034    std::stringstream errorStream;
   1035    errorStream << "Internal D3D11 error: " << gl::FmtHR(hr);
   1036 
   1037    if (d3d11::isDeviceLostError(hr))
   1038    {
   1039        HRESULT removalReason = mRenderer->getDevice()->GetDeviceRemovedReason();
   1040        errorStream << " (removal reason: " << gl::FmtHR(removalReason) << ")";
   1041        mRenderer->notifyDeviceLost();
   1042    }
   1043 
   1044    errorStream << ": " << message;
   1045 
   1046    mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
   1047 }
   1048 }  // namespace rx