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