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