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