• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 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/angleutils.h"
12 #include "common/bitset_utils.h"
13 #include "common/mathutil.h"
14 #include "common/utilities.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Query.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/VertexArray.h"
19 #include "libANGLE/renderer/d3d/DisplayD3D.h"
20 #include "libANGLE/renderer/d3d/TextureD3D.h"
21 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
22 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
23 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
24 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
25 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
26 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
27 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
28 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
29 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
30 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
31 #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
32 
33 namespace rx
34 {
35 
36 namespace
37 {
ImageIndexConflictsWithSRV(const gl::ImageIndex & index,D3D11_SHADER_RESOURCE_VIEW_DESC desc)38 bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
39 {
40     unsigned mipLevel           = index.getLevelIndex();
41     gl::TextureType textureType = index.getType();
42 
43     switch (desc.ViewDimension)
44     {
45         case D3D11_SRV_DIMENSION_TEXTURE2D:
46         {
47             bool allLevels         = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
48             unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
49             maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
50 
51             unsigned mipMin = index.getLevelIndex();
52             unsigned mipMax = INT_MAX;
53 
54             return textureType == gl::TextureType::_2D &&
55                    gl::RangeUI(mipMin, mipMax)
56                        .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
57         }
58 
59         case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
60         {
61             GLint layerIndex = index.getLayerIndex();
62 
63             bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
64             unsigned int maxSrvMip =
65                 desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
66             maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
67 
68             unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
69 
70             // Cube maps can be mapped to Texture2DArray SRVs
71             return (textureType == gl::TextureType::_2DArray ||
72                     textureType == gl::TextureType::CubeMap) &&
73                    desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
74                    desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
75                    static_cast<UINT>(layerIndex) < maxSlice;
76         }
77 
78         case D3D11_SRV_DIMENSION_TEXTURECUBE:
79         {
80             bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
81             unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
82             maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
83 
84             return textureType == gl::TextureType::CubeMap &&
85                    desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
86         }
87 
88         case D3D11_SRV_DIMENSION_TEXTURE3D:
89         {
90             bool allLevels         = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
91             unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
92             maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
93 
94             return textureType == gl::TextureType::_3D &&
95                    desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
96         }
97         default:
98             // We only handle the cases corresponding to valid image indexes
99             UNIMPLEMENTED();
100     }
101 
102     return false;
103 }
104 
ImageIndexConflictsWithUAV(const gl::ImageIndex & index,D3D11_UNORDERED_ACCESS_VIEW_DESC desc)105 bool ImageIndexConflictsWithUAV(const gl::ImageIndex &index, D3D11_UNORDERED_ACCESS_VIEW_DESC desc)
106 {
107     unsigned mipLevel           = index.getLevelIndex();
108     gl::TextureType textureType = index.getType();
109 
110     switch (desc.ViewDimension)
111     {
112         case D3D11_UAV_DIMENSION_TEXTURE2D:
113         {
114             return textureType == gl::TextureType::_2D && mipLevel == desc.Texture2D.MipSlice;
115         }
116 
117         case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
118         {
119             GLint layerIndex         = index.getLayerIndex();
120             unsigned mipSlice        = desc.Texture2DArray.MipSlice;
121             unsigned firstArraySlice = desc.Texture2DArray.FirstArraySlice;
122             unsigned lastArraySlice  = firstArraySlice + desc.Texture2DArray.ArraySize;
123 
124             return (textureType == gl::TextureType::_2DArray ||
125                     textureType == gl::TextureType::CubeMap) &&
126                    (mipLevel == mipSlice && gl::RangeUI(firstArraySlice, lastArraySlice)
127                                                 .contains(static_cast<UINT>(layerIndex)));
128         }
129 
130         case D3D11_UAV_DIMENSION_TEXTURE3D:
131         {
132             GLint layerIndex     = index.getLayerIndex();
133             unsigned mipSlice    = desc.Texture3D.MipSlice;
134             unsigned firstWSlice = desc.Texture3D.FirstWSlice;
135             unsigned lastWSlice  = firstWSlice + desc.Texture3D.WSize;
136 
137             return textureType == gl::TextureType::_3D &&
138                    (mipLevel == mipSlice &&
139                     gl::RangeUI(firstWSlice, lastWSlice).contains(static_cast<UINT>(layerIndex)));
140         }
141         default:
142             return false;
143     }
144 }
145 
146 // Does *not* increment the resource ref count!!
GetViewResource(ID3D11View * view)147 ID3D11Resource *GetViewResource(ID3D11View *view)
148 {
149     ID3D11Resource *resource = nullptr;
150     ASSERT(view);
151     view->GetResource(&resource);
152     resource->Release();
153     return resource;
154 }
155 
GetWrapBits(GLenum wrap)156 int GetWrapBits(GLenum wrap)
157 {
158     switch (wrap)
159     {
160         case GL_CLAMP_TO_EDGE:
161             return 0x0;
162         case GL_REPEAT:
163             return 0x1;
164         case GL_MIRRORED_REPEAT:
165             return 0x2;
166         case GL_CLAMP_TO_BORDER:
167             return 0x3;
168         default:
169             UNREACHABLE();
170             return 0;
171     }
172 }
173 
FindFirstNonInstanced(const std::vector<const TranslatedAttribute * > & currentAttributes)174 Optional<size_t> FindFirstNonInstanced(
175     const std::vector<const TranslatedAttribute *> &currentAttributes)
176 {
177     for (size_t index = 0; index < currentAttributes.size(); ++index)
178     {
179         if (currentAttributes[index]->divisor == 0)
180         {
181             return Optional<size_t>(index);
182         }
183     }
184 
185     return Optional<size_t>::Invalid();
186 }
187 
SortAttributesByLayout(const ProgramD3D & programD3D,const std::vector<TranslatedAttribute> & vertexArrayAttribs,const std::vector<TranslatedAttribute> & currentValueAttribs,AttribIndexArray * sortedD3DSemanticsOut,std::vector<const TranslatedAttribute * > * sortedAttributesOut)188 void SortAttributesByLayout(const ProgramD3D &programD3D,
189                             const std::vector<TranslatedAttribute> &vertexArrayAttribs,
190                             const std::vector<TranslatedAttribute> &currentValueAttribs,
191                             AttribIndexArray *sortedD3DSemanticsOut,
192                             std::vector<const TranslatedAttribute *> *sortedAttributesOut)
193 {
194     sortedAttributesOut->clear();
195 
196     const AttribIndexArray &locationToSemantic = programD3D.getAttribLocationToD3DSemantics();
197     const gl::ProgramExecutable &executable    = programD3D.getState().getExecutable();
198 
199     for (auto locationIndex : executable.getActiveAttribLocationsMask())
200     {
201         int d3dSemantic = locationToSemantic[locationIndex];
202         if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
203         {
204             sortedAttributesOut->resize(d3dSemantic + 1);
205         }
206 
207         (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
208 
209         const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
210         if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
211         {
212             (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
213         }
214         else
215         {
216             ASSERT(currentValueAttribs[locationIndex].attribute);
217             (*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
218         }
219     }
220 }
221 
UpdateUniformBuffer(ID3D11DeviceContext * deviceContext,UniformStorage11 * storage,const d3d11::Buffer * buffer)222 void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext,
223                          UniformStorage11 *storage,
224                          const d3d11::Buffer *buffer)
225 {
226     deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0,
227                                      0);
228 }
229 
GetReservedBufferCount(bool usesPointSpriteEmulation)230 size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
231 {
232     return usesPointSpriteEmulation ? 1 : 0;
233 }
234 
CullsEverything(const gl::State & glState)235 bool CullsEverything(const gl::State &glState)
236 {
237     return (glState.getRasterizerState().cullFace &&
238             glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
239 }
240 }  // anonymous namespace
241 
242 // StateManager11::ViewCache Implementation.
243 template <typename ViewType, typename DescType>
ViewCache()244 StateManager11::ViewCache<ViewType, DescType>::ViewCache() : mHighestUsedView(0)
245 {}
246 
247 template <typename ViewType, typename DescType>
~ViewCache()248 StateManager11::ViewCache<ViewType, DescType>::~ViewCache()
249 {}
250 
251 template <typename ViewType, typename DescType>
update(size_t resourceIndex,ViewType * view)252 void StateManager11::ViewCache<ViewType, DescType>::update(size_t resourceIndex, ViewType *view)
253 {
254     ASSERT(resourceIndex < mCurrentViews.size());
255     ViewRecord<DescType> *record = &mCurrentViews[resourceIndex];
256 
257     record->view = reinterpret_cast<uintptr_t>(view);
258     if (view)
259     {
260         record->resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
261         view->GetDesc(&record->desc);
262         mHighestUsedView = std::max(resourceIndex + 1, mHighestUsedView);
263     }
264     else
265     {
266         record->resource = 0;
267 
268         if (resourceIndex + 1 == mHighestUsedView)
269         {
270             do
271             {
272                 --mHighestUsedView;
273             } while (mHighestUsedView > 0 && mCurrentViews[mHighestUsedView].view == 0);
274         }
275     }
276 }
277 
278 template <typename ViewType, typename DescType>
clear()279 void StateManager11::ViewCache<ViewType, DescType>::clear()
280 {
281     if (mCurrentViews.empty())
282     {
283         return;
284     }
285 
286     memset(&mCurrentViews[0], 0, sizeof(ViewRecord<DescType>) * mCurrentViews.size());
287     mHighestUsedView = 0;
288 }
289 
getSRVCache(gl::ShaderType shaderType)290 StateManager11::SRVCache *StateManager11::getSRVCache(gl::ShaderType shaderType)
291 {
292     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
293     return &mCurShaderSRVs[shaderType];
294 }
295 
296 // ShaderConstants11 implementation
ShaderConstants11()297 ShaderConstants11::ShaderConstants11() : mNumActiveShaderSamplers({})
298 {
299     mShaderConstantsDirty.set();
300 }
301 
~ShaderConstants11()302 ShaderConstants11::~ShaderConstants11() {}
303 
init(const gl::Caps & caps)304 void ShaderConstants11::init(const gl::Caps &caps)
305 {
306     for (gl::ShaderType shaderType : gl::AllShaderTypes())
307     {
308         mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]);
309         mShaderReadonlyImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
310         mShaderImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
311     }
312 }
313 
GetShaderConstantsStructSize(gl::ShaderType shaderType)314 size_t ShaderConstants11::GetShaderConstantsStructSize(gl::ShaderType shaderType)
315 {
316     switch (shaderType)
317     {
318         case gl::ShaderType::Vertex:
319             return sizeof(Vertex);
320         case gl::ShaderType::Fragment:
321             return sizeof(Pixel);
322         case gl::ShaderType::Compute:
323             return sizeof(Compute);
324 
325         // TODO(jiawei.shao@intel.com): return geometry shader constant struct size
326         case gl::ShaderType::Geometry:
327             return 0u;
328 
329         default:
330             UNREACHABLE();
331             return 0u;
332     }
333 }
334 
getRequiredBufferSize(gl::ShaderType shaderType) const335 size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
336 {
337     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
338     return GetShaderConstantsStructSize(shaderType) +
339            mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) +
340            mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) +
341            mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata);
342 }
343 
markDirty()344 void ShaderConstants11::markDirty()
345 {
346     mShaderConstantsDirty.set();
347     mNumActiveShaderSamplers.fill(0);
348 }
349 
updateSamplerMetadata(SamplerMetadata * data,const gl::Texture & texture,const gl::SamplerState & samplerState)350 bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data,
351                                               const gl::Texture &texture,
352                                               const gl::SamplerState &samplerState)
353 {
354     bool dirty               = false;
355     unsigned int baseLevel   = texture.getTextureState().getEffectiveBaseLevel();
356     gl::TextureTarget target = (texture.getType() == gl::TextureType::CubeMap)
357                                    ? gl::kCubeMapTextureTargetMin
358                                    : gl::NonCubeTextureTypeToTarget(texture.getType());
359     GLenum sizedFormat = texture.getFormat(target, baseLevel).info->sizedInternalFormat;
360     if (data->baseLevel != static_cast<int>(baseLevel))
361     {
362         data->baseLevel = static_cast<int>(baseLevel);
363         dirty           = true;
364     }
365 
366     // Some metadata is needed only for integer textures. We avoid updating the constant buffer
367     // unnecessarily by changing the data only in case the texture is an integer texture and
368     // the values have changed.
369     bool needIntegerTextureMetadata = false;
370     // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
371     int internalFormatBits = 0;
372     switch (sizedFormat)
373     {
374         case GL_RGBA32I:
375         case GL_RGBA32UI:
376         case GL_RGB32I:
377         case GL_RGB32UI:
378         case GL_RG32I:
379         case GL_RG32UI:
380         case GL_R32I:
381         case GL_R32UI:
382             needIntegerTextureMetadata = true;
383             break;
384         case GL_RGBA16I:
385         case GL_RGBA16UI:
386         case GL_RGB16I:
387         case GL_RGB16UI:
388         case GL_RG16I:
389         case GL_RG16UI:
390         case GL_R16I:
391         case GL_R16UI:
392             needIntegerTextureMetadata = true;
393             internalFormatBits         = 16;
394             break;
395         case GL_RGBA8I:
396         case GL_RGBA8UI:
397         case GL_RGB8I:
398         case GL_RGB8UI:
399         case GL_RG8I:
400         case GL_RG8UI:
401         case GL_R8I:
402         case GL_R8UI:
403             needIntegerTextureMetadata = true;
404             internalFormatBits         = 8;
405             break;
406         case GL_RGB10_A2UI:
407             needIntegerTextureMetadata = true;
408             internalFormatBits         = 10;
409             break;
410         default:
411             break;
412     }
413     if (needIntegerTextureMetadata)
414     {
415         if (data->internalFormatBits != internalFormatBits)
416         {
417             data->internalFormatBits = internalFormatBits;
418             dirty                    = true;
419         }
420         // Pack the wrap values into one integer so we can fit all the metadata in two 4-integer
421         // vectors.
422         GLenum wrapS  = samplerState.getWrapS();
423         GLenum wrapT  = samplerState.getWrapT();
424         GLenum wrapR  = samplerState.getWrapR();
425         int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
426         if (data->wrapModes != wrapModes)
427         {
428             data->wrapModes = wrapModes;
429             dirty           = true;
430         }
431 
432         const angle::ColorGeneric &borderColor(samplerState.getBorderColor());
433         constexpr int kBlack[4]          = {};
434         const void *const intBorderColor = (borderColor.type == angle::ColorGeneric::Type::Float)
435                                                ? kBlack
436                                                : borderColor.colorI.data();
437         ASSERT(static_cast<const void *>(borderColor.colorI.data()) ==
438                static_cast<const void *>(borderColor.colorUI.data()));
439         if (memcmp(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor)) != 0)
440         {
441             memcpy(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor));
442             dirty = true;
443         }
444     }
445 
446     return dirty;
447 }
448 
updateImageMetadata(ImageMetadata * data,const gl::ImageUnit & imageUnit)449 bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit)
450 {
451     bool dirty = false;
452 
453     if (data->layer != static_cast<int>(imageUnit.layer))
454     {
455         data->layer = static_cast<int>(imageUnit.layer);
456         dirty       = true;
457     }
458 
459     if (data->level != static_cast<unsigned int>(imageUnit.level))
460     {
461         data->level = static_cast<unsigned int>(imageUnit.level);
462         dirty       = true;
463     }
464 
465     return dirty;
466 }
467 
setComputeWorkGroups(GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)468 void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
469                                              GLuint numGroupsY,
470                                              GLuint numGroupsZ)
471 {
472     mCompute.numWorkGroups[0] = numGroupsX;
473     mCompute.numWorkGroups[1] = numGroupsY;
474     mCompute.numWorkGroups[2] = numGroupsZ;
475     mShaderConstantsDirty.set(gl::ShaderType::Compute);
476 }
477 
setMultiviewWriteToViewportIndex(GLfloat index)478 void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index)
479 {
480     mVertex.multiviewWriteToViewportIndex = index;
481     mPixel.multiviewWriteToViewportIndex  = index;
482     mShaderConstantsDirty.set(gl::ShaderType::Vertex);
483     mShaderConstantsDirty.set(gl::ShaderType::Fragment);
484 }
485 
onViewportChange(const gl::Rectangle & glViewport,const D3D11_VIEWPORT & dxViewport,bool is9_3,bool presentPathFast)486 void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
487                                          const D3D11_VIEWPORT &dxViewport,
488                                          bool is9_3,
489                                          bool presentPathFast)
490 {
491     mShaderConstantsDirty.set(gl::ShaderType::Vertex);
492     mShaderConstantsDirty.set(gl::ShaderType::Fragment);
493 
494     // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
495     // using viewAdjust (like the D3D9 renderer).
496     if (is9_3)
497     {
498         mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
499                                                    2 * (glViewport.x - dxViewport.TopLeftX)) /
500                                 dxViewport.Width;
501         mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
502                                                    2 * (glViewport.y - dxViewport.TopLeftY)) /
503                                 dxViewport.Height;
504         mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
505         mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
506     }
507 
508     mPixel.viewCoords[0] = glViewport.width * 0.5f;
509     mPixel.viewCoords[1] = glViewport.height * 0.5f;
510     mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
511     mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);
512 
513     // Instanced pointsprite emulation requires ViewCoords to be defined in the
514     // the vertex shader.
515     mVertex.viewCoords[0] = mPixel.viewCoords[0];
516     mVertex.viewCoords[1] = mPixel.viewCoords[1];
517     mVertex.viewCoords[2] = mPixel.viewCoords[2];
518     mVertex.viewCoords[3] = mPixel.viewCoords[3];
519 
520     const float zNear = dxViewport.MinDepth;
521     const float zFar  = dxViewport.MaxDepth;
522 
523     mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
524     mPixel.depthFront[1] = (zNear + zFar) * 0.5f;
525 
526     mVertex.depthRange[0] = zNear;
527     mVertex.depthRange[1] = zFar;
528     mVertex.depthRange[2] = zFar - zNear;
529 
530     mPixel.depthRange[0] = zNear;
531     mPixel.depthRange[1] = zFar;
532     mPixel.depthRange[2] = zFar - zNear;
533 
534     mPixel.viewScale[0] = 1.0f;
535     mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
536     // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw
537     // framebuffer's layout is changed.
538 
539     mVertex.viewScale[0] = mPixel.viewScale[0];
540     mVertex.viewScale[1] = mPixel.viewScale[1];
541 }
542 
543 // Update the ShaderConstants with a new first vertex and return whether the update dirties them.
onFirstVertexChange(GLint firstVertex,GLint baseVertex)544 ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex, GLint baseVertex)
545 {
546     uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex + baseVertex);
547 
548     bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex);
549     if (firstVertexDirty)
550     {
551         mVertex.firstVertex = newFirstVertex;
552         mShaderConstantsDirty.set(gl::ShaderType::Vertex);
553     }
554     return firstVertexDirty;
555 }
556 
onSamplerChange(gl::ShaderType shaderType,unsigned int samplerIndex,const gl::Texture & texture,const gl::SamplerState & samplerState)557 void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
558                                         unsigned int samplerIndex,
559                                         const gl::Texture &texture,
560                                         const gl::SamplerState &samplerState)
561 {
562     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
563     if (updateSamplerMetadata(&mShaderSamplerMetadata[shaderType][samplerIndex], texture,
564                               samplerState))
565     {
566         mNumActiveShaderSamplers[shaderType] = 0;
567     }
568 }
569 
onImageChange(gl::ShaderType shaderType,unsigned int imageIndex,const gl::ImageUnit & imageUnit)570 void ShaderConstants11::onImageChange(gl::ShaderType shaderType,
571                                       unsigned int imageIndex,
572                                       const gl::ImageUnit &imageUnit)
573 {
574     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
575     if (imageUnit.access == GL_READ_ONLY)
576     {
577         if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit))
578         {
579             mNumActiveShaderReadonlyImages[shaderType] = 0;
580         }
581     }
582     else
583     {
584         if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit))
585         {
586             mNumActiveShaderImages[shaderType] = 0;
587         }
588     }
589 }
590 
updateBuffer(const gl::Context * context,Renderer11 * renderer,gl::ShaderType shaderType,const ProgramD3D & programD3D,const d3d11::Buffer & driverConstantBuffer)591 angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
592                                               Renderer11 *renderer,
593                                               gl::ShaderType shaderType,
594                                               const ProgramD3D &programD3D,
595                                               const d3d11::Buffer &driverConstantBuffer)
596 {
597     // Re-upload the sampler meta-data if the current program uses more samplers
598     // than we previously uploaded.
599     const int numSamplers       = programD3D.getUsedSamplerRange(shaderType).length();
600     const int numReadonlyImages = programD3D.getUsedImageRange(shaderType, true).length();
601     const int numImages         = programD3D.getUsedImageRange(shaderType, false).length();
602 
603     const bool dirty = mShaderConstantsDirty[shaderType] ||
604                        (mNumActiveShaderSamplers[shaderType] < numSamplers) ||
605                        (mNumActiveShaderReadonlyImages[shaderType] < numReadonlyImages) ||
606                        (mNumActiveShaderImages[shaderType] < numImages);
607 
608     const size_t dataSize = GetShaderConstantsStructSize(shaderType);
609     const uint8_t *samplerData =
610         reinterpret_cast<const uint8_t *>(mShaderSamplerMetadata[shaderType].data());
611     const size_t samplerDataSize = sizeof(SamplerMetadata) * numSamplers;
612     const uint8_t *readonlyImageData =
613         reinterpret_cast<const uint8_t *>(mShaderReadonlyImageMetadata[shaderType].data());
614     const size_t readonlyImageDataSize = sizeof(ImageMetadata) * numReadonlyImages;
615     const uint8_t *imageData =
616         reinterpret_cast<const uint8_t *>(mShaderImageMetadata[shaderType].data());
617     const size_t imageDataSize = sizeof(ImageMetadata) * numImages;
618 
619     mNumActiveShaderSamplers[shaderType]       = numSamplers;
620     mNumActiveShaderReadonlyImages[shaderType] = numReadonlyImages;
621     mNumActiveShaderImages[shaderType]         = numImages;
622     mShaderConstantsDirty.set(shaderType, false);
623 
624     const uint8_t *data = nullptr;
625     switch (shaderType)
626     {
627         case gl::ShaderType::Vertex:
628             data = reinterpret_cast<const uint8_t *>(&mVertex);
629             break;
630         case gl::ShaderType::Fragment:
631             data = reinterpret_cast<const uint8_t *>(&mPixel);
632             break;
633         case gl::ShaderType::Compute:
634             data = reinterpret_cast<const uint8_t *>(&mCompute);
635             break;
636         default:
637             UNREACHABLE();
638             break;
639     }
640 
641     ASSERT(driverConstantBuffer.valid());
642 
643     if (!dirty)
644     {
645         return angle::Result::Continue;
646     }
647 
648     // Previous buffer contents are discarded, so we need to refresh the whole buffer.
649     D3D11_MAPPED_SUBRESOURCE mapping = {};
650     ANGLE_TRY(renderer->mapResource(context, driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD,
651                                     0, &mapping));
652 
653     memcpy(mapping.pData, data, dataSize);
654     memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize, samplerData,
655            sizeof(SamplerMetadata) * numSamplers);
656 
657     memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize, readonlyImageData,
658            readonlyImageDataSize);
659     memcpy(
660         static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize + readonlyImageDataSize,
661         imageData, imageDataSize);
662     renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0);
663 
664     return angle::Result::Continue;
665 }
666 
StateManager11(Renderer11 * renderer)667 StateManager11::StateManager11(Renderer11 *renderer)
668     : mRenderer(renderer),
669       mInternalDirtyBits(),
670       mCurSampleAlphaToCoverage(false),
671       mCurBlendStateExt(),
672       mCurBlendColor(0, 0, 0, 0),
673       mCurSampleMask(0),
674       mCurStencilRef(0),
675       mCurStencilBackRef(0),
676       mCurStencilSize(0),
677       mCurScissorEnabled(false),
678       mCurScissorRect(),
679       mCurViewport(),
680       mCurNear(0.0f),
681       mCurFar(0.0f),
682       mViewportBounds(),
683       mRenderTargetIsDirty(true),
684       mCurPresentPathFastEnabled(false),
685       mCurPresentPathFastColorBufferHeight(0),
686       mDirtyCurrentValueAttribs(),
687       mCurrentValueAttribs(),
688       mCurrentInputLayout(),
689       mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0),
690       mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED),
691       mLastAppliedDrawMode(gl::PrimitiveMode::InvalidEnum),
692       mCullEverything(false),
693       mDirtySwizzles(false),
694       mAppliedIB(nullptr),
695       mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
696       mAppliedIBOffset(0),
697       mIndexBufferIsDirty(false),
698       mVertexDataManager(renderer),
699       mIndexDataManager(renderer),
700       mIsMultiviewEnabled(false),
701       mIndependentBlendStates(false),
702       mEmptySerial(mRenderer->generateSerial()),
703       mProgramD3D(nullptr),
704       mVertexArray11(nullptr),
705       mFramebuffer11(nullptr)
706 {
707     mCurDepthStencilState.depthTest                = false;
708     mCurDepthStencilState.depthFunc                = GL_LESS;
709     mCurDepthStencilState.depthMask                = true;
710     mCurDepthStencilState.stencilTest              = false;
711     mCurDepthStencilState.stencilMask              = true;
712     mCurDepthStencilState.stencilFail              = GL_KEEP;
713     mCurDepthStencilState.stencilPassDepthFail     = GL_KEEP;
714     mCurDepthStencilState.stencilPassDepthPass     = GL_KEEP;
715     mCurDepthStencilState.stencilWritemask         = static_cast<GLuint>(-1);
716     mCurDepthStencilState.stencilBackFunc          = GL_ALWAYS;
717     mCurDepthStencilState.stencilBackMask          = static_cast<GLuint>(-1);
718     mCurDepthStencilState.stencilBackFail          = GL_KEEP;
719     mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
720     mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
721     mCurDepthStencilState.stencilBackWritemask     = static_cast<GLuint>(-1);
722 
723     mCurRasterState.rasterizerDiscard   = false;
724     mCurRasterState.cullFace            = false;
725     mCurRasterState.cullMode            = gl::CullFaceMode::Back;
726     mCurRasterState.frontFace           = GL_CCW;
727     mCurRasterState.polygonOffsetFill   = false;
728     mCurRasterState.polygonOffsetFactor = 0.0f;
729     mCurRasterState.polygonOffsetUnits  = 0.0f;
730     mCurRasterState.pointDrawMode       = false;
731     mCurRasterState.multiSample         = false;
732     mCurRasterState.dither              = false;
733 
734     // Start with all internal dirty bits set except DIRTY_BIT_COMPUTE_SRVUAV_STATE and
735     // DIRTY_BIT_GRAPHICS_SRVUAV_STATE.
736     mInternalDirtyBits.set();
737     mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_SRVUAV_STATE);
738     mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
739 
740     mGraphicsDirtyBitsMask.set();
741     mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
742     mComputeDirtyBitsMask.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
743     mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORMS);
744     mComputeDirtyBitsMask.set(DIRTY_BIT_DRIVER_UNIFORMS);
745     mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
746     mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
747     mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
748     mComputeDirtyBitsMask.set(DIRTY_BIT_SHADERS);
749     mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
750 
751     // Initially all current value attributes must be updated on first use.
752     mDirtyCurrentValueAttribs.set();
753 
754     mCurrentVertexBuffers.fill(nullptr);
755     mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
756     mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
757 }
758 
~StateManager11()759 StateManager11::~StateManager11() {}
760 
761 template <typename SRVType>
setShaderResourceInternal(gl::ShaderType shaderType,UINT resourceSlot,const SRVType * srv)762 void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType,
763                                                UINT resourceSlot,
764                                                const SRVType *srv)
765 {
766     auto *currentSRVs = getSRVCache(shaderType);
767     ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs->size());
768     const ViewRecord<D3D11_SHADER_RESOURCE_VIEW_DESC> &record = (*currentSRVs)[resourceSlot];
769 
770     if (record.view != reinterpret_cast<uintptr_t>(srv))
771     {
772         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
773         ID3D11ShaderResourceView *srvPtr   = srv ? srv->get() : nullptr;
774         if (srvPtr)
775         {
776             uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
777             unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
778                                  resource, nullptr);
779         }
780 
781         switch (shaderType)
782         {
783             case gl::ShaderType::Vertex:
784                 deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr);
785                 break;
786             case gl::ShaderType::Fragment:
787                 deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr);
788                 break;
789             case gl::ShaderType::Compute:
790             {
791                 if (srvPtr)
792                 {
793                     uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
794                     unsetConflictingRTVs(resource);
795                 }
796                 deviceContext->CSSetShaderResources(resourceSlot, 1, &srvPtr);
797                 break;
798             }
799             default:
800                 UNREACHABLE();
801         }
802 
803         currentSRVs->update(resourceSlot, srvPtr);
804     }
805 }
806 
807 template <typename UAVType>
setUnorderedAccessViewInternal(gl::ShaderType shaderType,UINT resourceSlot,const UAVType * uav)808 void StateManager11::setUnorderedAccessViewInternal(gl::ShaderType shaderType,
809                                                     UINT resourceSlot,
810                                                     const UAVType *uav)
811 {
812     ASSERT(shaderType == gl::ShaderType::Compute);
813     ASSERT(static_cast<size_t>(resourceSlot) < mCurComputeUAVs.size());
814     const ViewRecord<D3D11_UNORDERED_ACCESS_VIEW_DESC> &record = mCurComputeUAVs[resourceSlot];
815 
816     if (record.view != reinterpret_cast<uintptr_t>(uav))
817     {
818         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
819         ID3D11UnorderedAccessView *uavPtr  = uav ? uav->get() : nullptr;
820         // We need to make sure that resource being set to UnorderedAccessView slot |resourceSlot|
821         // is not bound on SRV.
822         if (uavPtr)
823         {
824             uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(uavPtr));
825             unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Vertex,
826                                  resource, nullptr, false);
827             unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Fragment,
828                                  resource, nullptr, false);
829             unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Compute,
830                                  resource, nullptr, false);
831         }
832         deviceContext->CSSetUnorderedAccessViews(resourceSlot, 1, &uavPtr, nullptr);
833 
834         mCurComputeUAVs.update(resourceSlot, uavPtr);
835     }
836 }
837 
updateStencilSizeIfChanged(bool depthStencilInitialized,unsigned int stencilSize)838 void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
839                                                 unsigned int stencilSize)
840 {
841     if (!depthStencilInitialized || stencilSize != mCurStencilSize)
842     {
843         mCurStencilSize = stencilSize;
844         mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
845     }
846 }
847 
checkPresentPath(const gl::Context * context)848 void StateManager11::checkPresentPath(const gl::Context *context)
849 {
850     if (!mRenderer->presentPathFastEnabled())
851         return;
852 
853     const auto *framebuffer          = context->getState().getDrawFramebuffer();
854     const auto *firstColorAttachment = framebuffer->getFirstColorAttachment();
855     const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment);
856 
857     const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0;
858 
859     if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
860         (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
861     {
862         mCurPresentPathFastEnabled           = presentPathFastActive;
863         mCurPresentPathFastColorBufferHeight = colorBufferHeight;
864 
865         // Scissor rect may need to be vertically inverted
866         mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
867 
868         // Cull Mode may need to be inverted
869         mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
870 
871         // Viewport may need to be vertically inverted
872         invalidateViewport(context);
873     }
874 }
875 
updateStateForCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)876 angle::Result StateManager11::updateStateForCompute(const gl::Context *context,
877                                                     GLuint numGroupsX,
878                                                     GLuint numGroupsY,
879                                                     GLuint numGroupsZ)
880 {
881     mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
882 
883     if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
884     {
885         invalidateTexturesAndSamplers();
886     }
887 
888     if (mDirtySwizzles)
889     {
890         ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
891         mDirtySwizzles = false;
892     }
893 
894     if (mProgramD3D->anyShaderUniformsDirty())
895     {
896         mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
897     }
898 
899     auto dirtyBitsCopy = mInternalDirtyBits & mComputeDirtyBitsMask;
900     mInternalDirtyBits &= ~mComputeDirtyBitsMask;
901 
902     for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
903     {
904         switch (*iter)
905         {
906             case DIRTY_BIT_COMPUTE_SRVUAV_STATE:
907                 // Avoid to call syncTexturesForCompute function two times.
908                 iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
909                 ANGLE_TRY(syncTexturesForCompute(context));
910                 break;
911             case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
912                 ANGLE_TRY(syncTexturesForCompute(context));
913                 break;
914             case DIRTY_BIT_PROGRAM_UNIFORMS:
915             case DIRTY_BIT_DRIVER_UNIFORMS:
916                 ANGLE_TRY(applyComputeUniforms(context, mProgramD3D));
917                 break;
918             case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
919                 ANGLE_TRY(syncUniformBuffers(context));
920                 break;
921             case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
922                 ANGLE_TRY(syncAtomicCounterBuffers(context));
923                 break;
924             case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
925                 ANGLE_TRY(syncShaderStorageBuffers(context));
926                 break;
927             case DIRTY_BIT_SHADERS:
928                 ANGLE_TRY(syncProgramForCompute(context));
929                 break;
930             default:
931                 UNREACHABLE();
932                 break;
933         }
934     }
935 
936     return angle::Result::Continue;
937 }
938 
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits)939 void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
940 {
941     if (!dirtyBits.any())
942     {
943         return;
944     }
945 
946     const gl::State &state = context->getState();
947 
948     for (size_t dirtyBit : dirtyBits)
949     {
950         switch (dirtyBit)
951         {
952             case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
953             {
954                 const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
955                 ASSERT(mCurBlendStateExt.mMaxDrawBuffers == blendStateExt.mMaxDrawBuffers);
956                 // Compare blend equations only for buffers with blending enabled because
957                 // subsequent sync stages enforce default values for buffers with blending disabled.
958                 if ((blendStateExt.mEnabledMask &
959                      mCurBlendStateExt.compareEquations(blendStateExt.mEquationColor,
960                                                         blendStateExt.mEquationAlpha))
961                         .any())
962                 {
963                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
964                 }
965                 break;
966             }
967             case gl::State::DIRTY_BIT_BLEND_FUNCS:
968             {
969                 const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
970                 ASSERT(mCurBlendStateExt.mMaxDrawBuffers == blendStateExt.mMaxDrawBuffers);
971                 // Compare blend factors only for buffers with blending enabled because
972                 // subsequent sync stages enforce default values for buffers with blending disabled.
973                 if ((blendStateExt.mEnabledMask &
974                      mCurBlendStateExt.compareFactors(
975                          blendStateExt.mSrcColor, blendStateExt.mDstColor, blendStateExt.mSrcAlpha,
976                          blendStateExt.mDstAlpha))
977                         .any())
978                 {
979                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
980                 }
981                 break;
982             }
983             case gl::State::DIRTY_BIT_BLEND_ENABLED:
984             {
985                 if (state.getBlendStateExt().mEnabledMask != mCurBlendStateExt.mEnabledMask)
986                 {
987                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
988                 }
989                 break;
990             }
991             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
992                 if (state.isSampleAlphaToCoverageEnabled() != mCurSampleAlphaToCoverage)
993                 {
994                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
995                 }
996                 break;
997             case gl::State::DIRTY_BIT_DITHER_ENABLED:
998                 if (state.getRasterizerState().dither != mCurRasterState.dither)
999                 {
1000                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1001                 }
1002                 break;
1003             case gl::State::DIRTY_BIT_COLOR_MASK:
1004             {
1005                 if (state.getBlendStateExt().mColorMask != mCurBlendStateExt.mColorMask)
1006                 {
1007                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
1008                 }
1009                 break;
1010             }
1011             case gl::State::DIRTY_BIT_BLEND_COLOR:
1012                 if (state.getBlendColor() != mCurBlendColor)
1013                 {
1014                     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
1015                 }
1016                 break;
1017             // Depth and stencil redundant state changes are guarded in the
1018             // frontend so for related cases here just set the dirty bit.
1019             case gl::State::DIRTY_BIT_DEPTH_MASK:
1020                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1021                 break;
1022             case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
1023                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1024                 break;
1025             case gl::State::DIRTY_BIT_DEPTH_FUNC:
1026                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1027                 break;
1028             case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
1029                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1030                 break;
1031             case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
1032                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1033                 break;
1034             case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
1035                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1036                 break;
1037             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
1038                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1039                 break;
1040             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
1041                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1042                 break;
1043             case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
1044                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1045                 break;
1046             case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
1047                 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1048                 break;
1049 
1050             case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
1051                 if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
1052                 {
1053                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1054                     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
1055                 }
1056                 break;
1057             case gl::State::DIRTY_BIT_CULL_FACE:
1058                 if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
1059                 {
1060                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1061                     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
1062                 }
1063                 break;
1064             case gl::State::DIRTY_BIT_FRONT_FACE:
1065                 if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
1066                 {
1067                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1068                     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
1069                 }
1070                 break;
1071             case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
1072                 if (state.getRasterizerState().polygonOffsetFill !=
1073                     mCurRasterState.polygonOffsetFill)
1074                 {
1075                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1076                 }
1077                 break;
1078             case gl::State::DIRTY_BIT_POLYGON_OFFSET:
1079             {
1080                 const gl::RasterizerState &rasterState = state.getRasterizerState();
1081                 if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
1082                     rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
1083                 {
1084                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1085                 }
1086                 break;
1087             }
1088             case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
1089                 if (state.getRasterizerState().rasterizerDiscard !=
1090                     mCurRasterState.rasterizerDiscard)
1091                 {
1092                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1093 
1094                     // Enabling/disabling rasterizer discard affects the pixel shader.
1095                     invalidateShaders();
1096                 }
1097                 break;
1098             case gl::State::DIRTY_BIT_SCISSOR:
1099                 if (state.getScissor() != mCurScissorRect)
1100                 {
1101                     mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
1102                 }
1103                 break;
1104             case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1105                 if (state.isScissorTestEnabled() != mCurScissorEnabled)
1106                 {
1107                     mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
1108                     // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
1109                     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1110                 }
1111                 break;
1112             case gl::State::DIRTY_BIT_DEPTH_RANGE:
1113                 invalidateViewport(context);
1114                 break;
1115             case gl::State::DIRTY_BIT_VIEWPORT:
1116                 if (state.getViewport() != mCurViewport)
1117                 {
1118                     invalidateViewport(context);
1119                 }
1120                 break;
1121             case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
1122                 invalidateRenderTarget();
1123                 if (mIsMultiviewEnabled)
1124                 {
1125                     handleMultiviewDrawFramebufferChange(context);
1126                 }
1127                 mFramebuffer11 = GetImplAs<Framebuffer11>(state.getDrawFramebuffer());
1128                 break;
1129             case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
1130                 invalidateVertexBuffer();
1131                 // Force invalidate the current value attributes, since the VertexArray11 keeps an
1132                 // internal cache of TranslatedAttributes, and they CurrentValue attributes are
1133                 // owned by the StateManager11/Context.
1134                 mDirtyCurrentValueAttribs.set();
1135                 // Invalidate the cached index buffer.
1136                 invalidateIndexBuffer();
1137                 mVertexArray11 = GetImplAs<VertexArray11>(state.getVertexArray());
1138                 break;
1139             case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
1140                 invalidateProgramUniformBuffers();
1141                 break;
1142             case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
1143                 invalidateProgramAtomicCounterBuffers();
1144                 break;
1145             case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
1146                 invalidateProgramShaderStorageBuffers();
1147                 break;
1148             case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
1149                 invalidateTexturesAndSamplers();
1150                 break;
1151             case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
1152                 invalidateTexturesAndSamplers();
1153                 break;
1154             case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
1155                 // TODO(jie.a.chen@intel.com): More fine-grained update.
1156                 // Currently images are updated together with textures and samplers. It would be
1157                 // better to update them separately.
1158                 // http://anglebug.com/2814
1159                 invalidateTexturesAndSamplers();
1160                 break;
1161             case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
1162                 invalidateTransformFeedback();
1163                 break;
1164             case gl::State::DIRTY_BIT_PROGRAM_BINDING:
1165                 mProgramD3D = GetImplAs<ProgramD3D>(state.getProgram());
1166                 break;
1167             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
1168             {
1169                 invalidateShaders();
1170                 invalidateTexturesAndSamplers();
1171                 invalidateProgramUniforms();
1172                 invalidateProgramUniformBuffers();
1173                 invalidateProgramAtomicCounterBuffers();
1174                 invalidateProgramShaderStorageBuffers();
1175                 invalidateDriverUniforms();
1176                 const gl::ProgramExecutable *executable = state.getProgramExecutable();
1177                 if (!executable || !executable->isCompute())
1178                 {
1179                     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
1180                     invalidateVertexBuffer();
1181                     invalidateRenderTarget();
1182                     // If OVR_multiview2 is enabled, the attribute divisor has to be updated for
1183                     // each binding. When using compute, there could be no vertex array.
1184                     if (mIsMultiviewEnabled && mVertexArray11)
1185                     {
1186                         ASSERT(mProgramD3D);
1187                         ASSERT(mVertexArray11 == GetImplAs<VertexArray11>(state.getVertexArray()));
1188                         const gl::ProgramState &programState = mProgramD3D->getState();
1189                         int numViews =
1190                             programState.usesMultiview() ? programState.getNumViews() : 1;
1191                         mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews);
1192                     }
1193                 }
1194                 break;
1195             }
1196             case gl::State::DIRTY_BIT_CURRENT_VALUES:
1197             {
1198                 for (auto attribIndex : state.getAndResetDirtyCurrentValues())
1199                 {
1200                     invalidateCurrentValueAttrib(attribIndex);
1201                 }
1202                 break;
1203             }
1204             case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
1205                 invalidateShaders();
1206                 break;
1207             default:
1208                 break;
1209         }
1210     }
1211 
1212     // TODO(jmadill): Input layout and vertex buffer state.
1213 }
1214 
handleMultiviewDrawFramebufferChange(const gl::Context * context)1215 void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context)
1216 {
1217     const auto &glState                    = context->getState();
1218     const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1219     ASSERT(drawFramebuffer != nullptr);
1220 
1221     if (drawFramebuffer->isMultiview())
1222     {
1223         // Because the base view index is applied as an offset to the 2D texture array when the
1224         // RTV is created, we just have to pass a boolean to select which code path is to be
1225         // used.
1226         mShaderConstants.setMultiviewWriteToViewportIndex(0.0f);
1227     }
1228 }
1229 
syncBlendState(const gl::Context * context,const gl::BlendStateExt & blendStateExt,const gl::ColorF & blendColor,unsigned int sampleMask,bool sampleAlphaToCoverage,bool emulateConstantAlpha)1230 angle::Result StateManager11::syncBlendState(const gl::Context *context,
1231                                              const gl::BlendStateExt &blendStateExt,
1232                                              const gl::ColorF &blendColor,
1233                                              unsigned int sampleMask,
1234                                              bool sampleAlphaToCoverage,
1235                                              bool emulateConstantAlpha)
1236 {
1237     const d3d11::BlendState *dxBlendState = nullptr;
1238     const d3d11::BlendStateKey &key       = RenderStateCache::GetBlendStateKey(
1239         context, mFramebuffer11, blendStateExt, sampleAlphaToCoverage);
1240 
1241     ANGLE_TRY(mRenderer->getBlendState(context, key, &dxBlendState));
1242 
1243     ASSERT(dxBlendState != nullptr);
1244 
1245     // D3D11 does not support CONSTANT_ALPHA as source or destination color factor, so ANGLE sets
1246     // the factor to CONSTANT_COLOR and swizzles the color value to aaaa. For this reason, it's
1247     // impossible to simultaneously use CONSTANT_ALPHA and CONSTANT_COLOR as source or destination
1248     // color factors in the same blend state. This is enforced in the validation layer.
1249     float blendColors[4] = {0.0f};
1250     blendColors[0]       = emulateConstantAlpha ? blendColor.alpha : blendColor.red;
1251     blendColors[1]       = emulateConstantAlpha ? blendColor.alpha : blendColor.green;
1252     blendColors[2]       = emulateConstantAlpha ? blendColor.alpha : blendColor.blue;
1253     blendColors[3]       = blendColor.alpha;
1254 
1255     mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask);
1256 
1257     mCurBlendStateExt         = blendStateExt;
1258     mCurBlendColor            = blendColor;
1259     mCurSampleMask            = sampleMask;
1260     mCurSampleAlphaToCoverage = sampleAlphaToCoverage;
1261 
1262     return angle::Result::Continue;
1263 }
1264 
syncDepthStencilState(const gl::Context * context)1265 angle::Result StateManager11::syncDepthStencilState(const gl::Context *context)
1266 {
1267     const gl::State &glState = context->getState();
1268 
1269     mCurDepthStencilState = glState.getDepthStencilState();
1270     mCurStencilRef        = glState.getStencilRef();
1271     mCurStencilBackRef    = glState.getStencilBackRef();
1272 
1273     // get the maximum size of the stencil ref
1274     unsigned int maxStencil = 0;
1275     if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
1276     {
1277         maxStencil = (1 << mCurStencilSize) - 1;
1278     }
1279     ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
1280            (mCurDepthStencilState.stencilBackWritemask & maxStencil));
1281     ASSERT(gl::clamp(mCurStencilRef, 0, static_cast<int>(maxStencil)) ==
1282            gl::clamp(mCurStencilBackRef, 0, static_cast<int>(maxStencil)));
1283     ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
1284            (mCurDepthStencilState.stencilBackMask & maxStencil));
1285 
1286     gl::DepthStencilState modifiedGLState = glState.getDepthStencilState();
1287 
1288     ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid());
1289 
1290     if (mCurDisableDepth.value())
1291     {
1292         modifiedGLState.depthTest = false;
1293         modifiedGLState.depthMask = false;
1294     }
1295 
1296     if (mCurDisableStencil.value())
1297     {
1298         modifiedGLState.stencilTest = false;
1299     }
1300     if (!modifiedGLState.stencilTest)
1301     {
1302         modifiedGLState.stencilWritemask     = 0;
1303         modifiedGLState.stencilBackWritemask = 0;
1304     }
1305 
1306     // If STENCIL_TEST is disabled in glState, stencil testing and writing should be disabled.
1307     // Verify that's true in the modifiedGLState so it is propagated to d3dState.
1308     ASSERT(glState.getDepthStencilState().stencilTest ||
1309            (!modifiedGLState.stencilTest && modifiedGLState.stencilWritemask == 0 &&
1310             modifiedGLState.stencilBackWritemask == 0));
1311 
1312     const d3d11::DepthStencilState *d3dState = nullptr;
1313     ANGLE_TRY(mRenderer->getDepthStencilState(context, modifiedGLState, &d3dState));
1314     ASSERT(d3dState);
1315 
1316     // Max D3D11 stencil reference value is 0xFF,
1317     // corresponding to the max 8 bits in a stencil buffer
1318     // GL specifies we should clamp the ref value to the
1319     // nearest bit depth when doing stencil ops
1320     static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
1321                   "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
1322     static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
1323                   "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
1324     UINT dxStencilRef = static_cast<UINT>(gl::clamp(mCurStencilRef, 0, 0xFF));
1325 
1326     mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef);
1327 
1328     return angle::Result::Continue;
1329 }
1330 
syncRasterizerState(const gl::Context * context,gl::PrimitiveMode mode)1331 angle::Result StateManager11::syncRasterizerState(const gl::Context *context,
1332                                                   gl::PrimitiveMode mode)
1333 {
1334     // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
1335     gl::RasterizerState rasterState = context->getState().getRasterizerState();
1336     rasterState.pointDrawMode       = (mode == gl::PrimitiveMode::Points);
1337     rasterState.multiSample         = mCurRasterState.multiSample;
1338 
1339     ID3D11RasterizerState *dxRasterState = nullptr;
1340 
1341     if (mCurPresentPathFastEnabled)
1342     {
1343         gl::RasterizerState modifiedRasterState = rasterState;
1344 
1345         // If prseent path fast is active then we need invert the front face state.
1346         // This ensures that both gl_FrontFacing is correct, and front/back culling
1347         // is performed correctly.
1348         if (modifiedRasterState.frontFace == GL_CCW)
1349         {
1350             modifiedRasterState.frontFace = GL_CW;
1351         }
1352         else
1353         {
1354             ASSERT(modifiedRasterState.frontFace == GL_CW);
1355             modifiedRasterState.frontFace = GL_CCW;
1356         }
1357 
1358         ANGLE_TRY(mRenderer->getRasterizerState(context, modifiedRasterState, mCurScissorEnabled,
1359                                                 &dxRasterState));
1360     }
1361     else
1362     {
1363         ANGLE_TRY(mRenderer->getRasterizerState(context, rasterState, mCurScissorEnabled,
1364                                                 &dxRasterState));
1365     }
1366 
1367     mRenderer->getDeviceContext()->RSSetState(dxRasterState);
1368 
1369     mCurRasterState = rasterState;
1370 
1371     return angle::Result::Continue;
1372 }
1373 
syncScissorRectangle(const gl::Context * context)1374 void StateManager11::syncScissorRectangle(const gl::Context *context)
1375 {
1376     const auto &glState          = context->getState();
1377     gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
1378     const gl::Rectangle &scissor = glState.getScissor();
1379     const bool enabled           = glState.isScissorTestEnabled();
1380 
1381     mCurScissorOffset = framebuffer->getSurfaceTextureOffset();
1382 
1383     int scissorX = scissor.x + mCurScissorOffset.x;
1384     int scissorY = scissor.y + mCurScissorOffset.y;
1385 
1386     if (mCurPresentPathFastEnabled)
1387     {
1388         scissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
1389     }
1390 
1391     if (enabled)
1392     {
1393         D3D11_RECT rect;
1394         int x       = scissorX;
1395         int y       = scissorY;
1396         rect.left   = std::max(0, x);
1397         rect.top    = std::max(0, y);
1398         rect.right  = x + std::max(0, scissor.width);
1399         rect.bottom = y + std::max(0, scissor.height);
1400         mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
1401     }
1402 
1403     mCurScissorRect    = scissor;
1404     mCurScissorEnabled = enabled;
1405 }
1406 
syncViewport(const gl::Context * context)1407 void StateManager11::syncViewport(const gl::Context *context)
1408 {
1409     const auto &glState          = context->getState();
1410     gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
1411     float actualZNear            = gl::clamp01(glState.getNearPlane());
1412     float actualZFar             = gl::clamp01(glState.getFarPlane());
1413 
1414     const auto &caps         = context->getCaps();
1415     int dxMaxViewportBoundsX = caps.maxViewportWidth;
1416     int dxMaxViewportBoundsY = caps.maxViewportHeight;
1417     int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
1418     int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
1419 
1420     bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3;
1421 
1422     if (is9_3)
1423     {
1424         // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
1425         dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
1426         dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
1427         dxMinViewportBoundsX = 0;
1428         dxMinViewportBoundsY = 0;
1429     }
1430 
1431     const auto &viewport = glState.getViewport();
1432 
1433     int dxViewportTopLeftX = 0;
1434     int dxViewportTopLeftY = 0;
1435     int dxViewportWidth    = 0;
1436     int dxViewportHeight   = 0;
1437 
1438     mCurViewportOffset = framebuffer->getSurfaceTextureOffset();
1439 
1440     dxViewportTopLeftX =
1441         gl::clamp(viewport.x + mCurViewportOffset.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
1442     dxViewportTopLeftY =
1443         gl::clamp(viewport.y + mCurViewportOffset.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
1444     dxViewportWidth  = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
1445     dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
1446 
1447     D3D11_VIEWPORT dxViewport;
1448     dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
1449     if (mCurPresentPathFastEnabled)
1450     {
1451         // When present path fast is active and we're rendering to framebuffer 0, we must invert
1452         // the viewport in Y-axis.
1453         // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
1454         // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
1455         // unaltered dxViewportTopLeftY value.
1456         dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
1457                                                  dxViewportTopLeftY - dxViewportHeight);
1458     }
1459     else
1460     {
1461         dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
1462     }
1463 
1464     // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering
1465     // will be limited to a rectangle having a lower left of (0, 0) and an upper right of
1466     // (width, height), where width and height are the framebuffer object's default width
1467     // and height." See http://anglebug.com/1594
1468     // If the Framebuffer has no color attachment and the default width or height is smaller
1469     // than the current viewport, use the smaller of the two sizes.
1470     // If framebuffer default width or height is 0, the params should not set.
1471     if (!framebuffer->getFirstNonNullAttachment() &&
1472         (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight()))
1473     {
1474         dxViewport.Width =
1475             static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth()));
1476         dxViewport.Height =
1477             static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight()));
1478     }
1479     else
1480     {
1481         dxViewport.Width  = static_cast<float>(dxViewportWidth);
1482         dxViewport.Height = static_cast<float>(dxViewportHeight);
1483     }
1484     dxViewport.MinDepth = actualZNear;
1485     dxViewport.MaxDepth = actualZFar;
1486 
1487     mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
1488 
1489     mCurViewport = viewport;
1490     mCurNear     = actualZNear;
1491     mCurFar      = actualZFar;
1492 
1493     const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX),
1494                                            static_cast<FLOAT>(dxViewportTopLeftY),
1495                                            static_cast<FLOAT>(dxViewportWidth),
1496                                            static_cast<FLOAT>(dxViewportHeight),
1497                                            actualZNear,
1498                                            actualZFar};
1499     mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled);
1500 }
1501 
invalidateRenderTarget()1502 void StateManager11::invalidateRenderTarget()
1503 {
1504     mRenderTargetIsDirty = true;
1505 }
1506 
processFramebufferInvalidation(const gl::Context * context)1507 void StateManager11::processFramebufferInvalidation(const gl::Context *context)
1508 {
1509     ASSERT(mRenderTargetIsDirty);
1510     ASSERT(context);
1511 
1512     mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1513 
1514     // The pixel shader is dependent on the output layout.
1515     invalidateShaders();
1516 
1517     // The D3D11 blend state is heavily dependent on the current render target.
1518     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
1519 
1520     gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
1521     ASSERT(fbo);
1522 
1523     // Dirty scissor and viewport because surface texture offset might have changed.
1524     if (mCurViewportOffset != fbo->getSurfaceTextureOffset())
1525     {
1526         mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
1527     }
1528     if (mCurScissorOffset != fbo->getSurfaceTextureOffset())
1529     {
1530         mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
1531     }
1532 
1533     // Disable the depth test/depth write if we are using a stencil-only attachment.
1534     // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
1535     // nor write to the unused depth part of this emulated texture.
1536     bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil());
1537 
1538     // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
1539     bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil());
1540 
1541     if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() ||
1542         !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value())
1543     {
1544         mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1545         mCurDisableDepth   = disableDepth;
1546         mCurDisableStencil = disableStencil;
1547     }
1548 
1549     bool multiSample = (fbo->getSamples(context) != 0);
1550     if (multiSample != mCurRasterState.multiSample)
1551     {
1552         mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1553         mCurRasterState.multiSample = multiSample;
1554     }
1555 
1556     checkPresentPath(context);
1557 
1558     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
1559     {
1560         const auto *firstAttachment = fbo->getFirstNonNullAttachment();
1561         if (firstAttachment)
1562         {
1563             const auto &size = firstAttachment->getSize();
1564             if (mViewportBounds.width != size.width || mViewportBounds.height != size.height)
1565             {
1566                 mViewportBounds = gl::Extents(size.width, size.height, 1);
1567                 invalidateViewport(context);
1568             }
1569         }
1570     }
1571 }
1572 
invalidateBoundViews()1573 void StateManager11::invalidateBoundViews()
1574 {
1575     for (SRVCache &curShaderSRV : mCurShaderSRVs)
1576     {
1577         curShaderSRV.clear();
1578     }
1579 
1580     invalidateRenderTarget();
1581 }
1582 
invalidateVertexBuffer()1583 void StateManager11::invalidateVertexBuffer()
1584 {
1585     unsigned int limit      = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
1586                                                 gl::MAX_VERTEX_ATTRIBS);
1587     mDirtyVertexBufferRange = gl::RangeUI(0, limit);
1588     invalidateInputLayout();
1589     invalidateShaders();
1590     mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
1591 }
1592 
invalidateViewport(const gl::Context * context)1593 void StateManager11::invalidateViewport(const gl::Context *context)
1594 {
1595     mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
1596 
1597     // Viewport affects the driver constants.
1598     invalidateDriverUniforms();
1599 }
1600 
invalidateTexturesAndSamplers()1601 void StateManager11::invalidateTexturesAndSamplers()
1602 {
1603     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
1604     invalidateSwizzles();
1605 
1606     // Texture state affects the driver uniforms (base level, etc).
1607     invalidateDriverUniforms();
1608 }
1609 
invalidateSwizzles()1610 void StateManager11::invalidateSwizzles()
1611 {
1612     mDirtySwizzles = true;
1613 }
1614 
invalidateProgramUniforms()1615 void StateManager11::invalidateProgramUniforms()
1616 {
1617     mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
1618 }
1619 
invalidateDriverUniforms()1620 void StateManager11::invalidateDriverUniforms()
1621 {
1622     mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
1623 }
1624 
invalidateProgramUniformBuffers()1625 void StateManager11::invalidateProgramUniformBuffers()
1626 {
1627     mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
1628 }
1629 
invalidateProgramAtomicCounterBuffers()1630 void StateManager11::invalidateProgramAtomicCounterBuffers()
1631 {
1632     mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
1633 }
1634 
invalidateProgramShaderStorageBuffers()1635 void StateManager11::invalidateProgramShaderStorageBuffers()
1636 {
1637     mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
1638 }
1639 
invalidateConstantBuffer(unsigned int slot)1640 void StateManager11::invalidateConstantBuffer(unsigned int slot)
1641 {
1642     if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
1643     {
1644         invalidateDriverUniforms();
1645     }
1646     else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK)
1647     {
1648         invalidateProgramUniforms();
1649     }
1650     else
1651     {
1652         invalidateProgramUniformBuffers();
1653     }
1654 }
1655 
invalidateShaders()1656 void StateManager11::invalidateShaders()
1657 {
1658     mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
1659 }
1660 
invalidateTransformFeedback()1661 void StateManager11::invalidateTransformFeedback()
1662 {
1663     // Transform feedback affects the stream-out geometry shader.
1664     invalidateShaders();
1665     mInternalDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK);
1666     // syncPrimitiveTopology checks the transform feedback state.
1667     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
1668 }
1669 
invalidateInputLayout()1670 void StateManager11::invalidateInputLayout()
1671 {
1672     mInternalDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT);
1673 }
1674 
invalidateIndexBuffer()1675 void StateManager11::invalidateIndexBuffer()
1676 {
1677     mIndexBufferIsDirty = true;
1678 }
1679 
setRenderTarget(ID3D11RenderTargetView * rtv,ID3D11DepthStencilView * dsv)1680 void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv)
1681 {
1682     if (rtv)
1683     {
1684         unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtv, true);
1685     }
1686 
1687     if (dsv)
1688     {
1689         unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
1690     }
1691 
1692     mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
1693     mCurRTVs.clear();
1694     mCurRTVs.update(0, rtv);
1695     mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1696 }
1697 
setRenderTargets(ID3D11RenderTargetView ** rtvs,UINT numRTVs,ID3D11DepthStencilView * dsv)1698 void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs,
1699                                       UINT numRTVs,
1700                                       ID3D11DepthStencilView *dsv)
1701 {
1702     for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex)
1703     {
1704         unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtvs[rtvIndex], true);
1705     }
1706 
1707     if (dsv)
1708     {
1709         unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
1710     }
1711 
1712     mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv);
1713     mCurRTVs.clear();
1714     for (UINT i = 0; i < numRTVs; i++)
1715     {
1716         mCurRTVs.update(i, rtvs[i]);
1717     }
1718     mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1719 }
1720 
onBeginQuery(Query11 * query)1721 void StateManager11::onBeginQuery(Query11 *query)
1722 {
1723     mCurrentQueries.insert(query);
1724 }
1725 
onDeleteQueryObject(Query11 * query)1726 void StateManager11::onDeleteQueryObject(Query11 *query)
1727 {
1728     mCurrentQueries.erase(query);
1729 }
1730 
onMakeCurrent(const gl::Context * context)1731 angle::Result StateManager11::onMakeCurrent(const gl::Context *context)
1732 {
1733     ANGLE_TRY(ensureInitialized(context));
1734 
1735     const gl::State &state = context->getState();
1736 
1737     Context11 *context11 = GetImplAs<Context11>(context);
1738 
1739     for (Query11 *query : mCurrentQueries)
1740     {
1741         ANGLE_TRY(query->pause(context11));
1742     }
1743     mCurrentQueries.clear();
1744 
1745     for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
1746     {
1747         gl::Query *query = state.getActiveQuery(type);
1748         if (query != nullptr)
1749         {
1750             Query11 *query11 = GetImplAs<Query11>(query);
1751             ANGLE_TRY(query11->resume(context11));
1752             mCurrentQueries.insert(query11);
1753         }
1754     }
1755 
1756     // Reset the cache objects.
1757     mProgramD3D    = nullptr;
1758     mVertexArray11 = nullptr;
1759     mFramebuffer11 = nullptr;
1760 
1761     return angle::Result::Continue;
1762 }
1763 
unsetConflictingView(gl::PipelineType pipeline,ID3D11View * view,bool isRenderTarget)1764 void StateManager11::unsetConflictingView(gl::PipelineType pipeline,
1765                                           ID3D11View *view,
1766                                           bool isRenderTarget)
1767 {
1768     uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
1769 
1770     unsetConflictingSRVs(pipeline, gl::ShaderType::Vertex, resource, nullptr, isRenderTarget);
1771     unsetConflictingSRVs(pipeline, gl::ShaderType::Fragment, resource, nullptr, isRenderTarget);
1772     unsetConflictingSRVs(pipeline, gl::ShaderType::Compute, resource, nullptr, isRenderTarget);
1773     unsetConflictingUAVs(pipeline, gl::ShaderType::Compute, resource, nullptr);
1774 }
1775 
unsetConflictingSRVs(gl::PipelineType pipeline,gl::ShaderType shaderType,uintptr_t resource,const gl::ImageIndex * index,bool isRenderTarget)1776 void StateManager11::unsetConflictingSRVs(gl::PipelineType pipeline,
1777                                           gl::ShaderType shaderType,
1778                                           uintptr_t resource,
1779                                           const gl::ImageIndex *index,
1780                                           bool isRenderTarget)
1781 {
1782     auto *currentSRVs                 = getSRVCache(shaderType);
1783     gl::PipelineType conflictPipeline = gl::GetPipelineType(shaderType);
1784     bool foundOne                     = false;
1785     size_t count                      = std::min(currentSRVs->size(), currentSRVs->highestUsed());
1786     for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
1787     {
1788         auto &record = (*currentSRVs)[resourceIndex];
1789 
1790         if (record.view && record.resource == resource &&
1791             (!index || ImageIndexConflictsWithSRV(*index, record.desc)))
1792         {
1793             setShaderResourceInternal<d3d11::ShaderResourceView>(
1794                 shaderType, static_cast<UINT>(resourceIndex), nullptr);
1795             foundOne = true;
1796         }
1797     }
1798 
1799     if (foundOne && (pipeline != conflictPipeline || isRenderTarget))
1800     {
1801         switch (conflictPipeline)
1802         {
1803             case gl::PipelineType::GraphicsPipeline:
1804                 mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRVUAV_STATE);
1805                 break;
1806             case gl::PipelineType::ComputePipeline:
1807                 mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
1808                 break;
1809             default:
1810                 UNREACHABLE();
1811         }
1812     }
1813 }
1814 
unsetConflictingUAVs(gl::PipelineType pipeline,gl::ShaderType shaderType,uintptr_t resource,const gl::ImageIndex * index)1815 void StateManager11::unsetConflictingUAVs(gl::PipelineType pipeline,
1816                                           gl::ShaderType shaderType,
1817                                           uintptr_t resource,
1818                                           const gl::ImageIndex *index)
1819 {
1820     ASSERT(shaderType == gl::ShaderType::Compute);
1821     bool foundOne = false;
1822 
1823     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1824     size_t count = std::min(mCurComputeUAVs.size(), mCurComputeUAVs.highestUsed());
1825     for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
1826     {
1827         auto &record = mCurComputeUAVs[resourceIndex];
1828 
1829         if (record.view && record.resource == resource &&
1830             (!index || ImageIndexConflictsWithUAV(*index, record.desc)))
1831         {
1832             deviceContext->CSSetUnorderedAccessViews(static_cast<UINT>(resourceIndex), 1,
1833                                                      &mNullUAVs[0], nullptr);
1834             mCurComputeUAVs.update(resourceIndex, nullptr);
1835             foundOne = true;
1836         }
1837     }
1838 
1839     if (foundOne && pipeline == gl::PipelineType::GraphicsPipeline)
1840     {
1841         mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRVUAV_STATE);
1842     }
1843 }
1844 
unsetConflictingRTVs(uintptr_t resource)1845 void StateManager11::unsetConflictingRTVs(uintptr_t resource)
1846 {
1847     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1848     size_t count                       = std::min(mCurRTVs.size(), mCurRTVs.highestUsed());
1849     for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
1850     {
1851         auto &record = mCurRTVs[resourceIndex];
1852 
1853         if (record.view && record.resource == resource)
1854         {
1855             deviceContext->OMSetRenderTargets(0, nullptr, nullptr);
1856             mCurRTVs.clear();
1857             mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1858             return;
1859         }
1860     }
1861 }
1862 
unsetConflictingAttachmentResources(const gl::FramebufferAttachment & attachment,ID3D11Resource * resource)1863 void StateManager11::unsetConflictingAttachmentResources(
1864     const gl::FramebufferAttachment &attachment,
1865     ID3D11Resource *resource)
1866 {
1867     // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
1868     if (attachment.type() == GL_TEXTURE)
1869     {
1870         uintptr_t resourcePtr       = reinterpret_cast<uintptr_t>(resource);
1871         const gl::ImageIndex &index = attachment.getTextureImageIndex();
1872         // The index doesn't need to be corrected for the small compressed texture workaround
1873         // because a rendertarget is never compressed.
1874         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
1875                              resourcePtr, &index, false);
1876         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
1877                              resourcePtr, &index, false);
1878         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
1879                              resourcePtr, &index, false);
1880         unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
1881                              resourcePtr, &index);
1882     }
1883     else if (attachment.type() == GL_FRAMEBUFFER_DEFAULT)
1884     {
1885         uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
1886         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
1887                              resourcePtr, nullptr, false);
1888         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
1889                              resourcePtr, nullptr, false);
1890         unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
1891                              resourcePtr, nullptr, false);
1892         unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
1893                              resourcePtr, nullptr);
1894     }
1895 }
1896 
ensureInitialized(const gl::Context * context)1897 angle::Result StateManager11::ensureInitialized(const gl::Context *context)
1898 {
1899     Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
1900 
1901     const gl::Caps &caps             = renderer->getNativeCaps();
1902     const gl::Extensions &extensions = renderer->getNativeExtensions();
1903 
1904     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1905     {
1906         const GLuint maxShaderTextureImageUnits =
1907             static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType]);
1908 
1909         mCurShaderSRVs[shaderType].initialize(maxShaderTextureImageUnits);
1910         mForceSetShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits, true);
1911         mCurShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits);
1912     }
1913     mCurRTVs.initialize(caps.maxColorAttachments);
1914     mCurComputeUAVs.initialize(caps.maxImageUnits);
1915 
1916     // Initialize cached NULL SRV block
1917     mNullSRVs.resize(caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment], nullptr);
1918 
1919     mNullUAVs.resize(caps.maxImageUnits, nullptr);
1920 
1921     mCurrentValueAttribs.resize(caps.maxVertexAttributes);
1922 
1923     mShaderConstants.init(caps);
1924 
1925     mIsMultiviewEnabled = extensions.multiview || extensions.multiview2;
1926 
1927     mIndependentBlendStates = extensions.drawBuffersIndexedAny();  // requires FL10_1
1928 
1929     // FL9_3 is limited to 4; ES3.1 context on FL11_0 is limited to 7
1930     mCurBlendStateExt =
1931         gl::BlendStateExt(GetImplAs<Context11>(context)->getNativeCaps().maxDrawBuffers);
1932 
1933     ANGLE_TRY(mVertexDataManager.initialize(context));
1934 
1935     mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
1936 
1937     return angle::Result::Continue;
1938 }
1939 
deinitialize()1940 void StateManager11::deinitialize()
1941 {
1942     mCurrentValueAttribs.clear();
1943     mInputLayoutCache.clear();
1944     mVertexDataManager.deinitialize();
1945     mIndexDataManager.deinitialize();
1946 
1947     for (d3d11::Buffer &ShaderDriverConstantBuffer : mShaderDriverConstantBuffers)
1948     {
1949         ShaderDriverConstantBuffer.reset();
1950     }
1951 
1952     mPointSpriteVertexBuffer.reset();
1953     mPointSpriteIndexBuffer.reset();
1954 }
1955 
1956 // Applies the render target surface, depth stencil surface, viewport rectangle and
1957 // scissor rectangle to the renderer
syncFramebuffer(const gl::Context * context)1958 angle::Result StateManager11::syncFramebuffer(const gl::Context *context)
1959 {
1960     // Check for zero-sized default framebuffer, which is a special case.
1961     // in this case we do not wish to modify any state and just silently return false.
1962     // this will not report any gl error but will cause the calling method to return.
1963     if (mFramebuffer11->getState().isDefault())
1964     {
1965         RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
1966         const gl::Extents &size = firstRT->getExtents();
1967         if (size.empty())
1968         {
1969             return angle::Result::Continue;
1970         }
1971     }
1972 
1973     RTVArray framebufferRTVs = {{}};
1974     const auto &colorRTs     = mFramebuffer11->getCachedColorRenderTargets();
1975 
1976     size_t appliedRTIndex                   = 0;
1977     bool skipInactiveRTs                    = mRenderer->getFeatures().mrtPerfWorkaround.enabled;
1978     const auto &drawStates                  = mFramebuffer11->getState().getDrawBufferStates();
1979     gl::DrawBufferMask activeProgramOutputs = mProgramD3D->getState().getActiveOutputVariables();
1980     UINT maxExistingRT                      = 0;
1981     const auto &colorAttachments            = mFramebuffer11->getState().getColorAttachments();
1982 
1983     for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
1984     {
1985         const RenderTarget11 *renderTarget = colorRTs[rtIndex];
1986 
1987         // Skip inactive rendertargets if the workaround is enabled.
1988         if (skipInactiveRTs &&
1989             (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
1990         {
1991             continue;
1992         }
1993 
1994         if (renderTarget)
1995         {
1996             framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
1997             ASSERT(framebufferRTVs[appliedRTIndex]);
1998             maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
1999 
2000             // Unset conflicting texture SRVs
2001             const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
2002             ASSERT(attachment.isAttached());
2003             unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
2004         }
2005 
2006         appliedRTIndex++;
2007     }
2008 
2009     // Get the depth stencil buffers
2010     ID3D11DepthStencilView *framebufferDSV = nullptr;
2011     const auto *depthStencilRenderTarget   = mFramebuffer11->getCachedDepthStencilRenderTarget();
2012     if (depthStencilRenderTarget)
2013     {
2014         framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
2015         ASSERT(framebufferDSV);
2016 
2017         // Unset conflicting texture SRVs
2018         const gl::FramebufferAttachment *attachment =
2019             mFramebuffer11->getState().getDepthOrStencilAttachment();
2020         ASSERT(attachment);
2021         unsetConflictingAttachmentResources(*attachment,
2022                                             depthStencilRenderTarget->getTexture().get());
2023     }
2024 
2025     ASSERT(maxExistingRT <= static_cast<UINT>(context->getCaps().maxDrawBuffers));
2026 
2027     // Apply the render target and depth stencil
2028     mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
2029                                                       framebufferDSV);
2030     mCurRTVs.clear();
2031     for (UINT i = 0; i < maxExistingRT; i++)
2032     {
2033         mCurRTVs.update(i, framebufferRTVs[i]);
2034     }
2035     return angle::Result::Continue;
2036 }
2037 
invalidateCurrentValueAttrib(size_t attribIndex)2038 void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
2039 {
2040     mDirtyCurrentValueAttribs.set(attribIndex);
2041     mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
2042     invalidateInputLayout();
2043     invalidateShaders();
2044 }
2045 
syncCurrentValueAttribs(const gl::Context * context,const std::vector<gl::VertexAttribCurrentValueData> & currentValues)2046 angle::Result StateManager11::syncCurrentValueAttribs(
2047     const gl::Context *context,
2048     const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
2049 {
2050     const gl::ProgramExecutable &executable = mProgramD3D->getState().getExecutable();
2051     const auto &activeAttribsMask           = executable.getActiveAttribLocationsMask();
2052     const auto &dirtyActiveAttribs          = (activeAttribsMask & mDirtyCurrentValueAttribs);
2053 
2054     if (!dirtyActiveAttribs.any())
2055     {
2056         return angle::Result::Continue;
2057     }
2058 
2059     const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
2060     const auto &vertexBindings   = mVertexArray11->getState().getVertexBindings();
2061     mDirtyCurrentValueAttribs    = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
2062 
2063     for (auto attribIndex : dirtyActiveAttribs)
2064     {
2065         if (vertexAttributes[attribIndex].enabled)
2066             continue;
2067 
2068         const auto *attrib                      = &vertexAttributes[attribIndex];
2069         const auto &currentValue                = currentValues[attribIndex];
2070         TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
2071         currentValueAttrib->currentValueType    = currentValue.Type;
2072         currentValueAttrib->attribute           = attrib;
2073         currentValueAttrib->binding             = &vertexBindings[attrib->bindingIndex];
2074 
2075         mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
2076 
2077         ANGLE_TRY(mVertexDataManager.storeCurrentValue(context, currentValue, currentValueAttrib,
2078                                                        static_cast<size_t>(attribIndex)));
2079     }
2080 
2081     return angle::Result::Continue;
2082 }
2083 
setInputLayout(const d3d11::InputLayout * inputLayout)2084 void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
2085 {
2086     if (setInputLayoutInternal(inputLayout))
2087     {
2088         invalidateInputLayout();
2089     }
2090 }
2091 
setInputLayoutInternal(const d3d11::InputLayout * inputLayout)2092 bool StateManager11::setInputLayoutInternal(const d3d11::InputLayout *inputLayout)
2093 {
2094     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2095     if (inputLayout == nullptr)
2096     {
2097         if (!mCurrentInputLayout.empty())
2098         {
2099             deviceContext->IASetInputLayout(nullptr);
2100             mCurrentInputLayout.clear();
2101             return true;
2102         }
2103     }
2104     else if (inputLayout->getSerial() != mCurrentInputLayout)
2105     {
2106         deviceContext->IASetInputLayout(inputLayout->get());
2107         mCurrentInputLayout = inputLayout->getSerial();
2108         return true;
2109     }
2110 
2111     return false;
2112 }
2113 
queueVertexBufferChange(size_t bufferIndex,ID3D11Buffer * buffer,UINT stride,UINT offset)2114 bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
2115                                              ID3D11Buffer *buffer,
2116                                              UINT stride,
2117                                              UINT offset)
2118 {
2119     if (buffer != mCurrentVertexBuffers[bufferIndex] ||
2120         stride != mCurrentVertexStrides[bufferIndex] ||
2121         offset != mCurrentVertexOffsets[bufferIndex])
2122     {
2123         mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
2124 
2125         mCurrentVertexBuffers[bufferIndex] = buffer;
2126         mCurrentVertexStrides[bufferIndex] = stride;
2127         mCurrentVertexOffsets[bufferIndex] = offset;
2128         return true;
2129     }
2130 
2131     return false;
2132 }
2133 
applyVertexBufferChanges()2134 void StateManager11::applyVertexBufferChanges()
2135 {
2136     if (mDirtyVertexBufferRange.empty())
2137     {
2138         return;
2139     }
2140 
2141     ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
2142 
2143     UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
2144 
2145     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2146     deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
2147                                       &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
2148                                       &mCurrentVertexOffsets[start]);
2149 
2150     mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
2151 }
2152 
setSingleVertexBuffer(const d3d11::Buffer * buffer,UINT stride,UINT offset)2153 void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
2154 {
2155     ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
2156     if (queueVertexBufferChange(0, native, stride, offset))
2157     {
2158         invalidateInputLayout();
2159         applyVertexBufferChanges();
2160     }
2161 }
2162 
updateState(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLsizei instanceCount,GLint baseVertex)2163 angle::Result StateManager11::updateState(const gl::Context *context,
2164                                           gl::PrimitiveMode mode,
2165                                           GLint firstVertex,
2166                                           GLsizei vertexOrIndexCount,
2167                                           gl::DrawElementsType indexTypeOrInvalid,
2168                                           const void *indices,
2169                                           GLsizei instanceCount,
2170                                           GLint baseVertex)
2171 {
2172     const gl::State &glState = context->getState();
2173 
2174     // TODO(jmadill): Use dirty bits.
2175     if (mRenderTargetIsDirty)
2176     {
2177         processFramebufferInvalidation(context);
2178         mRenderTargetIsDirty = false;
2179     }
2180 
2181     // TODO(jmadill): Use dirty bits.
2182     if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
2183     {
2184         invalidateTexturesAndSamplers();
2185     }
2186 
2187     // TODO(jmadill): Use dirty bits.
2188     if (mProgramD3D->anyShaderUniformsDirty())
2189     {
2190         mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
2191     }
2192 
2193     // Swizzling can cause internal state changes with blit shaders.
2194     if (mDirtySwizzles)
2195     {
2196         ANGLE_TRY(generateSwizzles(context));
2197         mDirtySwizzles = false;
2198     }
2199 
2200     ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));
2201 
2202     // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
2203     // state changes.
2204     RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
2205     int samples             = (firstRT ? firstRT->getSamples() : 0);
2206     unsigned int sampleMask = GetBlendSampleMask(glState, samples);
2207     if (sampleMask != mCurSampleMask)
2208     {
2209         mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2210     }
2211 
2212     ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
2213                                                indexTypeOrInvalid, indices, instanceCount,
2214                                                baseVertex));
2215 
2216     // Changes in the draw call can affect the vertex buffer translations.
2217     if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
2218     {
2219         mLastFirstVertex = firstVertex;
2220         invalidateInputLayout();
2221     }
2222 
2223     // The ShaderConstants only need to be updated when the program uses vertexID
2224     if (mProgramD3D->usesVertexID())
2225     {
2226         if (mShaderConstants.onFirstVertexChange(firstVertex, baseVertex))
2227         {
2228             mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
2229         }
2230     }
2231 
2232     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
2233     {
2234         ANGLE_TRY(applyIndexBuffer(context, vertexOrIndexCount, indexTypeOrInvalid, indices));
2235     }
2236 
2237     if (mLastAppliedDrawMode != mode)
2238     {
2239         mLastAppliedDrawMode = mode;
2240         mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2241 
2242         bool pointDrawMode = (mode == gl::PrimitiveMode::Points);
2243         if (pointDrawMode != mCurRasterState.pointDrawMode)
2244         {
2245             mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2246 
2247             // Changing from points to not points (or vice-versa) affects the geometry shader.
2248             invalidateShaders();
2249         }
2250     }
2251 
2252     auto dirtyBitsCopy = mInternalDirtyBits & mGraphicsDirtyBitsMask;
2253     mInternalDirtyBits &= ~mGraphicsDirtyBitsMask;
2254 
2255     for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
2256     {
2257         switch (*iter)
2258         {
2259             case DIRTY_BIT_RENDER_TARGET:
2260                 ANGLE_TRY(syncFramebuffer(context));
2261                 break;
2262             case DIRTY_BIT_VIEWPORT_STATE:
2263                 syncViewport(context);
2264                 break;
2265             case DIRTY_BIT_SCISSOR_STATE:
2266                 syncScissorRectangle(context);
2267                 break;
2268             case DIRTY_BIT_RASTERIZER_STATE:
2269                 ANGLE_TRY(syncRasterizerState(context, mode));
2270                 break;
2271             case DIRTY_BIT_BLEND_STATE:
2272                 ANGLE_TRY(syncBlendState(
2273                     context, glState.getBlendStateExt(), glState.getBlendColor(), sampleMask,
2274                     glState.isSampleAlphaToCoverageEnabled(), glState.hasConstantAlphaBlendFunc()));
2275                 break;
2276             case DIRTY_BIT_DEPTH_STENCIL_STATE:
2277                 ANGLE_TRY(syncDepthStencilState(context));
2278                 break;
2279             case DIRTY_BIT_GRAPHICS_SRVUAV_STATE:
2280                 iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2281                 ANGLE_TRY(syncTextures(context));
2282                 break;
2283             case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
2284                 // TODO(jmadill): More fine-grained update.
2285                 ANGLE_TRY(syncTextures(context));
2286                 break;
2287             case DIRTY_BIT_PROGRAM_UNIFORMS:
2288                 ANGLE_TRY(applyUniforms(context));
2289                 break;
2290             case DIRTY_BIT_DRIVER_UNIFORMS:
2291                 // This must happen after viewport sync; the viewport affects builtin uniforms.
2292                 ANGLE_TRY(applyDriverUniforms(context));
2293                 break;
2294             case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
2295                 ANGLE_TRY(syncUniformBuffers(context));
2296                 break;
2297             case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
2298                 // TODO(jie.a.chen@intel.com): http://anglebug.com/1729
2299                 break;
2300             case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
2301                 // TODO(jie.a.chen@intel.com): http://anglebug.com/1951
2302                 break;
2303             case DIRTY_BIT_SHADERS:
2304                 ANGLE_TRY(syncProgram(context, mode));
2305                 break;
2306             case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
2307                 ANGLE_TRY(syncCurrentValueAttribs(context, glState.getVertexAttribCurrentValues()));
2308                 break;
2309             case DIRTY_BIT_TRANSFORM_FEEDBACK:
2310                 ANGLE_TRY(syncTransformFeedbackBuffers(context));
2311                 break;
2312             case DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT:
2313                 ANGLE_TRY(syncVertexBuffersAndInputLayout(context, mode, firstVertex,
2314                                                           vertexOrIndexCount, indexTypeOrInvalid,
2315                                                           instanceCount));
2316                 break;
2317             case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
2318                 syncPrimitiveTopology(glState, mode);
2319                 break;
2320             default:
2321                 UNREACHABLE();
2322                 break;
2323         }
2324     }
2325 
2326     // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except
2327     // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit.
2328     ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none());
2329 
2330     return angle::Result::Continue;
2331 }
2332 
setShaderResourceShared(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::SharedSRV * srv)2333 void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
2334                                              UINT resourceSlot,
2335                                              const d3d11::SharedSRV *srv)
2336 {
2337     setShaderResourceInternal(shaderType, resourceSlot, srv);
2338 
2339     // TODO(jmadill): Narrower dirty region.
2340     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2341 }
2342 
setShaderResource(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::ShaderResourceView * srv)2343 void StateManager11::setShaderResource(gl::ShaderType shaderType,
2344                                        UINT resourceSlot,
2345                                        const d3d11::ShaderResourceView *srv)
2346 {
2347     setShaderResourceInternal(shaderType, resourceSlot, srv);
2348 
2349     // TODO(jmadill): Narrower dirty region.
2350     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2351 }
2352 
setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2353 void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2354 {
2355     if (setPrimitiveTopologyInternal(primitiveTopology))
2356     {
2357         mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2358     }
2359 }
2360 
setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2361 bool StateManager11::setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2362 {
2363     if (primitiveTopology != mCurrentPrimitiveTopology)
2364     {
2365         mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
2366         mCurrentPrimitiveTopology = primitiveTopology;
2367         return true;
2368     }
2369     else
2370     {
2371         return false;
2372     }
2373 }
2374 
setDrawShaders(const d3d11::VertexShader * vertexShader,const d3d11::GeometryShader * geometryShader,const d3d11::PixelShader * pixelShader)2375 void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
2376                                     const d3d11::GeometryShader *geometryShader,
2377                                     const d3d11::PixelShader *pixelShader)
2378 {
2379     setVertexShader(vertexShader);
2380     setGeometryShader(geometryShader);
2381     setPixelShader(pixelShader);
2382 }
2383 
setVertexShader(const d3d11::VertexShader * shader)2384 void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
2385 {
2386     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2387 
2388     if (serial != mAppliedShaders[gl::ShaderType::Vertex])
2389     {
2390         ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
2391         mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
2392         mAppliedShaders[gl::ShaderType::Vertex] = serial;
2393         invalidateShaders();
2394     }
2395 }
2396 
setGeometryShader(const d3d11::GeometryShader * shader)2397 void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
2398 {
2399     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2400 
2401     if (serial != mAppliedShaders[gl::ShaderType::Geometry])
2402     {
2403         ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
2404         mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
2405         mAppliedShaders[gl::ShaderType::Geometry] = serial;
2406         invalidateShaders();
2407     }
2408 }
2409 
setPixelShader(const d3d11::PixelShader * shader)2410 void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
2411 {
2412     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2413 
2414     if (serial != mAppliedShaders[gl::ShaderType::Fragment])
2415     {
2416         ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
2417         mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
2418         mAppliedShaders[gl::ShaderType::Fragment] = serial;
2419         invalidateShaders();
2420     }
2421 }
2422 
setComputeShader(const d3d11::ComputeShader * shader)2423 void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
2424 {
2425     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2426 
2427     if (serial != mAppliedShaders[gl::ShaderType::Compute])
2428     {
2429         ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
2430         mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
2431         mAppliedShaders[gl::ShaderType::Compute] = serial;
2432         invalidateShaders();
2433     }
2434 }
2435 
setVertexConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2436 void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2437 {
2438     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2439     auto &currentSerial                = mCurrentConstantBufferVS[slot];
2440 
2441     mCurrentConstantBufferVSOffset[slot] = 0;
2442     mCurrentConstantBufferVSSize[slot]   = 0;
2443 
2444     if (buffer)
2445     {
2446         if (currentSerial != buffer->getSerial())
2447         {
2448             deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
2449             currentSerial = buffer->getSerial();
2450             invalidateConstantBuffer(slot);
2451         }
2452     }
2453     else
2454     {
2455         if (!currentSerial.empty())
2456         {
2457             ID3D11Buffer *nullBuffer = nullptr;
2458             deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
2459             currentSerial.clear();
2460             invalidateConstantBuffer(slot);
2461         }
2462     }
2463 }
2464 
setPixelConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2465 void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2466 {
2467     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2468     auto &currentSerial                = mCurrentConstantBufferPS[slot];
2469 
2470     mCurrentConstantBufferPSOffset[slot] = 0;
2471     mCurrentConstantBufferPSSize[slot]   = 0;
2472 
2473     if (buffer)
2474     {
2475         if (currentSerial != buffer->getSerial())
2476         {
2477             deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
2478             currentSerial = buffer->getSerial();
2479             invalidateConstantBuffer(slot);
2480         }
2481     }
2482     else
2483     {
2484         if (!currentSerial.empty())
2485         {
2486             ID3D11Buffer *nullBuffer = nullptr;
2487             deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
2488             currentSerial.clear();
2489             invalidateConstantBuffer(slot);
2490         }
2491     }
2492 }
2493 
setDepthStencilState(const d3d11::DepthStencilState * depthStencilState,UINT stencilRef)2494 void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
2495                                           UINT stencilRef)
2496 {
2497     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2498 
2499     if (depthStencilState)
2500     {
2501         deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
2502     }
2503     else
2504     {
2505         deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
2506     }
2507 
2508     mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
2509 }
2510 
setSimpleBlendState(const d3d11::BlendState * blendState)2511 void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
2512 {
2513     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2514 
2515     if (blendState)
2516     {
2517         deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
2518     }
2519     else
2520     {
2521         deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
2522     }
2523 
2524     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2525 }
2526 
setRasterizerState(const d3d11::RasterizerState * rasterizerState)2527 void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
2528 {
2529     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2530 
2531     if (rasterizerState)
2532     {
2533         deviceContext->RSSetState(rasterizerState->get());
2534     }
2535     else
2536     {
2537         deviceContext->RSSetState(nullptr);
2538     }
2539 
2540     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2541 }
2542 
setSimpleViewport(const gl::Extents & extents)2543 void StateManager11::setSimpleViewport(const gl::Extents &extents)
2544 {
2545     setSimpleViewport(extents.width, extents.height);
2546 }
2547 
setSimpleViewport(int width,int height)2548 void StateManager11::setSimpleViewport(int width, int height)
2549 {
2550     D3D11_VIEWPORT viewport;
2551     viewport.TopLeftX = 0;
2552     viewport.TopLeftY = 0;
2553     viewport.Width    = static_cast<FLOAT>(width);
2554     viewport.Height   = static_cast<FLOAT>(height);
2555     viewport.MinDepth = 0.0f;
2556     viewport.MaxDepth = 1.0f;
2557 
2558     mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
2559     mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
2560 }
2561 
setSimplePixelTextureAndSampler(const d3d11::SharedSRV & srv,const d3d11::SamplerState & samplerState)2562 void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
2563                                                      const d3d11::SamplerState &samplerState)
2564 {
2565     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2566 
2567     setShaderResourceInternal(gl::ShaderType::Fragment, 0, &srv);
2568     deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
2569 
2570     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2571     mForceSetShaderSamplerStates[gl::ShaderType::Fragment][0] = true;
2572 }
2573 
setSimpleScissorRect(const gl::Rectangle & glRect)2574 void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
2575 {
2576     D3D11_RECT scissorRect;
2577     scissorRect.left   = glRect.x;
2578     scissorRect.right  = glRect.x + glRect.width;
2579     scissorRect.top    = glRect.y;
2580     scissorRect.bottom = glRect.y + glRect.height;
2581     setScissorRectD3D(scissorRect);
2582 }
2583 
setScissorRectD3D(const D3D11_RECT & d3dRect)2584 void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
2585 {
2586     mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
2587     mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
2588 }
2589 
syncTextures(const gl::Context * context)2590 angle::Result StateManager11::syncTextures(const gl::Context *context)
2591 {
2592     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
2593     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
2594     if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
2595     {
2596         ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
2597     }
2598 
2599     return angle::Result::Continue;
2600 }
2601 
setSamplerState(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & samplerState)2602 angle::Result StateManager11::setSamplerState(const gl::Context *context,
2603                                               gl::ShaderType type,
2604                                               int index,
2605                                               gl::Texture *texture,
2606                                               const gl::SamplerState &samplerState)
2607 {
2608 #if !defined(NDEBUG)
2609     // Storage should exist, texture should be complete. Only verified in Debug.
2610     TextureD3D *textureD3D  = GetImplAs<TextureD3D>(texture);
2611     TextureStorage *storage = nullptr;
2612     ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
2613     ASSERT(storage);
2614 #endif  // !defined(NDEBUG)
2615 
2616     auto *deviceContext = mRenderer->getDeviceContext();
2617 
2618     ASSERT(index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[type]);
2619 
2620     if (mForceSetShaderSamplerStates[type][index] ||
2621         memcmp(&samplerState, &mCurShaderSamplerStates[type][index], sizeof(gl::SamplerState)) != 0)
2622     {
2623         ID3D11SamplerState *dxSamplerState = nullptr;
2624         ANGLE_TRY(mRenderer->getSamplerState(context, samplerState, &dxSamplerState));
2625 
2626         ASSERT(dxSamplerState != nullptr);
2627 
2628         switch (type)
2629         {
2630             case gl::ShaderType::Vertex:
2631                 deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
2632                 break;
2633             case gl::ShaderType::Fragment:
2634                 deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
2635                 break;
2636             case gl::ShaderType::Compute:
2637                 deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
2638                 break;
2639             case gl::ShaderType::Geometry:
2640                 deviceContext->GSSetSamplers(index, 1, &dxSamplerState);
2641                 break;
2642             default:
2643                 UNREACHABLE();
2644                 break;
2645         }
2646 
2647         mCurShaderSamplerStates[type][index] = samplerState;
2648     }
2649 
2650     mForceSetShaderSamplerStates[type][index] = false;
2651 
2652     // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
2653     // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
2654     // buffer, and it doesn't affect the state set by
2655     // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers.
2656     mShaderConstants.onSamplerChange(type, index, *texture, samplerState);
2657 
2658     return angle::Result::Continue;
2659 }
2660 
setTextureForSampler(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & sampler)2661 angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
2662                                                    gl::ShaderType type,
2663                                                    int index,
2664                                                    gl::Texture *texture,
2665                                                    const gl::SamplerState &sampler)
2666 {
2667     const d3d11::SharedSRV *textureSRV = nullptr;
2668 
2669     if (texture)
2670     {
2671         TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
2672 
2673         TextureStorage *texStorage = nullptr;
2674         ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2675 
2676         // Texture should be complete and have a storage
2677         ASSERT(texStorage);
2678 
2679         TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2680 
2681         ANGLE_TRY(
2682             storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));
2683 
2684         // If we get an invalid SRV here, something went wrong in the texture class and we're
2685         // unexpectedly missing the shader resource view.
2686         ASSERT(textureSRV->valid());
2687 
2688         textureImpl->resetDirty();
2689     }
2690 
2691     ASSERT(
2692         (type == gl::ShaderType::Fragment &&
2693          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
2694         (type == gl::ShaderType::Vertex &&
2695          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
2696         (type == gl::ShaderType::Compute &&
2697          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]));
2698 
2699     setShaderResourceInternal(type, index, textureSRV);
2700     return angle::Result::Continue;
2701 }
2702 
setImageState(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit)2703 angle::Result StateManager11::setImageState(const gl::Context *context,
2704                                             gl::ShaderType type,
2705                                             int index,
2706                                             const gl::ImageUnit &imageUnit)
2707 {
2708     ASSERT(index < mRenderer->getNativeCaps().maxShaderImageUniforms[type]);
2709 
2710     mShaderConstants.onImageChange(type, index, imageUnit);
2711 
2712     return angle::Result::Continue;
2713 }
2714 
2715 // For each Direct3D sampler of either the pixel or vertex stage,
2716 // looks up the corresponding OpenGL texture image unit and texture type,
2717 // and sets the texture and its addressing/filtering state (or NULL when inactive).
2718 // Sampler mapping needs to be up-to-date on the program object before this is called.
applyTexturesForSRVs(const gl::Context * context,gl::ShaderType shaderType)2719 angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
2720                                                    gl::ShaderType shaderType)
2721 {
2722     const auto &glState = context->getState();
2723     const auto &caps    = context->getCaps();
2724 
2725     ASSERT(!mProgramD3D->isSamplerMappingDirty());
2726 
2727     // TODO(jmadill): Use the Program's sampler bindings.
2728     const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
2729 
2730     const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
2731     for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
2732          samplerIndex++)
2733     {
2734         GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
2735         ASSERT(textureUnit != -1);
2736         gl::Texture *texture = completeTextures[textureUnit];
2737 
2738         // A nullptr texture indicates incomplete.
2739         if (texture)
2740         {
2741             gl::Sampler *samplerObject = glState.getSampler(textureUnit);
2742 
2743             const gl::SamplerState &samplerState =
2744                 samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
2745 
2746             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
2747             ANGLE_TRY(
2748                 setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
2749         }
2750         else
2751         {
2752             gl::TextureType textureType =
2753                 mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);
2754 
2755             // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
2756             // incomplete texture.
2757             gl::Texture *incompleteTexture = nullptr;
2758             ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
2759             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
2760                                       incompleteTexture->getSamplerState()));
2761             ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
2762                                            incompleteTexture->getSamplerState()));
2763         }
2764     }
2765 
2766     const gl::RangeUI readonlyImageRange = mProgramD3D->getUsedImageRange(shaderType, true);
2767     for (unsigned int readonlyImageIndex = readonlyImageRange.low();
2768          readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
2769     {
2770         GLint imageUnitIndex =
2771             mProgramD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
2772         ASSERT(imageUnitIndex != -1);
2773         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2774         if (!imageUnit.layered)
2775         {
2776             ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
2777                                     readonlyImageIndex - readonlyImageRange.low(), imageUnit));
2778             invalidateProgramUniforms();
2779         }
2780         ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, true, imageUnit));
2781     }
2782 
2783     return angle::Result::Continue;
2784 }
2785 
applyTexturesForUAVs(const gl::Context * context,gl::ShaderType shaderType)2786 angle::Result StateManager11::applyTexturesForUAVs(const gl::Context *context,
2787                                                    gl::ShaderType shaderType)
2788 {
2789     ASSERT(shaderType == gl::ShaderType::Compute);
2790     const auto &glState = context->getState();
2791     const auto &caps    = context->getCaps();
2792 
2793     const gl::RangeUI imageRange = mProgramD3D->getUsedImageRange(shaderType, false);
2794     for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
2795     {
2796         GLint imageUnitIndex = mProgramD3D->getImageMapping(shaderType, imageIndex, false, caps);
2797         ASSERT(imageUnitIndex != -1);
2798         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2799         if (!imageUnit.layered)
2800         {
2801             ANGLE_TRY(setImageState(context, gl::ShaderType::Compute, imageIndex - imageRange.low(),
2802                                     imageUnit));
2803             invalidateProgramUniforms();
2804         }
2805         ANGLE_TRY(setTextureForImage(context, shaderType, imageIndex, false, imageUnit));
2806     }
2807 
2808     return angle::Result::Continue;
2809 }
2810 
syncTexturesForCompute(const gl::Context * context)2811 angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
2812 {
2813     ANGLE_TRY(applyTexturesForUAVs(context, gl::ShaderType::Compute));
2814     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
2815     return angle::Result::Continue;
2816 }
2817 
setTextureForImage(const gl::Context * context,gl::ShaderType type,int index,bool readonly,const gl::ImageUnit & imageUnit)2818 angle::Result StateManager11::setTextureForImage(const gl::Context *context,
2819                                                  gl::ShaderType type,
2820                                                  int index,
2821                                                  bool readonly,
2822                                                  const gl::ImageUnit &imageUnit)
2823 {
2824     TextureD3D *textureImpl = nullptr;
2825     if (!imageUnit.texture.get())
2826     {
2827         // The texture is used in shader. However, there is no resource binding to it. We
2828         // should clear the corresponding UAV/SRV in case the previous view type is a buffer not a
2829         // texture. Otherwise, below error will be reported. The Unordered Access View dimension
2830         // declared in the shader code (TEXTURE2D) does not match the view type bound to slot 0
2831         // of the Compute Shader unit (BUFFER).
2832         if (readonly)
2833         {
2834             setShaderResourceInternal<d3d11::ShaderResourceView>(type, static_cast<UINT>(index),
2835                                                                  nullptr);
2836         }
2837         else
2838         {
2839             setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(
2840                 type, static_cast<UINT>(index), nullptr);
2841         }
2842         return angle::Result::Continue;
2843     }
2844 
2845     textureImpl                = GetImplAs<TextureD3D>(imageUnit.texture.get());
2846     TextureStorage *texStorage = nullptr;
2847     ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2848     // Texture should be complete and have a storage
2849     ASSERT(texStorage);
2850     TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2851 
2852     if (readonly)
2853     {
2854         const d3d11::SharedSRV *textureSRV = nullptr;
2855         ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
2856         // If we get an invalid SRV here, something went wrong in the texture class and we're
2857         // unexpectedly missing the shader resource view.
2858         ASSERT(textureSRV->valid());
2859         ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2860         setShaderResourceInternal(type, index, textureSRV);
2861     }
2862     else
2863     {
2864         const d3d11::SharedUAV *textureUAV = nullptr;
2865         ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
2866         // If we get an invalid UAV here, something went wrong in the texture class and we're
2867         // unexpectedly missing the unordered access view.
2868         ASSERT(textureUAV->valid());
2869         ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2870         setUnorderedAccessViewInternal(type, index, textureUAV);
2871     }
2872 
2873     textureImpl->resetDirty();
2874     return angle::Result::Continue;
2875 }
2876 
2877 // Things that affect a program's dirtyness:
2878 // 1. Directly changing the program executable -> triggered in StateManager11::syncState.
2879 // 2. The vertex attribute layout              -> triggered in VertexArray11::syncState/signal.
2880 // 3. The fragment shader's rendertargets      -> triggered in Framebuffer11::syncState/signal.
2881 // 4. Enabling/disabling rasterizer discard.   -> triggered in StateManager11::syncState.
2882 // 5. Enabling/disabling transform feedback.   -> checked in StateManager11::updateState.
2883 // 6. An internal shader was used.             -> triggered in StateManager11::set*Shader.
2884 // 7. Drawing with/without point sprites.      -> checked in StateManager11::updateState.
2885 // TODO(jmadill): Use dirty bits for transform feedback.
syncProgram(const gl::Context * context,gl::PrimitiveMode drawMode)2886 angle::Result StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode)
2887 {
2888     Context11 *context11 = GetImplAs<Context11>(context);
2889     ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
2890 
2891     const auto &glState = context->getState();
2892 
2893     mProgramD3D->updateCachedInputLayout(mVertexArray11->getCurrentStateSerial(), glState);
2894 
2895     // Binaries must be compiled before the sync.
2896     ASSERT(mProgramD3D->hasVertexExecutableForCachedInputLayout());
2897     ASSERT(mProgramD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode));
2898     ASSERT(mProgramD3D->hasPixelExecutableForCachedOutputLayout());
2899 
2900     ShaderExecutableD3D *vertexExe = nullptr;
2901     ANGLE_TRY(mProgramD3D->getVertexExecutableForCachedInputLayout(context11, &vertexExe, nullptr));
2902 
2903     ShaderExecutableD3D *pixelExe = nullptr;
2904     ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
2905 
2906     ShaderExecutableD3D *geometryExe = nullptr;
2907     ANGLE_TRY(mProgramD3D->getGeometryExecutableForPrimitiveType(context11, glState, drawMode,
2908                                                                  &geometryExe, nullptr));
2909 
2910     const d3d11::VertexShader *vertexShader =
2911         (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
2912 
2913     // Skip pixel shader if we're doing rasterizer discard.
2914     const d3d11::PixelShader *pixelShader = nullptr;
2915     if (!glState.getRasterizerState().rasterizerDiscard)
2916     {
2917         pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
2918     }
2919 
2920     const d3d11::GeometryShader *geometryShader = nullptr;
2921     if (glState.isTransformFeedbackActiveUnpaused())
2922     {
2923         geometryShader =
2924             (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
2925     }
2926     else
2927     {
2928         geometryShader =
2929             (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
2930     }
2931 
2932     setDrawShaders(vertexShader, geometryShader, pixelShader);
2933 
2934     // Explicitly clear the shaders dirty bit.
2935     mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
2936 
2937     return angle::Result::Continue;
2938 }
2939 
syncProgramForCompute(const gl::Context * context)2940 angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
2941 {
2942     Context11 *context11 = GetImplAs<Context11>(context);
2943     ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));
2944 
2945     mProgramD3D->updateCachedComputeImage2DBindLayout(context);
2946 
2947     // Binaries must be compiled before the sync.
2948     ASSERT(mProgramD3D->hasComputeExecutableForCachedImage2DBindLayout());
2949 
2950     ShaderExecutableD3D *computeExe = nullptr;
2951     ANGLE_TRY(
2952         mProgramD3D->getComputeExecutableForImage2DBindLayout(context11, &computeExe, nullptr));
2953 
2954     const d3d11::ComputeShader *computeShader =
2955         (computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
2956     setComputeShader(computeShader);
2957     // Explicitly clear the shaders dirty bit.
2958     mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
2959 
2960     return angle::Result::Continue;
2961 }
2962 
syncVertexBuffersAndInputLayout(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,GLsizei instanceCount)2963 angle::Result StateManager11::syncVertexBuffersAndInputLayout(
2964     const gl::Context *context,
2965     gl::PrimitiveMode mode,
2966     GLint firstVertex,
2967     GLsizei vertexOrIndexCount,
2968     gl::DrawElementsType indexTypeOrInvalid,
2969     GLsizei instanceCount)
2970 {
2971     const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();
2972 
2973     // Sort the attributes according to ensure we re-use similar input layouts.
2974     AttribIndexArray sortedSemanticIndices;
2975     SortAttributesByLayout(*mProgramD3D, vertexArrayAttribs, mCurrentValueAttribs,
2976                            &sortedSemanticIndices, &mCurrentAttributes);
2977 
2978     D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
2979 
2980     // If we are using FL 9_3, make sure the first attribute is not instanced
2981     if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
2982     {
2983         if (mCurrentAttributes[0]->divisor > 0)
2984         {
2985             Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
2986             if (firstNonInstancedIndex.valid())
2987             {
2988                 size_t index = firstNonInstancedIndex.value();
2989                 std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
2990                 std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
2991             }
2992         }
2993     }
2994 
2995     // Update the applied input layout by querying the cache.
2996     const gl::State &state                = context->getState();
2997     const d3d11::InputLayout *inputLayout = nullptr;
2998     ANGLE_TRY(mInputLayoutCache.getInputLayout(GetImplAs<Context11>(context), state,
2999                                                mCurrentAttributes, sortedSemanticIndices, mode,
3000                                                vertexOrIndexCount, instanceCount, &inputLayout));
3001     setInputLayoutInternal(inputLayout);
3002 
3003     // Update the applied vertex buffers.
3004     ANGLE_TRY(applyVertexBuffers(context, mode, indexTypeOrInvalid, firstVertex));
3005 
3006     return angle::Result::Continue;
3007 }
3008 
applyVertexBuffers(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexTypeOrInvalid,GLint firstVertex)3009 angle::Result StateManager11::applyVertexBuffers(const gl::Context *context,
3010                                                  gl::PrimitiveMode mode,
3011                                                  gl::DrawElementsType indexTypeOrInvalid,
3012                                                  GLint firstVertex)
3013 {
3014     bool programUsesInstancedPointSprites =
3015         mProgramD3D->usesPointSize() && mProgramD3D->usesInstancedPointSpriteEmulation();
3016     bool instancedPointSpritesActive =
3017         programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);
3018 
3019     // Note that if we use instance emulation, we reserve the first buffer slot.
3020     size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
3021 
3022     for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
3023          ++attribIndex)
3024     {
3025         ID3D11Buffer *buffer = nullptr;
3026         UINT vertexStride    = 0;
3027         UINT vertexOffset    = 0;
3028 
3029         if (attribIndex < mCurrentAttributes.size())
3030         {
3031             const TranslatedAttribute &attrib = *mCurrentAttributes[attribIndex];
3032             Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
3033 
3034             // If indexed pointsprite emulation is active, then we need to take a less efficent code
3035             // path. Emulated indexed pointsprite rendering requires that the vertex buffers match
3036             // exactly to the indices passed by the caller.  This could expand or shrink the vertex
3037             // buffer depending on the number of points indicated by the index list or how many
3038             // duplicates are found on the index list.
3039             if (bufferStorage == nullptr)
3040             {
3041                 ASSERT(attrib.vertexBuffer.get());
3042                 buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
3043             }
3044             else if (instancedPointSpritesActive &&
3045                      indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
3046             {
3047                 ASSERT(mVertexArray11->isCachedIndexInfoValid());
3048                 TranslatedIndexData indexInfo = mVertexArray11->getCachedIndexInfo();
3049                 if (indexInfo.srcIndexData.srcBuffer != nullptr)
3050                 {
3051                     const uint8_t *bufferData = nullptr;
3052                     ANGLE_TRY(indexInfo.srcIndexData.srcBuffer->getData(context, &bufferData));
3053                     ASSERT(bufferData != nullptr);
3054 
3055                     ptrdiff_t offset =
3056                         reinterpret_cast<ptrdiff_t>(indexInfo.srcIndexData.srcIndices);
3057                     indexInfo.srcIndexData.srcBuffer  = nullptr;
3058                     indexInfo.srcIndexData.srcIndices = bufferData + offset;
3059                 }
3060 
3061                 ANGLE_TRY(bufferStorage->getEmulatedIndexedBuffer(context, &indexInfo.srcIndexData,
3062                                                                   attrib, firstVertex, &buffer));
3063 
3064                 mVertexArray11->updateCachedIndexInfo(indexInfo);
3065             }
3066             else
3067             {
3068                 ANGLE_TRY(bufferStorage->getBuffer(
3069                     context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer));
3070             }
3071 
3072             vertexStride = attrib.stride;
3073             ANGLE_TRY(attrib.computeOffset(context, firstVertex, &vertexOffset));
3074         }
3075 
3076         size_t bufferIndex = reservedBuffers + attribIndex;
3077 
3078         queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
3079     }
3080 
3081     Context11 *context11 = GetImplAs<Context11>(context);
3082 
3083     // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
3084     // to be created and added to the list of current buffers, strides and offsets collections.
3085     // This buffer contains the vertices for a single PointSprite quad.
3086     // An index buffer also needs to be created and applied because rendering instanced data on
3087     // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and
3088     // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot
3089     // handle missing vertex data and will TDR the system.
3090     if (programUsesInstancedPointSprites)
3091     {
3092         constexpr UINT kPointSpriteVertexStride = sizeof(float) * 5;
3093 
3094         if (!mPointSpriteVertexBuffer.valid())
3095         {
3096             static constexpr float kPointSpriteVertices[] = {
3097                 // Position        | TexCoord
3098                 -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v0 */
3099                 -1.0f, 1.0f,  0.0f, 0.0f, 0.0f, /* v1 */
3100                 1.0f,  1.0f,  0.0f, 1.0f, 0.0f, /* v2 */
3101                 1.0f,  -1.0f, 0.0f, 1.0f, 1.0f, /* v3 */
3102                 -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v4 */
3103                 1.0f,  1.0f,  0.0f, 1.0f, 0.0f, /* v5 */
3104             };
3105 
3106             D3D11_SUBRESOURCE_DATA vertexBufferData = {kPointSpriteVertices, 0, 0};
3107             D3D11_BUFFER_DESC vertexBufferDesc;
3108             vertexBufferDesc.ByteWidth           = sizeof(kPointSpriteVertices);
3109             vertexBufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
3110             vertexBufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
3111             vertexBufferDesc.CPUAccessFlags      = 0;
3112             vertexBufferDesc.MiscFlags           = 0;
3113             vertexBufferDesc.StructureByteStride = 0;
3114 
3115             ANGLE_TRY(mRenderer->allocateResource(context11, vertexBufferDesc, &vertexBufferData,
3116                                                   &mPointSpriteVertexBuffer));
3117         }
3118 
3119         // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
3120         // indexing into the vertex buffer.
3121         UINT stride = instancedPointSpritesActive ? kPointSpriteVertexStride : 0;
3122         queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);
3123 
3124         if (!mPointSpriteIndexBuffer.valid())
3125         {
3126             // Create an index buffer and set it for pointsprite rendering
3127             static constexpr unsigned short kPointSpriteIndices[] = {
3128                 0, 1, 2, 3, 4, 5,
3129             };
3130 
3131             D3D11_SUBRESOURCE_DATA indexBufferData = {kPointSpriteIndices, 0, 0};
3132             D3D11_BUFFER_DESC indexBufferDesc;
3133             indexBufferDesc.ByteWidth           = sizeof(kPointSpriteIndices);
3134             indexBufferDesc.BindFlags           = D3D11_BIND_INDEX_BUFFER;
3135             indexBufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
3136             indexBufferDesc.CPUAccessFlags      = 0;
3137             indexBufferDesc.MiscFlags           = 0;
3138             indexBufferDesc.StructureByteStride = 0;
3139 
3140             ANGLE_TRY(mRenderer->allocateResource(context11, indexBufferDesc, &indexBufferData,
3141                                                   &mPointSpriteIndexBuffer));
3142         }
3143 
3144         if (instancedPointSpritesActive)
3145         {
3146             // The index buffer is applied here because Instanced PointSprite emulation uses the a
3147             // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
3148             // on the renderer will not be called and setting this buffer here ensures that the
3149             // rendering path will contain the correct index buffers.
3150             syncIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
3151         }
3152     }
3153 
3154     applyVertexBufferChanges();
3155     return angle::Result::Continue;
3156 }
3157 
applyIndexBuffer(const gl::Context * context,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices)3158 angle::Result StateManager11::applyIndexBuffer(const gl::Context *context,
3159                                                GLsizei indexCount,
3160                                                gl::DrawElementsType indexType,
3161                                                const void *indices)
3162 {
3163     if (!mIndexBufferIsDirty)
3164     {
3165         // No streaming or index buffer application necessary.
3166         return angle::Result::Continue;
3167     }
3168 
3169     gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType();
3170     gl::Buffer *elementArrayBuffer       = mVertexArray11->getState().getElementArrayBuffer();
3171 
3172     TranslatedIndexData indexInfo;
3173     ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount,
3174                                                  elementArrayBuffer, indices, &indexInfo));
3175 
3176     ID3D11Buffer *buffer     = nullptr;
3177     DXGI_FORMAT bufferFormat = (indexInfo.indexType == gl::DrawElementsType::UnsignedInt)
3178                                    ? DXGI_FORMAT_R32_UINT
3179                                    : DXGI_FORMAT_R16_UINT;
3180 
3181     if (indexInfo.storage)
3182     {
3183         Buffer11 *storage = GetAs<Buffer11>(indexInfo.storage);
3184         ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer));
3185     }
3186     else
3187     {
3188         IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo.indexBuffer);
3189         buffer                     = indexBuffer->getBuffer().get();
3190     }
3191 
3192     // Track dirty indices in the index range cache.
3193     indexInfo.srcIndexData.srcIndicesChanged =
3194         syncIndexBuffer(buffer, bufferFormat, indexInfo.startOffset);
3195 
3196     mIndexBufferIsDirty = false;
3197 
3198     mVertexArray11->updateCachedIndexInfo(indexInfo);
3199     return angle::Result::Continue;
3200 }
3201 
setIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3202 void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
3203                                     DXGI_FORMAT indexFormat,
3204                                     unsigned int offset)
3205 {
3206     if (syncIndexBuffer(buffer, indexFormat, offset))
3207     {
3208         invalidateIndexBuffer();
3209     }
3210 }
3211 
syncIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3212 bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
3213                                      DXGI_FORMAT indexFormat,
3214                                      unsigned int offset)
3215 {
3216     if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
3217     {
3218         mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
3219 
3220         mAppliedIB       = buffer;
3221         mAppliedIBFormat = indexFormat;
3222         mAppliedIBOffset = offset;
3223         return true;
3224     }
3225 
3226     return false;
3227 }
3228 
3229 // Vertex buffer is invalidated outside this function.
updateVertexOffsetsForPointSpritesEmulation(const gl::Context * context,GLint startVertex,GLsizei emulatedInstanceId)3230 angle::Result StateManager11::updateVertexOffsetsForPointSpritesEmulation(
3231     const gl::Context *context,
3232     GLint startVertex,
3233     GLsizei emulatedInstanceId)
3234 {
3235     size_t reservedBuffers = GetReservedBufferCount(true);
3236     for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
3237     {
3238         const auto &attrib = *mCurrentAttributes[attribIndex];
3239         size_t bufferIndex = reservedBuffers + attribIndex;
3240 
3241         if (attrib.divisor > 0)
3242         {
3243             unsigned int offset = 0;
3244             ANGLE_TRY(attrib.computeOffset(context, startVertex, &offset));
3245             offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
3246             if (offset != mCurrentVertexOffsets[bufferIndex])
3247             {
3248                 invalidateInputLayout();
3249                 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
3250                 mCurrentVertexOffsets[bufferIndex] = offset;
3251             }
3252         }
3253     }
3254 
3255     applyVertexBufferChanges();
3256     return angle::Result::Continue;
3257 }
3258 
generateSwizzle(const gl::Context * context,gl::Texture * texture)3259 angle::Result StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
3260 {
3261     if (!texture)
3262     {
3263         return angle::Result::Continue;
3264     }
3265 
3266     TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
3267     ASSERT(textureD3D);
3268 
3269     TextureStorage *texStorage = nullptr;
3270     ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
3271 
3272     if (texStorage)
3273     {
3274         TextureStorage11 *storage11          = GetAs<TextureStorage11>(texStorage);
3275         const gl::TextureState &textureState = texture->getTextureState();
3276         ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState()));
3277     }
3278 
3279     return angle::Result::Continue;
3280 }
3281 
generateSwizzlesForShader(const gl::Context * context,gl::ShaderType type)3282 angle::Result StateManager11::generateSwizzlesForShader(const gl::Context *context,
3283                                                         gl::ShaderType type)
3284 {
3285     const gl::State &glState       = context->getState();
3286     const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(type);
3287 
3288     for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
3289     {
3290         gl::TextureType textureType = mProgramD3D->getSamplerTextureType(type, i);
3291         GLint textureUnit           = mProgramD3D->getSamplerMapping(type, i, context->getCaps());
3292         if (textureUnit != -1)
3293         {
3294             gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
3295             ASSERT(texture);
3296             if (texture->getTextureState().swizzleRequired())
3297             {
3298                 ANGLE_TRY(generateSwizzle(context, texture));
3299             }
3300         }
3301     }
3302 
3303     return angle::Result::Continue;
3304 }
3305 
generateSwizzles(const gl::Context * context)3306 angle::Result StateManager11::generateSwizzles(const gl::Context *context)
3307 {
3308     ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Vertex));
3309     ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Fragment));
3310     return angle::Result::Continue;
3311 }
3312 
applyUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3313 angle::Result StateManager11::applyUniformsForShader(const gl::Context *context,
3314                                                      gl::ShaderType shaderType)
3315 {
3316     UniformStorage11 *shaderUniformStorage =
3317         GetAs<UniformStorage11>(mProgramD3D->getShaderUniformStorage(shaderType));
3318     ASSERT(shaderUniformStorage);
3319 
3320     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3321 
3322     const d3d11::Buffer *shaderConstantBuffer = nullptr;
3323     ANGLE_TRY(shaderUniformStorage->getConstantBuffer(context, mRenderer, &shaderConstantBuffer));
3324 
3325     if (shaderUniformStorage->size() > 0 && mProgramD3D->areShaderUniformsDirty(shaderType))
3326     {
3327         UpdateUniformBuffer(deviceContext, shaderUniformStorage, shaderConstantBuffer);
3328     }
3329 
3330     unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
3331 
3332     switch (shaderType)
3333     {
3334         case gl::ShaderType::Vertex:
3335             if (mCurrentConstantBufferVS[slot] != shaderConstantBuffer->getSerial())
3336             {
3337                 deviceContext->VSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3338                 mCurrentConstantBufferVS[slot]       = shaderConstantBuffer->getSerial();
3339                 mCurrentConstantBufferVSOffset[slot] = 0;
3340                 mCurrentConstantBufferVSSize[slot]   = 0;
3341             }
3342             break;
3343 
3344         case gl::ShaderType::Fragment:
3345             if (mCurrentConstantBufferPS[slot] != shaderConstantBuffer->getSerial())
3346             {
3347                 deviceContext->PSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3348                 mCurrentConstantBufferPS[slot]       = shaderConstantBuffer->getSerial();
3349                 mCurrentConstantBufferPSOffset[slot] = 0;
3350                 mCurrentConstantBufferPSSize[slot]   = 0;
3351             }
3352             break;
3353 
3354         // TODO(jiawei.shao@intel.com): apply geometry shader uniforms
3355         case gl::ShaderType::Geometry:
3356             UNIMPLEMENTED();
3357             break;
3358 
3359         default:
3360             UNREACHABLE();
3361             break;
3362     }
3363 
3364     return angle::Result::Continue;
3365 }
3366 
applyUniforms(const gl::Context * context)3367 angle::Result StateManager11::applyUniforms(const gl::Context *context)
3368 {
3369     ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Vertex));
3370     ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Fragment));
3371     if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
3372     {
3373         ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Geometry));
3374     }
3375 
3376     mProgramD3D->markUniformsClean();
3377 
3378     return angle::Result::Continue;
3379 }
3380 
applyDriverUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3381 angle::Result StateManager11::applyDriverUniformsForShader(const gl::Context *context,
3382                                                            gl::ShaderType shaderType)
3383 {
3384     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3385 
3386     d3d11::Buffer &shaderDriverConstantBuffer = mShaderDriverConstantBuffers[shaderType];
3387     if (!shaderDriverConstantBuffer.valid())
3388     {
3389         size_t requiredSize = mShaderConstants.getRequiredBufferSize(shaderType);
3390 
3391         D3D11_BUFFER_DESC constantBufferDescription = {};
3392         d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3393         ANGLE_TRY(mRenderer->allocateResource(
3394             GetImplAs<Context11>(context), constantBufferDescription, &shaderDriverConstantBuffer));
3395 
3396         ID3D11Buffer *driverConstants = shaderDriverConstantBuffer.get();
3397         switch (shaderType)
3398         {
3399             case gl::ShaderType::Vertex:
3400                 deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3401                                                     &driverConstants);
3402                 break;
3403 
3404             case gl::ShaderType::Fragment:
3405                 deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3406                                                     &driverConstants);
3407                 break;
3408 
3409             case gl::ShaderType::Geometry:
3410                 deviceContext->GSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3411                                                     &driverConstants);
3412                 break;
3413 
3414             default:
3415                 UNREACHABLE();
3416                 return angle::Result::Continue;
3417         }
3418     }
3419 
3420     // Sampler metadata and driver constants need to coexist in the same constant buffer to
3421     // conserve constant buffer slots. We update both in the constant buffer if needed.
3422     ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, shaderType, *mProgramD3D,
3423                                             shaderDriverConstantBuffer));
3424 
3425     return angle::Result::Continue;
3426 }
3427 
applyDriverUniforms(const gl::Context * context)3428 angle::Result StateManager11::applyDriverUniforms(const gl::Context *context)
3429 {
3430     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3431 
3432     ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Vertex));
3433     ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Fragment));
3434     if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
3435     {
3436         ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Geometry));
3437     }
3438 
3439     // needed for the point sprite geometry shader
3440     // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
3441     if (mRenderer->isES3Capable())
3442     {
3443         d3d11::Buffer &driverConstantBufferPS =
3444             mShaderDriverConstantBuffers[gl::ShaderType::Fragment];
3445         if (mCurrentGeometryConstantBuffer != driverConstantBufferPS.getSerial())
3446         {
3447             ASSERT(driverConstantBufferPS.valid());
3448             deviceContext->GSSetConstantBuffers(0, 1, driverConstantBufferPS.getPointer());
3449             mCurrentGeometryConstantBuffer = driverConstantBufferPS.getSerial();
3450         }
3451     }
3452 
3453     return angle::Result::Continue;
3454 }
3455 
applyComputeUniforms(const gl::Context * context,ProgramD3D * programD3D)3456 angle::Result StateManager11::applyComputeUniforms(const gl::Context *context,
3457                                                    ProgramD3D *programD3D)
3458 {
3459     UniformStorage11 *computeUniformStorage =
3460         GetAs<UniformStorage11>(programD3D->getShaderUniformStorage(gl::ShaderType::Compute));
3461     ASSERT(computeUniformStorage);
3462 
3463     const d3d11::Buffer *constantBuffer = nullptr;
3464     ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer));
3465 
3466     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3467 
3468     if (computeUniformStorage->size() > 0 &&
3469         programD3D->areShaderUniformsDirty(gl::ShaderType::Compute))
3470     {
3471         UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
3472         programD3D->markUniformsClean();
3473     }
3474 
3475     if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
3476     {
3477         deviceContext->CSSetConstantBuffers(
3478             d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
3479             constantBuffer->getPointer());
3480         mCurrentComputeConstantBuffer = constantBuffer->getSerial();
3481     }
3482 
3483     if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid())
3484     {
3485         size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute);
3486 
3487         D3D11_BUFFER_DESC constantBufferDescription = {};
3488         d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3489         ANGLE_TRY(
3490             mRenderer->allocateResource(GetImplAs<Context11>(context), constantBufferDescription,
3491                                         &mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3492         ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get();
3493         deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3494                                             &buffer);
3495     }
3496 
3497     ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute,
3498                                             *programD3D,
3499                                             mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3500 
3501     return angle::Result::Continue;
3502 }
3503 
syncUniformBuffersForShader(const gl::Context * context,gl::ShaderType shaderType)3504 angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context,
3505                                                           gl::ShaderType shaderType)
3506 {
3507     const auto &glState                  = context->getState();
3508     ID3D11DeviceContext *deviceContext   = mRenderer->getDeviceContext();
3509     ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
3510 
3511     const auto &shaderUniformBuffers = mProgramD3D->getShaderUniformBufferCache(shaderType);
3512 
3513     for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffers.size(); ++bufferIndex)
3514     {
3515         const D3DUBOCache cache = shaderUniformBuffers[bufferIndex];
3516         if (cache.binding == -1)
3517         {
3518             continue;
3519         }
3520 
3521         const auto &uniformBuffer          = glState.getIndexedUniformBuffer(cache.binding);
3522         const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3523         const GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
3524 
3525         if (uniformBuffer.get() == nullptr)
3526         {
3527             continue;
3528         }
3529 
3530         Buffer11 *bufferStorage             = GetImplAs<Buffer11>(uniformBuffer.get());
3531         const d3d11::Buffer *constantBuffer = nullptr;
3532         UINT firstConstant                  = 0;
3533         UINT numConstants                   = 0;
3534 
3535         ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
3536                                                         uniformBufferSize, &constantBuffer,
3537                                                         &firstConstant, &numConstants));
3538         ASSERT(constantBuffer);
3539 
3540         switch (shaderType)
3541         {
3542             case gl::ShaderType::Vertex:
3543             {
3544                 if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() &&
3545                     mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset &&
3546                     mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize)
3547                 {
3548                     continue;
3549                 }
3550 
3551                 if (firstConstant != 0 && uniformBufferSize != 0)
3552                 {
3553                     ASSERT(numConstants != 0);
3554                     deviceContext1->VSSetConstantBuffers1(cache.registerIndex, 1,
3555                                                           constantBuffer->getPointer(),
3556                                                           &firstConstant, &numConstants);
3557                 }
3558                 else
3559                 {
3560                     deviceContext->VSSetConstantBuffers(cache.registerIndex, 1,
3561                                                         constantBuffer->getPointer());
3562                 }
3563 
3564                 mCurrentConstantBufferVS[cache.registerIndex]       = constantBuffer->getSerial();
3565                 mCurrentConstantBufferVSOffset[cache.registerIndex] = uniformBufferOffset;
3566                 mCurrentConstantBufferVSSize[cache.registerIndex]   = uniformBufferSize;
3567                 break;
3568             }
3569 
3570             case gl::ShaderType::Fragment:
3571             {
3572                 if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() &&
3573                     mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset &&
3574                     mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize)
3575                 {
3576                     continue;
3577                 }
3578 
3579                 if (firstConstant != 0 && uniformBufferSize != 0)
3580                 {
3581                     deviceContext1->PSSetConstantBuffers1(cache.registerIndex, 1,
3582                                                           constantBuffer->getPointer(),
3583                                                           &firstConstant, &numConstants);
3584                 }
3585                 else
3586                 {
3587                     deviceContext->PSSetConstantBuffers(cache.registerIndex, 1,
3588                                                         constantBuffer->getPointer());
3589                 }
3590 
3591                 mCurrentConstantBufferPS[cache.registerIndex]       = constantBuffer->getSerial();
3592                 mCurrentConstantBufferPSOffset[cache.registerIndex] = uniformBufferOffset;
3593                 mCurrentConstantBufferPSSize[cache.registerIndex]   = uniformBufferSize;
3594                 break;
3595             }
3596 
3597             case gl::ShaderType::Compute:
3598             {
3599                 if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() &&
3600                     mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset &&
3601                     mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize)
3602                 {
3603                     continue;
3604                 }
3605 
3606                 if (firstConstant != 0 && uniformBufferSize != 0)
3607                 {
3608                     deviceContext1->CSSetConstantBuffers1(cache.registerIndex, 1,
3609                                                           constantBuffer->getPointer(),
3610                                                           &firstConstant, &numConstants);
3611                 }
3612                 else
3613                 {
3614                     deviceContext->CSSetConstantBuffers(cache.registerIndex, 1,
3615                                                         constantBuffer->getPointer());
3616                 }
3617 
3618                 mCurrentConstantBufferCS[cache.registerIndex]       = constantBuffer->getSerial();
3619                 mCurrentConstantBufferCSOffset[cache.registerIndex] = uniformBufferOffset;
3620                 mCurrentConstantBufferCSSize[cache.registerIndex]   = uniformBufferSize;
3621                 break;
3622             }
3623 
3624             // TODO(jiawei.shao@intel.com): update geometry shader uniform buffers.
3625             case gl::ShaderType::Geometry:
3626                 UNIMPLEMENTED();
3627                 break;
3628 
3629             default:
3630                 UNREACHABLE();
3631         }
3632     }
3633 
3634     const auto &shaderUniformBuffersUseSB =
3635         mProgramD3D->getShaderUniformBufferCacheUseSB(shaderType);
3636     for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffersUseSB.size(); ++bufferIndex)
3637     {
3638         const D3DUBOCacheUseSB cache = shaderUniformBuffersUseSB[bufferIndex];
3639         if (cache.binding == -1)
3640         {
3641             continue;
3642         }
3643 
3644         const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
3645         if (uniformBuffer.get() == nullptr)
3646         {
3647             continue;
3648         }
3649         const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3650 
3651         Buffer11 *bufferStorage                    = GetImplAs<Buffer11>(uniformBuffer.get());
3652         const d3d11::ShaderResourceView *bufferSRV = nullptr;
3653         ANGLE_TRY(bufferStorage->getStructuredBufferRangeSRV(
3654             context, static_cast<unsigned int>(uniformBufferOffset), cache.byteWidth,
3655             cache.structureByteStride, &bufferSRV));
3656 
3657         ASSERT(bufferSRV->valid());
3658         setShaderResourceInternal(shaderType, cache.registerIndex, bufferSRV);
3659     }
3660 
3661     return angle::Result::Continue;
3662 }
3663 
syncShaderStorageBuffersForShader(const gl::Context * context,gl::ShaderType shaderType)3664 angle::Result StateManager11::syncShaderStorageBuffersForShader(const gl::Context *context,
3665                                                                 gl::ShaderType shaderType)
3666 {
3667     const gl::State &glState   = context->getState();
3668     const gl::Program *program = glState.getProgram();
3669     angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
3670         previouslyBound;
3671     for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
3672          blockIndex++)
3673     {
3674         GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
3675         const unsigned int registerIndex = mProgramD3D->getShaderStorageBufferRegisterIndex(
3676             static_cast<GLuint>(blockIndex), shaderType);
3677         // It means this block is active but not statically used.
3678         if (registerIndex == GL_INVALID_INDEX)
3679         {
3680             continue;
3681         }
3682         const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
3683         if (shaderStorageBuffer.get() == nullptr)
3684         {
3685             // We didn't see a driver error like atomic buffer did. But theoretically, the same
3686             // thing should be done.
3687             setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(shaderType, registerIndex,
3688                                                                        nullptr);
3689             continue;
3690         }
3691 
3692         Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
3693         if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
3694             previouslyBound.end())
3695         {
3696             // D3D11 doesn't support binding a buffer multiple times
3697             // http://anglebug.com/3032
3698             ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
3699             return angle::Result::Stop;
3700         }
3701         previouslyBound.push_back(bufferStorage);
3702 
3703         d3d11::UnorderedAccessView *uavPtr = nullptr;
3704         GLsizeiptr viewSize                = 0;
3705         // Bindings only have a valid size if bound using glBindBufferRange
3706         if (shaderStorageBuffer.getSize() > 0)
3707         {
3708             viewSize = shaderStorageBuffer.getSize();
3709         }
3710         // We use the buffer size for glBindBufferBase
3711         else
3712         {
3713             viewSize = bufferStorage->getSize();
3714         }
3715         ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
3716                                                 &uavPtr));
3717 
3718         switch (shaderType)
3719         {
3720             case gl::ShaderType::Compute:
3721             {
3722                 setUnorderedAccessViewInternal(shaderType, registerIndex, uavPtr);
3723                 break;
3724             }
3725 
3726             case gl::ShaderType::Vertex:
3727             case gl::ShaderType::Fragment:
3728             case gl::ShaderType::Geometry:
3729                 UNIMPLEMENTED();
3730                 break;
3731 
3732             default:
3733                 UNREACHABLE();
3734         }
3735     }
3736 
3737     return angle::Result::Continue;
3738 }
3739 
syncUniformBuffers(const gl::Context * context)3740 angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
3741 {
3742     mProgramD3D->updateUniformBufferCache(context->getCaps());
3743 
3744     if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
3745     {
3746         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute));
3747     }
3748     else
3749     {
3750         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex));
3751         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment));
3752         if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
3753         {
3754             ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry));
3755         }
3756     }
3757 
3758     return angle::Result::Continue;
3759 }
3760 
syncAtomicCounterBuffers(const gl::Context * context)3761 angle::Result StateManager11::syncAtomicCounterBuffers(const gl::Context *context)
3762 {
3763     if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
3764     {
3765         ANGLE_TRY(syncAtomicCounterBuffersForShader(context, gl::ShaderType::Compute));
3766     }
3767 
3768     return angle::Result::Continue;
3769 }
3770 
syncAtomicCounterBuffersForShader(const gl::Context * context,gl::ShaderType shaderType)3771 angle::Result StateManager11::syncAtomicCounterBuffersForShader(const gl::Context *context,
3772                                                                 gl::ShaderType shaderType)
3773 {
3774     const gl::State &glState   = context->getState();
3775     const gl::Program *program = glState.getProgram();
3776     for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
3777     {
3778         GLuint binding     = atomicCounterBuffer.binding;
3779         const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
3780         const unsigned int registerIndex =
3781             mProgramD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
3782         ASSERT(registerIndex != GL_INVALID_INDEX);
3783         if (buffer.get() == nullptr)
3784         {
3785             // The atomic counter is used in shader. However, there is no buffer binding to it. We
3786             // should clear the corresponding UAV in case the previous view type is a texture not a
3787             // buffer. Otherwise, below error will be reported. The Unordered Access View dimension
3788             // declared in the shader code (BUFFER) does not match the view type bound to slot 0
3789             // of the Compute Shader unit (TEXTURE2D).
3790             setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(shaderType, registerIndex,
3791                                                                        nullptr);
3792             continue;
3793         }
3794 
3795         Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
3796         // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer
3797         // multiple times, as this is unsupported by D3D11. http://anglebug.com/3141
3798 
3799         // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
3800         // buffer size for glBindBufferBase
3801         GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
3802         d3d11::UnorderedAccessView *uavPtr = nullptr;
3803         ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));
3804 
3805         if (shaderType == gl::ShaderType::Compute)
3806         {
3807             setUnorderedAccessViewInternal(shaderType, registerIndex, uavPtr);
3808         }
3809         else
3810         {
3811             // Atomic Shaders on non-compute shaders are currently unimplemented
3812             // http://anglebug.com/1729
3813             UNIMPLEMENTED();
3814         }
3815     }
3816 
3817     return angle::Result::Continue;
3818 }
3819 
syncShaderStorageBuffers(const gl::Context * context)3820 angle::Result StateManager11::syncShaderStorageBuffers(const gl::Context *context)
3821 {
3822     if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
3823     {
3824         ANGLE_TRY(syncShaderStorageBuffersForShader(context, gl::ShaderType::Compute));
3825     }
3826 
3827     return angle::Result::Continue;
3828 }
3829 
syncTransformFeedbackBuffers(const gl::Context * context)3830 angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
3831 {
3832     const auto &glState = context->getState();
3833 
3834     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3835 
3836     // If transform feedback is not active, unbind all buffers
3837     if (!glState.isTransformFeedbackActiveUnpaused())
3838     {
3839         if (mAppliedTFSerial != mEmptySerial)
3840         {
3841             deviceContext->SOSetTargets(0, nullptr, nullptr);
3842             mAppliedTFSerial = mEmptySerial;
3843         }
3844         return angle::Result::Continue;
3845     }
3846 
3847     gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
3848     TransformFeedback11 *tf11                = GetImplAs<TransformFeedback11>(transformFeedback);
3849     if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
3850     {
3851         return angle::Result::Continue;
3852     }
3853 
3854     const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
3855     ANGLE_TRY(tf11->getSOBuffers(context, &soBuffers));
3856     const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
3857 
3858     deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
3859 
3860     mAppliedTFSerial = tf11->getSerial();
3861     tf11->onApply();
3862 
3863     return angle::Result::Continue;
3864 }
3865 
syncPrimitiveTopology(const gl::State & glState,gl::PrimitiveMode currentDrawMode)3866 void StateManager11::syncPrimitiveTopology(const gl::State &glState,
3867                                            gl::PrimitiveMode currentDrawMode)
3868 {
3869     D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
3870     // Don't cull everything by default, this also resets if we were previously culling
3871     mCullEverything = false;
3872 
3873     switch (currentDrawMode)
3874     {
3875         case gl::PrimitiveMode::Points:
3876         {
3877             bool usesPointSize = mProgramD3D->usesPointSize();
3878 
3879             // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
3880             // which affects varying interpolation. Since the value of gl_PointSize is
3881             // undefined when not written, just skip drawing to avoid unexpected results.
3882             if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
3883             {
3884                 // Notify developers of risking undefined behavior.
3885                 WARN() << "Point rendering without writing to gl_PointSize.";
3886                 mCullEverything = true;
3887                 return;
3888             }
3889 
3890             // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
3891             // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
3892             if (usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled)
3893             {
3894                 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
3895             }
3896             else
3897             {
3898                 primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
3899             }
3900             break;
3901         }
3902         case gl::PrimitiveMode::Lines:
3903             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
3904             break;
3905         case gl::PrimitiveMode::LineLoop:
3906             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
3907             break;
3908         case gl::PrimitiveMode::LineStrip:
3909             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
3910             break;
3911         case gl::PrimitiveMode::Triangles:
3912             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
3913             mCullEverything   = CullsEverything(glState);
3914             break;
3915         case gl::PrimitiveMode::TriangleStrip:
3916             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
3917             mCullEverything   = CullsEverything(glState);
3918             break;
3919         // emulate fans via rewriting index buffer
3920         case gl::PrimitiveMode::TriangleFan:
3921             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
3922             mCullEverything   = CullsEverything(glState);
3923             break;
3924         default:
3925             UNREACHABLE();
3926             break;
3927     }
3928 
3929     setPrimitiveTopologyInternal(primitiveTopology);
3930 }
3931 
3932 }  // namespace rx
3933