1 // 2 // Copyright (c) 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 "libGLESv2/renderer/d3d/d3d11/Clear11.h" 10 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" 11 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" 12 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" 13 #include "libGLESv2/formatutils.h" 14 #include "libGLESv2/Framebuffer.h" 15 #include "libGLESv2/FramebufferAttachment.h" 16 17 // Precompiled shaders 18 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" 19 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" 20 21 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" 22 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" 23 24 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" 25 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" 26 27 namespace rx 28 { 29 30 template <typename T> 31 static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color<T> &color, float depth, void *buffer) 32 { 33 d3d11::PositionDepthColorVertex<T> *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex<T>*>(buffer); 34 35 float depthClear = gl::clamp01(depth); 36 float left = -1.0f; 37 float right = 1.0f; 38 float top = -1.0f; 39 float bottom = 1.0f; 40 41 // Clip the quad coordinates to the scissor if needed 42 if (scissor != NULL) 43 { 44 left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); 45 right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); 46 top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); 47 bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); 48 } 49 50 d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left, bottom, depthClear, color); 51 d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left, top, depthClear, color); 52 d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color); 53 d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top, depthClear, color); 54 } 55 56 template <unsigned int vsSize, unsigned int psSize> 57 Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) 58 { 59 HRESULT result; 60 61 ClearShader shader = { 0 }; 62 63 D3D11_INPUT_ELEMENT_DESC quadLayout[] = 64 { 65 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 66 { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 67 }; 68 69 result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); 70 ASSERT(SUCCEEDED(result)); 71 72 result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); 73 ASSERT(SUCCEEDED(result)); 74 75 result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); 76 ASSERT(SUCCEEDED(result)); 77 78 return shader; 79 } 80 81 Clear11::Clear11(Renderer11 *renderer) 82 : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>), 83 mVertexBuffer(NULL), mRasterizerState(NULL) 84 { 85 HRESULT result; 86 ID3D11Device *device = renderer->getDevice(); 87 88 D3D11_BUFFER_DESC vbDesc; 89 vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4; 90 vbDesc.Usage = D3D11_USAGE_DYNAMIC; 91 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 92 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 93 vbDesc.MiscFlags = 0; 94 vbDesc.StructureByteStride = 0; 95 96 result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); 97 ASSERT(SUCCEEDED(result)); 98 d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); 99 100 D3D11_RASTERIZER_DESC rsDesc; 101 rsDesc.FillMode = D3D11_FILL_SOLID; 102 rsDesc.CullMode = D3D11_CULL_NONE; 103 rsDesc.FrontCounterClockwise = FALSE; 104 rsDesc.DepthBias = 0; 105 rsDesc.DepthBiasClamp = 0.0f; 106 rsDesc.SlopeScaledDepthBias = 0.0f; 107 rsDesc.DepthClipEnable = FALSE; 108 rsDesc.ScissorEnable = FALSE; 109 rsDesc.MultisampleEnable = FALSE; 110 rsDesc.AntialiasedLineEnable = FALSE; 111 112 result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); 113 ASSERT(SUCCEEDED(result)); 114 d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); 115 116 mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); 117 mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); 118 mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); 119 } 120 121 Clear11::~Clear11() 122 { 123 for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) 124 { 125 SafeRelease(i->second); 126 } 127 mClearBlendStates.clear(); 128 129 SafeRelease(mFloatClearShader.inputLayout); 130 SafeRelease(mFloatClearShader.vertexShader); 131 SafeRelease(mFloatClearShader.pixelShader); 132 133 SafeRelease(mUintClearShader.inputLayout); 134 SafeRelease(mUintClearShader.vertexShader); 135 SafeRelease(mUintClearShader.pixelShader); 136 137 SafeRelease(mIntClearShader.inputLayout); 138 SafeRelease(mIntClearShader.vertexShader); 139 SafeRelease(mIntClearShader.pixelShader); 140 141 for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) 142 { 143 SafeRelease(i->second); 144 } 145 mClearDepthStencilStates.clear(); 146 147 SafeRelease(mVertexBuffer); 148 SafeRelease(mRasterizerState); 149 } 150 151 gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) 152 { 153 // First determine if a scissored clear is needed, this will always require drawing a quad. 154 // 155 // Otherwise, iterate over the color buffers which require clearing and determine if they can be 156 // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: 157 // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer 158 // render targets as expected but does not work the other way around) 159 // 2) The format of the render target has no color channels that are currently masked out. 160 // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. 161 // 162 // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView 163 // by checking if the stencil write mask covers the entire stencil. 164 // 165 // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color 166 // attribute. 167 168 gl::Extents framebufferSize; 169 if (frameBuffer->getFirstColorbuffer() != NULL) 170 { 171 gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); 172 framebufferSize.width = attachment->getWidth(); 173 framebufferSize.height = attachment->getHeight(); 174 framebufferSize.depth = 1; 175 } 176 else if (frameBuffer->getDepthOrStencilbuffer() != NULL) 177 { 178 gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); 179 framebufferSize.width = attachment->getWidth(); 180 framebufferSize.height = attachment->getHeight(); 181 framebufferSize.depth = 1; 182 } 183 else 184 { 185 UNREACHABLE(); 186 return gl::Error(GL_INVALID_OPERATION); 187 } 188 189 if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || 190 clearParams.scissor.y >= framebufferSize.height || 191 clearParams.scissor.x + clearParams.scissor.width <= 0 || 192 clearParams.scissor.y + clearParams.scissor.height <= 0)) 193 { 194 // Scissor is enabled and the scissor rectangle is outside the renderbuffer 195 return gl::Error(GL_NO_ERROR); 196 } 197 198 bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || 199 clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || 200 clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); 201 202 std::vector<MaskedRenderTarget> maskedClearRenderTargets; 203 RenderTarget11* maskedClearDepthStencil = NULL; 204 205 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 206 207 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 208 { 209 if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) 210 { 211 gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); 212 if (attachment) 213 { 214 RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); 215 if (!renderTarget) 216 { 217 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); 218 } 219 220 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); 221 222 if (clearParams.colorClearType == GL_FLOAT && 223 !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) 224 { 225 ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" 226 "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, 227 attachment->getInternalFormat()); 228 } 229 230 if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && 231 (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && 232 (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && 233 (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) 234 { 235 // Every channel either does not exist in the render target or is masked out 236 continue; 237 } 238 else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || 239 (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || 240 (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || 241 (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || 242 (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) 243 { 244 // A scissored or masked clear is required 245 MaskedRenderTarget maskAndRt; 246 bool clearColor = clearParams.clearColor[colorAttachment]; 247 maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); 248 maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); 249 maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); 250 maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); 251 maskAndRt.renderTarget = renderTarget; 252 maskedClearRenderTargets.push_back(maskAndRt); 253 } 254 else 255 { 256 // ID3D11DeviceContext::ClearRenderTargetView is possible 257 258 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); 259 if (!framebufferRTV) 260 { 261 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); 262 } 263 264 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); 265 266 // Check if the actual format has a channel that the internal format does not and set them to the 267 // default values 268 const float clearValues[4] = 269 { 270 ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), 271 ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), 272 ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), 273 ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), 274 }; 275 276 deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); 277 } 278 } 279 } 280 } 281 282 if (clearParams.clearDepth || clearParams.clearStencil) 283 { 284 gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); 285 if (attachment) 286 { 287 RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); 288 if (!renderTarget) 289 { 290 return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); 291 } 292 293 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); 294 295 unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0; 296 bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; 297 298 if (needScissoredClear || needMaskedStencilClear) 299 { 300 maskedClearDepthStencil = renderTarget; 301 } 302 else 303 { 304 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); 305 if (!framebufferDSV) 306 { 307 return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); 308 } 309 310 UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | 311 (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); 312 FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); 313 UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; 314 315 deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); 316 } 317 } 318 } 319 320 if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) 321 { 322 // To clear the render targets and depth stencil in one pass: 323 // 324 // Render a quad clipped to the scissor rectangle which draws the clear color and a blend 325 // state that will perform the required color masking. 326 // 327 // The quad's depth is equal to the depth clear value with a depth stencil state that 328 // will enable or disable depth test/writes if the depth buffer should be cleared or not. 329 // 330 // The rasterizer state's stencil is set to always pass or fail based on if the stencil 331 // should be cleared or not with a stencil write mask of the stencil clear value. 332 // 333 // ====================================================================================== 334 // 335 // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- 336 // buffer that is not normalized fixed point or floating point with floating point values 337 // are undefined so we can just write floats to them and D3D11 will bit cast them to 338 // integers. 339 // 340 // Also, we don't have to worry about attempting to clear a normalized fixed/floating point 341 // buffer with integer values because there is no gl API call which would allow it, 342 // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to 343 // be a compatible clear type. 344 345 // Bind all the render targets which need clearing 346 ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); 347 std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); 348 for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) 349 { 350 RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; 351 ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); 352 if (!rtv) 353 { 354 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); 355 } 356 357 rtvs[i] = rtv; 358 } 359 ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; 360 361 ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); 362 const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; 363 const UINT sampleMask = 0xFFFFFFFF; 364 365 ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); 366 const UINT stencilClear = clearParams.stencilClearValue & 0xFF; 367 368 // Set the vertices 369 UINT vertexStride = 0; 370 const UINT startIdx = 0; 371 const ClearShader* shader = NULL; 372 D3D11_MAPPED_SUBRESOURCE mappedResource; 373 HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); 374 if (FAILED(result)) 375 { 376 return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); 377 } 378 379 const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; 380 switch (clearParams.colorClearType) 381 { 382 case GL_FLOAT: 383 ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); 384 vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); 385 shader = &mFloatClearShader; 386 break; 387 388 case GL_UNSIGNED_INT: 389 ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); 390 vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); 391 shader = &mUintClearShader; 392 break; 393 394 case GL_INT: 395 ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); 396 vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); 397 shader = &mIntClearShader; 398 break; 399 400 default: 401 UNREACHABLE(); 402 break; 403 } 404 405 deviceContext->Unmap(mVertexBuffer, 0); 406 407 // Set the viewport to be the same size as the framebuffer 408 D3D11_VIEWPORT viewport; 409 viewport.TopLeftX = 0; 410 viewport.TopLeftY = 0; 411 viewport.Width = framebufferSize.width; 412 viewport.Height = framebufferSize.height; 413 viewport.MinDepth = 0; 414 viewport.MaxDepth = 1; 415 deviceContext->RSSetViewports(1, &viewport); 416 417 // Apply state 418 deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); 419 deviceContext->OMSetDepthStencilState(dsState, stencilClear); 420 deviceContext->RSSetState(mRasterizerState); 421 422 // Apply shaders 423 deviceContext->IASetInputLayout(shader->inputLayout); 424 deviceContext->VSSetShader(shader->vertexShader, NULL, 0); 425 deviceContext->PSSetShader(shader->pixelShader, NULL, 0); 426 deviceContext->GSSetShader(NULL, NULL, 0); 427 428 // Apply vertex buffer 429 deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); 430 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 431 432 // Apply render targets 433 deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); 434 435 // Draw the clear quad 436 deviceContext->Draw(4, 0); 437 438 // Clean up 439 mRenderer->markAllStateDirty(); 440 } 441 442 return gl::Error(GL_NO_ERROR); 443 } 444 445 ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts) 446 { 447 ClearBlendInfo blendKey = { 0 }; 448 for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) 449 { 450 if (i < rts.size()) 451 { 452 RenderTarget11 *rt = rts[i].renderTarget; 453 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); 454 455 blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); 456 blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); 457 blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); 458 blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); 459 } 460 else 461 { 462 blendKey.maskChannels[i][0] = false; 463 blendKey.maskChannels[i][1] = false; 464 blendKey.maskChannels[i][2] = false; 465 blendKey.maskChannels[i][3] = false; 466 } 467 } 468 469 ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); 470 if (i != mClearBlendStates.end()) 471 { 472 return i->second; 473 } 474 else 475 { 476 D3D11_BLEND_DESC blendDesc = { 0 }; 477 blendDesc.AlphaToCoverageEnable = FALSE; 478 blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; 479 480 for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) 481 { 482 blendDesc.RenderTarget[i].BlendEnable = FALSE; 483 blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0], 484 blendKey.maskChannels[i][1], 485 blendKey.maskChannels[i][2], 486 blendKey.maskChannels[i][3]); 487 } 488 489 ID3D11Device *device = mRenderer->getDevice(); 490 ID3D11BlendState* blendState = NULL; 491 HRESULT result = device->CreateBlendState(&blendDesc, &blendState); 492 if (FAILED(result) || !blendState) 493 { 494 ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); 495 return NULL; 496 } 497 498 mClearBlendStates[blendKey] = blendState; 499 500 return blendState; 501 } 502 } 503 504 ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams) 505 { 506 ClearDepthStencilInfo dsKey = { 0 }; 507 dsKey.clearDepth = clearParams.clearDepth; 508 dsKey.clearStencil = clearParams.clearStencil; 509 dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; 510 511 ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); 512 if (i != mClearDepthStencilStates.end()) 513 { 514 return i->second; 515 } 516 else 517 { 518 D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; 519 dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; 520 dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; 521 dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; 522 dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; 523 dsDesc.StencilReadMask = 0; 524 dsDesc.StencilWriteMask = dsKey.stencilWriteMask; 525 dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; 526 dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; 527 dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; 528 dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 529 dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; 530 dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; 531 dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; 532 dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 533 534 ID3D11Device *device = mRenderer->getDevice(); 535 ID3D11DepthStencilState* dsState = NULL; 536 HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); 537 if (FAILED(result) || !dsState) 538 { 539 ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); 540 return NULL; 541 } 542 543 mClearDepthStencilStates[dsKey] = dsState; 544 545 return dsState; 546 } 547 } 548 549 } 550