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