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 &currentSRVs = (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 &currentSRVs = (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 &currentSRVs = (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 &currentValue =
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