xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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([email protected]): 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/42260558
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     // 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 
2024 // Applies the render target surface, depth stencil surface, viewport rectangle and
2025 // scissor rectangle to the renderer
syncFramebuffer(const gl::Context * context)2026 angle::Result StateManager11::syncFramebuffer(const gl::Context *context)
2027 {
2028     // Check for zero-sized default framebuffer, which is a special case.
2029     // in this case we do not wish to modify any state and just silently return false.
2030     // this will not report any gl error but will cause the calling method to return.
2031     if (mFramebuffer11->getState().isDefault())
2032     {
2033         RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
2034         const gl::Extents &size = firstRT->getExtents();
2035         if (size.empty())
2036         {
2037             return angle::Result::Continue;
2038         }
2039     }
2040 
2041     RTVArray framebufferRTVs = {{}};
2042     const auto &colorRTs     = mFramebuffer11->getCachedColorRenderTargets();
2043 
2044     size_t appliedRTIndex  = 0;
2045     bool skipInactiveRTs   = mRenderer->getFeatures().mrtPerfWorkaround.enabled;
2046     const auto &drawStates = mFramebuffer11->getState().getDrawBufferStates();
2047     gl::DrawBufferMask activeProgramOutputs =
2048         mExecutableD3D->getExecutable()->getActiveOutputVariablesMask();
2049     UINT maxExistingRT           = 0;
2050     const auto &colorAttachments = mFramebuffer11->getState().getColorAttachments();
2051 
2052     for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
2053     {
2054         const RenderTarget11 *renderTarget = colorRTs[rtIndex];
2055 
2056         // Skip inactive rendertargets if the workaround is enabled.
2057         if (skipInactiveRTs &&
2058             (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
2059         {
2060             continue;
2061         }
2062 
2063         if (renderTarget)
2064         {
2065             framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
2066             ASSERT(framebufferRTVs[appliedRTIndex]);
2067             maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
2068 
2069             // Unset conflicting texture SRVs
2070             const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
2071             ASSERT(attachment.isAttached());
2072             unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
2073         }
2074 
2075         appliedRTIndex++;
2076     }
2077 
2078     // Get the depth stencil buffers
2079     ID3D11DepthStencilView *framebufferDSV = nullptr;
2080     const auto *depthStencilRenderTarget   = mFramebuffer11->getCachedDepthStencilRenderTarget();
2081     if (depthStencilRenderTarget)
2082     {
2083         framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
2084         ASSERT(framebufferDSV);
2085 
2086         // Unset conflicting texture SRVs
2087         const gl::FramebufferAttachment *attachment =
2088             mFramebuffer11->getState().getDepthOrStencilAttachment();
2089         ASSERT(attachment);
2090         unsetConflictingAttachmentResources(*attachment,
2091                                             depthStencilRenderTarget->getTexture().get());
2092     }
2093 
2094     ASSERT(maxExistingRT <= static_cast<UINT>(context->getCaps().maxDrawBuffers));
2095 
2096     // Apply the render target and depth stencil
2097     mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
2098                                                       framebufferDSV);
2099     mCurRTVs.clear();
2100     for (UINT i = 0; i < maxExistingRT; i++)
2101     {
2102         mCurRTVs.update(i, framebufferRTVs[i]);
2103     }
2104     mCurrentDSV.clear();
2105     mCurrentDSV.update(0, framebufferDSV);
2106     return angle::Result::Continue;
2107 }
2108 
invalidateCurrentValueAttrib(size_t attribIndex)2109 void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
2110 {
2111     mDirtyCurrentValueAttribs.set(attribIndex);
2112     mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
2113     invalidateInputLayout();
2114     invalidateShaders();
2115 }
2116 
syncCurrentValueAttribs(const gl::Context * context,const std::vector<gl::VertexAttribCurrentValueData> & currentValues)2117 angle::Result StateManager11::syncCurrentValueAttribs(
2118     const gl::Context *context,
2119     const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
2120 {
2121     const gl::ProgramExecutable *executable = mExecutableD3D->getExecutable();
2122     const auto &activeAttribsMask           = executable->getActiveAttribLocationsMask();
2123     const auto &dirtyActiveAttribs          = (activeAttribsMask & mDirtyCurrentValueAttribs);
2124 
2125     if (!dirtyActiveAttribs.any())
2126     {
2127         return angle::Result::Continue;
2128     }
2129 
2130     const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
2131     const auto &vertexBindings   = mVertexArray11->getState().getVertexBindings();
2132     mDirtyCurrentValueAttribs    = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
2133 
2134     for (auto attribIndex : dirtyActiveAttribs)
2135     {
2136         if (vertexAttributes[attribIndex].enabled)
2137             continue;
2138 
2139         const auto *attrib                      = &vertexAttributes[attribIndex];
2140         const auto &currentValue                = currentValues[attribIndex];
2141         TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
2142         currentValueAttrib->currentValueType    = currentValue.Type;
2143         currentValueAttrib->attribute           = attrib;
2144         currentValueAttrib->binding             = &vertexBindings[attrib->bindingIndex];
2145 
2146         mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
2147 
2148         ANGLE_TRY(mVertexDataManager.storeCurrentValue(context, currentValue, currentValueAttrib,
2149                                                        static_cast<size_t>(attribIndex)));
2150     }
2151 
2152     return angle::Result::Continue;
2153 }
2154 
setInputLayout(const d3d11::InputLayout * inputLayout)2155 void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
2156 {
2157     if (setInputLayoutInternal(inputLayout))
2158     {
2159         invalidateInputLayout();
2160     }
2161 }
2162 
setInputLayoutInternal(const d3d11::InputLayout * inputLayout)2163 bool StateManager11::setInputLayoutInternal(const d3d11::InputLayout *inputLayout)
2164 {
2165     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2166     if (inputLayout == nullptr)
2167     {
2168         if (!mCurrentInputLayout.empty())
2169         {
2170             deviceContext->IASetInputLayout(nullptr);
2171             mCurrentInputLayout.clear();
2172             return true;
2173         }
2174     }
2175     else if (inputLayout->getSerial() != mCurrentInputLayout)
2176     {
2177         deviceContext->IASetInputLayout(inputLayout->get());
2178         mCurrentInputLayout = inputLayout->getSerial();
2179         return true;
2180     }
2181 
2182     return false;
2183 }
2184 
queueVertexBufferChange(size_t bufferIndex,ID3D11Buffer * buffer,UINT stride,UINT offset)2185 bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
2186                                              ID3D11Buffer *buffer,
2187                                              UINT stride,
2188                                              UINT offset)
2189 {
2190     if (buffer != mCurrentVertexBuffers[bufferIndex] ||
2191         stride != mCurrentVertexStrides[bufferIndex] ||
2192         offset != mCurrentVertexOffsets[bufferIndex])
2193     {
2194         mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
2195 
2196         mCurrentVertexBuffers[bufferIndex] = buffer;
2197         mCurrentVertexStrides[bufferIndex] = stride;
2198         mCurrentVertexOffsets[bufferIndex] = offset;
2199         return true;
2200     }
2201 
2202     return false;
2203 }
2204 
applyVertexBufferChanges()2205 void StateManager11::applyVertexBufferChanges()
2206 {
2207     if (mDirtyVertexBufferRange.empty())
2208     {
2209         return;
2210     }
2211 
2212     ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
2213 
2214     UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
2215 
2216     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2217     deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
2218                                       &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
2219                                       &mCurrentVertexOffsets[start]);
2220 
2221     mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
2222 }
2223 
setSingleVertexBuffer(const d3d11::Buffer * buffer,UINT stride,UINT offset)2224 void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
2225 {
2226     ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
2227     if (queueVertexBufferChange(0, native, stride, offset))
2228     {
2229         invalidateInputLayout();
2230         applyVertexBufferChanges();
2231     }
2232 }
2233 
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)2234 angle::Result StateManager11::updateState(const gl::Context *context,
2235                                           gl::PrimitiveMode mode,
2236                                           GLint firstVertex,
2237                                           GLsizei vertexOrIndexCount,
2238                                           gl::DrawElementsType indexTypeOrInvalid,
2239                                           const void *indices,
2240                                           GLsizei instanceCount,
2241                                           GLint baseVertex,
2242                                           GLuint baseInstance,
2243                                           bool promoteDynamic)
2244 {
2245     const gl::State &glState = context->getState();
2246 
2247     // TODO(jmadill): Use dirty bits.
2248     if (mRenderTargetIsDirty)
2249     {
2250         processFramebufferInvalidation(context);
2251         mRenderTargetIsDirty = false;
2252     }
2253 
2254     // TODO(jmadill): Use dirty bits.
2255     if (mExecutableD3D->isSamplerMappingDirty())
2256     {
2257         mExecutableD3D->updateSamplerMapping();
2258         invalidateTexturesAndSamplers();
2259     }
2260 
2261     // TODO(jmadill): Use dirty bits.
2262     if (mExecutableD3D->anyShaderUniformsDirty())
2263     {
2264         mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
2265     }
2266 
2267     // Swizzling can cause internal state changes with blit shaders.
2268     if (mDirtySwizzles)
2269     {
2270         ANGLE_TRY(generateSwizzles(context));
2271         mDirtySwizzles = false;
2272     }
2273 
2274     ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));
2275 
2276     // TODO([email protected]): This can be recomputed only on framebuffer or multisample mask
2277     // state changes.
2278     RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
2279     const int samples       = (firstRT ? firstRT->getSamples() : 0);
2280     // Single-sampled rendering requires ignoring sample coverage and sample mask states.
2281     unsigned int sampleMask = (samples != 0) ? GetBlendSampleMask(glState, samples) : 0xFFFFFFFF;
2282     if (sampleMask != mCurSampleMask)
2283     {
2284         mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2285     }
2286 
2287     ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
2288                                                indexTypeOrInvalid, indices, instanceCount,
2289                                                baseVertex, baseInstance, promoteDynamic));
2290 
2291     // Changes in the draw call can affect the vertex buffer translations.
2292     if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
2293     {
2294         mLastFirstVertex = firstVertex;
2295         invalidateInputLayout();
2296     }
2297 
2298     // The ShaderConstants only need to be updated when the program uses vertexID
2299     if (mExecutableD3D->usesVertexID())
2300     {
2301         GLint firstVertexOnChange = firstVertex + baseVertex;
2302         ASSERT(mVertexArray11);
2303         if (mVertexArray11->hasActiveDynamicAttrib(context) &&
2304             indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
2305         {
2306             // drawElements with Dynamic attribute
2307             // the firstVertex is already including baseVertex when
2308             // doing ComputeStartVertex
2309             firstVertexOnChange = firstVertex;
2310         }
2311 
2312         if (mShaderConstants.onFirstVertexChange(firstVertexOnChange))
2313         {
2314             mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
2315         }
2316     }
2317 
2318     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
2319     {
2320         ANGLE_TRY(applyIndexBuffer(context, vertexOrIndexCount, indexTypeOrInvalid, indices));
2321     }
2322 
2323     if (mLastAppliedDrawMode != mode)
2324     {
2325         mLastAppliedDrawMode = mode;
2326         mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2327 
2328         bool pointDrawMode = (mode == gl::PrimitiveMode::Points);
2329         if (pointDrawMode != mCurRasterState.pointDrawMode)
2330         {
2331             mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2332 
2333             // Changing from points to not points (or vice-versa) affects the geometry shader.
2334             invalidateShaders();
2335         }
2336     }
2337 
2338     auto dirtyBitsCopy = mInternalDirtyBits & mGraphicsDirtyBitsMask;
2339 
2340     for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
2341     {
2342         mInternalDirtyBits.reset(*iter);
2343         switch (*iter)
2344         {
2345             case DIRTY_BIT_RENDER_TARGET:
2346                 ANGLE_TRY(syncFramebuffer(context));
2347                 break;
2348             case DIRTY_BIT_VIEWPORT_STATE:
2349                 syncViewport(context);
2350                 break;
2351             case DIRTY_BIT_SCISSOR_STATE:
2352                 syncScissorRectangle(context);
2353                 break;
2354             case DIRTY_BIT_RASTERIZER_STATE:
2355                 ANGLE_TRY(syncRasterizerState(context, mode));
2356                 break;
2357             case DIRTY_BIT_BLEND_STATE:
2358                 // Single-sampled rendering requires ignoring alpha-to-coverage state.
2359                 ANGLE_TRY(syncBlendState(context, glState.getBlendStateExt(),
2360                                          glState.getBlendColor(), sampleMask,
2361                                          glState.isSampleAlphaToCoverageEnabled() && (samples != 0),
2362                                          glState.hasConstantAlphaBlendFunc()));
2363                 break;
2364             case DIRTY_BIT_DEPTH_STENCIL_STATE:
2365                 ANGLE_TRY(syncDepthStencilState(context));
2366                 break;
2367             case DIRTY_BIT_GRAPHICS_SRV_STATE:
2368                 ANGLE_TRY(syncTextures(context));
2369                 break;
2370             case DIRTY_BIT_GRAPHICS_UAV_STATE:
2371                 ANGLE_TRY(syncUAVsForGraphics(context));
2372                 break;
2373             case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
2374                 // TODO(jmadill): More fine-grained update.
2375                 ANGLE_TRY(syncTextures(context));
2376                 break;
2377             case DIRTY_BIT_PROGRAM_UNIFORMS:
2378                 ANGLE_TRY(applyUniforms(context));
2379                 break;
2380             case DIRTY_BIT_DRIVER_UNIFORMS:
2381                 // This must happen after viewport sync; the viewport affects builtin uniforms.
2382                 ANGLE_TRY(applyDriverUniforms(context));
2383                 break;
2384             case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
2385                 ANGLE_TRY(syncUniformBuffers(context));
2386                 break;
2387             case DIRTY_BIT_SHADERS:
2388                 ANGLE_TRY(syncProgram(context, mode));
2389                 break;
2390             case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
2391                 ANGLE_TRY(syncCurrentValueAttribs(context, glState.getVertexAttribCurrentValues()));
2392                 break;
2393             case DIRTY_BIT_TRANSFORM_FEEDBACK:
2394                 ANGLE_TRY(syncTransformFeedbackBuffers(context));
2395                 break;
2396             case DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT:
2397                 ANGLE_TRY(syncVertexBuffersAndInputLayout(context, mode, firstVertex,
2398                                                           vertexOrIndexCount, indexTypeOrInvalid,
2399                                                           instanceCount));
2400                 break;
2401             case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
2402                 syncPrimitiveTopology(glState, mode);
2403                 break;
2404             default:
2405                 UNREACHABLE();
2406                 break;
2407         }
2408     }
2409 
2410     // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except
2411     // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit.
2412     ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none());
2413 
2414     return angle::Result::Continue;
2415 }
2416 
setShaderResourceShared(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::SharedSRV * srv)2417 void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
2418                                              UINT resourceSlot,
2419                                              const d3d11::SharedSRV *srv)
2420 {
2421     setShaderResourceInternal(shaderType, resourceSlot, srv);
2422 
2423     // TODO(jmadill): Narrower dirty region.
2424     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2425 }
2426 
setShaderResource(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::ShaderResourceView * srv)2427 void StateManager11::setShaderResource(gl::ShaderType shaderType,
2428                                        UINT resourceSlot,
2429                                        const d3d11::ShaderResourceView *srv)
2430 {
2431     setShaderResourceInternal(shaderType, resourceSlot, srv);
2432 
2433     // TODO(jmadill): Narrower dirty region.
2434     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2435 }
2436 
setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2437 void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2438 {
2439     if (setPrimitiveTopologyInternal(primitiveTopology))
2440     {
2441         mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2442     }
2443 }
2444 
setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2445 bool StateManager11::setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2446 {
2447     if (primitiveTopology != mCurrentPrimitiveTopology)
2448     {
2449         mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
2450         mCurrentPrimitiveTopology = primitiveTopology;
2451         return true;
2452     }
2453     else
2454     {
2455         return false;
2456     }
2457 }
2458 
setDrawShaders(const d3d11::VertexShader * vertexShader,const d3d11::GeometryShader * geometryShader,const d3d11::PixelShader * pixelShader)2459 void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
2460                                     const d3d11::GeometryShader *geometryShader,
2461                                     const d3d11::PixelShader *pixelShader)
2462 {
2463     setVertexShader(vertexShader);
2464     setGeometryShader(geometryShader);
2465     setPixelShader(pixelShader);
2466 }
2467 
setVertexShader(const d3d11::VertexShader * shader)2468 void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
2469 {
2470     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2471 
2472     if (serial != mAppliedShaders[gl::ShaderType::Vertex])
2473     {
2474         ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
2475         mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
2476         mAppliedShaders[gl::ShaderType::Vertex] = serial;
2477         invalidateShaders();
2478     }
2479 }
2480 
setGeometryShader(const d3d11::GeometryShader * shader)2481 void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
2482 {
2483     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2484 
2485     if (serial != mAppliedShaders[gl::ShaderType::Geometry])
2486     {
2487         ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
2488         mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
2489         mAppliedShaders[gl::ShaderType::Geometry] = serial;
2490         invalidateShaders();
2491     }
2492 }
2493 
setPixelShader(const d3d11::PixelShader * shader)2494 void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
2495 {
2496     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2497 
2498     if (serial != mAppliedShaders[gl::ShaderType::Fragment])
2499     {
2500         ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
2501         mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
2502         mAppliedShaders[gl::ShaderType::Fragment] = serial;
2503         invalidateShaders();
2504     }
2505 }
2506 
setComputeShader(const d3d11::ComputeShader * shader)2507 void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
2508 {
2509     ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2510 
2511     if (serial != mAppliedShaders[gl::ShaderType::Compute])
2512     {
2513         ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
2514         mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
2515         mAppliedShaders[gl::ShaderType::Compute] = serial;
2516         invalidateShaders();
2517     }
2518 }
2519 
setVertexConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2520 void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2521 {
2522     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2523     auto &currentSerial                = mCurrentConstantBufferVS[slot];
2524 
2525     mCurrentConstantBufferVSOffset[slot] = 0;
2526     mCurrentConstantBufferVSSize[slot]   = 0;
2527 
2528     if (buffer)
2529     {
2530         if (currentSerial != buffer->getSerial())
2531         {
2532             deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
2533             currentSerial = buffer->getSerial();
2534             invalidateConstantBuffer(slot);
2535         }
2536     }
2537     else
2538     {
2539         if (!currentSerial.empty())
2540         {
2541             ID3D11Buffer *nullBuffer = nullptr;
2542             deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
2543             currentSerial.clear();
2544             invalidateConstantBuffer(slot);
2545         }
2546     }
2547 }
2548 
setPixelConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2549 void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2550 {
2551     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2552     auto &currentSerial                = mCurrentConstantBufferPS[slot];
2553 
2554     mCurrentConstantBufferPSOffset[slot] = 0;
2555     mCurrentConstantBufferPSSize[slot]   = 0;
2556 
2557     if (buffer)
2558     {
2559         if (currentSerial != buffer->getSerial())
2560         {
2561             deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
2562             currentSerial = buffer->getSerial();
2563             invalidateConstantBuffer(slot);
2564         }
2565     }
2566     else
2567     {
2568         if (!currentSerial.empty())
2569         {
2570             ID3D11Buffer *nullBuffer = nullptr;
2571             deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
2572             currentSerial.clear();
2573             invalidateConstantBuffer(slot);
2574         }
2575     }
2576 }
2577 
setDepthStencilState(const d3d11::DepthStencilState * depthStencilState,UINT stencilRef)2578 void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
2579                                           UINT stencilRef)
2580 {
2581     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2582 
2583     if (depthStencilState)
2584     {
2585         deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
2586     }
2587     else
2588     {
2589         deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
2590     }
2591 
2592     mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
2593 }
2594 
setSimpleBlendState(const d3d11::BlendState * blendState)2595 void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
2596 {
2597     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2598 
2599     if (blendState)
2600     {
2601         deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
2602     }
2603     else
2604     {
2605         deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
2606     }
2607 
2608     mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2609 }
2610 
setRasterizerState(const d3d11::RasterizerState * rasterizerState)2611 void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
2612 {
2613     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2614 
2615     if (rasterizerState)
2616     {
2617         deviceContext->RSSetState(rasterizerState->get());
2618     }
2619     else
2620     {
2621         deviceContext->RSSetState(nullptr);
2622     }
2623 
2624     mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2625 }
2626 
setSimpleViewport(const gl::Extents & extents)2627 void StateManager11::setSimpleViewport(const gl::Extents &extents)
2628 {
2629     setSimpleViewport(extents.width, extents.height);
2630 }
2631 
setSimpleViewport(int width,int height)2632 void StateManager11::setSimpleViewport(int width, int height)
2633 {
2634     D3D11_VIEWPORT viewport;
2635     viewport.TopLeftX = 0;
2636     viewport.TopLeftY = 0;
2637     viewport.Width    = static_cast<FLOAT>(width);
2638     viewport.Height   = static_cast<FLOAT>(height);
2639     viewport.MinDepth = 0.0f;
2640     viewport.MaxDepth = 1.0f;
2641 
2642     mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
2643     mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
2644 }
2645 
setSimplePixelTextureAndSampler(const d3d11::SharedSRV & srv,const d3d11::SamplerState & samplerState)2646 void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
2647                                                      const d3d11::SamplerState &samplerState)
2648 {
2649     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2650 
2651     setShaderResourceInternal(gl::ShaderType::Fragment, 0, &srv);
2652     deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
2653 
2654     mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2655     mForceSetShaderSamplerStates[gl::ShaderType::Fragment][0] = true;
2656 }
2657 
setSimpleScissorRect(const gl::Rectangle & glRect)2658 void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
2659 {
2660     D3D11_RECT scissorRect;
2661     scissorRect.left   = glRect.x;
2662     scissorRect.right  = glRect.x + glRect.width;
2663     scissorRect.top    = glRect.y;
2664     scissorRect.bottom = glRect.y + glRect.height;
2665     setScissorRectD3D(scissorRect);
2666 }
2667 
setScissorRectD3D(const D3D11_RECT & d3dRect)2668 void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
2669 {
2670     mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
2671     mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
2672 }
2673 
syncTextures(const gl::Context * context)2674 angle::Result StateManager11::syncTextures(const gl::Context *context)
2675 {
2676     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
2677     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
2678     if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
2679     {
2680         ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
2681     }
2682 
2683     return angle::Result::Continue;
2684 }
2685 
setSamplerState(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & samplerState)2686 angle::Result StateManager11::setSamplerState(const gl::Context *context,
2687                                               gl::ShaderType type,
2688                                               int index,
2689                                               gl::Texture *texture,
2690                                               const gl::SamplerState &samplerState)
2691 {
2692 #if !defined(NDEBUG)
2693     // Storage should exist, texture should be complete. Only verified in Debug.
2694     TextureD3D *textureD3D  = GetImplAs<TextureD3D>(texture);
2695     TextureStorage *storage = nullptr;
2696     ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
2697     ASSERT(storage);
2698 #endif  // !defined(NDEBUG)
2699 
2700     auto *deviceContext = mRenderer->getDeviceContext();
2701 
2702     ASSERT(index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[type]);
2703 
2704     // When border color is used, its value may need to be readjusted based on the texture format.
2705     const bool usesBorderColor = samplerState.usesBorderColor();
2706 
2707     if (mForceSetShaderSamplerStates[type][index] || usesBorderColor ||
2708         memcmp(&samplerState, &mCurShaderSamplerStates[type][index], sizeof(gl::SamplerState)) != 0)
2709     {
2710         // When clamp-to-border mode is used and a floating-point border color is set, the color
2711         // value must be adjusted based on the texture format. Reset it to zero in all other cases
2712         // to reduce the number of cached sampler entries. Address modes for integer texture
2713         // formats are emulated in shaders and do not rely on this state.
2714         angle::ColorGeneric borderColor;
2715         if (usesBorderColor)
2716         {
2717             if (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float)
2718             {
2719                 borderColor = samplerState.getBorderColor();
2720             }
2721             const uint32_t baseLevel       = texture->getTextureState().getEffectiveBaseLevel();
2722             const gl::TextureTarget target = TextureTypeToTarget(texture->getType(), 0);
2723             const angle::Format &format    = angle::Format::Get(angle::Format::InternalFormatToID(
2724                 texture->getFormat(target, baseLevel).info->sizedInternalFormat));
2725 
2726             borderColor = AdjustBorderColor<false>(borderColor, format, false);
2727         }
2728         gl::SamplerState adjustedSamplerState(samplerState);
2729         adjustedSamplerState.setBorderColor(borderColor.colorF);
2730 
2731         ID3D11SamplerState *dxSamplerState = nullptr;
2732         ANGLE_TRY(mRenderer->getSamplerState(context, adjustedSamplerState, &dxSamplerState));
2733 
2734         ASSERT(dxSamplerState != nullptr);
2735 
2736         switch (type)
2737         {
2738             case gl::ShaderType::Vertex:
2739                 deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
2740                 break;
2741             case gl::ShaderType::Fragment:
2742                 deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
2743                 break;
2744             case gl::ShaderType::Compute:
2745                 deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
2746                 break;
2747             case gl::ShaderType::Geometry:
2748                 deviceContext->GSSetSamplers(index, 1, &dxSamplerState);
2749                 break;
2750             default:
2751                 UNREACHABLE();
2752                 break;
2753         }
2754 
2755         mCurShaderSamplerStates[type][index] = samplerState;
2756     }
2757 
2758     mForceSetShaderSamplerStates[type][index] = false;
2759 
2760     // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
2761     // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
2762     // buffer, and it doesn't affect the state set by
2763     // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers.
2764     mShaderConstants.onSamplerChange(type, index, *texture, samplerState);
2765 
2766     return angle::Result::Continue;
2767 }
2768 
setTextureForSampler(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & sampler)2769 angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
2770                                                    gl::ShaderType type,
2771                                                    int index,
2772                                                    gl::Texture *texture,
2773                                                    const gl::SamplerState &sampler)
2774 {
2775     const d3d11::SharedSRV *textureSRV = nullptr;
2776 
2777     if (texture)
2778     {
2779         TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
2780 
2781         TextureStorage *texStorage = nullptr;
2782         ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2783 
2784         // Texture should be complete and have a storage
2785         ASSERT(texStorage);
2786 
2787         TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2788 
2789         ANGLE_TRY(
2790             storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));
2791 
2792         // If we get an invalid SRV here, something went wrong in the texture class and we're
2793         // unexpectedly missing the shader resource view.
2794         ASSERT(textureSRV->valid());
2795 
2796         textureImpl->resetDirty();
2797     }
2798 
2799     ASSERT(
2800         (type == gl::ShaderType::Fragment &&
2801          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
2802         (type == gl::ShaderType::Vertex &&
2803          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
2804         (type == gl::ShaderType::Compute &&
2805          index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]));
2806 
2807     setShaderResourceInternal(type, index, textureSRV);
2808     return angle::Result::Continue;
2809 }
2810 
setImageState(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit)2811 angle::Result StateManager11::setImageState(const gl::Context *context,
2812                                             gl::ShaderType type,
2813                                             int index,
2814                                             const gl::ImageUnit &imageUnit)
2815 {
2816     ASSERT(index < mRenderer->getNativeCaps().maxShaderImageUniforms[type]);
2817 
2818     if (mShaderConstants.onImageChange(type, index, imageUnit))
2819     {
2820         invalidateDriverUniforms();
2821     }
2822 
2823     return angle::Result::Continue;
2824 }
2825 
2826 // For each Direct3D sampler of either the pixel or vertex stage,
2827 // looks up the corresponding OpenGL texture image unit and texture type,
2828 // and sets the texture and its addressing/filtering state (or NULL when inactive).
2829 // Sampler mapping needs to be up-to-date on the program object before this is called.
applyTexturesForSRVs(const gl::Context * context,gl::ShaderType shaderType)2830 angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
2831                                                    gl::ShaderType shaderType)
2832 {
2833     const auto &glState = context->getState();
2834     const auto &caps    = context->getCaps();
2835 
2836     ASSERT(!mExecutableD3D->isSamplerMappingDirty());
2837 
2838     // TODO(jmadill): Use the Program's sampler bindings.
2839     const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
2840 
2841     const gl::RangeUI samplerRange = mExecutableD3D->getUsedSamplerRange(shaderType);
2842     for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
2843          samplerIndex++)
2844     {
2845         GLint textureUnit = mExecutableD3D->getSamplerMapping(shaderType, samplerIndex, caps);
2846         ASSERT(textureUnit != -1);
2847         gl::Texture *texture = completeTextures[textureUnit];
2848 
2849         // A nullptr texture indicates incomplete.
2850         if (texture)
2851         {
2852             gl::Sampler *samplerObject = glState.getSampler(textureUnit);
2853 
2854             const gl::SamplerState &samplerState =
2855                 samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
2856 
2857             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
2858             ANGLE_TRY(
2859                 setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
2860         }
2861         else
2862         {
2863             gl::TextureType textureType =
2864                 mExecutableD3D->getSamplerTextureType(shaderType, samplerIndex);
2865 
2866             // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
2867             // incomplete texture.
2868             gl::Texture *incompleteTexture = nullptr;
2869             ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
2870             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
2871                                       incompleteTexture->getSamplerState()));
2872             ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
2873                                            incompleteTexture->getSamplerState()));
2874         }
2875     }
2876 
2877     const gl::RangeUI readonlyImageRange = mExecutableD3D->getUsedImageRange(shaderType, true);
2878     for (unsigned int readonlyImageIndex = readonlyImageRange.low();
2879          readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
2880     {
2881         GLint imageUnitIndex =
2882             mExecutableD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
2883         ASSERT(imageUnitIndex != -1);
2884         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2885         if (!imageUnit.layered)
2886         {
2887             ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
2888                                     readonlyImageIndex - readonlyImageRange.low(), imageUnit));
2889         }
2890         ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, imageUnit));
2891     }
2892 
2893     return angle::Result::Continue;
2894 }
2895 
getUAVsForRWImages(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)2896 angle::Result StateManager11::getUAVsForRWImages(const gl::Context *context,
2897                                                  gl::ShaderType shaderType,
2898                                                  UAVList *uavList)
2899 {
2900     const auto &glState = context->getState();
2901     const auto &caps    = context->getCaps();
2902 
2903     const gl::RangeUI imageRange = mExecutableD3D->getUsedImageRange(shaderType, false);
2904     for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
2905     {
2906         GLint imageUnitIndex = mExecutableD3D->getImageMapping(shaderType, imageIndex, false, caps);
2907         ASSERT(imageUnitIndex != -1);
2908         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2909         if (!imageUnit.layered)
2910         {
2911             ANGLE_TRY(setImageState(context, shaderType, imageIndex - imageRange.low(), imageUnit));
2912         }
2913         ANGLE_TRY(getUAVForRWImage(context, shaderType, imageIndex, imageUnit, uavList));
2914     }
2915 
2916     return angle::Result::Continue;
2917 }
2918 
syncTexturesForCompute(const gl::Context * context)2919 angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
2920 {
2921     ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
2922     return angle::Result::Continue;
2923 }
2924 
setTextureForImage(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit)2925 angle::Result StateManager11::setTextureForImage(const gl::Context *context,
2926                                                  gl::ShaderType type,
2927                                                  int index,
2928                                                  const gl::ImageUnit &imageUnit)
2929 {
2930     TextureD3D *textureImpl = nullptr;
2931     if (!imageUnit.texture.get())
2932     {
2933         setShaderResourceInternal<d3d11::ShaderResourceView>(type, static_cast<UINT>(index),
2934                                                              nullptr);
2935         return angle::Result::Continue;
2936     }
2937 
2938     textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
2939 
2940     // Ensure that texture has unordered access; convert it if not.
2941     ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
2942 
2943     TextureStorage *texStorage = nullptr;
2944     ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2945     // Texture should be complete and have a storage
2946     ASSERT(texStorage);
2947     TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2948 
2949     const d3d11::SharedSRV *textureSRV = nullptr;
2950     ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
2951     // If we get an invalid SRV here, something went wrong in the texture class and we're
2952     // unexpectedly missing the shader resource view.
2953     ASSERT(textureSRV->valid());
2954     ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2955     setShaderResourceInternal(type, index, textureSRV);
2956 
2957     textureImpl->resetDirty();
2958     return angle::Result::Continue;
2959 }
2960 
getUAVForRWImage(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit,UAVList * uavList)2961 angle::Result StateManager11::getUAVForRWImage(const gl::Context *context,
2962                                                gl::ShaderType type,
2963                                                int index,
2964                                                const gl::ImageUnit &imageUnit,
2965                                                UAVList *uavList)
2966 {
2967     TextureD3D *textureImpl = nullptr;
2968     if (!imageUnit.texture.get())
2969     {
2970         setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(static_cast<UINT>(index),
2971                                                                    nullptr, uavList);
2972         return angle::Result::Continue;
2973     }
2974 
2975     textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
2976 
2977     // Ensure that texture has unordered access; convert it if not.
2978     ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
2979 
2980     TextureStorage *texStorage = nullptr;
2981     ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2982     // Texture should be complete and have a storage
2983     ASSERT(texStorage);
2984     TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2985 
2986     const d3d11::SharedUAV *textureUAV = nullptr;
2987     ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
2988     // If we get an invalid UAV here, something went wrong in the texture class and we're
2989     // unexpectedly missing the unordered access view.
2990     ASSERT(textureUAV->valid());
2991     ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2992     setUnorderedAccessViewInternal(index, textureUAV, uavList);
2993 
2994     textureImpl->resetDirty();
2995     return angle::Result::Continue;
2996 }
2997 
2998 // Things that affect a program's dirtyness:
2999 // 1. Directly changing the program executable -> triggered in StateManager11::syncState.
3000 // 2. The vertex attribute layout              -> triggered in VertexArray11::syncState/signal.
3001 // 3. The fragment shader's rendertargets      -> triggered in Framebuffer11::syncState/signal.
3002 // 4. Enabling/disabling rasterizer discard.   -> triggered in StateManager11::syncState.
3003 // 5. Enabling/disabling transform feedback.   -> checked in StateManager11::updateState.
3004 // 6. An internal shader was used.             -> triggered in StateManager11::set*Shader.
3005 // 7. Drawing with/without point sprites.      -> checked in StateManager11::updateState.
3006 // TODO(jmadill): Use dirty bits for transform feedback.
syncProgram(const gl::Context * context,gl::PrimitiveMode drawMode)3007 angle::Result StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode)
3008 {
3009     Context11 *context11  = GetImplAs<Context11>(context);
3010     RendererD3D *renderer = context11->getRenderer();
3011     ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
3012 
3013     const auto &glState = context->getState();
3014 
3015     // TODO: change mExecutableD3D to mExecutableD3D?
3016     mExecutableD3D->updateCachedInputLayout(context11->getRenderer(),
3017                                             mVertexArray11->getCurrentStateSerial(), glState);
3018 
3019     // Binaries must be compiled before the sync.
3020     ASSERT(mExecutableD3D->hasVertexExecutableForCachedInputLayout());
3021     ASSERT(mExecutableD3D->hasGeometryExecutableForPrimitiveType(context11->getRenderer(), glState,
3022                                                                  drawMode));
3023     ASSERT(mExecutableD3D->hasPixelExecutableForCachedOutputLayout());
3024 
3025     ShaderExecutableD3D *vertexExe = nullptr;
3026     ANGLE_TRY(mExecutableD3D->getVertexExecutableForCachedInputLayout(context11, renderer,
3027                                                                       &vertexExe, nullptr));
3028 
3029     ShaderExecutableD3D *pixelExe = nullptr;
3030     ANGLE_TRY(mExecutableD3D->getPixelExecutableForCachedOutputLayout(context11, renderer,
3031                                                                       &pixelExe, nullptr));
3032 
3033     ShaderExecutableD3D *geometryExe = nullptr;
3034     ANGLE_TRY(mExecutableD3D->getGeometryExecutableForPrimitiveType(
3035         context11, renderer, glState.getCaps(), glState.getProvokingVertex(), drawMode,
3036         &geometryExe, nullptr));
3037 
3038     const d3d11::VertexShader *vertexShader =
3039         (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
3040 
3041     // Skip pixel shader if we're doing rasterizer discard.
3042     const d3d11::PixelShader *pixelShader = nullptr;
3043     if (!glState.getRasterizerState().rasterizerDiscard)
3044     {
3045         pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
3046     }
3047 
3048     const d3d11::GeometryShader *geometryShader = nullptr;
3049     if (glState.isTransformFeedbackActiveUnpaused())
3050     {
3051         geometryShader =
3052             (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
3053     }
3054     else
3055     {
3056         geometryShader =
3057             (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
3058     }
3059 
3060     setDrawShaders(vertexShader, geometryShader, pixelShader);
3061 
3062     // Explicitly clear the shaders dirty bit.
3063     mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
3064 
3065     return angle::Result::Continue;
3066 }
3067 
syncProgramForCompute(const gl::Context * context)3068 angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
3069 {
3070     Context11 *context11 = GetImplAs<Context11>(context);
3071     ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));
3072 
3073     mExecutableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Compute);
3074 
3075     // Binaries must be compiled before the sync.
3076     ASSERT(mExecutableD3D->hasComputeExecutableForCachedImage2DBindLayout());
3077 
3078     ShaderExecutableD3D *computeExe = nullptr;
3079     ANGLE_TRY(mExecutableD3D->getComputeExecutableForImage2DBindLayout(
3080         context11, context11->getRenderer(), &computeExe, nullptr));
3081 
3082     const d3d11::ComputeShader *computeShader =
3083         (computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
3084     setComputeShader(computeShader);
3085     // Explicitly clear the shaders dirty bit.
3086     mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
3087 
3088     return angle::Result::Continue;
3089 }
3090 
syncVertexBuffersAndInputLayout(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,GLsizei instanceCount)3091 angle::Result StateManager11::syncVertexBuffersAndInputLayout(
3092     const gl::Context *context,
3093     gl::PrimitiveMode mode,
3094     GLint firstVertex,
3095     GLsizei vertexOrIndexCount,
3096     gl::DrawElementsType indexTypeOrInvalid,
3097     GLsizei instanceCount)
3098 {
3099     const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();
3100 
3101     // Sort the attributes according to ensure we re-use similar input layouts.
3102     AttribIndexArray sortedSemanticIndices;
3103     SortAttributesByLayout(*mExecutableD3D, vertexArrayAttribs, mCurrentValueAttribs,
3104                            &sortedSemanticIndices, &mCurrentAttributes);
3105 
3106     D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
3107 
3108     // If we are using FL 9_3, make sure the first attribute is not instanced
3109     if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
3110     {
3111         if (mCurrentAttributes[0]->divisor > 0)
3112         {
3113             Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
3114             if (firstNonInstancedIndex.valid())
3115             {
3116                 size_t index = firstNonInstancedIndex.value();
3117                 std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
3118                 std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
3119             }
3120         }
3121     }
3122 
3123     // Update the applied input layout by querying the cache.
3124     const gl::State &state                = context->getState();
3125     const d3d11::InputLayout *inputLayout = nullptr;
3126     ANGLE_TRY(mInputLayoutCache.getInputLayout(GetImplAs<Context11>(context), state,
3127                                                mCurrentAttributes, sortedSemanticIndices, mode,
3128                                                vertexOrIndexCount, instanceCount, &inputLayout));
3129     setInputLayoutInternal(inputLayout);
3130 
3131     // Update the applied vertex buffers.
3132     ANGLE_TRY(applyVertexBuffers(context, mode, indexTypeOrInvalid, firstVertex));
3133 
3134     return angle::Result::Continue;
3135 }
3136 
applyVertexBuffers(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexTypeOrInvalid,GLint firstVertex)3137 angle::Result StateManager11::applyVertexBuffers(const gl::Context *context,
3138                                                  gl::PrimitiveMode mode,
3139                                                  gl::DrawElementsType indexTypeOrInvalid,
3140                                                  GLint firstVertex)
3141 {
3142     for (size_t attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; ++attribIndex)
3143     {
3144         ID3D11Buffer *buffer = nullptr;
3145         UINT vertexStride    = 0;
3146         UINT vertexOffset    = 0;
3147 
3148         if (attribIndex < mCurrentAttributes.size())
3149         {
3150             const TranslatedAttribute &attrib = *mCurrentAttributes[attribIndex];
3151             Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
3152 
3153             // If indexed pointsprite emulation is active, then we need to take a less efficent code
3154             // path. Emulated indexed pointsprite rendering requires that the vertex buffers match
3155             // exactly to the indices passed by the caller.  This could expand or shrink the vertex
3156             // buffer depending on the number of points indicated by the index list or how many
3157             // duplicates are found on the index list.
3158             if (bufferStorage == nullptr)
3159             {
3160                 ASSERT(attrib.vertexBuffer.get());
3161                 buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
3162             }
3163             else
3164             {
3165                 ANGLE_TRY(bufferStorage->getBuffer(
3166                     context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer));
3167             }
3168 
3169             vertexStride = attrib.stride;
3170             ANGLE_TRY(attrib.computeOffset(context, firstVertex, &vertexOffset));
3171         }
3172 
3173         queueVertexBufferChange(attribIndex, buffer, vertexStride, vertexOffset);
3174     }
3175 
3176     applyVertexBufferChanges();
3177     return angle::Result::Continue;
3178 }
3179 
applyIndexBuffer(const gl::Context * context,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices)3180 angle::Result StateManager11::applyIndexBuffer(const gl::Context *context,
3181                                                GLsizei indexCount,
3182                                                gl::DrawElementsType indexType,
3183                                                const void *indices)
3184 {
3185     if (!mIndexBufferIsDirty)
3186     {
3187         // No streaming or index buffer application necessary.
3188         return angle::Result::Continue;
3189     }
3190 
3191     gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType();
3192     gl::Buffer *elementArrayBuffer       = mVertexArray11->getState().getElementArrayBuffer();
3193 
3194     TranslatedIndexData indexInfo;
3195     ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount,
3196                                                  elementArrayBuffer, indices, &indexInfo));
3197 
3198     ID3D11Buffer *buffer     = nullptr;
3199     DXGI_FORMAT bufferFormat = (indexInfo.indexType == gl::DrawElementsType::UnsignedInt)
3200                                    ? DXGI_FORMAT_R32_UINT
3201                                    : DXGI_FORMAT_R16_UINT;
3202 
3203     if (indexInfo.storage)
3204     {
3205         Buffer11 *storage = GetAs<Buffer11>(indexInfo.storage);
3206         ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer));
3207     }
3208     else
3209     {
3210         IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo.indexBuffer);
3211         buffer                     = indexBuffer->getBuffer().get();
3212     }
3213 
3214     // Track dirty indices in the index range cache.
3215     indexInfo.srcIndexData.srcIndicesChanged =
3216         syncIndexBuffer(buffer, bufferFormat, indexInfo.startOffset);
3217 
3218     mIndexBufferIsDirty = false;
3219 
3220     mVertexArray11->updateCachedIndexInfo(indexInfo);
3221     return angle::Result::Continue;
3222 }
3223 
setIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3224 void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
3225                                     DXGI_FORMAT indexFormat,
3226                                     unsigned int offset)
3227 {
3228     if (syncIndexBuffer(buffer, indexFormat, offset))
3229     {
3230         invalidateIndexBuffer();
3231     }
3232 }
3233 
syncIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3234 bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
3235                                      DXGI_FORMAT indexFormat,
3236                                      unsigned int offset)
3237 {
3238     if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
3239     {
3240         mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
3241 
3242         mAppliedIB       = buffer;
3243         mAppliedIBFormat = indexFormat;
3244         mAppliedIBOffset = offset;
3245         return true;
3246     }
3247 
3248     return false;
3249 }
3250 
3251 // Vertex buffer is invalidated outside this function.
updateVertexOffsetsForPointSpritesEmulation(const gl::Context * context,GLint startVertex,GLsizei emulatedInstanceId)3252 angle::Result StateManager11::updateVertexOffsetsForPointSpritesEmulation(
3253     const gl::Context *context,
3254     GLint startVertex,
3255     GLsizei emulatedInstanceId)
3256 {
3257     size_t reservedBuffers = GetReservedBufferCount(true);
3258     for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
3259     {
3260         const auto &attrib = *mCurrentAttributes[attribIndex];
3261         size_t bufferIndex = reservedBuffers + attribIndex;
3262 
3263         if (attrib.divisor > 0)
3264         {
3265             unsigned int offset = 0;
3266             ANGLE_TRY(attrib.computeOffset(context, startVertex, &offset));
3267             offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
3268             if (offset != mCurrentVertexOffsets[bufferIndex])
3269             {
3270                 invalidateInputLayout();
3271                 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
3272                 mCurrentVertexOffsets[bufferIndex] = offset;
3273             }
3274         }
3275     }
3276 
3277     applyVertexBufferChanges();
3278     return angle::Result::Continue;
3279 }
3280 
generateSwizzle(const gl::Context * context,gl::Texture * texture)3281 angle::Result StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
3282 {
3283     if (!texture)
3284     {
3285         return angle::Result::Continue;
3286     }
3287 
3288     TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
3289     ASSERT(textureD3D);
3290 
3291     TextureStorage *texStorage = nullptr;
3292     ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
3293 
3294     if (texStorage)
3295     {
3296         TextureStorage11 *storage11          = GetAs<TextureStorage11>(texStorage);
3297         const gl::TextureState &textureState = texture->getTextureState();
3298         ANGLE_TRY(storage11->generateSwizzles(context, textureState));
3299     }
3300 
3301     return angle::Result::Continue;
3302 }
3303 
generateSwizzlesForShader(const gl::Context * context,gl::ShaderType type)3304 angle::Result StateManager11::generateSwizzlesForShader(const gl::Context *context,
3305                                                         gl::ShaderType type)
3306 {
3307     const gl::State &glState       = context->getState();
3308     const gl::RangeUI samplerRange = mExecutableD3D->getUsedSamplerRange(type);
3309 
3310     for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
3311     {
3312         gl::TextureType textureType = mExecutableD3D->getSamplerTextureType(type, i);
3313         GLint textureUnit = mExecutableD3D->getSamplerMapping(type, i, context->getCaps());
3314         if (textureUnit != -1)
3315         {
3316             gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
3317             ASSERT(texture);
3318             if (SwizzleRequired(texture->getTextureState()))
3319             {
3320                 ANGLE_TRY(generateSwizzle(context, texture));
3321             }
3322         }
3323     }
3324 
3325     return angle::Result::Continue;
3326 }
3327 
generateSwizzles(const gl::Context * context)3328 angle::Result StateManager11::generateSwizzles(const gl::Context *context)
3329 {
3330     ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Vertex));
3331     ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Fragment));
3332     return angle::Result::Continue;
3333 }
3334 
applyUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3335 angle::Result StateManager11::applyUniformsForShader(const gl::Context *context,
3336                                                      gl::ShaderType shaderType)
3337 {
3338     UniformStorage11 *shaderUniformStorage =
3339         GetAs<UniformStorage11>(mExecutableD3D->getShaderUniformStorage(shaderType));
3340     ASSERT(shaderUniformStorage);
3341 
3342     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3343 
3344     const d3d11::Buffer *shaderConstantBuffer = nullptr;
3345     ANGLE_TRY(shaderUniformStorage->getConstantBuffer(context, mRenderer, &shaderConstantBuffer));
3346 
3347     if (shaderUniformStorage->size() > 0 && mExecutableD3D->areShaderUniformsDirty(shaderType))
3348     {
3349         UpdateUniformBuffer(deviceContext, shaderUniformStorage, shaderConstantBuffer);
3350     }
3351 
3352     unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
3353 
3354     switch (shaderType)
3355     {
3356         case gl::ShaderType::Vertex:
3357             if (mCurrentConstantBufferVS[slot] != shaderConstantBuffer->getSerial())
3358             {
3359                 deviceContext->VSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3360                 mCurrentConstantBufferVS[slot]       = shaderConstantBuffer->getSerial();
3361                 mCurrentConstantBufferVSOffset[slot] = 0;
3362                 mCurrentConstantBufferVSSize[slot]   = 0;
3363             }
3364             break;
3365 
3366         case gl::ShaderType::Fragment:
3367             if (mCurrentConstantBufferPS[slot] != shaderConstantBuffer->getSerial())
3368             {
3369                 deviceContext->PSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3370                 mCurrentConstantBufferPS[slot]       = shaderConstantBuffer->getSerial();
3371                 mCurrentConstantBufferPSOffset[slot] = 0;
3372                 mCurrentConstantBufferPSSize[slot]   = 0;
3373             }
3374             break;
3375 
3376         // TODO([email protected]): apply geometry shader uniforms
3377         case gl::ShaderType::Geometry:
3378             UNIMPLEMENTED();
3379             break;
3380 
3381         default:
3382             UNREACHABLE();
3383             break;
3384     }
3385 
3386     return angle::Result::Continue;
3387 }
3388 
applyUniforms(const gl::Context * context)3389 angle::Result StateManager11::applyUniforms(const gl::Context *context)
3390 {
3391     ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Vertex));
3392     ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Fragment));
3393     if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3394     {
3395         ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Geometry));
3396     }
3397 
3398     mExecutableD3D->markUniformsClean();
3399 
3400     return angle::Result::Continue;
3401 }
3402 
applyDriverUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3403 angle::Result StateManager11::applyDriverUniformsForShader(const gl::Context *context,
3404                                                            gl::ShaderType shaderType)
3405 {
3406     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3407 
3408     d3d11::Buffer &shaderDriverConstantBuffer = mShaderDriverConstantBuffers[shaderType];
3409     if (!shaderDriverConstantBuffer.valid())
3410     {
3411         size_t requiredSize = mShaderConstants.getRequiredBufferSize(shaderType);
3412 
3413         D3D11_BUFFER_DESC constantBufferDescription = {};
3414         d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3415         ANGLE_TRY(mRenderer->allocateResource(
3416             GetImplAs<Context11>(context), constantBufferDescription, &shaderDriverConstantBuffer));
3417 
3418         ID3D11Buffer *driverConstants = shaderDriverConstantBuffer.get();
3419         switch (shaderType)
3420         {
3421             case gl::ShaderType::Vertex:
3422                 deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3423                                                     &driverConstants);
3424                 break;
3425 
3426             case gl::ShaderType::Fragment:
3427                 deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3428                                                     &driverConstants);
3429                 break;
3430 
3431             case gl::ShaderType::Geometry:
3432                 deviceContext->GSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3433                                                     &driverConstants);
3434                 break;
3435 
3436             default:
3437                 UNREACHABLE();
3438                 return angle::Result::Continue;
3439         }
3440     }
3441 
3442     // Sampler metadata and driver constants need to coexist in the same constant buffer to
3443     // conserve constant buffer slots. We update both in the constant buffer if needed.
3444     ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, shaderType, *mExecutableD3D,
3445                                             shaderDriverConstantBuffer));
3446 
3447     return angle::Result::Continue;
3448 }
3449 
applyDriverUniforms(const gl::Context * context)3450 angle::Result StateManager11::applyDriverUniforms(const gl::Context *context)
3451 {
3452     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3453 
3454     ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Vertex));
3455     ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Fragment));
3456     if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3457     {
3458         ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Geometry));
3459     }
3460 
3461     // needed for the point sprite geometry shader
3462     // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
3463     if (mRenderer->isES3Capable())
3464     {
3465         d3d11::Buffer &driverConstantBufferPS =
3466             mShaderDriverConstantBuffers[gl::ShaderType::Fragment];
3467         if (mCurrentGeometryConstantBuffer != driverConstantBufferPS.getSerial())
3468         {
3469             ASSERT(driverConstantBufferPS.valid());
3470             deviceContext->GSSetConstantBuffers(0, 1, driverConstantBufferPS.getPointer());
3471             mCurrentGeometryConstantBuffer = driverConstantBufferPS.getSerial();
3472         }
3473     }
3474 
3475     return angle::Result::Continue;
3476 }
3477 
applyComputeUniforms(const gl::Context * context,ProgramExecutableD3D * executableD3D)3478 angle::Result StateManager11::applyComputeUniforms(const gl::Context *context,
3479                                                    ProgramExecutableD3D *executableD3D)
3480 {
3481     UniformStorage11 *computeUniformStorage =
3482         GetAs<UniformStorage11>(executableD3D->getShaderUniformStorage(gl::ShaderType::Compute));
3483     ASSERT(computeUniformStorage);
3484 
3485     const d3d11::Buffer *constantBuffer = nullptr;
3486     ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer));
3487 
3488     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3489 
3490     if (computeUniformStorage->size() > 0 &&
3491         executableD3D->areShaderUniformsDirty(gl::ShaderType::Compute))
3492     {
3493         UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
3494         executableD3D->markUniformsClean();
3495     }
3496 
3497     if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
3498     {
3499         deviceContext->CSSetConstantBuffers(
3500             d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
3501             constantBuffer->getPointer());
3502         mCurrentComputeConstantBuffer = constantBuffer->getSerial();
3503     }
3504 
3505     if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid())
3506     {
3507         size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute);
3508 
3509         D3D11_BUFFER_DESC constantBufferDescription = {};
3510         d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3511         ANGLE_TRY(
3512             mRenderer->allocateResource(GetImplAs<Context11>(context), constantBufferDescription,
3513                                         &mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3514         ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get();
3515         deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3516                                             &buffer);
3517     }
3518 
3519     ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute,
3520                                             *executableD3D,
3521                                             mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3522 
3523     return angle::Result::Continue;
3524 }
3525 
syncUniformBuffersForShader(const gl::Context * context,gl::ShaderType shaderType)3526 angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context,
3527                                                           gl::ShaderType shaderType)
3528 {
3529     const auto &glState                  = context->getState();
3530     ID3D11DeviceContext *deviceContext   = mRenderer->getDeviceContext();
3531     ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
3532 
3533     const auto &shaderUniformBuffers = mExecutableD3D->getShaderUniformBufferCache(shaderType);
3534 
3535     for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffers.size(); ++bufferIndex)
3536     {
3537         const D3DUBOCache cache = shaderUniformBuffers[bufferIndex];
3538         if (cache.binding == -1)
3539         {
3540             continue;
3541         }
3542 
3543         const auto &uniformBuffer          = glState.getIndexedUniformBuffer(cache.binding);
3544         const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3545         const GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
3546 
3547         if (uniformBuffer.get() == nullptr)
3548         {
3549             continue;
3550         }
3551 
3552         Buffer11 *bufferStorage             = GetImplAs<Buffer11>(uniformBuffer.get());
3553         const d3d11::Buffer *constantBuffer = nullptr;
3554         UINT firstConstant                  = 0;
3555         UINT numConstants                   = 0;
3556 
3557         ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
3558                                                         uniformBufferSize, &constantBuffer,
3559                                                         &firstConstant, &numConstants));
3560         ASSERT(constantBuffer);
3561 
3562         switch (shaderType)
3563         {
3564             case gl::ShaderType::Vertex:
3565             {
3566                 if (mCurrentConstantBufferVS[cache.registerIndex] == constantBuffer->getSerial() &&
3567                     mCurrentConstantBufferVSOffset[cache.registerIndex] == uniformBufferOffset &&
3568                     mCurrentConstantBufferVSSize[cache.registerIndex] == uniformBufferSize)
3569                 {
3570                     continue;
3571                 }
3572 
3573                 if (firstConstant != 0 && uniformBufferSize != 0)
3574                 {
3575                     ASSERT(numConstants != 0);
3576                     deviceContext1->VSSetConstantBuffers1(cache.registerIndex, 1,
3577                                                           constantBuffer->getPointer(),
3578                                                           &firstConstant, &numConstants);
3579                 }
3580                 else
3581                 {
3582                     deviceContext->VSSetConstantBuffers(cache.registerIndex, 1,
3583                                                         constantBuffer->getPointer());
3584                 }
3585 
3586                 mCurrentConstantBufferVS[cache.registerIndex]       = constantBuffer->getSerial();
3587                 mCurrentConstantBufferVSOffset[cache.registerIndex] = uniformBufferOffset;
3588                 mCurrentConstantBufferVSSize[cache.registerIndex]   = uniformBufferSize;
3589                 break;
3590             }
3591 
3592             case gl::ShaderType::Fragment:
3593             {
3594                 if (mCurrentConstantBufferPS[cache.registerIndex] == constantBuffer->getSerial() &&
3595                     mCurrentConstantBufferPSOffset[cache.registerIndex] == uniformBufferOffset &&
3596                     mCurrentConstantBufferPSSize[cache.registerIndex] == uniformBufferSize)
3597                 {
3598                     continue;
3599                 }
3600 
3601                 if (firstConstant != 0 && uniformBufferSize != 0)
3602                 {
3603                     deviceContext1->PSSetConstantBuffers1(cache.registerIndex, 1,
3604                                                           constantBuffer->getPointer(),
3605                                                           &firstConstant, &numConstants);
3606                 }
3607                 else
3608                 {
3609                     deviceContext->PSSetConstantBuffers(cache.registerIndex, 1,
3610                                                         constantBuffer->getPointer());
3611                 }
3612 
3613                 mCurrentConstantBufferPS[cache.registerIndex]       = constantBuffer->getSerial();
3614                 mCurrentConstantBufferPSOffset[cache.registerIndex] = uniformBufferOffset;
3615                 mCurrentConstantBufferPSSize[cache.registerIndex]   = uniformBufferSize;
3616                 break;
3617             }
3618 
3619             case gl::ShaderType::Compute:
3620             {
3621                 if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() &&
3622                     mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset &&
3623                     mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize)
3624                 {
3625                     continue;
3626                 }
3627 
3628                 if (firstConstant != 0 && uniformBufferSize != 0)
3629                 {
3630                     deviceContext1->CSSetConstantBuffers1(cache.registerIndex, 1,
3631                                                           constantBuffer->getPointer(),
3632                                                           &firstConstant, &numConstants);
3633                 }
3634                 else
3635                 {
3636                     deviceContext->CSSetConstantBuffers(cache.registerIndex, 1,
3637                                                         constantBuffer->getPointer());
3638                 }
3639 
3640                 mCurrentConstantBufferCS[cache.registerIndex]       = constantBuffer->getSerial();
3641                 mCurrentConstantBufferCSOffset[cache.registerIndex] = uniformBufferOffset;
3642                 mCurrentConstantBufferCSSize[cache.registerIndex]   = uniformBufferSize;
3643                 break;
3644             }
3645 
3646             // TODO([email protected]): update geometry shader uniform buffers.
3647             case gl::ShaderType::Geometry:
3648                 UNIMPLEMENTED();
3649                 break;
3650 
3651             default:
3652                 UNREACHABLE();
3653         }
3654     }
3655 
3656     const auto &shaderUniformBuffersUseSB =
3657         mExecutableD3D->getShaderUniformBufferCacheUseSB(shaderType);
3658     for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffersUseSB.size(); ++bufferIndex)
3659     {
3660         const D3DUBOCacheUseSB cache = shaderUniformBuffersUseSB[bufferIndex];
3661         if (cache.binding == -1)
3662         {
3663             continue;
3664         }
3665 
3666         const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
3667         if (uniformBuffer.get() == nullptr)
3668         {
3669             continue;
3670         }
3671         const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3672 
3673         Buffer11 *bufferStorage                    = GetImplAs<Buffer11>(uniformBuffer.get());
3674         const d3d11::ShaderResourceView *bufferSRV = nullptr;
3675         ANGLE_TRY(bufferStorage->getStructuredBufferRangeSRV(
3676             context, static_cast<unsigned int>(uniformBufferOffset), cache.byteWidth,
3677             cache.structureByteStride, &bufferSRV));
3678 
3679         ASSERT(bufferSRV->valid());
3680         setShaderResourceInternal(shaderType, cache.registerIndex, bufferSRV);
3681     }
3682 
3683     return angle::Result::Continue;
3684 }
3685 
getUAVsForShaderStorageBuffers(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3686 angle::Result StateManager11::getUAVsForShaderStorageBuffers(const gl::Context *context,
3687                                                              gl::ShaderType shaderType,
3688                                                              UAVList *uavList)
3689 {
3690     const gl::State &glState                = context->getState();
3691     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3692     angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
3693         previouslyBound;
3694     for (size_t blockIndex = 0; blockIndex < executable->getShaderStorageBlocks().size();
3695          blockIndex++)
3696     {
3697         GLuint binding = executable->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
3698         const unsigned int registerIndex = mExecutableD3D->getShaderStorageBufferRegisterIndex(
3699             static_cast<GLuint>(blockIndex), shaderType);
3700         // It means this block is active but not statically used.
3701         if (registerIndex == GL_INVALID_INDEX)
3702         {
3703             continue;
3704         }
3705         const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
3706         if (shaderStorageBuffer.get() == nullptr)
3707         {
3708             // We didn't see a driver error like atomic buffer did. But theoretically, the same
3709             // thing should be done.
3710             setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
3711                                                                        uavList);
3712             continue;
3713         }
3714 
3715         Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
3716         if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
3717             previouslyBound.end())
3718         {
3719             // D3D11 doesn't support binding a buffer multiple times
3720             // http://anglebug.com/42261718
3721             ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
3722             return angle::Result::Stop;
3723         }
3724         previouslyBound.push_back(bufferStorage);
3725 
3726         d3d11::UnorderedAccessView *uavPtr = nullptr;
3727         GLsizeiptr viewSize                = 0;
3728         // Bindings only have a valid size if bound using glBindBufferRange
3729         if (shaderStorageBuffer.getSize() > 0)
3730         {
3731             viewSize = shaderStorageBuffer.getSize();
3732         }
3733         // We use the buffer size for glBindBufferBase
3734         else
3735         {
3736             viewSize = bufferStorage->getSize();
3737         }
3738         ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
3739                                                 &uavPtr));
3740 
3741         setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
3742     }
3743 
3744     return angle::Result::Continue;
3745 }
3746 
syncUniformBuffers(const gl::Context * context)3747 angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
3748 {
3749     mExecutableD3D->updateUniformBufferCache(context->getCaps());
3750 
3751     if (mExecutableD3D->hasShaderStage(gl::ShaderType::Compute))
3752     {
3753         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute));
3754     }
3755     else
3756     {
3757         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex));
3758         ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment));
3759         if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3760         {
3761             ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry));
3762         }
3763     }
3764 
3765     return angle::Result::Continue;
3766 }
3767 
getUAVsForAtomicCounterBuffers(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3768 angle::Result StateManager11::getUAVsForAtomicCounterBuffers(const gl::Context *context,
3769                                                              gl::ShaderType shaderType,
3770                                                              UAVList *uavList)
3771 {
3772     const gl::State &glState                = context->getState();
3773     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3774     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
3775         executable->getAtomicCounterBuffers();
3776     for (size_t index = 0; index < atomicCounterBuffers.size(); ++index)
3777     {
3778         const GLuint binding = executable->getAtomicCounterBufferBinding(index);
3779         const auto &buffer   = glState.getIndexedAtomicCounterBuffer(binding);
3780         const unsigned int registerIndex =
3781             mExecutableD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
3782         ASSERT(registerIndex != GL_INVALID_INDEX);
3783         if (buffer.get() == nullptr)
3784         {
3785             // The atomic counter is used in shader. However, there is no buffer binding to it. We
3786             // should clear the corresponding UAV in case the previous view type is a texture not a
3787             // buffer. Otherwise, below error will be reported. The Unordered Access View dimension
3788             // declared in the shader code (BUFFER) does not match the view type bound to slot 0
3789             // of the Compute Shader unit (TEXTURE2D).
3790             setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
3791                                                                        uavList);
3792             continue;
3793         }
3794 
3795         Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
3796         // TODO([email protected]): Check to make sure that we aren't binding the same buffer
3797         // multiple times, as this is unsupported by D3D11. http://anglebug.com/42261818
3798 
3799         // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
3800         // buffer size for glBindBufferBase
3801         GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
3802         d3d11::UnorderedAccessView *uavPtr = nullptr;
3803         ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));
3804 
3805         setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
3806     }
3807 
3808     return angle::Result::Continue;
3809 }
3810 
getUAVsForShader(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3811 angle::Result StateManager11::getUAVsForShader(const gl::Context *context,
3812                                                gl::ShaderType shaderType,
3813                                                UAVList *uavList)
3814 {
3815     ANGLE_TRY(getUAVsForShaderStorageBuffers(context, shaderType, uavList));
3816     ANGLE_TRY(getUAVsForRWImages(context, shaderType, uavList));
3817     ANGLE_TRY(getUAVsForAtomicCounterBuffers(context, shaderType, uavList));
3818 
3819     return angle::Result::Continue;
3820 }
3821 
syncUAVsForGraphics(const gl::Context * context)3822 angle::Result StateManager11::syncUAVsForGraphics(const gl::Context *context)
3823 {
3824     UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
3825 
3826     ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Fragment, &uavList));
3827     ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Vertex, &uavList));
3828 
3829     if (uavList.highestUsed >= 0)
3830     {
3831         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3832         UINT baseUAVRegister = static_cast<UINT>(mExecutableD3D->getPixelShaderKey().size());
3833         deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
3834             D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, baseUAVRegister,
3835             uavList.highestUsed + 1, uavList.data.data(), nullptr);
3836     }
3837 
3838     return angle::Result::Continue;
3839 }
3840 
syncUAVsForCompute(const gl::Context * context)3841 angle::Result StateManager11::syncUAVsForCompute(const gl::Context *context)
3842 {
3843     UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
3844 
3845     ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Compute, &uavList));
3846 
3847     if (uavList.highestUsed >= 0)
3848     {
3849         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3850         deviceContext->CSSetUnorderedAccessViews(0, uavList.highestUsed + 1, uavList.data.data(),
3851                                                  nullptr);
3852     }
3853 
3854     return angle::Result::Continue;
3855 }
3856 
syncTransformFeedbackBuffers(const gl::Context * context)3857 angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
3858 {
3859     const auto &glState = context->getState();
3860 
3861     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3862 
3863     // If transform feedback is not active, unbind all buffers
3864     if (!glState.isTransformFeedbackActiveUnpaused())
3865     {
3866         if (mAppliedTFSerial != mEmptySerial)
3867         {
3868             deviceContext->SOSetTargets(0, nullptr, nullptr);
3869             mAppliedTFSerial = mEmptySerial;
3870         }
3871         return angle::Result::Continue;
3872     }
3873 
3874     gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
3875     TransformFeedback11 *tf11                = GetImplAs<TransformFeedback11>(transformFeedback);
3876     if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
3877     {
3878         return angle::Result::Continue;
3879     }
3880 
3881     const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
3882     ANGLE_TRY(tf11->getSOBuffers(context, &soBuffers));
3883     const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
3884 
3885     deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
3886 
3887     mAppliedTFSerial = tf11->getSerial();
3888     tf11->onApply();
3889 
3890     return angle::Result::Continue;
3891 }
3892 
syncPrimitiveTopology(const gl::State & glState,gl::PrimitiveMode currentDrawMode)3893 void StateManager11::syncPrimitiveTopology(const gl::State &glState,
3894                                            gl::PrimitiveMode currentDrawMode)
3895 {
3896     D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
3897     // Don't cull everything by default, this also resets if we were previously culling
3898     mCullEverything = false;
3899 
3900     switch (currentDrawMode)
3901     {
3902         case gl::PrimitiveMode::Points:
3903         {
3904             bool usesPointSize = mExecutableD3D->usesPointSize();
3905 
3906             // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
3907             // which affects varying interpolation. Since the value of gl_PointSize is
3908             // undefined when not written, just skip drawing to avoid unexpected results.
3909             if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
3910             {
3911                 // Notify developers of risking undefined behavior.
3912                 WARN() << "Point rendering without writing to gl_PointSize.";
3913                 mCullEverything = true;
3914                 return;
3915             }
3916 
3917             primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
3918             break;
3919         }
3920         case gl::PrimitiveMode::Lines:
3921             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
3922             break;
3923         case gl::PrimitiveMode::LineLoop:
3924             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
3925             break;
3926         case gl::PrimitiveMode::LineStrip:
3927             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
3928             break;
3929         case gl::PrimitiveMode::Triangles:
3930             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
3931             mCullEverything   = CullsEverything(glState);
3932             break;
3933         case gl::PrimitiveMode::TriangleStrip:
3934             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
3935             mCullEverything   = CullsEverything(glState);
3936             break;
3937         // emulate fans via rewriting index buffer
3938         case gl::PrimitiveMode::TriangleFan:
3939             primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
3940             mCullEverything   = CullsEverything(glState);
3941             break;
3942         default:
3943             UNREACHABLE();
3944             break;
3945     }
3946 
3947     setPrimitiveTopologyInternal(primitiveTopology);
3948 }
3949 
3950 }  // namespace rx
3951