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