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