blob: c60b7a6c8d9d4a0c9c968da1ded1c310281646e3 [file] [log] [blame]
Geoff Langda507fe2013-08-20 12:01:42 -04001//
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
Brandon Jonesc7a41042014-06-23 12:03:25 -07009#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"
Geoff Langda507fe2013-08-20 12:01:42 -040013#include "libGLESv2/formatutils.h"
14#include "libGLESv2/Framebuffer.h"
Jamie Madille261b442014-06-25 12:42:21 -040015#include "libGLESv2/FramebufferAttachment.h"
Geoff Langda507fe2013-08-20 12:01:42 -040016
Geoff Lang0b7eef72014-06-12 14:10:47 -040017// Precompiled shaders
Brandon Jonesc7a41042014-06-23 12:03:25 -070018#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
19#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
Geoff Langda507fe2013-08-20 12:01:42 -040020
Brandon Jonesc7a41042014-06-23 12:03:25 -070021#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
22#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
Geoff Langda507fe2013-08-20 12:01:42 -040023
Brandon Jonesc7a41042014-06-23 12:03:25 -070024#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
25#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
Geoff Langda507fe2013-08-20 12:01:42 -040026
27namespace rx
28{
29
Geoff Langda507fe2013-08-20 12:01:42 -040030template <typename T>
31static 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
56template <unsigned int vsSize, unsigned int psSize>
57Clear11::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
81Clear11::Clear11(Renderer11 *renderer)
Jamie Madilld3f0f1e2013-09-20 13:31:08 -040082 : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
Geoff Langda507fe2013-08-20 12:01:42 -040083 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
121Clear11::~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
Geoff Langcc79b8c2014-07-25 13:48:02 -0400151gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
Geoff Langda507fe2013-08-20 12:01:42 -0400152{
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 {
Jamie Madill3c7fa222014-06-05 13:08:51 -0400171 gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
172 framebufferSize.width = attachment->getWidth();
173 framebufferSize.height = attachment->getHeight();
Geoff Langda507fe2013-08-20 12:01:42 -0400174 framebufferSize.depth = 1;
175 }
176 else if (frameBuffer->getDepthOrStencilbuffer() != NULL)
177 {
Jamie Madill3c7fa222014-06-05 13:08:51 -0400178 gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
179 framebufferSize.width = attachment->getWidth();
180 framebufferSize.height = attachment->getHeight();
Geoff Langda507fe2013-08-20 12:01:42 -0400181 framebufferSize.depth = 1;
182 }
183 else
184 {
185 UNREACHABLE();
Geoff Langcc79b8c2014-07-25 13:48:02 -0400186 return gl::Error(GL_INVALID_OPERATION);
Geoff Langda507fe2013-08-20 12:01:42 -0400187 }
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
Geoff Langcc79b8c2014-07-25 13:48:02 -0400195 return gl::Error(GL_NO_ERROR);
Geoff Langda507fe2013-08-20 12:01:42 -0400196 }
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
Jamie Madilla09403c2014-07-21 10:03:36 -0400202 std::vector<MaskedRenderTarget> maskedClearRenderTargets;
Geoff Langda507fe2013-08-20 12:01:42 -0400203 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 {
Jamie Madill3c7fa222014-06-05 13:08:51 -0400211 gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment);
212 if (attachment)
Geoff Langda507fe2013-08-20 12:01:42 -0400213 {
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400214 RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
Geoff Langda507fe2013-08-20 12:01:42 -0400215 if (!renderTarget)
216 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400217 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
Geoff Langda507fe2013-08-20 12:01:42 -0400218 }
219
Geoff Lang5d601382014-07-22 15:14:06 -0400220 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
221
Geoff Langda507fe2013-08-20 12:01:42 -0400222 if (clearParams.colorClearType == GL_FLOAT &&
Geoff Lang5d601382014-07-22 15:14:06 -0400223 !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
Geoff Langda507fe2013-08-20 12:01:42 -0400224 {
225 ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-"
Geoff Lang5d601382014-07-22 15:14:06 -0400226 "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment,
227 attachment->getInternalFormat());
Geoff Langda507fe2013-08-20 12:01:42 -0400228 }
229
Geoff Lang5d601382014-07-22 15:14:06 -0400230 if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
231 (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
232 (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
233 (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
Geoff Langda507fe2013-08-20 12:01:42 -0400234 {
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 ||
Geoff Lang5d601382014-07-22 15:14:06 -0400239 (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
240 (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
241 (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
242 (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
Geoff Langda507fe2013-08-20 12:01:42 -0400243 {
244 // A scissored or masked clear is required
Jamie Madilla09403c2014-07-21 10:03:36 -0400245 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);
Geoff Langda507fe2013-08-20 12:01:42 -0400253 }
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 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400261 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
Geoff Langda507fe2013-08-20 12:01:42 -0400262 }
263
Geoff Lang5d601382014-07-22 15:14:06 -0400264 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
265
Geoff Lange8bc3192014-02-14 13:04:03 -0500266 // Check if the actual format has a channel that the internal format does not and set them to the
267 // default values
Geoff Lange8bc3192014-02-14 13:04:03 -0500268 const float clearValues[4] =
269 {
Geoff Lang5d601382014-07-22 15:14:06 -0400270 ((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),
Geoff Lange8bc3192014-02-14 13:04:03 -0500274 };
275
Geoff Langda507fe2013-08-20 12:01:42 -0400276 deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
277 }
278 }
279 }
280 }
281
282 if (clearParams.clearDepth || clearParams.clearStencil)
283 {
Jamie Madill3c7fa222014-06-05 13:08:51 -0400284 gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
285 if (attachment)
Geoff Langda507fe2013-08-20 12:01:42 -0400286 {
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400287 RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
Geoff Langda507fe2013-08-20 12:01:42 -0400288 if (!renderTarget)
289 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400290 return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
Geoff Langda507fe2013-08-20 12:01:42 -0400291 }
292
Geoff Lang5d601382014-07-22 15:14:06 -0400293 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
Geoff Langda507fe2013-08-20 12:01:42 -0400294
Geoff Lang5d601382014-07-22 15:14:06 -0400295 unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0;
Geoff Langda507fe2013-08-20 12:01:42 -0400296 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 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400307 return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
Geoff Langda507fe2013-08-20 12:01:42 -0400308 }
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
Geoff Langc0b9ef42014-07-02 10:02:37 -0400346 ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers);
Geoff Langda507fe2013-08-20 12:01:42 -0400347 std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
348 for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
349 {
Jamie Madilla09403c2014-07-21 10:03:36 -0400350 RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
351 ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
352 if (!rtv)
Geoff Langda507fe2013-08-20 12:01:42 -0400353 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400354 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
Geoff Langda507fe2013-08-20 12:01:42 -0400355 }
356
Jamie Madilla09403c2014-07-21 10:03:36 -0400357 rtvs[i] = rtv;
Geoff Langda507fe2013-08-20 12:01:42 -0400358 }
359 ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL;
360
Jamie Madilla09403c2014-07-21 10:03:36 -0400361 ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
Geoff Langda507fe2013-08-20 12:01:42 -0400362 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 {
Geoff Langcc79b8c2014-07-25 13:48:02 -0400376 return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result);
Geoff Langda507fe2013-08-20 12:01:42 -0400377 }
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
Jamie Madilld2a88382014-01-06 14:03:51 -0500433 deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv);
Geoff Langda507fe2013-08-20 12:01:42 -0400434
435 // Draw the clear quad
436 deviceContext->Draw(4, 0);
437
438 // Clean up
439 mRenderer->markAllStateDirty();
440 }
Geoff Langcc79b8c2014-07-25 13:48:02 -0400441
442 return gl::Error(GL_NO_ERROR);
Geoff Langda507fe2013-08-20 12:01:42 -0400443}
444
Jamie Madilla09403c2014-07-21 10:03:36 -0400445ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
Geoff Langda507fe2013-08-20 12:01:42 -0400446{
447 ClearBlendInfo blendKey = { 0 };
Geoff Lang3b866b62013-09-30 15:21:00 -0400448 for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
449 {
450 if (i < rts.size())
451 {
Jamie Madilla09403c2014-07-21 10:03:36 -0400452 RenderTarget11 *rt = rts[i].renderTarget;
Geoff Lang5d601382014-07-22 15:14:06 -0400453 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat());
Geoff Lang3b866b62013-09-30 15:21:00 -0400454
Geoff Lang5d601382014-07-22 15:14:06 -0400455 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);
Geoff Lang3b866b62013-09-30 15:21:00 -0400459 }
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 }
Geoff Langda507fe2013-08-20 12:01:42 -0400468
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;
Geoff Lang3b866b62013-09-30 15:21:00 -0400478 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 }
Geoff Langda507fe2013-08-20 12:01:42 -0400488
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
504ID3D11DepthStencilState *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}