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