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