tor-browser

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

Clear11.cpp (33813B)


      1 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 
      6 // Clear11.cpp: Framebuffer clear utility class.
      7 
      8 #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
      9 
     10 #include <algorithm>
     11 
     12 #include "libANGLE/Context.h"
     13 #include "libANGLE/FramebufferAttachment.h"
     14 #include "libANGLE/formatutils.h"
     15 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
     16 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     17 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
     18 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     19 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
     20 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
     21 #include "libANGLE/trace.h"
     22 
     23 // Precompiled shaders
     24 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h"
     25 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h"
     26 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h"
     27 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h"
     28 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h"
     29 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
     30 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h"
     31 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h"
     32 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h"
     33 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h"
     34 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h"
     35 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h"
     36 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h"
     37 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h"
     38 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h"
     39 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h"
     40 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h"
     41 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h"
     42 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h"
     43 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h"
     44 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h"
     45 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h"
     46 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h"
     47 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h"
     48 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h"
     49 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h"
     50 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h"
     51 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h"
     52 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h"
     53 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h"
     54 
     55 namespace rx
     56 {
     57 
     58 namespace
     59 {
     60 constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo<float>);
     61 constexpr uint32_t g_VertexSize         = sizeof(d3d11::PositionVertex);
     62 
     63 // Updates color, depth and alpha components of cached CB if necessary.
     64 // Returns true if any constants are updated, false otherwise.
     65 template <typename T>
     66 bool UpdateDataCache(RtvDsvClearInfo<T> *dataCache,
     67                     const gl::Color<T> &color,
     68                     const float *zValue,
     69                     const uint32_t numRtvs,
     70                     const uint8_t writeMask)
     71 {
     72    bool cacheDirty = false;
     73 
     74    if (numRtvs > 0)
     75    {
     76        const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
     77        if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0)
     78        {
     79            dataCache->r = color.red;
     80            dataCache->g = color.green;
     81            dataCache->b = color.blue;
     82            cacheDirty   = true;
     83        }
     84 
     85        const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
     86        if (writeAlpha && (dataCache->a != color.alpha))
     87        {
     88            dataCache->a = color.alpha;
     89            cacheDirty   = true;
     90        }
     91    }
     92 
     93    if (zValue)
     94    {
     95        const float clampedZValue = gl::clamp01(*zValue);
     96 
     97        if (clampedZValue != dataCache->z)
     98        {
     99            dataCache->z = clampedZValue;
    100            cacheDirty   = true;
    101        }
    102    }
    103 
    104    return cacheDirty;
    105 }
    106 
    107 }  // anonymous namespace
    108 
    109 #define CLEARPS(Index)                                                                    \
    110    d3d11::LazyShader<ID3D11PixelShader>(g_PS_Clear##Index, ArraySize(g_PS_Clear##Index), \
    111                                         "Clear11 PS " ANGLE_STRINGIFY(Index))
    112 
    113 Clear11::ShaderManager::ShaderManager()
    114    : mIl9(),
    115      mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"),
    116      mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"),
    117      mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"),
    118      mVsMultiview(g_VS_Multiview_Clear, ArraySize(g_VS_Multiview_Clear), "Clear11 VS Multiview"),
    119      mGsMultiview(g_GS_Multiview_Clear, ArraySize(g_GS_Multiview_Clear), "Clear11 GS Multiview"),
    120      mPsDepth(g_PS_ClearDepth, ArraySize(g_PS_ClearDepth), "Clear11 PS Depth"),
    121      mPsFloat{{CLEARPS(Float1), CLEARPS(Float2), CLEARPS(Float3), CLEARPS(Float4), CLEARPS(Float5),
    122                CLEARPS(Float6), CLEARPS(Float7), CLEARPS(Float8)}},
    123      mPsUInt{{CLEARPS(Uint1), CLEARPS(Uint2), CLEARPS(Uint3), CLEARPS(Uint4), CLEARPS(Uint5),
    124               CLEARPS(Uint6), CLEARPS(Uint7), CLEARPS(Uint8)}},
    125      mPsSInt{{CLEARPS(Sint1), CLEARPS(Sint2), CLEARPS(Sint3), CLEARPS(Sint4), CLEARPS(Sint5),
    126               CLEARPS(Sint6), CLEARPS(Sint7), CLEARPS(Sint8)}}
    127 {}
    128 
    129 #undef CLEARPS
    130 
    131 Clear11::ShaderManager::~ShaderManager() {}
    132 
    133 angle::Result Clear11::ShaderManager::getShadersAndLayout(const gl::Context *context,
    134                                                          Renderer11 *renderer,
    135                                                          const INT clearType,
    136                                                          const uint32_t numRTs,
    137                                                          const bool hasLayeredLayout,
    138                                                          const d3d11::InputLayout **il,
    139                                                          const d3d11::VertexShader **vs,
    140                                                          const d3d11::GeometryShader **gs,
    141                                                          const d3d11::PixelShader **ps)
    142 {
    143    Context11 *context11 = GetImplAs<Context11>(context);
    144 
    145    if (renderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
    146    {
    147        ASSERT(clearType == GL_FLOAT);
    148 
    149        ANGLE_TRY(mVs9.resolve(context11, renderer));
    150        ANGLE_TRY(mPsFloat9.resolve(context11, renderer));
    151 
    152        if (!mIl9.valid())
    153        {
    154            const D3D11_INPUT_ELEMENT_DESC ilDesc[] = {
    155                {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}};
    156 
    157            InputElementArray ilDescArray(ilDesc);
    158            ShaderData vertexShader(g_VS_Clear_FL9);
    159 
    160            ANGLE_TRY(renderer->allocateResource(context11, ilDescArray, &vertexShader, &mIl9));
    161        }
    162 
    163        *vs = &mVs9.getObj();
    164        *gs = nullptr;
    165        *il = &mIl9;
    166        *ps = &mPsFloat9.getObj();
    167        return angle::Result::Continue;
    168    }
    169 
    170    if (!hasLayeredLayout)
    171    {
    172        ANGLE_TRY(mVs.resolve(context11, renderer));
    173        *vs = &mVs.getObj();
    174        *gs = nullptr;
    175    }
    176    else
    177    {
    178        // For layered framebuffers we have to use the multi-view versions of the VS and GS.
    179        ANGLE_TRY(mVsMultiview.resolve(context11, renderer));
    180        ANGLE_TRY(mGsMultiview.resolve(context11, renderer));
    181        *vs = &mVsMultiview.getObj();
    182        *gs = &mGsMultiview.getObj();
    183    }
    184 
    185    *il = nullptr;
    186 
    187    if (numRTs == 0)
    188    {
    189        ANGLE_TRY(mPsDepth.resolve(context11, renderer));
    190        *ps = &mPsDepth.getObj();
    191        return angle::Result::Continue;
    192    }
    193 
    194    switch (clearType)
    195    {
    196        case GL_FLOAT:
    197            ANGLE_TRY(mPsFloat[numRTs - 1].resolve(context11, renderer));
    198            *ps = &mPsFloat[numRTs - 1].getObj();
    199            break;
    200        case GL_UNSIGNED_INT:
    201            ANGLE_TRY(mPsUInt[numRTs - 1].resolve(context11, renderer));
    202            *ps = &mPsUInt[numRTs - 1].getObj();
    203            break;
    204        case GL_INT:
    205            ANGLE_TRY(mPsSInt[numRTs - 1].resolve(context11, renderer));
    206            *ps = &mPsSInt[numRTs - 1].getObj();
    207            break;
    208        default:
    209            UNREACHABLE();
    210            break;
    211    }
    212 
    213    return angle::Result::Continue;
    214 }
    215 
    216 Clear11::Clear11(Renderer11 *renderer)
    217    : mRenderer(renderer),
    218      mResourcesInitialized(false),
    219      mScissorEnabledRasterizerState(),
    220      mScissorDisabledRasterizerState(),
    221      mShaderManager(),
    222      mConstantBuffer(),
    223      mVertexBuffer(),
    224      mShaderData({})
    225 {}
    226 
    227 Clear11::~Clear11() {}
    228 
    229 angle::Result Clear11::ensureResourcesInitialized(const gl::Context *context)
    230 {
    231    if (mResourcesInitialized)
    232    {
    233        return angle::Result::Continue;
    234    }
    235 
    236    ANGLE_TRACE_EVENT0("gpu.angle", "Clear11::ensureResourcesInitialized");
    237 
    238    static_assert((sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<int>)),
    239                  "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<int>");
    240 
    241    static_assert(
    242        (sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<uint32_t>)),
    243        "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<uint32_t>");
    244 
    245    static_assert((sizeof(RtvDsvClearInfo<float>) % 16 == 0),
    246                  "The size of RtvDsvClearInfo<float> should be a multiple of 16bytes.");
    247 
    248    // Create Rasterizer States
    249    D3D11_RASTERIZER_DESC rsDesc;
    250    rsDesc.FillMode              = D3D11_FILL_SOLID;
    251    rsDesc.CullMode              = D3D11_CULL_NONE;
    252    rsDesc.FrontCounterClockwise = FALSE;
    253    rsDesc.DepthBias             = 0;
    254    rsDesc.DepthBiasClamp        = 0.0f;
    255    rsDesc.SlopeScaledDepthBias  = 0.0f;
    256    rsDesc.DepthClipEnable       = TRUE;
    257    rsDesc.ScissorEnable         = FALSE;
    258    rsDesc.MultisampleEnable     = FALSE;
    259    rsDesc.AntialiasedLineEnable = FALSE;
    260 
    261    Context11 *context11 = GetImplAs<Context11>(context);
    262 
    263    ANGLE_TRY(mRenderer->allocateResource(context11, rsDesc, &mScissorDisabledRasterizerState));
    264    mScissorDisabledRasterizerState.setInternalName("Clear11RasterizerStateWithScissorDisabled");
    265 
    266    rsDesc.ScissorEnable = TRUE;
    267    ANGLE_TRY(mRenderer->allocateResource(context11, rsDesc, &mScissorEnabledRasterizerState));
    268    mScissorEnabledRasterizerState.setInternalName("Clear11RasterizerStateWithScissorEnabled");
    269 
    270    // Initialize Depthstencil state with defaults
    271    mDepthStencilStateKey.depthTest                = false;
    272    mDepthStencilStateKey.depthMask                = false;
    273    mDepthStencilStateKey.depthFunc                = GL_ALWAYS;
    274    mDepthStencilStateKey.stencilWritemask         = static_cast<GLuint>(-1);
    275    mDepthStencilStateKey.stencilBackWritemask     = static_cast<GLuint>(-1);
    276    mDepthStencilStateKey.stencilBackMask          = 0;
    277    mDepthStencilStateKey.stencilTest              = false;
    278    mDepthStencilStateKey.stencilMask              = 0;
    279    mDepthStencilStateKey.stencilFail              = GL_REPLACE;
    280    mDepthStencilStateKey.stencilPassDepthFail     = GL_REPLACE;
    281    mDepthStencilStateKey.stencilPassDepthPass     = GL_REPLACE;
    282    mDepthStencilStateKey.stencilFunc              = GL_ALWAYS;
    283    mDepthStencilStateKey.stencilBackFail          = GL_REPLACE;
    284    mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE;
    285    mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE;
    286    mDepthStencilStateKey.stencilBackFunc          = GL_ALWAYS;
    287 
    288    // Initialize BlendStateKey with defaults
    289    mBlendStateKey.blendStateExt = gl::BlendStateExt(mRenderer->getNativeCaps().maxDrawBuffers);
    290 
    291    mResourcesInitialized = true;
    292    return angle::Result::Continue;
    293 }
    294 
    295 bool Clear11::useVertexBuffer() const
    296 {
    297    return (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3);
    298 }
    299 
    300 angle::Result Clear11::ensureConstantBufferCreated(const gl::Context *context)
    301 {
    302    if (mConstantBuffer.valid())
    303    {
    304        return angle::Result::Continue;
    305    }
    306 
    307    // Create constant buffer for color & depth data
    308 
    309    D3D11_BUFFER_DESC bufferDesc;
    310    bufferDesc.ByteWidth           = g_ConstantBufferSize;
    311    bufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
    312    bufferDesc.BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
    313    bufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
    314    bufferDesc.MiscFlags           = 0;
    315    bufferDesc.StructureByteStride = 0;
    316 
    317    D3D11_SUBRESOURCE_DATA initialData;
    318    initialData.pSysMem          = &mShaderData;
    319    initialData.SysMemPitch      = g_ConstantBufferSize;
    320    initialData.SysMemSlicePitch = g_ConstantBufferSize;
    321 
    322    ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &initialData,
    323                                          &mConstantBuffer));
    324    mConstantBuffer.setInternalName("Clear11ConstantBuffer");
    325    return angle::Result::Continue;
    326 }
    327 
    328 angle::Result Clear11::ensureVertexBufferCreated(const gl::Context *context)
    329 {
    330    ASSERT(useVertexBuffer());
    331 
    332    if (mVertexBuffer.valid())
    333    {
    334        return angle::Result::Continue;
    335    }
    336 
    337    // Create vertex buffer with vertices for a quad covering the entire surface
    338 
    339    static_assert((sizeof(d3d11::PositionVertex) % 16) == 0,
    340                  "d3d11::PositionVertex should be a multiple of 16 bytes");
    341    const d3d11::PositionVertex vbData[6] = {{-1.0f, 1.0f, 0.0f, 1.0f},  {1.0f, -1.0f, 0.0f, 1.0f},
    342                                             {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f},
    343                                             {1.0f, 1.0f, 0.0f, 1.0f},   {1.0f, -1.0f, 0.0f, 1.0f}};
    344 
    345    const UINT vbSize = sizeof(vbData);
    346 
    347    D3D11_BUFFER_DESC bufferDesc;
    348    bufferDesc.ByteWidth           = vbSize;
    349    bufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
    350    bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
    351    bufferDesc.CPUAccessFlags      = 0;
    352    bufferDesc.MiscFlags           = 0;
    353    bufferDesc.StructureByteStride = 0;
    354 
    355    D3D11_SUBRESOURCE_DATA initialData;
    356    initialData.pSysMem          = vbData;
    357    initialData.SysMemPitch      = vbSize;
    358    initialData.SysMemSlicePitch = initialData.SysMemPitch;
    359 
    360    ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &initialData,
    361                                          &mVertexBuffer));
    362    mVertexBuffer.setInternalName("Clear11VertexBuffer");
    363    return angle::Result::Continue;
    364 }
    365 
    366 angle::Result Clear11::clearFramebuffer(const gl::Context *context,
    367                                        const ClearParameters &clearParams,
    368                                        const gl::FramebufferState &fboData)
    369 {
    370    ANGLE_TRY(ensureResourcesInitialized(context));
    371 
    372    // Iterate over the color buffers which require clearing and determine if they can be
    373    // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
    374    // This requires:
    375    // 1) The render target is being cleared to a float value (will be cast to integer when clearing
    376    // integer render targets as expected but does not work the other way around)
    377    // 2) The format of the render target has no color channels that are currently masked out.
    378    // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
    379    // work.
    380    //
    381    // If these conditions are met, and:
    382    // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView.
    383    // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available.
    384    // Otherwise perform a shader based clear.
    385    //
    386    // Also determine if the DSV can be cleared withID3D11DeviceContext::ClearDepthStencilView by
    387    // checking if the stencil write mask covers the entire stencil.
    388    //
    389    // To clear the remaining buffers, a shader based clear is performed:
    390    // - The appropriate ShaderManagers (VS & PS) for the clearType is set
    391    // - A CB containing the clear color and Z values is bound
    392    // - An IL and VB are bound (for FL93 and below)
    393    // - ScissorRect/Raststate/Viewport set as required
    394    // - Blendstate set containing appropriate colorMasks
    395    // - DepthStencilState set with appropriate parameters for a z or stencil clear if required
    396    // - Color and/or Z buffers to be cleared are bound
    397    // - Primitive covering entire clear area is drawn
    398 
    399    gl::Extents framebufferSize;
    400 
    401    const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
    402    if (depthStencilAttachment != nullptr)
    403    {
    404        framebufferSize = depthStencilAttachment->getSize();
    405    }
    406    else
    407    {
    408        const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
    409        ASSERT(colorAttachment);
    410        framebufferSize = colorAttachment->getSize();
    411    }
    412 
    413    bool needScissoredClear = false;
    414    D3D11_RECT scissorRect;
    415    if (clearParams.scissorEnabled)
    416    {
    417        if (clearParams.scissor.x >= framebufferSize.width ||
    418            clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.width == 0 ||
    419            clearParams.scissor.height == 0)
    420        {
    421            // The check assumes that the viewport offsets are not negative as according to the
    422            // OVR_multiview2 spec.
    423            // Scissor rect is outside the renderbuffer or is an empty rect.
    424            return angle::Result::Continue;
    425        }
    426 
    427        if (clearParams.scissor.x + clearParams.scissor.width <= 0 ||
    428            clearParams.scissor.y + clearParams.scissor.height <= 0)
    429        {
    430            // Scissor rect is outside the renderbuffer.
    431            return angle::Result::Continue;
    432        }
    433        needScissoredClear =
    434            clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
    435            clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
    436            clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height;
    437 
    438        if (needScissoredClear)
    439        {
    440            // Apply viewport offsets to compute the final scissor rectangles.
    441            // Even in multiview all layers share the same viewport and scissor.
    442            scissorRect.left   = clearParams.scissor.x;
    443            scissorRect.right  = scissorRect.left + clearParams.scissor.width;
    444            scissorRect.top    = clearParams.scissor.y;
    445            scissorRect.bottom = scissorRect.top + clearParams.scissor.height;
    446        }
    447    }
    448 
    449    ID3D11DeviceContext *deviceContext   = mRenderer->getDeviceContext();
    450    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
    451 
    452    std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
    453    std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks = {};
    454 
    455    uint32_t numRtvs        = 0;
    456    uint8_t commonColorMask = 0;
    457 
    458    const auto &colorAttachments = fboData.getColorAttachments();
    459    for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers())
    460    {
    461        const uint8_t colorMask = gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(
    462            colorAttachmentIndex, clearParams.colorMask);
    463 
    464        commonColorMask |= colorMask;
    465 
    466        const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
    467 
    468        if (!clearParams.clearColor[colorAttachmentIndex])
    469        {
    470            continue;
    471        }
    472 
    473        RenderTarget11 *renderTarget = nullptr;
    474        ANGLE_TRY(attachment.getRenderTarget(context, attachment.getRenderToTextureSamples(),
    475                                             &renderTarget));
    476 
    477        const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
    478 
    479        if (clearParams.colorType == GL_FLOAT &&
    480            !(formatInfo.componentType == GL_FLOAT ||
    481              formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
    482              formatInfo.componentType == GL_SIGNED_NORMALIZED))
    483        {
    484            WARN() << "It is undefined behaviour to clear a render buffer which is not "
    485                      "normalized fixed point or floating-point to floating point values (color "
    486                      "attachment "
    487                   << colorAttachmentIndex << " has internal format " << attachment.getFormat()
    488                   << ").";
    489        }
    490 
    491        bool r, g, b, a;
    492        gl::BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
    493        if ((formatInfo.redBits == 0 || !r) && (formatInfo.greenBits == 0 || !g) &&
    494            (formatInfo.blueBits == 0 || !b) && (formatInfo.alphaBits == 0 || !a))
    495        {
    496            // Every channel either does not exist in the render target or is masked out
    497            continue;
    498        }
    499 
    500        const auto &framebufferRTV = renderTarget->getRenderTargetView();
    501        ASSERT(framebufferRTV.valid());
    502 
    503        bool canClearView = mRenderer->getRenderer11DeviceCaps().supportsClearView;
    504        if (canClearView &&
    505            mRenderer->getFeatures().emulateClearViewAfterDualSourceBlending.enabled)
    506        {
    507            // Check the current state to see if we were using dual source blending
    508            const auto isDualSource = [](const auto blend) {
    509                switch (blend)
    510                {
    511                    case D3D11_BLEND_SRC1_COLOR:
    512                    case D3D11_BLEND_INV_SRC1_COLOR:
    513                    case D3D11_BLEND_SRC1_ALPHA:
    514                    case D3D11_BLEND_INV_SRC1_ALPHA:
    515                        return true;
    516                    default:
    517                        return false;
    518                }
    519            };
    520            FLOAT blendFactor[4];
    521            UINT sampleMask;
    522            ID3D11BlendState *blendState;
    523            deviceContext->OMGetBlendState(&blendState, blendFactor, &sampleMask);
    524            if (blendState)
    525            {
    526                D3D11_BLEND_DESC blendDesc;
    527                blendState->GetDesc(&blendDesc);
    528                // You can only use dual source blending on slot 0 so only check there
    529                if (isDualSource(blendDesc.RenderTarget[0].SrcBlend) ||
    530                    isDualSource(blendDesc.RenderTarget[0].DestBlend) ||
    531                    isDualSource(blendDesc.RenderTarget[0].SrcBlendAlpha) ||
    532                    isDualSource(blendDesc.RenderTarget[0].DestBlendAlpha))
    533                {
    534                    canClearView = false;
    535                }
    536            }
    537        }
    538 
    539        if (needScissoredClear && mRenderer->getFeatures().scissoredClearArtifacts.enabled)
    540        {
    541            canClearView = false;
    542        }
    543 
    544        if ((!canClearView && needScissoredClear) || clearParams.colorType != GL_FLOAT ||
    545            (formatInfo.redBits > 0 && !r) || (formatInfo.greenBits > 0 && !g) ||
    546            (formatInfo.blueBits > 0 && !b) || (formatInfo.alphaBits > 0 && !a))
    547        {
    548            rtvs[numRtvs]     = framebufferRTV.get();
    549            rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask;
    550            numRtvs++;
    551        }
    552        else
    553        {
    554            // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
    555            // possible
    556 
    557            const auto &nativeFormat = renderTarget->getFormatSet().format();
    558 
    559            // Check if the actual format has a channel that the internal format does not and
    560            // set them to the default values
    561            float clearValues[4] = {
    562                ((formatInfo.redBits == 0 && nativeFormat.redBits > 0) ? 0.0f
    563                                                                       : clearParams.colorF.red),
    564                ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
    565                     ? 0.0f
    566                     : clearParams.colorF.green),
    567                ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f
    568                                                                         : clearParams.colorF.blue),
    569                ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
    570                     ? 1.0f
    571                     : clearParams.colorF.alpha),
    572            };
    573 
    574            if (formatInfo.alphaBits == 1)
    575            {
    576                // Some drivers do not correctly handle calling Clear() on a format with 1-bit
    577                // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
    578                // WARP does not do this. We should handle the rounding for them instead.
    579                clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
    580            }
    581 
    582            if (needScissoredClear)
    583            {
    584                // We shouldn't reach here if deviceContext1 is unavailable.
    585                ASSERT(deviceContext1);
    586                deviceContext1->ClearView(framebufferRTV.get(), clearValues, &scissorRect, 1);
    587                if (mRenderer->getFeatures().callClearTwice.enabled)
    588                {
    589                    deviceContext1->ClearView(framebufferRTV.get(), clearValues, &scissorRect, 1);
    590                }
    591            }
    592            else
    593            {
    594                deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
    595                if (mRenderer->getFeatures().callClearTwice.enabled)
    596                {
    597                    deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
    598                }
    599            }
    600        }
    601    }
    602 
    603    ID3D11DepthStencilView *dsv = nullptr;
    604 
    605    if (clearParams.clearDepth || clearParams.clearStencil)
    606    {
    607        RenderTarget11 *depthStencilRenderTarget = nullptr;
    608 
    609        ASSERT(depthStencilAttachment != nullptr);
    610        ANGLE_TRY(depthStencilAttachment->getRenderTarget(
    611            context, depthStencilAttachment->getRenderToTextureSamples(),
    612            &depthStencilRenderTarget));
    613 
    614        dsv = depthStencilRenderTarget->getDepthStencilView().get();
    615        ASSERT(dsv != nullptr);
    616 
    617        const auto &nativeFormat      = depthStencilRenderTarget->getFormatSet().format();
    618        const auto *stencilAttachment = fboData.getStencilAttachment();
    619 
    620        uint32_t stencilUnmasked =
    621            (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
    622        bool needMaskedStencilClear =
    623            clearParams.clearStencil &&
    624            (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
    625 
    626        if (!needScissoredClear && !needMaskedStencilClear)
    627        {
    628            const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
    629                                    (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
    630            const FLOAT depthClear   = gl::clamp01(clearParams.depthValue);
    631            const UINT8 stencilClear = clearParams.stencilValue & 0xFF;
    632 
    633            deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
    634 
    635            dsv = nullptr;
    636        }
    637    }
    638 
    639    if (numRtvs == 0 && dsv == nullptr)
    640    {
    641        return angle::Result::Continue;
    642    }
    643 
    644    // Clear the remaining render targets and depth stencil in one pass by rendering a quad:
    645    //
    646    // IA/VS: Vertices containing position and color members are passed through to the next stage.
    647    // The vertex position has XY coordinates equal to clip extents and a Z component equal to the
    648    // Z clear value. The vertex color contains the clear color.
    649    //
    650    // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether
    651    // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without
    652    // the scissor test enabled is set as well.
    653    //
    654    // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or
    655    // disabled or set depending on what the input depthStencil clear parameters are. Since the PS
    656    // is not writing out depth or rejecting pixels, this should happen prior to the PS stage.
    657    //
    658    // PS: Will write out the color values passed through from the previous stage to all outputs.
    659    //
    660    // OM: BlendState will perform the required color masking and output to RTV(s).
    661 
    662    //
    663    // ======================================================================================
    664    //
    665    // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
    666    // buffer that is not normalized fixed point or floating point with floating point values
    667    // are undefined so we can just write floats to them and D3D11 will bit cast them to
    668    // integers.
    669    //
    670    // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
    671    // buffer with integer values because there is no gl API call which would allow it,
    672    // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
    673    // be a compatible clear type.
    674 
    675    ASSERT(numRtvs <= static_cast<uint32_t>(mRenderer->getNativeCaps().maxDrawBuffers));
    676 
    677    // Setup BlendStateKey parameters
    678    mBlendStateKey.blendStateExt.setColorMask(false, false, false, false);
    679    for (size_t i = 0; i < numRtvs; i++)
    680    {
    681        mBlendStateKey.blendStateExt.setColorMaskIndexed(i, rtvMasks[i]);
    682    }
    683 
    684    mBlendStateKey.rtvMax = static_cast<uint16_t>(numRtvs);
    685 
    686    // Get BlendState
    687    const d3d11::BlendState *blendState = nullptr;
    688    ANGLE_TRY(mRenderer->getBlendState(context, mBlendStateKey, &blendState));
    689 
    690    const d3d11::DepthStencilState *dsState = nullptr;
    691    const float *zValue                     = nullptr;
    692 
    693    if (dsv)
    694    {
    695        // Setup DepthStencilStateKey
    696        mDepthStencilStateKey.depthTest        = clearParams.clearDepth;
    697        mDepthStencilStateKey.depthMask        = clearParams.clearDepth;
    698        mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask;
    699        mDepthStencilStateKey.stencilTest      = clearParams.clearStencil;
    700 
    701        // Get DepthStencilState
    702        ANGLE_TRY(mRenderer->getDepthStencilState(context, mDepthStencilStateKey, &dsState));
    703        zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr;
    704    }
    705 
    706    bool dirtyCb = false;
    707 
    708    // Compare the input color/z values against the CB cache and update it if necessary
    709    switch (clearParams.colorType)
    710    {
    711        case GL_FLOAT:
    712            dirtyCb =
    713                UpdateDataCache(&mShaderData, clearParams.colorF, zValue, numRtvs, commonColorMask);
    714            break;
    715        case GL_UNSIGNED_INT:
    716            dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<uint32_t> *>(&mShaderData),
    717                                      clearParams.colorUI, zValue, numRtvs, commonColorMask);
    718            break;
    719        case GL_INT:
    720            dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<int> *>(&mShaderData),
    721                                      clearParams.colorI, zValue, numRtvs, commonColorMask);
    722            break;
    723        default:
    724            UNREACHABLE();
    725            break;
    726    }
    727 
    728    ANGLE_TRY(ensureConstantBufferCreated(context));
    729 
    730    if (dirtyCb)
    731    {
    732        // Update the constant buffer with the updated cache contents
    733        // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible.
    734        D3D11_MAPPED_SUBRESOURCE mappedResource;
    735        ANGLE_TRY(mRenderer->mapResource(context, mConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD,
    736                                         0, &mappedResource));
    737 
    738        memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize);
    739        deviceContext->Unmap(mConstantBuffer.get(), 0);
    740    }
    741 
    742    auto *stateManager = mRenderer->getStateManager();
    743 
    744    // Set the viewport to be the same size as the framebuffer.
    745    stateManager->setSimpleViewport(framebufferSize);
    746 
    747    // Apply state
    748    stateManager->setSimpleBlendState(blendState);
    749 
    750    const UINT stencilValue = clearParams.stencilValue & 0xFF;
    751    stateManager->setDepthStencilState(dsState, stencilValue);
    752 
    753    if (needScissoredClear)
    754    {
    755        stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
    756    }
    757    else
    758    {
    759        stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
    760    }
    761 
    762    // Get Shaders
    763    const d3d11::VertexShader *vs   = nullptr;
    764    const d3d11::GeometryShader *gs = nullptr;
    765    const d3d11::InputLayout *il    = nullptr;
    766    const d3d11::PixelShader *ps    = nullptr;
    767    const bool hasLayeredLayout     = (fboData.isMultiview());
    768    ANGLE_TRY(mShaderManager.getShadersAndLayout(context, mRenderer, clearParams.colorType, numRtvs,
    769                                                 hasLayeredLayout, &il, &vs, &gs, &ps));
    770 
    771    // Apply Shaders
    772    stateManager->setDrawShaders(vs, gs, ps);
    773    stateManager->setPixelConstantBuffer(0, &mConstantBuffer);
    774 
    775    // Bind IL & VB if needed
    776    stateManager->setIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
    777    stateManager->setInputLayout(il);
    778 
    779    if (useVertexBuffer())
    780    {
    781        ANGLE_TRY(ensureVertexBufferCreated(context));
    782        stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0);
    783    }
    784    else
    785    {
    786        stateManager->setSingleVertexBuffer(nullptr, 0, 0);
    787    }
    788 
    789    stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    790 
    791    // Apply render targets
    792    stateManager->setRenderTargets(&rtvs[0], numRtvs, dsv);
    793 
    794    if (needScissoredClear)
    795    {
    796        stateManager->setScissorRectD3D(scissorRect);
    797    }
    798    // Draw the fullscreen quad.
    799    if (!hasLayeredLayout)
    800    {
    801        deviceContext->Draw(6, 0);
    802    }
    803    else
    804    {
    805        ASSERT(hasLayeredLayout);
    806        deviceContext->DrawInstanced(6, static_cast<UINT>(fboData.getNumViews()), 0, 0);
    807    }
    808 
    809    return angle::Result::Continue;
    810 }
    811 
    812 }  // namespace rx