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