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