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