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