1 //
2 // Copyright (c) 2015 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 // StateManager11.cpp: Defines a class for caching D3D11 state
8
9 #include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
10
11 #include "common/BitSetIterator.h"
12 #include "common/utilities.h"
13 #include "libANGLE/Query.h"
14 #include "libANGLE/VertexArray.h"
15 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
16 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
17 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
18
19 namespace rx
20 {
21
22 namespace
23 {
ImageIndexConflictsWithSRV(const gl::ImageIndex & index,D3D11_SHADER_RESOURCE_VIEW_DESC desc)24 bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
25 {
26 unsigned mipLevel = index.mipIndex;
27 GLint layerIndex = index.layerIndex;
28 GLenum type = index.type;
29
30 switch (desc.ViewDimension)
31 {
32 case D3D11_SRV_DIMENSION_TEXTURE2D:
33 {
34 bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
35 unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
36 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
37
38 unsigned mipMin = index.mipIndex;
39 unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
40
41 return type == GL_TEXTURE_2D &&
42 gl::RangeUI(mipMin, mipMax)
43 .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
44 }
45
46 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
47 {
48 bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
49 unsigned int maxSrvMip =
50 desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
51 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
52
53 unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
54
55 // Cube maps can be mapped to Texture2DArray SRVs
56 return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
57 desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
58 desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
59 static_cast<UINT>(layerIndex) < maxSlice;
60 }
61
62 case D3D11_SRV_DIMENSION_TEXTURECUBE:
63 {
64 bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
65 unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
66 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
67
68 return gl::IsCubeMapTextureTarget(type) &&
69 desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
70 }
71
72 case D3D11_SRV_DIMENSION_TEXTURE3D:
73 {
74 bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
75 unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
76 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
77
78 return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
79 mipLevel < maxSrvMip;
80 }
81 default:
82 // We only handle the cases corresponding to valid image indexes
83 UNIMPLEMENTED();
84 }
85
86 return false;
87 }
88
89 // Does *not* increment the resource ref count!!
GetViewResource(ID3D11View * view)90 ID3D11Resource *GetViewResource(ID3D11View *view)
91 {
92 ID3D11Resource *resource = NULL;
93 ASSERT(view);
94 view->GetResource(&resource);
95 resource->Release();
96 return resource;
97 }
98
99 } // anonymous namespace
100
update(size_t resourceIndex,ID3D11ShaderResourceView * srv)101 void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
102 {
103 ASSERT(resourceIndex < mCurrentSRVs.size());
104 SRVRecord *record = &mCurrentSRVs[resourceIndex];
105
106 record->srv = reinterpret_cast<uintptr_t>(srv);
107 if (srv)
108 {
109 record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
110 srv->GetDesc(&record->desc);
111 mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV);
112 }
113 else
114 {
115 record->resource = 0;
116
117 if (resourceIndex + 1 == mHighestUsedSRV)
118 {
119 do
120 {
121 --mHighestUsedSRV;
122 } while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0);
123 }
124 }
125 }
126
clear()127 void StateManager11::SRVCache::clear()
128 {
129 if (mCurrentSRVs.empty())
130 {
131 return;
132 }
133
134 memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size());
135 mHighestUsedSRV = 0;
136 }
137
138 static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
139 GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT,
140 GL_COMMANDS_COMPLETED_CHROMIUM};
141
StateManager11(Renderer11 * renderer)142 StateManager11::StateManager11(Renderer11 *renderer)
143 : mRenderer(renderer),
144 mBlendStateIsDirty(false),
145 mCurBlendColor(0, 0, 0, 0),
146 mCurSampleMask(0),
147 mDepthStencilStateIsDirty(false),
148 mCurStencilRef(0),
149 mCurStencilBackRef(0),
150 mCurStencilSize(0),
151 mRasterizerStateIsDirty(false),
152 mScissorStateIsDirty(false),
153 mCurScissorEnabled(false),
154 mCurScissorRect(),
155 mViewportStateIsDirty(false),
156 mCurViewport(),
157 mCurNear(0.0f),
158 mCurFar(0.0f),
159 mViewportBounds(),
160 mRenderTargetIsDirty(false),
161 mDirtyCurrentValueAttribs(),
162 mCurrentValueAttribs()
163 {
164 mCurBlendState.blend = false;
165 mCurBlendState.sourceBlendRGB = GL_ONE;
166 mCurBlendState.destBlendRGB = GL_ZERO;
167 mCurBlendState.sourceBlendAlpha = GL_ONE;
168 mCurBlendState.destBlendAlpha = GL_ZERO;
169 mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
170 mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
171 mCurBlendState.colorMaskRed = true;
172 mCurBlendState.colorMaskBlue = true;
173 mCurBlendState.colorMaskGreen = true;
174 mCurBlendState.colorMaskAlpha = true;
175 mCurBlendState.sampleAlphaToCoverage = false;
176 mCurBlendState.dither = false;
177
178 mCurDepthStencilState.depthTest = false;
179 mCurDepthStencilState.depthFunc = GL_LESS;
180 mCurDepthStencilState.depthMask = true;
181 mCurDepthStencilState.stencilTest = false;
182 mCurDepthStencilState.stencilMask = true;
183 mCurDepthStencilState.stencilFail = GL_KEEP;
184 mCurDepthStencilState.stencilPassDepthFail = GL_KEEP;
185 mCurDepthStencilState.stencilPassDepthPass = GL_KEEP;
186 mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1);
187 mCurDepthStencilState.stencilBackFunc = GL_ALWAYS;
188 mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1);
189 mCurDepthStencilState.stencilBackFail = GL_KEEP;
190 mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
191 mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
192 mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1);
193
194 mCurRasterState.rasterizerDiscard = false;
195 mCurRasterState.cullFace = false;
196 mCurRasterState.cullMode = GL_BACK;
197 mCurRasterState.frontFace = GL_CCW;
198 mCurRasterState.polygonOffsetFill = false;
199 mCurRasterState.polygonOffsetFactor = 0.0f;
200 mCurRasterState.polygonOffsetUnits = 0.0f;
201 mCurRasterState.pointDrawMode = false;
202 mCurRasterState.multiSample = false;
203
204 // Initially all current value attributes must be updated on first use.
205 mDirtyCurrentValueAttribs.flip();
206 }
207
~StateManager11()208 StateManager11::~StateManager11()
209 {
210 }
211
updateStencilSizeIfChanged(bool depthStencilInitialized,unsigned int stencilSize)212 void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
213 unsigned int stencilSize)
214 {
215 if (!depthStencilInitialized || stencilSize != mCurStencilSize)
216 {
217 mCurStencilSize = stencilSize;
218 mDepthStencilStateIsDirty = true;
219 }
220 }
221
setViewportBounds(const int width,const int height)222 void StateManager11::setViewportBounds(const int width, const int height)
223 {
224 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
225 (mViewportBounds.width != width || mViewportBounds.height != height))
226 {
227 mViewportBounds = gl::Extents(width, height, 1);
228 mViewportStateIsDirty = true;
229 }
230 }
231
updatePresentPath(bool presentPathFastActive,const gl::FramebufferAttachment * framebufferAttachment)232 void StateManager11::updatePresentPath(bool presentPathFastActive,
233 const gl::FramebufferAttachment *framebufferAttachment)
234 {
235 const int colorBufferHeight =
236 framebufferAttachment ? framebufferAttachment->getSize().height : 0;
237
238 if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
239 (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
240 {
241 mCurPresentPathFastEnabled = presentPathFastActive;
242 mCurPresentPathFastColorBufferHeight = colorBufferHeight;
243 mViewportStateIsDirty = true; // Viewport may need to be vertically inverted
244 mScissorStateIsDirty = true; // Scissor rect may need to be vertically inverted
245 mRasterizerStateIsDirty = true; // Cull Mode may need to be inverted
246 }
247 }
248
syncState(const gl::State & state,const gl::State::DirtyBits & dirtyBits)249 void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
250 {
251 if (!dirtyBits.any())
252 {
253 return;
254 }
255
256 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
257 {
258 switch (dirtyBit)
259 {
260 case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
261 {
262 const gl::BlendState &blendState = state.getBlendState();
263 if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
264 blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
265 {
266 mBlendStateIsDirty = true;
267 }
268 break;
269 }
270 case gl::State::DIRTY_BIT_BLEND_FUNCS:
271 {
272 const gl::BlendState &blendState = state.getBlendState();
273 if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
274 blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
275 blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
276 blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
277 {
278 mBlendStateIsDirty = true;
279 }
280 break;
281 }
282 case gl::State::DIRTY_BIT_BLEND_ENABLED:
283 if (state.getBlendState().blend != mCurBlendState.blend)
284 {
285 mBlendStateIsDirty = true;
286 }
287 break;
288 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
289 if (state.getBlendState().sampleAlphaToCoverage !=
290 mCurBlendState.sampleAlphaToCoverage)
291 {
292 mBlendStateIsDirty = true;
293 }
294 break;
295 case gl::State::DIRTY_BIT_DITHER_ENABLED:
296 if (state.getBlendState().dither != mCurBlendState.dither)
297 {
298 mBlendStateIsDirty = true;
299 }
300 break;
301 case gl::State::DIRTY_BIT_COLOR_MASK:
302 {
303 const gl::BlendState &blendState = state.getBlendState();
304 if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
305 blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
306 blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
307 blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
308 {
309 mBlendStateIsDirty = true;
310 }
311 break;
312 }
313 case gl::State::DIRTY_BIT_BLEND_COLOR:
314 if (state.getBlendColor() != mCurBlendColor)
315 {
316 mBlendStateIsDirty = true;
317 }
318 break;
319 case gl::State::DIRTY_BIT_DEPTH_MASK:
320 if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
321 {
322 mDepthStencilStateIsDirty = true;
323 }
324 break;
325 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
326 if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
327 {
328 mDepthStencilStateIsDirty = true;
329 }
330 break;
331 case gl::State::DIRTY_BIT_DEPTH_FUNC:
332 if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
333 {
334 mDepthStencilStateIsDirty = true;
335 }
336 break;
337 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
338 if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
339 {
340 mDepthStencilStateIsDirty = true;
341 }
342 break;
343 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
344 {
345 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
346 if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
347 depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
348 state.getStencilRef() != mCurStencilRef)
349 {
350 mDepthStencilStateIsDirty = true;
351 }
352 break;
353 }
354 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
355 {
356 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
357 if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
358 depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
359 state.getStencilBackRef() != mCurStencilBackRef)
360 {
361 mDepthStencilStateIsDirty = true;
362 }
363 break;
364 }
365 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
366 if (state.getDepthStencilState().stencilWritemask !=
367 mCurDepthStencilState.stencilWritemask)
368 {
369 mDepthStencilStateIsDirty = true;
370 }
371 break;
372 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
373 if (state.getDepthStencilState().stencilBackWritemask !=
374 mCurDepthStencilState.stencilBackWritemask)
375 {
376 mDepthStencilStateIsDirty = true;
377 }
378 break;
379 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
380 {
381 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
382 if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
383 depthStencil.stencilPassDepthFail !=
384 mCurDepthStencilState.stencilPassDepthFail ||
385 depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
386 {
387 mDepthStencilStateIsDirty = true;
388 }
389 break;
390 }
391 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
392 {
393 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
394 if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
395 depthStencil.stencilBackPassDepthFail !=
396 mCurDepthStencilState.stencilBackPassDepthFail ||
397 depthStencil.stencilBackPassDepthPass !=
398 mCurDepthStencilState.stencilBackPassDepthPass)
399 {
400 mDepthStencilStateIsDirty = true;
401 }
402 break;
403 }
404 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
405 if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
406 {
407 mRasterizerStateIsDirty = true;
408 }
409 break;
410 case gl::State::DIRTY_BIT_CULL_FACE:
411 if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
412 {
413 mRasterizerStateIsDirty = true;
414 }
415 break;
416 case gl::State::DIRTY_BIT_FRONT_FACE:
417 if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
418 {
419 mRasterizerStateIsDirty = true;
420 }
421 break;
422 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
423 if (state.getRasterizerState().polygonOffsetFill !=
424 mCurRasterState.polygonOffsetFill)
425 {
426 mRasterizerStateIsDirty = true;
427 }
428 break;
429 case gl::State::DIRTY_BIT_POLYGON_OFFSET:
430 {
431 const gl::RasterizerState &rasterState = state.getRasterizerState();
432 if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
433 rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
434 {
435 mRasterizerStateIsDirty = true;
436 }
437 break;
438 }
439 case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
440 if (state.getRasterizerState().rasterizerDiscard !=
441 mCurRasterState.rasterizerDiscard)
442 {
443 mRasterizerStateIsDirty = true;
444 }
445 break;
446 case gl::State::DIRTY_BIT_SCISSOR:
447 if (state.getScissor() != mCurScissorRect)
448 {
449 mScissorStateIsDirty = true;
450 }
451 break;
452 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
453 if (state.isScissorTestEnabled() != mCurScissorEnabled)
454 {
455 mScissorStateIsDirty = true;
456 // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
457 mRasterizerStateIsDirty = true;
458 }
459 break;
460 case gl::State::DIRTY_BIT_DEPTH_RANGE:
461 if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
462 {
463 mViewportStateIsDirty = true;
464 }
465 break;
466 case gl::State::DIRTY_BIT_VIEWPORT:
467 if (state.getViewport() != mCurViewport)
468 {
469 mViewportStateIsDirty = true;
470 }
471 break;
472 case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
473 mRenderTargetIsDirty = true;
474 break;
475 default:
476 if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
477 dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX)
478 {
479 size_t attribIndex =
480 static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0);
481 mDirtyCurrentValueAttribs.set(attribIndex);
482 }
483 break;
484 }
485 }
486 }
487
setBlendState(const gl::Framebuffer * framebuffer,const gl::BlendState & blendState,const gl::ColorF & blendColor,unsigned int sampleMask)488 gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
489 const gl::BlendState &blendState,
490 const gl::ColorF &blendColor,
491 unsigned int sampleMask)
492 {
493 if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
494 {
495 return gl::NoError();
496 }
497
498 ID3D11BlendState *dxBlendState = nullptr;
499 ANGLE_TRY(mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState));
500
501 ASSERT(dxBlendState != nullptr);
502
503 float blendColors[4] = {0.0f};
504 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
505 blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
506 blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
507 blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
508 {
509 blendColors[0] = blendColor.red;
510 blendColors[1] = blendColor.green;
511 blendColors[2] = blendColor.blue;
512 blendColors[3] = blendColor.alpha;
513 }
514 else
515 {
516 blendColors[0] = blendColor.alpha;
517 blendColors[1] = blendColor.alpha;
518 blendColors[2] = blendColor.alpha;
519 blendColors[3] = blendColor.alpha;
520 }
521
522 mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
523
524 mCurBlendState = blendState;
525 mCurBlendColor = blendColor;
526 mCurSampleMask = sampleMask;
527
528 mBlendStateIsDirty = false;
529
530 return gl::NoError();
531 }
532
setDepthStencilState(const gl::State & glState)533 gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
534 {
535 const auto &fbo = *glState.getDrawFramebuffer();
536
537 // Disable the depth test/depth write if we are using a stencil-only attachment.
538 // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
539 // nor write to the unused depth part of this emulated texture.
540 bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil());
541
542 // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
543 bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil());
544
545 // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
546 if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
547 disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
548 disableStencil == mCurDisableStencil.value())
549 {
550 return gl::NoError();
551 }
552
553 const auto &depthStencilState = glState.getDepthStencilState();
554 int stencilRef = glState.getStencilRef();
555 int stencilBackRef = glState.getStencilBackRef();
556
557 // get the maximum size of the stencil ref
558 unsigned int maxStencil = 0;
559 if (depthStencilState.stencilTest && mCurStencilSize > 0)
560 {
561 maxStencil = (1 << mCurStencilSize) - 1;
562 }
563 ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
564 (depthStencilState.stencilBackWritemask & maxStencil));
565 ASSERT(stencilRef == stencilBackRef);
566 ASSERT((depthStencilState.stencilMask & maxStencil) ==
567 (depthStencilState.stencilBackMask & maxStencil));
568
569 ID3D11DepthStencilState *dxDepthStencilState = NULL;
570 ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(
571 depthStencilState, disableDepth, disableStencil, &dxDepthStencilState));
572
573 ASSERT(dxDepthStencilState);
574
575 // Max D3D11 stencil reference value is 0xFF,
576 // corresponding to the max 8 bits in a stencil buffer
577 // GL specifies we should clamp the ref value to the
578 // nearest bit depth when doing stencil ops
579 static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
580 "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
581 static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
582 "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
583 UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
584
585 mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
586
587 mCurDepthStencilState = depthStencilState;
588 mCurStencilRef = stencilRef;
589 mCurStencilBackRef = stencilBackRef;
590 mCurDisableDepth = disableDepth;
591 mCurDisableStencil = disableStencil;
592
593 mDepthStencilStateIsDirty = false;
594
595 return gl::NoError();
596 }
597
setRasterizerState(const gl::RasterizerState & rasterState)598 gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
599 {
600 // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
601 if (!mRasterizerStateIsDirty && rasterState.pointDrawMode == mCurRasterState.pointDrawMode &&
602 rasterState.multiSample == mCurRasterState.multiSample)
603 {
604 return gl::NoError();
605 }
606
607 ID3D11RasterizerState *dxRasterState = nullptr;
608
609 if (mCurPresentPathFastEnabled)
610 {
611 gl::RasterizerState modifiedRasterState = rasterState;
612
613 // If prseent path fast is active then we need invert the front face state.
614 // This ensures that both gl_FrontFacing is correct, and front/back culling
615 // is performed correctly.
616 if (modifiedRasterState.frontFace == GL_CCW)
617 {
618 modifiedRasterState.frontFace = GL_CW;
619 }
620 else
621 {
622 ASSERT(modifiedRasterState.frontFace == GL_CW);
623 modifiedRasterState.frontFace = GL_CCW;
624 }
625
626 ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(
627 modifiedRasterState, mCurScissorEnabled, &dxRasterState));
628 }
629 else
630 {
631 ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled,
632 &dxRasterState));
633 }
634
635 mRenderer->getDeviceContext()->RSSetState(dxRasterState);
636
637 mCurRasterState = rasterState;
638 mRasterizerStateIsDirty = false;
639
640 return gl::NoError();
641 }
642
setScissorRectangle(const gl::Rectangle & scissor,bool enabled)643 void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
644 {
645 if (!mScissorStateIsDirty)
646 return;
647
648 int modifiedScissorY = scissor.y;
649 if (mCurPresentPathFastEnabled)
650 {
651 modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
652 }
653
654 if (enabled)
655 {
656 D3D11_RECT rect;
657 rect.left = std::max(0, scissor.x);
658 rect.top = std::max(0, modifiedScissorY);
659 rect.right = scissor.x + std::max(0, scissor.width);
660 rect.bottom = modifiedScissorY + std::max(0, scissor.height);
661
662 mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
663 }
664
665 mCurScissorRect = scissor;
666 mCurScissorEnabled = enabled;
667 mScissorStateIsDirty = false;
668 }
669
setViewport(const gl::Caps * caps,const gl::Rectangle & viewport,float zNear,float zFar)670 void StateManager11::setViewport(const gl::Caps *caps,
671 const gl::Rectangle &viewport,
672 float zNear,
673 float zFar)
674 {
675 if (!mViewportStateIsDirty)
676 return;
677
678 float actualZNear = gl::clamp01(zNear);
679 float actualZFar = gl::clamp01(zFar);
680
681 int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
682 int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
683 int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
684 int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
685
686 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
687 {
688 // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
689 dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
690 dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
691 dxMinViewportBoundsX = 0;
692 dxMinViewportBoundsY = 0;
693 }
694
695 int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
696 int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
697 int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
698 int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
699
700 D3D11_VIEWPORT dxViewport;
701 dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
702
703 if (mCurPresentPathFastEnabled)
704 {
705 // When present path fast is active and we're rendering to framebuffer 0, we must invert
706 // the viewport in Y-axis.
707 // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
708 // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
709 // unaltered dxViewportTopLeftY value.
710 dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
711 dxViewportTopLeftY - dxViewportHeight);
712 }
713 else
714 {
715 dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
716 }
717
718 dxViewport.Width = static_cast<float>(dxViewportWidth);
719 dxViewport.Height = static_cast<float>(dxViewportHeight);
720 dxViewport.MinDepth = actualZNear;
721 dxViewport.MaxDepth = actualZFar;
722
723 mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
724
725 mCurViewport = viewport;
726 mCurNear = actualZNear;
727 mCurFar = actualZFar;
728
729 // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
730 // using viewAdjust (like the D3D9 renderer).
731 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
732 {
733 mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
734 2 * (viewport.x - dxViewportTopLeftX)) /
735 dxViewport.Width;
736 mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
737 2 * (viewport.y - dxViewportTopLeftY)) /
738 dxViewport.Height;
739 mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
740 mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
741 }
742
743 mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
744 mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
745 mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
746 mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
747
748 // Instanced pointsprite emulation requires ViewCoords to be defined in the
749 // the vertex shader.
750 mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
751 mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
752 mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
753 mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
754
755 mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
756 mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
757
758 mVertexConstants.depthRange[0] = actualZNear;
759 mVertexConstants.depthRange[1] = actualZFar;
760 mVertexConstants.depthRange[2] = actualZFar - actualZNear;
761
762 mPixelConstants.depthRange[0] = actualZNear;
763 mPixelConstants.depthRange[1] = actualZFar;
764 mPixelConstants.depthRange[2] = actualZFar - actualZNear;
765
766 mPixelConstants.viewScale[0] = 1.0f;
767 mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f;
768 mPixelConstants.viewScale[2] = 1.0f;
769 mPixelConstants.viewScale[3] = 1.0f;
770
771 mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0];
772 mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1];
773 mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2];
774 mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3];
775
776 mViewportStateIsDirty = false;
777 }
778
invalidateRenderTarget()779 void StateManager11::invalidateRenderTarget()
780 {
781 mRenderTargetIsDirty = true;
782 }
783
invalidateBoundViews()784 void StateManager11::invalidateBoundViews()
785 {
786 mCurVertexSRVs.clear();
787 mCurPixelSRVs.clear();
788
789 invalidateRenderTarget();
790 }
791
invalidateEverything()792 void StateManager11::invalidateEverything()
793 {
794 mBlendStateIsDirty = true;
795 mDepthStencilStateIsDirty = true;
796 mRasterizerStateIsDirty = true;
797 mScissorStateIsDirty = true;
798 mViewportStateIsDirty = true;
799
800 // We reset the current SRV data because it might not be in sync with D3D's state
801 // anymore. For example when a currently used SRV is used as an RTV, D3D silently
802 // remove it from its state.
803 invalidateBoundViews();
804 }
805
setOneTimeRenderTarget(ID3D11RenderTargetView * renderTarget,ID3D11DepthStencilView * depthStencil)806 void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget,
807 ID3D11DepthStencilView *depthStencil)
808 {
809 mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil);
810 mRenderTargetIsDirty = true;
811 }
812
setOneTimeRenderTargets(const std::vector<ID3D11RenderTargetView * > & renderTargets,ID3D11DepthStencilView * depthStencil)813 void StateManager11::setOneTimeRenderTargets(
814 const std::vector<ID3D11RenderTargetView *> &renderTargets,
815 ID3D11DepthStencilView *depthStencil)
816 {
817 UINT count = static_cast<UINT>(renderTargets.size());
818 auto renderTargetPointer = (!renderTargets.empty() ? renderTargets.data() : nullptr);
819
820 mRenderer->getDeviceContext()->OMSetRenderTargets(count, renderTargetPointer, depthStencil);
821 mRenderTargetIsDirty = true;
822 }
823
onBeginQuery(Query11 * query)824 void StateManager11::onBeginQuery(Query11 *query)
825 {
826 mCurrentQueries.insert(query);
827 }
828
onDeleteQueryObject(Query11 * query)829 void StateManager11::onDeleteQueryObject(Query11 *query)
830 {
831 mCurrentQueries.erase(query);
832 }
833
onMakeCurrent(const gl::ContextState & data)834 gl::Error StateManager11::onMakeCurrent(const gl::ContextState &data)
835 {
836 const gl::State &state = data.getState();
837
838 for (Query11 *query : mCurrentQueries)
839 {
840 query->pause();
841 }
842 mCurrentQueries.clear();
843
844 for (GLenum queryType : QueryTypes)
845 {
846 gl::Query *query = state.getActiveQuery(queryType);
847 if (query != nullptr)
848 {
849 Query11 *query11 = GetImplAs<Query11>(query);
850 query11->resume();
851 mCurrentQueries.insert(query11);
852 }
853 }
854
855 return gl::NoError();
856 }
857
setShaderResource(gl::SamplerType shaderType,UINT resourceSlot,ID3D11ShaderResourceView * srv)858 void StateManager11::setShaderResource(gl::SamplerType shaderType,
859 UINT resourceSlot,
860 ID3D11ShaderResourceView *srv)
861 {
862 auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
863
864 ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
865 const SRVRecord &record = currentSRVs[resourceSlot];
866
867 if (record.srv != reinterpret_cast<uintptr_t>(srv))
868 {
869 auto deviceContext = mRenderer->getDeviceContext();
870 if (shaderType == gl::SAMPLER_VERTEX)
871 {
872 deviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
873 }
874 else
875 {
876 deviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
877 }
878
879 currentSRVs.update(resourceSlot, srv);
880 }
881 }
882
clearTextures(gl::SamplerType samplerType,size_t rangeStart,size_t rangeEnd)883 gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
884 size_t rangeStart,
885 size_t rangeEnd)
886 {
887 if (rangeStart == rangeEnd)
888 {
889 return gl::NoError();
890 }
891
892 auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
893
894 gl::Range<size_t> clearRange(rangeStart, rangeStart);
895 clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
896
897 if (clearRange.empty())
898 {
899 return gl::NoError();
900 }
901
902 auto deviceContext = mRenderer->getDeviceContext();
903 if (samplerType == gl::SAMPLER_VERTEX)
904 {
905 deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
906 static_cast<unsigned int>(rangeEnd - rangeStart),
907 &mNullSRVs[0]);
908 }
909 else
910 {
911 deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
912 static_cast<unsigned int>(rangeEnd - rangeStart),
913 &mNullSRVs[0]);
914 }
915
916 for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
917 {
918 currentSRVs.update(samplerIndex, nullptr);
919 }
920
921 return gl::NoError();
922 }
923
unsetConflictingSRVs(gl::SamplerType samplerType,uintptr_t resource,const gl::ImageIndex & index)924 void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
925 uintptr_t resource,
926 const gl::ImageIndex &index)
927 {
928 auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
929
930 for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
931 {
932 auto &record = currentSRVs[resourceIndex];
933
934 if (record.srv && record.resource == resource &&
935 ImageIndexConflictsWithSRV(index, record.desc))
936 {
937 setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
938 }
939 }
940 }
941
unsetConflictingAttachmentResources(const gl::FramebufferAttachment * attachment,ID3D11Resource * resource)942 void StateManager11::unsetConflictingAttachmentResources(
943 const gl::FramebufferAttachment *attachment,
944 ID3D11Resource *resource)
945 {
946 // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
947 if (attachment->type() == GL_TEXTURE)
948 {
949 uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
950 const gl::ImageIndex &index = attachment->getTextureImageIndex();
951 // The index doesn't need to be corrected for the small compressed texture workaround
952 // because a rendertarget is never compressed.
953 unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, index);
954 unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, index);
955 }
956 }
957
initialize(const gl::Caps & caps)958 void StateManager11::initialize(const gl::Caps &caps)
959 {
960 mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
961 mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
962
963 // Initialize cached NULL SRV block
964 mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
965
966 mCurrentValueAttribs.resize(caps.maxVertexAttributes);
967 }
968
deinitialize()969 void StateManager11::deinitialize()
970 {
971 mCurrentValueAttribs.clear();
972 }
973
syncFramebuffer(gl::Framebuffer * framebuffer)974 gl::Error StateManager11::syncFramebuffer(gl::Framebuffer *framebuffer)
975 {
976 Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
977 ANGLE_TRY(framebuffer11->markAttachmentsDirty());
978
979 if (framebuffer11->hasAnyInternalDirtyBit())
980 {
981 ASSERT(framebuffer->id() != 0);
982 framebuffer11->syncInternalState();
983 }
984
985 if (!mRenderTargetIsDirty)
986 {
987 return gl::NoError();
988 }
989
990 mRenderTargetIsDirty = false;
991
992 // Check for zero-sized default framebuffer, which is a special case.
993 // in this case we do not wish to modify any state and just silently return false.
994 // this will not report any gl error but will cause the calling method to return.
995 if (framebuffer->id() == 0)
996 {
997 ASSERT(!framebuffer11->hasAnyInternalDirtyBit());
998 const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize();
999 if (size.width == 0 || size.height == 0)
1000 {
1001 return gl::NoError();
1002 }
1003 }
1004
1005 // Get the color render buffer and serial
1006 // Also extract the render target dimensions and view
1007 unsigned int renderTargetWidth = 0;
1008 unsigned int renderTargetHeight = 0;
1009 RTVArray framebufferRTVs;
1010 bool missingColorRenderTarget = true;
1011
1012 framebufferRTVs.fill(nullptr);
1013
1014 const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
1015
1016 size_t appliedRTIndex = 0;
1017 bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround;
1018 const auto &drawStates = framebuffer->getDrawBufferStates();
1019
1020 for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
1021 {
1022 const RenderTarget11 *renderTarget = colorRTs[rtIndex];
1023
1024 // Skip inactive rendertargets if the workaround is enabled.
1025 if (skipInactiveRTs && (!renderTarget || drawStates[rtIndex] == GL_NONE))
1026 {
1027 continue;
1028 }
1029
1030 if (renderTarget)
1031 {
1032 framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView();
1033 ASSERT(framebufferRTVs[appliedRTIndex]);
1034
1035 if (missingColorRenderTarget)
1036 {
1037 renderTargetWidth = renderTarget->getWidth();
1038 renderTargetHeight = renderTarget->getHeight();
1039 missingColorRenderTarget = false;
1040 }
1041 }
1042
1043 // Unset conflicting texture SRVs
1044 const auto *attachment = framebuffer->getColorbuffer(rtIndex);
1045 ASSERT(attachment);
1046 unsetConflictingAttachmentResources(attachment, renderTarget->getTexture());
1047
1048 appliedRTIndex++;
1049 }
1050
1051 // Get the depth stencil buffers
1052 ID3D11DepthStencilView *framebufferDSV = nullptr;
1053 const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget();
1054 if (depthStencilRenderTarget)
1055 {
1056 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
1057 ASSERT(framebufferDSV);
1058
1059 // If there is no render buffer, the width, height and format values come from
1060 // the depth stencil
1061 if (missingColorRenderTarget)
1062 {
1063 renderTargetWidth = depthStencilRenderTarget->getWidth();
1064 renderTargetHeight = depthStencilRenderTarget->getHeight();
1065 }
1066
1067 // Unset conflicting texture SRVs
1068 const auto *attachment = framebuffer->getDepthOrStencilbuffer();
1069 ASSERT(attachment);
1070 unsetConflictingAttachmentResources(attachment, depthStencilRenderTarget->getTexture());
1071 }
1072
1073 // TODO(jmadill): Use context caps?
1074 UINT drawBuffers = mRenderer->getNativeCaps().maxDrawBuffers;
1075
1076 // Apply the render target and depth stencil
1077 mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, framebufferRTVs.data(),
1078 framebufferDSV);
1079
1080 // The D3D11 blend state is heavily dependent on the current render target.
1081 mBlendStateIsDirty = true;
1082
1083 setViewportBounds(renderTargetWidth, renderTargetHeight);
1084
1085 return gl::NoError();
1086 }
1087
updateCurrentValueAttribs(const gl::State & state,VertexDataManager * vertexDataManager)1088 gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
1089 VertexDataManager *vertexDataManager)
1090 {
1091 const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask();
1092 const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
1093 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
1094
1095 for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs))
1096 {
1097 if (vertexAttributes[attribIndex].enabled)
1098 continue;
1099
1100 mDirtyCurrentValueAttribs.reset(attribIndex);
1101
1102 const auto ¤tValue =
1103 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
1104 auto currentValueAttrib = &mCurrentValueAttribs[attribIndex];
1105 currentValueAttrib->currentValueType = currentValue.Type;
1106 currentValueAttrib->attribute = &vertexAttributes[attribIndex];
1107
1108 ANGLE_TRY(vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib,
1109 static_cast<size_t>(attribIndex)));
1110 }
1111
1112 return gl::NoError();
1113 }
1114
getCurrentValueAttribs() const1115 const std::vector<TranslatedAttribute> &StateManager11::getCurrentValueAttribs() const
1116 {
1117 return mCurrentValueAttribs;
1118 }
1119
1120 } // namespace rx
1121