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