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(jiawei.shao@intel.com): return geometry shader constant struct size
315 case gl::ShaderType::Geometry:
316 return 0u;
317
318 default:
319 UNREACHABLE();
320 return 0u;
321 }
322 }
323
getRequiredBufferSize(gl::ShaderType shaderType) const324 size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
325 {
326 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
327 return GetShaderConstantsStructSize(shaderType) +
328 mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) +
329 mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) +
330 mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata);
331 }
332
markDirty()333 void ShaderConstants11::markDirty()
334 {
335 mShaderConstantsDirty.set();
336 mNumActiveShaderSamplers.fill(0);
337 }
338
updateSamplerMetadata(SamplerMetadata * data,const gl::Texture & texture,const gl::SamplerState & samplerState)339 bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data,
340 const gl::Texture &texture,
341 const gl::SamplerState &samplerState)
342 {
343 bool dirty = false;
344 unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
345 gl::TextureTarget target = (texture.getType() == gl::TextureType::CubeMap)
346 ? gl::kCubeMapTextureTargetMin
347 : gl::NonCubeTextureTypeToTarget(texture.getType());
348 if (data->baseLevel != static_cast<int>(baseLevel))
349 {
350 data->baseLevel = static_cast<int>(baseLevel);
351 dirty = true;
352 }
353
354 // Some metadata is needed only for integer textures. We avoid updating the constant buffer
355 // unnecessarily by changing the data only in case the texture is an integer texture and
356 // the values have changed.
357 const gl::InternalFormat &info = *texture.getFormat(target, baseLevel).info;
358 if (!info.isInt() && !texture.getState().isStencilMode())
359 {
360 return dirty;
361 }
362
363 // Pack the wrap values into one integer so we can fit all the metadata in two 4-integer
364 // vectors.
365 const GLenum wrapS = samplerState.getWrapS();
366 const GLenum wrapT = samplerState.getWrapT();
367 const GLenum wrapR = samplerState.getWrapR();
368 const int wrapModes =
369 GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 3) | (GetWrapBits(wrapR) << 6);
370 if (data->wrapModes != wrapModes)
371 {
372 data->wrapModes = wrapModes;
373 dirty = true;
374 }
375
376 // Skip checking and syncing integer border color if it is not used
377 if (wrapS != GL_CLAMP_TO_BORDER && wrapT != GL_CLAMP_TO_BORDER && wrapR != GL_CLAMP_TO_BORDER)
378 {
379 return dirty;
380 }
381
382 // Use the sampler state border color only if it is integer, initialize to zeros otherwise
383 angle::ColorGeneric borderColor;
384 ASSERT(borderColor.colorI.red == 0 && borderColor.colorI.green == 0 &&
385 borderColor.colorI.blue == 0 && borderColor.colorI.alpha == 0);
386 if (samplerState.getBorderColor().type != angle::ColorGeneric::Type::Float)
387 {
388 borderColor = samplerState.getBorderColor();
389 }
390
391 // Adjust the border color value to the texture format
392 borderColor = AdjustBorderColor<false>(
393 borderColor,
394 angle::Format::Get(angle::Format::InternalFormatToID(info.sizedInternalFormat)),
395 texture.getState().isStencilMode());
396
397 ASSERT(static_cast<const void *>(borderColor.colorI.data()) ==
398 static_cast<const void *>(borderColor.colorUI.data()));
399 if (memcmp(data->intBorderColor, borderColor.colorI.data(), sizeof(data->intBorderColor)) != 0)
400 {
401 memcpy(data->intBorderColor, borderColor.colorI.data(), sizeof(data->intBorderColor));
402 dirty = true;
403 }
404
405 return dirty;
406 }
407
updateImageMetadata(ImageMetadata * data,const gl::ImageUnit & imageUnit)408 bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit)
409 {
410 bool dirty = false;
411
412 if (data->layer != static_cast<int>(imageUnit.layer))
413 {
414 data->layer = static_cast<int>(imageUnit.layer);
415 dirty = true;
416 }
417
418 if (data->level != static_cast<unsigned int>(imageUnit.level))
419 {
420 data->level = static_cast<unsigned int>(imageUnit.level);
421 dirty = true;
422 }
423
424 return dirty;
425 }
426
setComputeWorkGroups(GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)427 void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
428 GLuint numGroupsY,
429 GLuint numGroupsZ)
430 {
431 mCompute.numWorkGroups[0] = numGroupsX;
432 mCompute.numWorkGroups[1] = numGroupsY;
433 mCompute.numWorkGroups[2] = numGroupsZ;
434 mShaderConstantsDirty.set(gl::ShaderType::Compute);
435 }
436
onViewportChange(const gl::Rectangle & glViewport,const D3D11_VIEWPORT & dxViewport,const gl::Offset & glFragCoordOffset,bool is9_3,bool presentPathFast)437 void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
438 const D3D11_VIEWPORT &dxViewport,
439 const gl::Offset &glFragCoordOffset,
440 bool is9_3,
441 bool presentPathFast)
442 {
443 mShaderConstantsDirty.set(gl::ShaderType::Vertex);
444 mShaderConstantsDirty.set(gl::ShaderType::Fragment);
445
446 // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
447 // using viewAdjust (like the D3D9 renderer).
448 if (is9_3)
449 {
450 mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
451 2 * (glViewport.x - dxViewport.TopLeftX)) /
452 dxViewport.Width;
453 mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
454 2 * (glViewport.y - dxViewport.TopLeftY)) /
455 dxViewport.Height;
456 mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
457 mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
458 }
459
460 mPixel.viewCoords[0] = glViewport.width * 0.5f;
461 mPixel.viewCoords[1] = glViewport.height * 0.5f;
462 mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
463 mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);
464
465 // Instanced pointsprite emulation requires ViewCoords to be defined in the
466 // the vertex shader.
467 mVertex.viewCoords[0] = mPixel.viewCoords[0];
468 mVertex.viewCoords[1] = mPixel.viewCoords[1];
469 mVertex.viewCoords[2] = mPixel.viewCoords[2];
470 mVertex.viewCoords[3] = mPixel.viewCoords[3];
471
472 const float zNear = dxViewport.MinDepth;
473 const float zFar = dxViewport.MaxDepth;
474
475 mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
476 mPixel.depthFront[1] = (zNear + zFar) * 0.5f;
477
478 mVertex.depthRange[0] = zNear;
479 mVertex.depthRange[1] = zFar;
480 mVertex.depthRange[2] = zFar - zNear;
481
482 mPixel.depthRange[0] = zNear;
483 mPixel.depthRange[1] = zFar;
484 mPixel.depthRange[2] = zFar - zNear;
485
486 mPixel.viewScale[0] = 1.0f;
487 mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
488
489 mVertex.viewScale[0] = mPixel.viewScale[0];
490 mVertex.viewScale[1] = mPixel.viewScale[1];
491
492 mPixel.fragCoordOffset[0] = static_cast<float>(glFragCoordOffset.x);
493 mPixel.fragCoordOffset[1] = static_cast<float>(glFragCoordOffset.y);
494 }
495
496 // Update the ShaderConstants with a new first vertex and return whether the update dirties them.
onFirstVertexChange(GLint firstVertex)497 ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex)
498 {
499 // firstVertex should already include baseVertex, if any.
500 uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex);
501
502 bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex);
503 if (firstVertexDirty)
504 {
505 mVertex.firstVertex = newFirstVertex;
506 mShaderConstantsDirty.set(gl::ShaderType::Vertex);
507 }
508 return firstVertexDirty;
509 }
510
onSamplerChange(gl::ShaderType shaderType,unsigned int samplerIndex,const gl::Texture & texture,const gl::SamplerState & samplerState)511 void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
512 unsigned int samplerIndex,
513 const gl::Texture &texture,
514 const gl::SamplerState &samplerState)
515 {
516 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
517 if (updateSamplerMetadata(&mShaderSamplerMetadata[shaderType][samplerIndex], texture,
518 samplerState))
519 {
520 mNumActiveShaderSamplers[shaderType] = 0;
521 }
522 }
523
onImageChange(gl::ShaderType shaderType,unsigned int imageIndex,const gl::ImageUnit & imageUnit)524 bool ShaderConstants11::onImageChange(gl::ShaderType shaderType,
525 unsigned int imageIndex,
526 const gl::ImageUnit &imageUnit)
527 {
528 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
529 bool dirty = false;
530 if (imageUnit.access == GL_READ_ONLY)
531 {
532 if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit))
533 {
534 mNumActiveShaderReadonlyImages[shaderType] = 0;
535 dirty = true;
536 }
537 }
538 else
539 {
540 if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit))
541 {
542 mNumActiveShaderImages[shaderType] = 0;
543 dirty = true;
544 }
545 }
546 return dirty;
547 }
548
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/1594
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 // FL9_3 is limited to 4; 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 mPointSpriteVertexBuffer.reset();
2024 mPointSpriteIndexBuffer.reset();
2025 }
2026
2027 // Applies the render target surface, depth stencil surface, viewport rectangle and
2028 // scissor rectangle to the renderer
syncFramebuffer(const gl::Context * context)2029 angle::Result StateManager11::syncFramebuffer(const gl::Context *context)
2030 {
2031 // Check for zero-sized default framebuffer, which is a special case.
2032 // in this case we do not wish to modify any state and just silently return false.
2033 // this will not report any gl error but will cause the calling method to return.
2034 if (mFramebuffer11->getState().isDefault())
2035 {
2036 RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
2037 const gl::Extents &size = firstRT->getExtents();
2038 if (size.empty())
2039 {
2040 return angle::Result::Continue;
2041 }
2042 }
2043
2044 RTVArray framebufferRTVs = {{}};
2045 const auto &colorRTs = mFramebuffer11->getCachedColorRenderTargets();
2046
2047 size_t appliedRTIndex = 0;
2048 bool skipInactiveRTs = mRenderer->getFeatures().mrtPerfWorkaround.enabled;
2049 const auto &drawStates = mFramebuffer11->getState().getDrawBufferStates();
2050 gl::DrawBufferMask activeProgramOutputs =
2051 mExecutableD3D->getExecutable()->getActiveOutputVariablesMask();
2052 UINT maxExistingRT = 0;
2053 const auto &colorAttachments = mFramebuffer11->getState().getColorAttachments();
2054
2055 for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
2056 {
2057 const RenderTarget11 *renderTarget = colorRTs[rtIndex];
2058
2059 // Skip inactive rendertargets if the workaround is enabled.
2060 if (skipInactiveRTs &&
2061 (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
2062 {
2063 continue;
2064 }
2065
2066 if (renderTarget)
2067 {
2068 framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
2069 ASSERT(framebufferRTVs[appliedRTIndex]);
2070 maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
2071
2072 // Unset conflicting texture SRVs
2073 const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
2074 ASSERT(attachment.isAttached());
2075 unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
2076 }
2077
2078 appliedRTIndex++;
2079 }
2080
2081 // Get the depth stencil buffers
2082 ID3D11DepthStencilView *framebufferDSV = nullptr;
2083 const auto *depthStencilRenderTarget = mFramebuffer11->getCachedDepthStencilRenderTarget();
2084 if (depthStencilRenderTarget)
2085 {
2086 framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
2087 ASSERT(framebufferDSV);
2088
2089 // Unset conflicting texture SRVs
2090 const gl::FramebufferAttachment *attachment =
2091 mFramebuffer11->getState().getDepthOrStencilAttachment();
2092 ASSERT(attachment);
2093 unsetConflictingAttachmentResources(*attachment,
2094 depthStencilRenderTarget->getTexture().get());
2095 }
2096
2097 ASSERT(maxExistingRT <= static_cast<UINT>(context->getCaps().maxDrawBuffers));
2098
2099 // Apply the render target and depth stencil
2100 mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
2101 framebufferDSV);
2102 mCurRTVs.clear();
2103 for (UINT i = 0; i < maxExistingRT; i++)
2104 {
2105 mCurRTVs.update(i, framebufferRTVs[i]);
2106 }
2107 mCurrentDSV.clear();
2108 mCurrentDSV.update(0, framebufferDSV);
2109 return angle::Result::Continue;
2110 }
2111
invalidateCurrentValueAttrib(size_t attribIndex)2112 void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
2113 {
2114 mDirtyCurrentValueAttribs.set(attribIndex);
2115 mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
2116 invalidateInputLayout();
2117 invalidateShaders();
2118 }
2119
syncCurrentValueAttribs(const gl::Context * context,const std::vector<gl::VertexAttribCurrentValueData> & currentValues)2120 angle::Result StateManager11::syncCurrentValueAttribs(
2121 const gl::Context *context,
2122 const std::vector<gl::VertexAttribCurrentValueData> ¤tValues)
2123 {
2124 const gl::ProgramExecutable *executable = mExecutableD3D->getExecutable();
2125 const auto &activeAttribsMask = executable->getActiveAttribLocationsMask();
2126 const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
2127
2128 if (!dirtyActiveAttribs.any())
2129 {
2130 return angle::Result::Continue;
2131 }
2132
2133 const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
2134 const auto &vertexBindings = mVertexArray11->getState().getVertexBindings();
2135 mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
2136
2137 for (auto attribIndex : dirtyActiveAttribs)
2138 {
2139 if (vertexAttributes[attribIndex].enabled)
2140 continue;
2141
2142 const auto *attrib = &vertexAttributes[attribIndex];
2143 const auto ¤tValue = currentValues[attribIndex];
2144 TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
2145 currentValueAttrib->currentValueType = currentValue.Type;
2146 currentValueAttrib->attribute = attrib;
2147 currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex];
2148
2149 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
2150
2151 ANGLE_TRY(mVertexDataManager.storeCurrentValue(context, currentValue, currentValueAttrib,
2152 static_cast<size_t>(attribIndex)));
2153 }
2154
2155 return angle::Result::Continue;
2156 }
2157
setInputLayout(const d3d11::InputLayout * inputLayout)2158 void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
2159 {
2160 if (setInputLayoutInternal(inputLayout))
2161 {
2162 invalidateInputLayout();
2163 }
2164 }
2165
setInputLayoutInternal(const d3d11::InputLayout * inputLayout)2166 bool StateManager11::setInputLayoutInternal(const d3d11::InputLayout *inputLayout)
2167 {
2168 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2169 if (inputLayout == nullptr)
2170 {
2171 if (!mCurrentInputLayout.empty())
2172 {
2173 deviceContext->IASetInputLayout(nullptr);
2174 mCurrentInputLayout.clear();
2175 return true;
2176 }
2177 }
2178 else if (inputLayout->getSerial() != mCurrentInputLayout)
2179 {
2180 deviceContext->IASetInputLayout(inputLayout->get());
2181 mCurrentInputLayout = inputLayout->getSerial();
2182 return true;
2183 }
2184
2185 return false;
2186 }
2187
queueVertexBufferChange(size_t bufferIndex,ID3D11Buffer * buffer,UINT stride,UINT offset)2188 bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
2189 ID3D11Buffer *buffer,
2190 UINT stride,
2191 UINT offset)
2192 {
2193 if (buffer != mCurrentVertexBuffers[bufferIndex] ||
2194 stride != mCurrentVertexStrides[bufferIndex] ||
2195 offset != mCurrentVertexOffsets[bufferIndex])
2196 {
2197 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
2198
2199 mCurrentVertexBuffers[bufferIndex] = buffer;
2200 mCurrentVertexStrides[bufferIndex] = stride;
2201 mCurrentVertexOffsets[bufferIndex] = offset;
2202 return true;
2203 }
2204
2205 return false;
2206 }
2207
applyVertexBufferChanges()2208 void StateManager11::applyVertexBufferChanges()
2209 {
2210 if (mDirtyVertexBufferRange.empty())
2211 {
2212 return;
2213 }
2214
2215 ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
2216
2217 UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
2218
2219 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2220 deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
2221 &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
2222 &mCurrentVertexOffsets[start]);
2223
2224 mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
2225 }
2226
setSingleVertexBuffer(const d3d11::Buffer * buffer,UINT stride,UINT offset)2227 void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
2228 {
2229 ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
2230 if (queueVertexBufferChange(0, native, stride, offset))
2231 {
2232 invalidateInputLayout();
2233 applyVertexBufferChanges();
2234 }
2235 }
2236
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)2237 angle::Result StateManager11::updateState(const gl::Context *context,
2238 gl::PrimitiveMode mode,
2239 GLint firstVertex,
2240 GLsizei vertexOrIndexCount,
2241 gl::DrawElementsType indexTypeOrInvalid,
2242 const void *indices,
2243 GLsizei instanceCount,
2244 GLint baseVertex,
2245 GLuint baseInstance,
2246 bool promoteDynamic)
2247 {
2248 const gl::State &glState = context->getState();
2249
2250 // TODO(jmadill): Use dirty bits.
2251 if (mRenderTargetIsDirty)
2252 {
2253 processFramebufferInvalidation(context);
2254 mRenderTargetIsDirty = false;
2255 }
2256
2257 // TODO(jmadill): Use dirty bits.
2258 if (mExecutableD3D->isSamplerMappingDirty())
2259 {
2260 mExecutableD3D->updateSamplerMapping();
2261 invalidateTexturesAndSamplers();
2262 }
2263
2264 // TODO(jmadill): Use dirty bits.
2265 if (mExecutableD3D->anyShaderUniformsDirty())
2266 {
2267 mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
2268 }
2269
2270 // Swizzling can cause internal state changes with blit shaders.
2271 if (mDirtySwizzles)
2272 {
2273 ANGLE_TRY(generateSwizzles(context));
2274 mDirtySwizzles = false;
2275 }
2276
2277 ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));
2278
2279 // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
2280 // state changes.
2281 RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
2282 const int samples = (firstRT ? firstRT->getSamples() : 0);
2283 // Single-sampled rendering requires ignoring sample coverage and sample mask states.
2284 unsigned int sampleMask = (samples != 0) ? GetBlendSampleMask(glState, samples) : 0xFFFFFFFF;
2285 if (sampleMask != mCurSampleMask)
2286 {
2287 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2288 }
2289
2290 ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
2291 indexTypeOrInvalid, indices, instanceCount,
2292 baseVertex, baseInstance, promoteDynamic));
2293
2294 // Changes in the draw call can affect the vertex buffer translations.
2295 if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
2296 {
2297 mLastFirstVertex = firstVertex;
2298 invalidateInputLayout();
2299 }
2300
2301 // The ShaderConstants only need to be updated when the program uses vertexID
2302 if (mExecutableD3D->usesVertexID())
2303 {
2304 GLint firstVertexOnChange = firstVertex + baseVertex;
2305 ASSERT(mVertexArray11);
2306 if (mVertexArray11->hasActiveDynamicAttrib(context) &&
2307 indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
2308 {
2309 // drawElements with Dynamic attribute
2310 // the firstVertex is already including baseVertex when
2311 // doing ComputeStartVertex
2312 firstVertexOnChange = firstVertex;
2313 }
2314
2315 if (mShaderConstants.onFirstVertexChange(firstVertexOnChange))
2316 {
2317 mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
2318 }
2319 }
2320
2321 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
2322 {
2323 ANGLE_TRY(applyIndexBuffer(context, vertexOrIndexCount, indexTypeOrInvalid, indices));
2324 }
2325
2326 if (mLastAppliedDrawMode != mode)
2327 {
2328 mLastAppliedDrawMode = mode;
2329 mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2330
2331 bool pointDrawMode = (mode == gl::PrimitiveMode::Points);
2332 if (pointDrawMode != mCurRasterState.pointDrawMode)
2333 {
2334 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2335
2336 // Changing from points to not points (or vice-versa) affects the geometry shader.
2337 invalidateShaders();
2338 }
2339 }
2340
2341 auto dirtyBitsCopy = mInternalDirtyBits & mGraphicsDirtyBitsMask;
2342
2343 for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
2344 {
2345 mInternalDirtyBits.reset(*iter);
2346 switch (*iter)
2347 {
2348 case DIRTY_BIT_RENDER_TARGET:
2349 ANGLE_TRY(syncFramebuffer(context));
2350 break;
2351 case DIRTY_BIT_VIEWPORT_STATE:
2352 syncViewport(context);
2353 break;
2354 case DIRTY_BIT_SCISSOR_STATE:
2355 syncScissorRectangle(context);
2356 break;
2357 case DIRTY_BIT_RASTERIZER_STATE:
2358 ANGLE_TRY(syncRasterizerState(context, mode));
2359 break;
2360 case DIRTY_BIT_BLEND_STATE:
2361 // Single-sampled rendering requires ignoring alpha-to-coverage state.
2362 ANGLE_TRY(syncBlendState(context, glState.getBlendStateExt(),
2363 glState.getBlendColor(), sampleMask,
2364 glState.isSampleAlphaToCoverageEnabled() && (samples != 0),
2365 glState.hasConstantAlphaBlendFunc()));
2366 break;
2367 case DIRTY_BIT_DEPTH_STENCIL_STATE:
2368 ANGLE_TRY(syncDepthStencilState(context));
2369 break;
2370 case DIRTY_BIT_GRAPHICS_SRV_STATE:
2371 ANGLE_TRY(syncTextures(context));
2372 break;
2373 case DIRTY_BIT_GRAPHICS_UAV_STATE:
2374 ANGLE_TRY(syncUAVsForGraphics(context));
2375 break;
2376 case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
2377 // TODO(jmadill): More fine-grained update.
2378 ANGLE_TRY(syncTextures(context));
2379 break;
2380 case DIRTY_BIT_PROGRAM_UNIFORMS:
2381 ANGLE_TRY(applyUniforms(context));
2382 break;
2383 case DIRTY_BIT_DRIVER_UNIFORMS:
2384 // This must happen after viewport sync; the viewport affects builtin uniforms.
2385 ANGLE_TRY(applyDriverUniforms(context));
2386 break;
2387 case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
2388 ANGLE_TRY(syncUniformBuffers(context));
2389 break;
2390 case DIRTY_BIT_SHADERS:
2391 ANGLE_TRY(syncProgram(context, mode));
2392 break;
2393 case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
2394 ANGLE_TRY(syncCurrentValueAttribs(context, glState.getVertexAttribCurrentValues()));
2395 break;
2396 case DIRTY_BIT_TRANSFORM_FEEDBACK:
2397 ANGLE_TRY(syncTransformFeedbackBuffers(context));
2398 break;
2399 case DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT:
2400 ANGLE_TRY(syncVertexBuffersAndInputLayout(context, mode, firstVertex,
2401 vertexOrIndexCount, indexTypeOrInvalid,
2402 instanceCount));
2403 break;
2404 case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
2405 syncPrimitiveTopology(glState, mode);
2406 break;
2407 default:
2408 UNREACHABLE();
2409 break;
2410 }
2411 }
2412
2413 // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except
2414 // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit.
2415 ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none());
2416
2417 return angle::Result::Continue;
2418 }
2419
setShaderResourceShared(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::SharedSRV * srv)2420 void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
2421 UINT resourceSlot,
2422 const d3d11::SharedSRV *srv)
2423 {
2424 setShaderResourceInternal(shaderType, resourceSlot, srv);
2425
2426 // TODO(jmadill): Narrower dirty region.
2427 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2428 }
2429
setShaderResource(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::ShaderResourceView * srv)2430 void StateManager11::setShaderResource(gl::ShaderType shaderType,
2431 UINT resourceSlot,
2432 const d3d11::ShaderResourceView *srv)
2433 {
2434 setShaderResourceInternal(shaderType, resourceSlot, srv);
2435
2436 // TODO(jmadill): Narrower dirty region.
2437 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2438 }
2439
setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2440 void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2441 {
2442 if (setPrimitiveTopologyInternal(primitiveTopology))
2443 {
2444 mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
2445 }
2446 }
2447
setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2448 bool StateManager11::setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2449 {
2450 if (primitiveTopology != mCurrentPrimitiveTopology)
2451 {
2452 mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
2453 mCurrentPrimitiveTopology = primitiveTopology;
2454 return true;
2455 }
2456 else
2457 {
2458 return false;
2459 }
2460 }
2461
setDrawShaders(const d3d11::VertexShader * vertexShader,const d3d11::GeometryShader * geometryShader,const d3d11::PixelShader * pixelShader)2462 void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
2463 const d3d11::GeometryShader *geometryShader,
2464 const d3d11::PixelShader *pixelShader)
2465 {
2466 setVertexShader(vertexShader);
2467 setGeometryShader(geometryShader);
2468 setPixelShader(pixelShader);
2469 }
2470
setVertexShader(const d3d11::VertexShader * shader)2471 void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
2472 {
2473 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2474
2475 if (serial != mAppliedShaders[gl::ShaderType::Vertex])
2476 {
2477 ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
2478 mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
2479 mAppliedShaders[gl::ShaderType::Vertex] = serial;
2480 invalidateShaders();
2481 }
2482 }
2483
setGeometryShader(const d3d11::GeometryShader * shader)2484 void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
2485 {
2486 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2487
2488 if (serial != mAppliedShaders[gl::ShaderType::Geometry])
2489 {
2490 ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
2491 mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
2492 mAppliedShaders[gl::ShaderType::Geometry] = serial;
2493 invalidateShaders();
2494 }
2495 }
2496
setPixelShader(const d3d11::PixelShader * shader)2497 void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
2498 {
2499 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2500
2501 if (serial != mAppliedShaders[gl::ShaderType::Fragment])
2502 {
2503 ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
2504 mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
2505 mAppliedShaders[gl::ShaderType::Fragment] = serial;
2506 invalidateShaders();
2507 }
2508 }
2509
setComputeShader(const d3d11::ComputeShader * shader)2510 void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
2511 {
2512 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2513
2514 if (serial != mAppliedShaders[gl::ShaderType::Compute])
2515 {
2516 ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
2517 mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
2518 mAppliedShaders[gl::ShaderType::Compute] = serial;
2519 invalidateShaders();
2520 }
2521 }
2522
setVertexConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2523 void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2524 {
2525 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2526 auto ¤tSerial = mCurrentConstantBufferVS[slot];
2527
2528 mCurrentConstantBufferVSOffset[slot] = 0;
2529 mCurrentConstantBufferVSSize[slot] = 0;
2530
2531 if (buffer)
2532 {
2533 if (currentSerial != buffer->getSerial())
2534 {
2535 deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
2536 currentSerial = buffer->getSerial();
2537 invalidateConstantBuffer(slot);
2538 }
2539 }
2540 else
2541 {
2542 if (!currentSerial.empty())
2543 {
2544 ID3D11Buffer *nullBuffer = nullptr;
2545 deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
2546 currentSerial.clear();
2547 invalidateConstantBuffer(slot);
2548 }
2549 }
2550 }
2551
setPixelConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2552 void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2553 {
2554 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2555 auto ¤tSerial = mCurrentConstantBufferPS[slot];
2556
2557 mCurrentConstantBufferPSOffset[slot] = 0;
2558 mCurrentConstantBufferPSSize[slot] = 0;
2559
2560 if (buffer)
2561 {
2562 if (currentSerial != buffer->getSerial())
2563 {
2564 deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
2565 currentSerial = buffer->getSerial();
2566 invalidateConstantBuffer(slot);
2567 }
2568 }
2569 else
2570 {
2571 if (!currentSerial.empty())
2572 {
2573 ID3D11Buffer *nullBuffer = nullptr;
2574 deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
2575 currentSerial.clear();
2576 invalidateConstantBuffer(slot);
2577 }
2578 }
2579 }
2580
setDepthStencilState(const d3d11::DepthStencilState * depthStencilState,UINT stencilRef)2581 void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
2582 UINT stencilRef)
2583 {
2584 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2585
2586 if (depthStencilState)
2587 {
2588 deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
2589 }
2590 else
2591 {
2592 deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
2593 }
2594
2595 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
2596 }
2597
setSimpleBlendState(const d3d11::BlendState * blendState)2598 void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
2599 {
2600 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2601
2602 if (blendState)
2603 {
2604 deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
2605 }
2606 else
2607 {
2608 deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
2609 }
2610
2611 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2612 }
2613
setRasterizerState(const d3d11::RasterizerState * rasterizerState)2614 void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
2615 {
2616 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2617
2618 if (rasterizerState)
2619 {
2620 deviceContext->RSSetState(rasterizerState->get());
2621 }
2622 else
2623 {
2624 deviceContext->RSSetState(nullptr);
2625 }
2626
2627 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2628 }
2629
setSimpleViewport(const gl::Extents & extents)2630 void StateManager11::setSimpleViewport(const gl::Extents &extents)
2631 {
2632 setSimpleViewport(extents.width, extents.height);
2633 }
2634
setSimpleViewport(int width,int height)2635 void StateManager11::setSimpleViewport(int width, int height)
2636 {
2637 D3D11_VIEWPORT viewport;
2638 viewport.TopLeftX = 0;
2639 viewport.TopLeftY = 0;
2640 viewport.Width = static_cast<FLOAT>(width);
2641 viewport.Height = static_cast<FLOAT>(height);
2642 viewport.MinDepth = 0.0f;
2643 viewport.MaxDepth = 1.0f;
2644
2645 mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
2646 mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
2647 }
2648
setSimplePixelTextureAndSampler(const d3d11::SharedSRV & srv,const d3d11::SamplerState & samplerState)2649 void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
2650 const d3d11::SamplerState &samplerState)
2651 {
2652 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2653
2654 setShaderResourceInternal(gl::ShaderType::Fragment, 0, &srv);
2655 deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
2656
2657 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2658 mForceSetShaderSamplerStates[gl::ShaderType::Fragment][0] = true;
2659 }
2660
setSimpleScissorRect(const gl::Rectangle & glRect)2661 void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
2662 {
2663 D3D11_RECT scissorRect;
2664 scissorRect.left = glRect.x;
2665 scissorRect.right = glRect.x + glRect.width;
2666 scissorRect.top = glRect.y;
2667 scissorRect.bottom = glRect.y + glRect.height;
2668 setScissorRectD3D(scissorRect);
2669 }
2670
setScissorRectD3D(const D3D11_RECT & d3dRect)2671 void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
2672 {
2673 mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
2674 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
2675 }
2676
syncTextures(const gl::Context * context)2677 angle::Result StateManager11::syncTextures(const gl::Context *context)
2678 {
2679 ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
2680 ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
2681 if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
2682 {
2683 ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
2684 }
2685
2686 return angle::Result::Continue;
2687 }
2688
setSamplerState(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & samplerState)2689 angle::Result StateManager11::setSamplerState(const gl::Context *context,
2690 gl::ShaderType type,
2691 int index,
2692 gl::Texture *texture,
2693 const gl::SamplerState &samplerState)
2694 {
2695 #if !defined(NDEBUG)
2696 // Storage should exist, texture should be complete. Only verified in Debug.
2697 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
2698 TextureStorage *storage = nullptr;
2699 ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
2700 ASSERT(storage);
2701 #endif // !defined(NDEBUG)
2702
2703 auto *deviceContext = mRenderer->getDeviceContext();
2704
2705 ASSERT(index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[type]);
2706
2707 // When border color is used, its value may need to be readjusted based on the texture format.
2708 const bool usesBorderColor = samplerState.usesBorderColor();
2709
2710 if (mForceSetShaderSamplerStates[type][index] || usesBorderColor ||
2711 memcmp(&samplerState, &mCurShaderSamplerStates[type][index], sizeof(gl::SamplerState)) != 0)
2712 {
2713 // When clamp-to-border mode is used and a floating-point border color is set, the color
2714 // value must be adjusted based on the texture format. Reset it to zero in all other cases
2715 // to reduce the number of cached sampler entries. Address modes for integer texture
2716 // formats are emulated in shaders and do not rely on this state.
2717 angle::ColorGeneric borderColor;
2718 if (usesBorderColor)
2719 {
2720 if (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float)
2721 {
2722 borderColor = samplerState.getBorderColor();
2723 }
2724 const uint32_t baseLevel = texture->getTextureState().getEffectiveBaseLevel();
2725 const gl::TextureTarget target = TextureTypeToTarget(texture->getType(), 0);
2726 const angle::Format &format = angle::Format::Get(angle::Format::InternalFormatToID(
2727 texture->getFormat(target, baseLevel).info->sizedInternalFormat));
2728
2729 borderColor = AdjustBorderColor<false>(borderColor, format, false);
2730 }
2731 gl::SamplerState adjustedSamplerState(samplerState);
2732 adjustedSamplerState.setBorderColor(borderColor.colorF);
2733
2734 ID3D11SamplerState *dxSamplerState = nullptr;
2735 ANGLE_TRY(mRenderer->getSamplerState(context, adjustedSamplerState, &dxSamplerState));
2736
2737 ASSERT(dxSamplerState != nullptr);
2738
2739 switch (type)
2740 {
2741 case gl::ShaderType::Vertex:
2742 deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
2743 break;
2744 case gl::ShaderType::Fragment:
2745 deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
2746 break;
2747 case gl::ShaderType::Compute:
2748 deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
2749 break;
2750 case gl::ShaderType::Geometry:
2751 deviceContext->GSSetSamplers(index, 1, &dxSamplerState);
2752 break;
2753 default:
2754 UNREACHABLE();
2755 break;
2756 }
2757
2758 mCurShaderSamplerStates[type][index] = samplerState;
2759 }
2760
2761 mForceSetShaderSamplerStates[type][index] = false;
2762
2763 // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
2764 // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
2765 // buffer, and it doesn't affect the state set by
2766 // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers.
2767 mShaderConstants.onSamplerChange(type, index, *texture, samplerState);
2768
2769 return angle::Result::Continue;
2770 }
2771
setTextureForSampler(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & sampler)2772 angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
2773 gl::ShaderType type,
2774 int index,
2775 gl::Texture *texture,
2776 const gl::SamplerState &sampler)
2777 {
2778 const d3d11::SharedSRV *textureSRV = nullptr;
2779
2780 if (texture)
2781 {
2782 TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
2783
2784 TextureStorage *texStorage = nullptr;
2785 ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2786
2787 // Texture should be complete and have a storage
2788 ASSERT(texStorage);
2789
2790 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2791
2792 ANGLE_TRY(
2793 storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));
2794
2795 // If we get an invalid SRV here, something went wrong in the texture class and we're
2796 // unexpectedly missing the shader resource view.
2797 ASSERT(textureSRV->valid());
2798
2799 textureImpl->resetDirty();
2800 }
2801
2802 ASSERT(
2803 (type == gl::ShaderType::Fragment &&
2804 index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
2805 (type == gl::ShaderType::Vertex &&
2806 index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
2807 (type == gl::ShaderType::Compute &&
2808 index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]));
2809
2810 setShaderResourceInternal(type, index, textureSRV);
2811 return angle::Result::Continue;
2812 }
2813
setImageState(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit)2814 angle::Result StateManager11::setImageState(const gl::Context *context,
2815 gl::ShaderType type,
2816 int index,
2817 const gl::ImageUnit &imageUnit)
2818 {
2819 ASSERT(index < mRenderer->getNativeCaps().maxShaderImageUniforms[type]);
2820
2821 if (mShaderConstants.onImageChange(type, index, imageUnit))
2822 {
2823 invalidateDriverUniforms();
2824 }
2825
2826 return angle::Result::Continue;
2827 }
2828
2829 // For each Direct3D sampler of either the pixel or vertex stage,
2830 // looks up the corresponding OpenGL texture image unit and texture type,
2831 // and sets the texture and its addressing/filtering state (or NULL when inactive).
2832 // Sampler mapping needs to be up-to-date on the program object before this is called.
applyTexturesForSRVs(const gl::Context * context,gl::ShaderType shaderType)2833 angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
2834 gl::ShaderType shaderType)
2835 {
2836 const auto &glState = context->getState();
2837 const auto &caps = context->getCaps();
2838
2839 ASSERT(!mExecutableD3D->isSamplerMappingDirty());
2840
2841 // TODO(jmadill): Use the Program's sampler bindings.
2842 const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
2843
2844 const gl::RangeUI samplerRange = mExecutableD3D->getUsedSamplerRange(shaderType);
2845 for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
2846 samplerIndex++)
2847 {
2848 GLint textureUnit = mExecutableD3D->getSamplerMapping(shaderType, samplerIndex, caps);
2849 ASSERT(textureUnit != -1);
2850 gl::Texture *texture = completeTextures[textureUnit];
2851
2852 // A nullptr texture indicates incomplete.
2853 if (texture)
2854 {
2855 gl::Sampler *samplerObject = glState.getSampler(textureUnit);
2856
2857 const gl::SamplerState &samplerState =
2858 samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
2859
2860 ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
2861 ANGLE_TRY(
2862 setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
2863 }
2864 else
2865 {
2866 gl::TextureType textureType =
2867 mExecutableD3D->getSamplerTextureType(shaderType, samplerIndex);
2868
2869 // Texture is not sampler complete or it is in use by the framebuffer. Bind the
2870 // incomplete texture.
2871 gl::Texture *incompleteTexture = nullptr;
2872 ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
2873 ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
2874 incompleteTexture->getSamplerState()));
2875 ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
2876 incompleteTexture->getSamplerState()));
2877 }
2878 }
2879
2880 const gl::RangeUI readonlyImageRange = mExecutableD3D->getUsedImageRange(shaderType, true);
2881 for (unsigned int readonlyImageIndex = readonlyImageRange.low();
2882 readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
2883 {
2884 GLint imageUnitIndex =
2885 mExecutableD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
2886 ASSERT(imageUnitIndex != -1);
2887 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2888 if (!imageUnit.layered)
2889 {
2890 ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
2891 readonlyImageIndex - readonlyImageRange.low(), imageUnit));
2892 }
2893 ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, imageUnit));
2894 }
2895
2896 return angle::Result::Continue;
2897 }
2898
getUAVsForRWImages(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)2899 angle::Result StateManager11::getUAVsForRWImages(const gl::Context *context,
2900 gl::ShaderType shaderType,
2901 UAVList *uavList)
2902 {
2903 const auto &glState = context->getState();
2904 const auto &caps = context->getCaps();
2905
2906 const gl::RangeUI imageRange = mExecutableD3D->getUsedImageRange(shaderType, false);
2907 for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
2908 {
2909 GLint imageUnitIndex = mExecutableD3D->getImageMapping(shaderType, imageIndex, false, caps);
2910 ASSERT(imageUnitIndex != -1);
2911 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2912 if (!imageUnit.layered)
2913 {
2914 ANGLE_TRY(setImageState(context, shaderType, imageIndex - imageRange.low(), imageUnit));
2915 }
2916 ANGLE_TRY(getUAVForRWImage(context, shaderType, imageIndex, imageUnit, uavList));
2917 }
2918
2919 return angle::Result::Continue;
2920 }
2921
syncTexturesForCompute(const gl::Context * context)2922 angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
2923 {
2924 ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
2925 return angle::Result::Continue;
2926 }
2927
setTextureForImage(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit)2928 angle::Result StateManager11::setTextureForImage(const gl::Context *context,
2929 gl::ShaderType type,
2930 int index,
2931 const gl::ImageUnit &imageUnit)
2932 {
2933 TextureD3D *textureImpl = nullptr;
2934 if (!imageUnit.texture.get())
2935 {
2936 setShaderResourceInternal<d3d11::ShaderResourceView>(type, static_cast<UINT>(index),
2937 nullptr);
2938 return angle::Result::Continue;
2939 }
2940
2941 textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
2942
2943 // Ensure that texture has unordered access; convert it if not.
2944 ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
2945
2946 TextureStorage *texStorage = nullptr;
2947 ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2948 // Texture should be complete and have a storage
2949 ASSERT(texStorage);
2950 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2951
2952 const d3d11::SharedSRV *textureSRV = nullptr;
2953 ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
2954 // If we get an invalid SRV here, something went wrong in the texture class and we're
2955 // unexpectedly missing the shader resource view.
2956 ASSERT(textureSRV->valid());
2957 ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2958 setShaderResourceInternal(type, index, textureSRV);
2959
2960 textureImpl->resetDirty();
2961 return angle::Result::Continue;
2962 }
2963
getUAVForRWImage(const gl::Context * context,gl::ShaderType type,int index,const gl::ImageUnit & imageUnit,UAVList * uavList)2964 angle::Result StateManager11::getUAVForRWImage(const gl::Context *context,
2965 gl::ShaderType type,
2966 int index,
2967 const gl::ImageUnit &imageUnit,
2968 UAVList *uavList)
2969 {
2970 TextureD3D *textureImpl = nullptr;
2971 if (!imageUnit.texture.get())
2972 {
2973 setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(static_cast<UINT>(index),
2974 nullptr, uavList);
2975 return angle::Result::Continue;
2976 }
2977
2978 textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
2979
2980 // Ensure that texture has unordered access; convert it if not.
2981 ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
2982
2983 TextureStorage *texStorage = nullptr;
2984 ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2985 // Texture should be complete and have a storage
2986 ASSERT(texStorage);
2987 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2988
2989 const d3d11::SharedUAV *textureUAV = nullptr;
2990 ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
2991 // If we get an invalid UAV here, something went wrong in the texture class and we're
2992 // unexpectedly missing the unordered access view.
2993 ASSERT(textureUAV->valid());
2994 ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
2995 setUnorderedAccessViewInternal(index, textureUAV, uavList);
2996
2997 textureImpl->resetDirty();
2998 return angle::Result::Continue;
2999 }
3000
3001 // Things that affect a program's dirtyness:
3002 // 1. Directly changing the program executable -> triggered in StateManager11::syncState.
3003 // 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal.
3004 // 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal.
3005 // 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState.
3006 // 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState.
3007 // 6. An internal shader was used. -> triggered in StateManager11::set*Shader.
3008 // 7. Drawing with/without point sprites. -> checked in StateManager11::updateState.
3009 // TODO(jmadill): Use dirty bits for transform feedback.
syncProgram(const gl::Context * context,gl::PrimitiveMode drawMode)3010 angle::Result StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode)
3011 {
3012 Context11 *context11 = GetImplAs<Context11>(context);
3013 RendererD3D *renderer = context11->getRenderer();
3014 ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
3015
3016 const auto &glState = context->getState();
3017
3018 // TODO: change mExecutableD3D to mExecutableD3D?
3019 mExecutableD3D->updateCachedInputLayout(context11->getRenderer(),
3020 mVertexArray11->getCurrentStateSerial(), glState);
3021
3022 // Binaries must be compiled before the sync.
3023 ASSERT(mExecutableD3D->hasVertexExecutableForCachedInputLayout());
3024 ASSERT(mExecutableD3D->hasGeometryExecutableForPrimitiveType(context11->getRenderer(), glState,
3025 drawMode));
3026 ASSERT(mExecutableD3D->hasPixelExecutableForCachedOutputLayout());
3027
3028 ShaderExecutableD3D *vertexExe = nullptr;
3029 ANGLE_TRY(mExecutableD3D->getVertexExecutableForCachedInputLayout(context11, renderer,
3030 &vertexExe, nullptr));
3031
3032 ShaderExecutableD3D *pixelExe = nullptr;
3033 ANGLE_TRY(mExecutableD3D->getPixelExecutableForCachedOutputLayout(context11, renderer,
3034 &pixelExe, nullptr));
3035
3036 ShaderExecutableD3D *geometryExe = nullptr;
3037 ANGLE_TRY(mExecutableD3D->getGeometryExecutableForPrimitiveType(
3038 context11, renderer, glState.getCaps(), glState.getProvokingVertex(), drawMode,
3039 &geometryExe, nullptr));
3040
3041 const d3d11::VertexShader *vertexShader =
3042 (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
3043
3044 // Skip pixel shader if we're doing rasterizer discard.
3045 const d3d11::PixelShader *pixelShader = nullptr;
3046 if (!glState.getRasterizerState().rasterizerDiscard)
3047 {
3048 pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
3049 }
3050
3051 const d3d11::GeometryShader *geometryShader = nullptr;
3052 if (glState.isTransformFeedbackActiveUnpaused())
3053 {
3054 geometryShader =
3055 (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
3056 }
3057 else
3058 {
3059 geometryShader =
3060 (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
3061 }
3062
3063 setDrawShaders(vertexShader, geometryShader, pixelShader);
3064
3065 // Explicitly clear the shaders dirty bit.
3066 mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
3067
3068 return angle::Result::Continue;
3069 }
3070
syncProgramForCompute(const gl::Context * context)3071 angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
3072 {
3073 Context11 *context11 = GetImplAs<Context11>(context);
3074 ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));
3075
3076 mExecutableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Compute);
3077
3078 // Binaries must be compiled before the sync.
3079 ASSERT(mExecutableD3D->hasComputeExecutableForCachedImage2DBindLayout());
3080
3081 ShaderExecutableD3D *computeExe = nullptr;
3082 ANGLE_TRY(mExecutableD3D->getComputeExecutableForImage2DBindLayout(
3083 context11, context11->getRenderer(), &computeExe, nullptr));
3084
3085 const d3d11::ComputeShader *computeShader =
3086 (computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
3087 setComputeShader(computeShader);
3088 // Explicitly clear the shaders dirty bit.
3089 mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
3090
3091 return angle::Result::Continue;
3092 }
3093
syncVertexBuffersAndInputLayout(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,GLsizei instanceCount)3094 angle::Result StateManager11::syncVertexBuffersAndInputLayout(
3095 const gl::Context *context,
3096 gl::PrimitiveMode mode,
3097 GLint firstVertex,
3098 GLsizei vertexOrIndexCount,
3099 gl::DrawElementsType indexTypeOrInvalid,
3100 GLsizei instanceCount)
3101 {
3102 const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();
3103
3104 // Sort the attributes according to ensure we re-use similar input layouts.
3105 AttribIndexArray sortedSemanticIndices;
3106 SortAttributesByLayout(*mExecutableD3D, vertexArrayAttribs, mCurrentValueAttribs,
3107 &sortedSemanticIndices, &mCurrentAttributes);
3108
3109 D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
3110
3111 // If we are using FL 9_3, make sure the first attribute is not instanced
3112 if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
3113 {
3114 if (mCurrentAttributes[0]->divisor > 0)
3115 {
3116 Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
3117 if (firstNonInstancedIndex.valid())
3118 {
3119 size_t index = firstNonInstancedIndex.value();
3120 std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
3121 std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
3122 }
3123 }
3124 }
3125
3126 // Update the applied input layout by querying the cache.
3127 const gl::State &state = context->getState();
3128 const d3d11::InputLayout *inputLayout = nullptr;
3129 ANGLE_TRY(mInputLayoutCache.getInputLayout(GetImplAs<Context11>(context), state,
3130 mCurrentAttributes, sortedSemanticIndices, mode,
3131 vertexOrIndexCount, instanceCount, &inputLayout));
3132 setInputLayoutInternal(inputLayout);
3133
3134 // Update the applied vertex buffers.
3135 ANGLE_TRY(applyVertexBuffers(context, mode, indexTypeOrInvalid, firstVertex));
3136
3137 return angle::Result::Continue;
3138 }
3139
applyVertexBuffers(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexTypeOrInvalid,GLint firstVertex)3140 angle::Result StateManager11::applyVertexBuffers(const gl::Context *context,
3141 gl::PrimitiveMode mode,
3142 gl::DrawElementsType indexTypeOrInvalid,
3143 GLint firstVertex)
3144 {
3145 Context11 *context11 = GetImplAs<Context11>(context);
3146 RendererD3D *renderer = context11->getRenderer();
3147
3148 bool programUsesInstancedPointSprites =
3149 mExecutableD3D->usesPointSize() &&
3150 mExecutableD3D->usesInstancedPointSpriteEmulation(renderer);
3151 bool instancedPointSpritesActive =
3152 programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);
3153
3154 // Note that if we use instance emulation, we reserve the first buffer slot.
3155 size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
3156
3157 for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
3158 ++attribIndex)
3159 {
3160 ID3D11Buffer *buffer = nullptr;
3161 UINT vertexStride = 0;
3162 UINT vertexOffset = 0;
3163
3164 if (attribIndex < mCurrentAttributes.size())
3165 {
3166 const TranslatedAttribute &attrib = *mCurrentAttributes[attribIndex];
3167 Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
3168
3169 // If indexed pointsprite emulation is active, then we need to take a less efficent code
3170 // path. Emulated indexed pointsprite rendering requires that the vertex buffers match
3171 // exactly to the indices passed by the caller. This could expand or shrink the vertex
3172 // buffer depending on the number of points indicated by the index list or how many
3173 // duplicates are found on the index list.
3174 if (bufferStorage == nullptr)
3175 {
3176 ASSERT(attrib.vertexBuffer.get());
3177 buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
3178 }
3179 else if (instancedPointSpritesActive &&
3180 indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
3181 {
3182 ASSERT(mVertexArray11->isCachedIndexInfoValid());
3183 TranslatedIndexData indexInfo = mVertexArray11->getCachedIndexInfo();
3184 if (indexInfo.srcIndexData.srcBuffer != nullptr)
3185 {
3186 const uint8_t *bufferData = nullptr;
3187 ANGLE_TRY(indexInfo.srcIndexData.srcBuffer->getData(context, &bufferData));
3188 ASSERT(bufferData != nullptr);
3189
3190 ptrdiff_t offset =
3191 reinterpret_cast<ptrdiff_t>(indexInfo.srcIndexData.srcIndices);
3192 indexInfo.srcIndexData.srcBuffer = nullptr;
3193 indexInfo.srcIndexData.srcIndices = bufferData + offset;
3194 }
3195
3196 ANGLE_TRY(bufferStorage->getEmulatedIndexedBuffer(context, &indexInfo.srcIndexData,
3197 attrib, firstVertex, &buffer));
3198
3199 mVertexArray11->updateCachedIndexInfo(indexInfo);
3200 }
3201 else
3202 {
3203 ANGLE_TRY(bufferStorage->getBuffer(
3204 context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer));
3205 }
3206
3207 vertexStride = attrib.stride;
3208 ANGLE_TRY(attrib.computeOffset(context, firstVertex, &vertexOffset));
3209 }
3210
3211 size_t bufferIndex = reservedBuffers + attribIndex;
3212
3213 queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
3214 }
3215
3216 // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
3217 // to be created and added to the list of current buffers, strides and offsets collections.
3218 // This buffer contains the vertices for a single PointSprite quad.
3219 // An index buffer also needs to be created and applied because rendering instanced data on
3220 // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and
3221 // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot
3222 // handle missing vertex data and will TDR the system.
3223 if (programUsesInstancedPointSprites)
3224 {
3225 constexpr UINT kPointSpriteVertexStride = sizeof(float) * 5;
3226
3227 if (!mPointSpriteVertexBuffer.valid())
3228 {
3229 static constexpr float kPointSpriteVertices[] = {
3230 // Position | TexCoord
3231 -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v0 */
3232 -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, /* v1 */
3233 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, /* v2 */
3234 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, /* v3 */
3235 -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v4 */
3236 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, /* v5 */
3237 };
3238
3239 D3D11_SUBRESOURCE_DATA vertexBufferData = {kPointSpriteVertices, 0, 0};
3240 D3D11_BUFFER_DESC vertexBufferDesc;
3241 vertexBufferDesc.ByteWidth = sizeof(kPointSpriteVertices);
3242 vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
3243 vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
3244 vertexBufferDesc.CPUAccessFlags = 0;
3245 vertexBufferDesc.MiscFlags = 0;
3246 vertexBufferDesc.StructureByteStride = 0;
3247
3248 ANGLE_TRY(mRenderer->allocateResource(context11, vertexBufferDesc, &vertexBufferData,
3249 &mPointSpriteVertexBuffer));
3250 }
3251
3252 // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
3253 // indexing into the vertex buffer.
3254 UINT stride = instancedPointSpritesActive ? kPointSpriteVertexStride : 0;
3255 queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);
3256
3257 if (!mPointSpriteIndexBuffer.valid())
3258 {
3259 // Create an index buffer and set it for pointsprite rendering
3260 static constexpr unsigned short kPointSpriteIndices[] = {
3261 0, 1, 2, 3, 4, 5,
3262 };
3263
3264 D3D11_SUBRESOURCE_DATA indexBufferData = {kPointSpriteIndices, 0, 0};
3265 D3D11_BUFFER_DESC indexBufferDesc;
3266 indexBufferDesc.ByteWidth = sizeof(kPointSpriteIndices);
3267 indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
3268 indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
3269 indexBufferDesc.CPUAccessFlags = 0;
3270 indexBufferDesc.MiscFlags = 0;
3271 indexBufferDesc.StructureByteStride = 0;
3272
3273 ANGLE_TRY(mRenderer->allocateResource(context11, indexBufferDesc, &indexBufferData,
3274 &mPointSpriteIndexBuffer));
3275 }
3276
3277 if (instancedPointSpritesActive)
3278 {
3279 // The index buffer is applied here because Instanced PointSprite emulation uses the a
3280 // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
3281 // on the renderer will not be called and setting this buffer here ensures that the
3282 // rendering path will contain the correct index buffers.
3283 syncIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
3284 }
3285 }
3286
3287 applyVertexBufferChanges();
3288 return angle::Result::Continue;
3289 }
3290
applyIndexBuffer(const gl::Context * context,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices)3291 angle::Result StateManager11::applyIndexBuffer(const gl::Context *context,
3292 GLsizei indexCount,
3293 gl::DrawElementsType indexType,
3294 const void *indices)
3295 {
3296 if (!mIndexBufferIsDirty)
3297 {
3298 // No streaming or index buffer application necessary.
3299 return angle::Result::Continue;
3300 }
3301
3302 gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType();
3303 gl::Buffer *elementArrayBuffer = mVertexArray11->getState().getElementArrayBuffer();
3304
3305 TranslatedIndexData indexInfo;
3306 ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount,
3307 elementArrayBuffer, indices, &indexInfo));
3308
3309 ID3D11Buffer *buffer = nullptr;
3310 DXGI_FORMAT bufferFormat = (indexInfo.indexType == gl::DrawElementsType::UnsignedInt)
3311 ? DXGI_FORMAT_R32_UINT
3312 : DXGI_FORMAT_R16_UINT;
3313
3314 if (indexInfo.storage)
3315 {
3316 Buffer11 *storage = GetAs<Buffer11>(indexInfo.storage);
3317 ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer));
3318 }
3319 else
3320 {
3321 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo.indexBuffer);
3322 buffer = indexBuffer->getBuffer().get();
3323 }
3324
3325 // Track dirty indices in the index range cache.
3326 indexInfo.srcIndexData.srcIndicesChanged =
3327 syncIndexBuffer(buffer, bufferFormat, indexInfo.startOffset);
3328
3329 mIndexBufferIsDirty = false;
3330
3331 mVertexArray11->updateCachedIndexInfo(indexInfo);
3332 return angle::Result::Continue;
3333 }
3334
setIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3335 void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
3336 DXGI_FORMAT indexFormat,
3337 unsigned int offset)
3338 {
3339 if (syncIndexBuffer(buffer, indexFormat, offset))
3340 {
3341 invalidateIndexBuffer();
3342 }
3343 }
3344
syncIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)3345 bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
3346 DXGI_FORMAT indexFormat,
3347 unsigned int offset)
3348 {
3349 if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
3350 {
3351 mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
3352
3353 mAppliedIB = buffer;
3354 mAppliedIBFormat = indexFormat;
3355 mAppliedIBOffset = offset;
3356 return true;
3357 }
3358
3359 return false;
3360 }
3361
3362 // Vertex buffer is invalidated outside this function.
updateVertexOffsetsForPointSpritesEmulation(const gl::Context * context,GLint startVertex,GLsizei emulatedInstanceId)3363 angle::Result StateManager11::updateVertexOffsetsForPointSpritesEmulation(
3364 const gl::Context *context,
3365 GLint startVertex,
3366 GLsizei emulatedInstanceId)
3367 {
3368 size_t reservedBuffers = GetReservedBufferCount(true);
3369 for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
3370 {
3371 const auto &attrib = *mCurrentAttributes[attribIndex];
3372 size_t bufferIndex = reservedBuffers + attribIndex;
3373
3374 if (attrib.divisor > 0)
3375 {
3376 unsigned int offset = 0;
3377 ANGLE_TRY(attrib.computeOffset(context, startVertex, &offset));
3378 offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
3379 if (offset != mCurrentVertexOffsets[bufferIndex])
3380 {
3381 invalidateInputLayout();
3382 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
3383 mCurrentVertexOffsets[bufferIndex] = offset;
3384 }
3385 }
3386 }
3387
3388 applyVertexBufferChanges();
3389 return angle::Result::Continue;
3390 }
3391
generateSwizzle(const gl::Context * context,gl::Texture * texture)3392 angle::Result StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
3393 {
3394 if (!texture)
3395 {
3396 return angle::Result::Continue;
3397 }
3398
3399 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
3400 ASSERT(textureD3D);
3401
3402 TextureStorage *texStorage = nullptr;
3403 ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
3404
3405 if (texStorage)
3406 {
3407 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
3408 const gl::TextureState &textureState = texture->getTextureState();
3409 ANGLE_TRY(storage11->generateSwizzles(context, textureState));
3410 }
3411
3412 return angle::Result::Continue;
3413 }
3414
generateSwizzlesForShader(const gl::Context * context,gl::ShaderType type)3415 angle::Result StateManager11::generateSwizzlesForShader(const gl::Context *context,
3416 gl::ShaderType type)
3417 {
3418 const gl::State &glState = context->getState();
3419 const gl::RangeUI samplerRange = mExecutableD3D->getUsedSamplerRange(type);
3420
3421 for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
3422 {
3423 gl::TextureType textureType = mExecutableD3D->getSamplerTextureType(type, i);
3424 GLint textureUnit = mExecutableD3D->getSamplerMapping(type, i, context->getCaps());
3425 if (textureUnit != -1)
3426 {
3427 gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
3428 ASSERT(texture);
3429 if (SwizzleRequired(texture->getTextureState()))
3430 {
3431 ANGLE_TRY(generateSwizzle(context, texture));
3432 }
3433 }
3434 }
3435
3436 return angle::Result::Continue;
3437 }
3438
generateSwizzles(const gl::Context * context)3439 angle::Result StateManager11::generateSwizzles(const gl::Context *context)
3440 {
3441 ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Vertex));
3442 ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Fragment));
3443 return angle::Result::Continue;
3444 }
3445
applyUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3446 angle::Result StateManager11::applyUniformsForShader(const gl::Context *context,
3447 gl::ShaderType shaderType)
3448 {
3449 UniformStorage11 *shaderUniformStorage =
3450 GetAs<UniformStorage11>(mExecutableD3D->getShaderUniformStorage(shaderType));
3451 ASSERT(shaderUniformStorage);
3452
3453 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3454
3455 const d3d11::Buffer *shaderConstantBuffer = nullptr;
3456 ANGLE_TRY(shaderUniformStorage->getConstantBuffer(context, mRenderer, &shaderConstantBuffer));
3457
3458 if (shaderUniformStorage->size() > 0 && mExecutableD3D->areShaderUniformsDirty(shaderType))
3459 {
3460 UpdateUniformBuffer(deviceContext, shaderUniformStorage, shaderConstantBuffer);
3461 }
3462
3463 unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
3464
3465 switch (shaderType)
3466 {
3467 case gl::ShaderType::Vertex:
3468 if (mCurrentConstantBufferVS[slot] != shaderConstantBuffer->getSerial())
3469 {
3470 deviceContext->VSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3471 mCurrentConstantBufferVS[slot] = shaderConstantBuffer->getSerial();
3472 mCurrentConstantBufferVSOffset[slot] = 0;
3473 mCurrentConstantBufferVSSize[slot] = 0;
3474 }
3475 break;
3476
3477 case gl::ShaderType::Fragment:
3478 if (mCurrentConstantBufferPS[slot] != shaderConstantBuffer->getSerial())
3479 {
3480 deviceContext->PSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
3481 mCurrentConstantBufferPS[slot] = shaderConstantBuffer->getSerial();
3482 mCurrentConstantBufferPSOffset[slot] = 0;
3483 mCurrentConstantBufferPSSize[slot] = 0;
3484 }
3485 break;
3486
3487 // TODO(jiawei.shao@intel.com): apply geometry shader uniforms
3488 case gl::ShaderType::Geometry:
3489 UNIMPLEMENTED();
3490 break;
3491
3492 default:
3493 UNREACHABLE();
3494 break;
3495 }
3496
3497 return angle::Result::Continue;
3498 }
3499
applyUniforms(const gl::Context * context)3500 angle::Result StateManager11::applyUniforms(const gl::Context *context)
3501 {
3502 ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Vertex));
3503 ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Fragment));
3504 if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3505 {
3506 ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Geometry));
3507 }
3508
3509 mExecutableD3D->markUniformsClean();
3510
3511 return angle::Result::Continue;
3512 }
3513
applyDriverUniformsForShader(const gl::Context * context,gl::ShaderType shaderType)3514 angle::Result StateManager11::applyDriverUniformsForShader(const gl::Context *context,
3515 gl::ShaderType shaderType)
3516 {
3517 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3518
3519 d3d11::Buffer &shaderDriverConstantBuffer = mShaderDriverConstantBuffers[shaderType];
3520 if (!shaderDriverConstantBuffer.valid())
3521 {
3522 size_t requiredSize = mShaderConstants.getRequiredBufferSize(shaderType);
3523
3524 D3D11_BUFFER_DESC constantBufferDescription = {};
3525 d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3526 ANGLE_TRY(mRenderer->allocateResource(
3527 GetImplAs<Context11>(context), constantBufferDescription, &shaderDriverConstantBuffer));
3528
3529 ID3D11Buffer *driverConstants = shaderDriverConstantBuffer.get();
3530 switch (shaderType)
3531 {
3532 case gl::ShaderType::Vertex:
3533 deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3534 &driverConstants);
3535 break;
3536
3537 case gl::ShaderType::Fragment:
3538 deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3539 &driverConstants);
3540 break;
3541
3542 case gl::ShaderType::Geometry:
3543 deviceContext->GSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3544 &driverConstants);
3545 break;
3546
3547 default:
3548 UNREACHABLE();
3549 return angle::Result::Continue;
3550 }
3551 }
3552
3553 // Sampler metadata and driver constants need to coexist in the same constant buffer to
3554 // conserve constant buffer slots. We update both in the constant buffer if needed.
3555 ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, shaderType, *mExecutableD3D,
3556 shaderDriverConstantBuffer));
3557
3558 return angle::Result::Continue;
3559 }
3560
applyDriverUniforms(const gl::Context * context)3561 angle::Result StateManager11::applyDriverUniforms(const gl::Context *context)
3562 {
3563 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3564
3565 ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Vertex));
3566 ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Fragment));
3567 if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3568 {
3569 ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Geometry));
3570 }
3571
3572 // needed for the point sprite geometry shader
3573 // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
3574 if (mRenderer->isES3Capable())
3575 {
3576 d3d11::Buffer &driverConstantBufferPS =
3577 mShaderDriverConstantBuffers[gl::ShaderType::Fragment];
3578 if (mCurrentGeometryConstantBuffer != driverConstantBufferPS.getSerial())
3579 {
3580 ASSERT(driverConstantBufferPS.valid());
3581 deviceContext->GSSetConstantBuffers(0, 1, driverConstantBufferPS.getPointer());
3582 mCurrentGeometryConstantBuffer = driverConstantBufferPS.getSerial();
3583 }
3584 }
3585
3586 return angle::Result::Continue;
3587 }
3588
applyComputeUniforms(const gl::Context * context,ProgramExecutableD3D * executableD3D)3589 angle::Result StateManager11::applyComputeUniforms(const gl::Context *context,
3590 ProgramExecutableD3D *executableD3D)
3591 {
3592 UniformStorage11 *computeUniformStorage =
3593 GetAs<UniformStorage11>(executableD3D->getShaderUniformStorage(gl::ShaderType::Compute));
3594 ASSERT(computeUniformStorage);
3595
3596 const d3d11::Buffer *constantBuffer = nullptr;
3597 ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer));
3598
3599 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3600
3601 if (computeUniformStorage->size() > 0 &&
3602 executableD3D->areShaderUniformsDirty(gl::ShaderType::Compute))
3603 {
3604 UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
3605 executableD3D->markUniformsClean();
3606 }
3607
3608 if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
3609 {
3610 deviceContext->CSSetConstantBuffers(
3611 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
3612 constantBuffer->getPointer());
3613 mCurrentComputeConstantBuffer = constantBuffer->getSerial();
3614 }
3615
3616 if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid())
3617 {
3618 size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute);
3619
3620 D3D11_BUFFER_DESC constantBufferDescription = {};
3621 d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3622 ANGLE_TRY(
3623 mRenderer->allocateResource(GetImplAs<Context11>(context), constantBufferDescription,
3624 &mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3625 ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get();
3626 deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3627 &buffer);
3628 }
3629
3630 ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute,
3631 *executableD3D,
3632 mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
3633
3634 return angle::Result::Continue;
3635 }
3636
syncUniformBuffersForShader(const gl::Context * context,gl::ShaderType shaderType)3637 angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context,
3638 gl::ShaderType shaderType)
3639 {
3640 const auto &glState = context->getState();
3641 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3642 ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
3643
3644 const auto &shaderUniformBuffers = mExecutableD3D->getShaderUniformBufferCache(shaderType);
3645
3646 for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffers.size(); ++bufferIndex)
3647 {
3648 const D3DUBOCache cache = shaderUniformBuffers[bufferIndex];
3649 if (cache.binding == -1)
3650 {
3651 continue;
3652 }
3653
3654 const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
3655 const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3656 const GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
3657
3658 if (uniformBuffer.get() == nullptr)
3659 {
3660 continue;
3661 }
3662
3663 Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
3664 const d3d11::Buffer *constantBuffer = nullptr;
3665 UINT firstConstant = 0;
3666 UINT numConstants = 0;
3667
3668 ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
3669 uniformBufferSize, &constantBuffer,
3670 &firstConstant, &numConstants));
3671 ASSERT(constantBuffer);
3672
3673 switch (shaderType)
3674 {
3675 case gl::ShaderType::Vertex:
3676 {
3677 if (mCurrentConstantBufferVS[cache.registerIndex] == constantBuffer->getSerial() &&
3678 mCurrentConstantBufferVSOffset[cache.registerIndex] == uniformBufferOffset &&
3679 mCurrentConstantBufferVSSize[cache.registerIndex] == uniformBufferSize)
3680 {
3681 continue;
3682 }
3683
3684 if (firstConstant != 0 && uniformBufferSize != 0)
3685 {
3686 ASSERT(numConstants != 0);
3687 deviceContext1->VSSetConstantBuffers1(cache.registerIndex, 1,
3688 constantBuffer->getPointer(),
3689 &firstConstant, &numConstants);
3690 }
3691 else
3692 {
3693 deviceContext->VSSetConstantBuffers(cache.registerIndex, 1,
3694 constantBuffer->getPointer());
3695 }
3696
3697 mCurrentConstantBufferVS[cache.registerIndex] = constantBuffer->getSerial();
3698 mCurrentConstantBufferVSOffset[cache.registerIndex] = uniformBufferOffset;
3699 mCurrentConstantBufferVSSize[cache.registerIndex] = uniformBufferSize;
3700 break;
3701 }
3702
3703 case gl::ShaderType::Fragment:
3704 {
3705 if (mCurrentConstantBufferPS[cache.registerIndex] == constantBuffer->getSerial() &&
3706 mCurrentConstantBufferPSOffset[cache.registerIndex] == uniformBufferOffset &&
3707 mCurrentConstantBufferPSSize[cache.registerIndex] == uniformBufferSize)
3708 {
3709 continue;
3710 }
3711
3712 if (firstConstant != 0 && uniformBufferSize != 0)
3713 {
3714 deviceContext1->PSSetConstantBuffers1(cache.registerIndex, 1,
3715 constantBuffer->getPointer(),
3716 &firstConstant, &numConstants);
3717 }
3718 else
3719 {
3720 deviceContext->PSSetConstantBuffers(cache.registerIndex, 1,
3721 constantBuffer->getPointer());
3722 }
3723
3724 mCurrentConstantBufferPS[cache.registerIndex] = constantBuffer->getSerial();
3725 mCurrentConstantBufferPSOffset[cache.registerIndex] = uniformBufferOffset;
3726 mCurrentConstantBufferPSSize[cache.registerIndex] = uniformBufferSize;
3727 break;
3728 }
3729
3730 case gl::ShaderType::Compute:
3731 {
3732 if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() &&
3733 mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset &&
3734 mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize)
3735 {
3736 continue;
3737 }
3738
3739 if (firstConstant != 0 && uniformBufferSize != 0)
3740 {
3741 deviceContext1->CSSetConstantBuffers1(cache.registerIndex, 1,
3742 constantBuffer->getPointer(),
3743 &firstConstant, &numConstants);
3744 }
3745 else
3746 {
3747 deviceContext->CSSetConstantBuffers(cache.registerIndex, 1,
3748 constantBuffer->getPointer());
3749 }
3750
3751 mCurrentConstantBufferCS[cache.registerIndex] = constantBuffer->getSerial();
3752 mCurrentConstantBufferCSOffset[cache.registerIndex] = uniformBufferOffset;
3753 mCurrentConstantBufferCSSize[cache.registerIndex] = uniformBufferSize;
3754 break;
3755 }
3756
3757 // TODO(jiawei.shao@intel.com): update geometry shader uniform buffers.
3758 case gl::ShaderType::Geometry:
3759 UNIMPLEMENTED();
3760 break;
3761
3762 default:
3763 UNREACHABLE();
3764 }
3765 }
3766
3767 const auto &shaderUniformBuffersUseSB =
3768 mExecutableD3D->getShaderUniformBufferCacheUseSB(shaderType);
3769 for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffersUseSB.size(); ++bufferIndex)
3770 {
3771 const D3DUBOCacheUseSB cache = shaderUniformBuffersUseSB[bufferIndex];
3772 if (cache.binding == -1)
3773 {
3774 continue;
3775 }
3776
3777 const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
3778 if (uniformBuffer.get() == nullptr)
3779 {
3780 continue;
3781 }
3782 const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3783
3784 Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
3785 const d3d11::ShaderResourceView *bufferSRV = nullptr;
3786 ANGLE_TRY(bufferStorage->getStructuredBufferRangeSRV(
3787 context, static_cast<unsigned int>(uniformBufferOffset), cache.byteWidth,
3788 cache.structureByteStride, &bufferSRV));
3789
3790 ASSERT(bufferSRV->valid());
3791 setShaderResourceInternal(shaderType, cache.registerIndex, bufferSRV);
3792 }
3793
3794 return angle::Result::Continue;
3795 }
3796
getUAVsForShaderStorageBuffers(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3797 angle::Result StateManager11::getUAVsForShaderStorageBuffers(const gl::Context *context,
3798 gl::ShaderType shaderType,
3799 UAVList *uavList)
3800 {
3801 const gl::State &glState = context->getState();
3802 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3803 angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
3804 previouslyBound;
3805 for (size_t blockIndex = 0; blockIndex < executable->getShaderStorageBlocks().size();
3806 blockIndex++)
3807 {
3808 GLuint binding = executable->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
3809 const unsigned int registerIndex = mExecutableD3D->getShaderStorageBufferRegisterIndex(
3810 static_cast<GLuint>(blockIndex), shaderType);
3811 // It means this block is active but not statically used.
3812 if (registerIndex == GL_INVALID_INDEX)
3813 {
3814 continue;
3815 }
3816 const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
3817 if (shaderStorageBuffer.get() == nullptr)
3818 {
3819 // We didn't see a driver error like atomic buffer did. But theoretically, the same
3820 // thing should be done.
3821 setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
3822 uavList);
3823 continue;
3824 }
3825
3826 Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
3827 if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
3828 previouslyBound.end())
3829 {
3830 // D3D11 doesn't support binding a buffer multiple times
3831 // http://anglebug.com/3032
3832 ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
3833 return angle::Result::Stop;
3834 }
3835 previouslyBound.push_back(bufferStorage);
3836
3837 d3d11::UnorderedAccessView *uavPtr = nullptr;
3838 GLsizeiptr viewSize = 0;
3839 // Bindings only have a valid size if bound using glBindBufferRange
3840 if (shaderStorageBuffer.getSize() > 0)
3841 {
3842 viewSize = shaderStorageBuffer.getSize();
3843 }
3844 // We use the buffer size for glBindBufferBase
3845 else
3846 {
3847 viewSize = bufferStorage->getSize();
3848 }
3849 ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
3850 &uavPtr));
3851
3852 setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
3853 }
3854
3855 return angle::Result::Continue;
3856 }
3857
syncUniformBuffers(const gl::Context * context)3858 angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
3859 {
3860 mExecutableD3D->updateUniformBufferCache(context->getCaps());
3861
3862 if (mExecutableD3D->hasShaderStage(gl::ShaderType::Compute))
3863 {
3864 ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute));
3865 }
3866 else
3867 {
3868 ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex));
3869 ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment));
3870 if (mExecutableD3D->hasShaderStage(gl::ShaderType::Geometry))
3871 {
3872 ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry));
3873 }
3874 }
3875
3876 return angle::Result::Continue;
3877 }
3878
getUAVsForAtomicCounterBuffers(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3879 angle::Result StateManager11::getUAVsForAtomicCounterBuffers(const gl::Context *context,
3880 gl::ShaderType shaderType,
3881 UAVList *uavList)
3882 {
3883 const gl::State &glState = context->getState();
3884 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3885 const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
3886 executable->getAtomicCounterBuffers();
3887 for (size_t index = 0; index < atomicCounterBuffers.size(); ++index)
3888 {
3889 const GLuint binding = executable->getAtomicCounterBufferBinding(index);
3890 const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
3891 const unsigned int registerIndex =
3892 mExecutableD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
3893 ASSERT(registerIndex != GL_INVALID_INDEX);
3894 if (buffer.get() == nullptr)
3895 {
3896 // The atomic counter is used in shader. However, there is no buffer binding to it. We
3897 // should clear the corresponding UAV in case the previous view type is a texture not a
3898 // buffer. Otherwise, below error will be reported. The Unordered Access View dimension
3899 // declared in the shader code (BUFFER) does not match the view type bound to slot 0
3900 // of the Compute Shader unit (TEXTURE2D).
3901 setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
3902 uavList);
3903 continue;
3904 }
3905
3906 Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
3907 // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer
3908 // multiple times, as this is unsupported by D3D11. http://anglebug.com/3141
3909
3910 // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
3911 // buffer size for glBindBufferBase
3912 GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
3913 d3d11::UnorderedAccessView *uavPtr = nullptr;
3914 ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));
3915
3916 setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
3917 }
3918
3919 return angle::Result::Continue;
3920 }
3921
getUAVsForShader(const gl::Context * context,gl::ShaderType shaderType,UAVList * uavList)3922 angle::Result StateManager11::getUAVsForShader(const gl::Context *context,
3923 gl::ShaderType shaderType,
3924 UAVList *uavList)
3925 {
3926 ANGLE_TRY(getUAVsForShaderStorageBuffers(context, shaderType, uavList));
3927 ANGLE_TRY(getUAVsForRWImages(context, shaderType, uavList));
3928 ANGLE_TRY(getUAVsForAtomicCounterBuffers(context, shaderType, uavList));
3929
3930 return angle::Result::Continue;
3931 }
3932
syncUAVsForGraphics(const gl::Context * context)3933 angle::Result StateManager11::syncUAVsForGraphics(const gl::Context *context)
3934 {
3935 UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
3936
3937 ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Fragment, &uavList));
3938 ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Vertex, &uavList));
3939
3940 if (uavList.highestUsed >= 0)
3941 {
3942 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3943 UINT baseUAVRegister = static_cast<UINT>(mExecutableD3D->getPixelShaderKey().size());
3944 deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
3945 D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, baseUAVRegister,
3946 uavList.highestUsed + 1, uavList.data.data(), nullptr);
3947 }
3948
3949 return angle::Result::Continue;
3950 }
3951
syncUAVsForCompute(const gl::Context * context)3952 angle::Result StateManager11::syncUAVsForCompute(const gl::Context *context)
3953 {
3954 UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
3955
3956 ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Compute, &uavList));
3957
3958 if (uavList.highestUsed >= 0)
3959 {
3960 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3961 deviceContext->CSSetUnorderedAccessViews(0, uavList.highestUsed + 1, uavList.data.data(),
3962 nullptr);
3963 }
3964
3965 return angle::Result::Continue;
3966 }
3967
syncTransformFeedbackBuffers(const gl::Context * context)3968 angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
3969 {
3970 const auto &glState = context->getState();
3971
3972 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3973
3974 // If transform feedback is not active, unbind all buffers
3975 if (!glState.isTransformFeedbackActiveUnpaused())
3976 {
3977 if (mAppliedTFSerial != mEmptySerial)
3978 {
3979 deviceContext->SOSetTargets(0, nullptr, nullptr);
3980 mAppliedTFSerial = mEmptySerial;
3981 }
3982 return angle::Result::Continue;
3983 }
3984
3985 gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
3986 TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback);
3987 if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
3988 {
3989 return angle::Result::Continue;
3990 }
3991
3992 const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
3993 ANGLE_TRY(tf11->getSOBuffers(context, &soBuffers));
3994 const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
3995
3996 deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
3997
3998 mAppliedTFSerial = tf11->getSerial();
3999 tf11->onApply();
4000
4001 return angle::Result::Continue;
4002 }
4003
syncPrimitiveTopology(const gl::State & glState,gl::PrimitiveMode currentDrawMode)4004 void StateManager11::syncPrimitiveTopology(const gl::State &glState,
4005 gl::PrimitiveMode currentDrawMode)
4006 {
4007 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
4008 // Don't cull everything by default, this also resets if we were previously culling
4009 mCullEverything = false;
4010
4011 switch (currentDrawMode)
4012 {
4013 case gl::PrimitiveMode::Points:
4014 {
4015 bool usesPointSize = mExecutableD3D->usesPointSize();
4016
4017 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
4018 // which affects varying interpolation. Since the value of gl_PointSize is
4019 // undefined when not written, just skip drawing to avoid unexpected results.
4020 if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
4021 {
4022 // Notify developers of risking undefined behavior.
4023 WARN() << "Point rendering without writing to gl_PointSize.";
4024 mCullEverything = true;
4025 return;
4026 }
4027
4028 // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
4029 // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
4030 if (usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled)
4031 {
4032 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4033 }
4034 else
4035 {
4036 primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4037 }
4038 break;
4039 }
4040 case gl::PrimitiveMode::Lines:
4041 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
4042 break;
4043 case gl::PrimitiveMode::LineLoop:
4044 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
4045 break;
4046 case gl::PrimitiveMode::LineStrip:
4047 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
4048 break;
4049 case gl::PrimitiveMode::Triangles:
4050 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4051 mCullEverything = CullsEverything(glState);
4052 break;
4053 case gl::PrimitiveMode::TriangleStrip:
4054 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4055 mCullEverything = CullsEverything(glState);
4056 break;
4057 // emulate fans via rewriting index buffer
4058 case gl::PrimitiveMode::TriangleFan:
4059 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4060 mCullEverything = CullsEverything(glState);
4061 break;
4062 default:
4063 UNREACHABLE();
4064 break;
4065 }
4066
4067 setPrimitiveTopologyInternal(primitiveTopology);
4068 }
4069
4070 } // namespace rx
4071