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