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