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