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