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