1 //
2 // Copyright (c) 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/bitset_utils.h"
12 #include "common/utilities.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Query.h"
15 #include "libANGLE/VertexArray.h"
16 #include "libANGLE/renderer/d3d/TextureD3D.h"
17 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
18 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
19 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
20 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
21 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
22 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
23 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
24 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
25 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
26 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
27
28 namespace rx
29 {
30
31 namespace
32 {
ImageIndexConflictsWithSRV(const gl::ImageIndex & index,D3D11_SHADER_RESOURCE_VIEW_DESC desc)33 bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
34 {
35 unsigned mipLevel = index.mipIndex;
36 GLenum textureType = index.type;
37
38 switch (desc.ViewDimension)
39 {
40 case D3D11_SRV_DIMENSION_TEXTURE2D:
41 {
42 bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
43 unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
44 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
45
46 unsigned mipMin = index.mipIndex;
47 unsigned mipMax = INT_MAX;
48
49 return textureType == GL_TEXTURE_2D &&
50 gl::RangeUI(mipMin, mipMax)
51 .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
52 }
53
54 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
55 {
56 GLint layerIndex = index.layerIndex;
57
58 bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
59 unsigned int maxSrvMip =
60 desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
61 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
62
63 unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
64
65 // Cube maps can be mapped to Texture2DArray SRVs
66 return (textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_CUBE_MAP) &&
67 desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
68 desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
69 static_cast<UINT>(layerIndex) < maxSlice;
70 }
71
72 case D3D11_SRV_DIMENSION_TEXTURECUBE:
73 {
74 bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
75 unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
76 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
77
78 return textureType == GL_TEXTURE_CUBE_MAP &&
79 desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
80 }
81
82 case D3D11_SRV_DIMENSION_TEXTURE3D:
83 {
84 bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
85 unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
86 maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
87
88 return textureType == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
89 mipLevel < maxSrvMip;
90 }
91 default:
92 // We only handle the cases corresponding to valid image indexes
93 UNIMPLEMENTED();
94 }
95
96 return false;
97 }
98
99 // Does *not* increment the resource ref count!!
GetViewResource(ID3D11View * view)100 ID3D11Resource *GetViewResource(ID3D11View *view)
101 {
102 ID3D11Resource *resource = nullptr;
103 ASSERT(view);
104 view->GetResource(&resource);
105 resource->Release();
106 return resource;
107 }
108
GetWrapBits(GLenum wrap)109 int GetWrapBits(GLenum wrap)
110 {
111 switch (wrap)
112 {
113 case GL_CLAMP_TO_EDGE:
114 return 0x1;
115 case GL_REPEAT:
116 return 0x2;
117 case GL_MIRRORED_REPEAT:
118 return 0x3;
119 default:
120 UNREACHABLE();
121 return 0;
122 }
123 }
124
FindFirstNonInstanced(const std::vector<const TranslatedAttribute * > & currentAttributes)125 Optional<size_t> FindFirstNonInstanced(
126 const std::vector<const TranslatedAttribute *> ¤tAttributes)
127 {
128 for (size_t index = 0; index < currentAttributes.size(); ++index)
129 {
130 if (currentAttributes[index]->divisor == 0)
131 {
132 return Optional<size_t>(index);
133 }
134 }
135
136 return Optional<size_t>::Invalid();
137 }
138
SortAttributesByLayout(const gl::Program * program,const std::vector<TranslatedAttribute> & vertexArrayAttribs,const std::vector<TranslatedAttribute> & currentValueAttribs,AttribIndexArray * sortedD3DSemanticsOut,std::vector<const TranslatedAttribute * > * sortedAttributesOut)139 void SortAttributesByLayout(const gl::Program *program,
140 const std::vector<TranslatedAttribute> &vertexArrayAttribs,
141 const std::vector<TranslatedAttribute> ¤tValueAttribs,
142 AttribIndexArray *sortedD3DSemanticsOut,
143 std::vector<const TranslatedAttribute *> *sortedAttributesOut)
144 {
145 sortedAttributesOut->clear();
146
147 const auto &locationToSemantic =
148 GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
149
150 for (auto locationIndex : program->getActiveAttribLocationsMask())
151 {
152 int d3dSemantic = locationToSemantic[locationIndex];
153 if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
154 {
155 sortedAttributesOut->resize(d3dSemantic + 1);
156 }
157
158 (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
159
160 const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
161 if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
162 {
163 (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
164 }
165 else
166 {
167 ASSERT(currentValueAttribs[locationIndex].attribute);
168 (*sortedAttributesOut)[d3dSemantic] = ¤tValueAttribs[locationIndex];
169 }
170 }
171 }
172
UpdateUniformBuffer(ID3D11DeviceContext * deviceContext,UniformStorage11 * storage,const d3d11::Buffer * buffer)173 void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext,
174 UniformStorage11 *storage,
175 const d3d11::Buffer *buffer)
176 {
177 deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0,
178 0);
179 }
180
181 } // anonymous namespace
182
183 // StateManager11::ViewCache Implementation.
184 template <typename ViewType, typename DescType>
ViewCache()185 StateManager11::ViewCache<ViewType, DescType>::ViewCache() : mHighestUsedView(0)
186 {
187 }
188
189 template <typename ViewType, typename DescType>
~ViewCache()190 StateManager11::ViewCache<ViewType, DescType>::~ViewCache()
191 {
192 }
193
194 template <typename ViewType, typename DescType>
update(size_t resourceIndex,ViewType * view)195 void StateManager11::ViewCache<ViewType, DescType>::update(size_t resourceIndex, ViewType *view)
196 {
197 ASSERT(resourceIndex < mCurrentViews.size());
198 ViewRecord<DescType> *record = &mCurrentViews[resourceIndex];
199
200 record->view = reinterpret_cast<uintptr_t>(view);
201 if (view)
202 {
203 record->resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
204 view->GetDesc(&record->desc);
205 mHighestUsedView = std::max(resourceIndex + 1, mHighestUsedView);
206 }
207 else
208 {
209 record->resource = 0;
210
211 if (resourceIndex + 1 == mHighestUsedView)
212 {
213 do
214 {
215 --mHighestUsedView;
216 } while (mHighestUsedView > 0 && mCurrentViews[mHighestUsedView].view == 0);
217 }
218 }
219 }
220
221 template <typename ViewType, typename DescType>
clear()222 void StateManager11::ViewCache<ViewType, DescType>::clear()
223 {
224 if (mCurrentViews.empty())
225 {
226 return;
227 }
228
229 memset(&mCurrentViews[0], 0, sizeof(ViewRecord<DescType>) * mCurrentViews.size());
230 mHighestUsedView = 0;
231 }
232
getSRVCache(gl::ShaderType shaderType)233 StateManager11::SRVCache *StateManager11::getSRVCache(gl::ShaderType shaderType)
234 {
235 switch (shaderType)
236 {
237 case gl::SHADER_VERTEX:
238 return &mCurVertexSRVs;
239 case gl::SHADER_FRAGMENT:
240 return &mCurPixelSRVs;
241 case gl::SHADER_COMPUTE:
242 return &mCurComputeSRVs;
243 default:
244 UNREACHABLE();
245 return &mCurVertexSRVs;
246 }
247 }
248
249 // ShaderConstants11 implementation
ShaderConstants11()250 ShaderConstants11::ShaderConstants11()
251 : mVertexDirty(true),
252 mPixelDirty(true),
253 mComputeDirty(true),
254 mSamplerMetadataVSDirty(true),
255 mSamplerMetadataPSDirty(true),
256 mSamplerMetadataCSDirty(true)
257 {
258 }
259
~ShaderConstants11()260 ShaderConstants11::~ShaderConstants11()
261 {
262 }
263
init(const gl::Caps & caps)264 void ShaderConstants11::init(const gl::Caps &caps)
265 {
266 mSamplerMetadataVS.resize(caps.maxVertexTextureImageUnits);
267 mSamplerMetadataPS.resize(caps.maxTextureImageUnits);
268 mSamplerMetadataCS.resize(caps.maxComputeTextureImageUnits);
269 }
270
getRequiredBufferSize(gl::ShaderType shaderType) const271 size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
272 {
273 switch (shaderType)
274 {
275 case gl::SHADER_VERTEX:
276 return sizeof(Vertex) + mSamplerMetadataVS.size() * sizeof(SamplerMetadata);
277 case gl::SHADER_FRAGMENT:
278 return sizeof(Pixel) + mSamplerMetadataPS.size() * sizeof(SamplerMetadata);
279 case gl::SHADER_COMPUTE:
280 return sizeof(Compute) + mSamplerMetadataCS.size() * sizeof(SamplerMetadata);
281 default:
282 UNREACHABLE();
283 return 0;
284 }
285 }
286
markDirty()287 void ShaderConstants11::markDirty()
288 {
289 mVertexDirty = true;
290 mPixelDirty = true;
291 mComputeDirty = true;
292 mSamplerMetadataVSDirty = true;
293 mSamplerMetadataPSDirty = true;
294 mSamplerMetadataCSDirty = true;
295 }
296
updateSamplerMetadata(SamplerMetadata * data,const gl::Texture & texture)297 bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture)
298 {
299 bool dirty = false;
300 unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
301 GLenum sizedFormat =
302 texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat;
303 if (data->baseLevel != static_cast<int>(baseLevel))
304 {
305 data->baseLevel = static_cast<int>(baseLevel);
306 dirty = true;
307 }
308
309 // Some metadata is needed only for integer textures. We avoid updating the constant buffer
310 // unnecessarily by changing the data only in case the texture is an integer texture and
311 // the values have changed.
312 bool needIntegerTextureMetadata = false;
313 // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
314 int internalFormatBits = 0;
315 switch (sizedFormat)
316 {
317 case GL_RGBA32I:
318 case GL_RGBA32UI:
319 case GL_RGB32I:
320 case GL_RGB32UI:
321 case GL_RG32I:
322 case GL_RG32UI:
323 case GL_R32I:
324 case GL_R32UI:
325 needIntegerTextureMetadata = true;
326 break;
327 case GL_RGBA16I:
328 case GL_RGBA16UI:
329 case GL_RGB16I:
330 case GL_RGB16UI:
331 case GL_RG16I:
332 case GL_RG16UI:
333 case GL_R16I:
334 case GL_R16UI:
335 needIntegerTextureMetadata = true;
336 internalFormatBits = 16;
337 break;
338 case GL_RGBA8I:
339 case GL_RGBA8UI:
340 case GL_RGB8I:
341 case GL_RGB8UI:
342 case GL_RG8I:
343 case GL_RG8UI:
344 case GL_R8I:
345 case GL_R8UI:
346 needIntegerTextureMetadata = true;
347 internalFormatBits = 8;
348 break;
349 case GL_RGB10_A2UI:
350 needIntegerTextureMetadata = true;
351 internalFormatBits = 10;
352 break;
353 default:
354 break;
355 }
356 if (needIntegerTextureMetadata)
357 {
358 if (data->internalFormatBits != internalFormatBits)
359 {
360 data->internalFormatBits = internalFormatBits;
361 dirty = true;
362 }
363 // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer
364 // vector.
365 GLenum wrapS = texture.getWrapS();
366 GLenum wrapT = texture.getWrapT();
367 GLenum wrapR = texture.getWrapR();
368 int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
369 if (data->wrapModes != wrapModes)
370 {
371 data->wrapModes = wrapModes;
372 dirty = true;
373 }
374 }
375
376 return dirty;
377 }
378
setComputeWorkGroups(GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)379 void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
380 GLuint numGroupsY,
381 GLuint numGroupsZ)
382 {
383 mCompute.numWorkGroups[0] = numGroupsX;
384 mCompute.numWorkGroups[1] = numGroupsY;
385 mCompute.numWorkGroups[2] = numGroupsZ;
386 mComputeDirty = true;
387 }
388
setMultiviewWriteToViewportIndex(GLfloat index)389 void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index)
390 {
391 mVertex.multiviewWriteToViewportIndex = index;
392 mVertexDirty = true;
393 mPixel.multiviewWriteToViewportIndex = index;
394 mPixelDirty = true;
395 }
396
onViewportChange(const gl::Rectangle & glViewport,const D3D11_VIEWPORT & dxViewport,bool is9_3,bool presentPathFast)397 void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
398 const D3D11_VIEWPORT &dxViewport,
399 bool is9_3,
400 bool presentPathFast)
401 {
402 mVertexDirty = true;
403 mPixelDirty = true;
404
405 // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
406 // using viewAdjust (like the D3D9 renderer).
407 if (is9_3)
408 {
409 mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
410 2 * (glViewport.x - dxViewport.TopLeftX)) /
411 dxViewport.Width;
412 mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
413 2 * (glViewport.y - dxViewport.TopLeftY)) /
414 dxViewport.Height;
415 mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
416 mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
417 }
418
419 mPixel.viewCoords[0] = glViewport.width * 0.5f;
420 mPixel.viewCoords[1] = glViewport.height * 0.5f;
421 mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
422 mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);
423
424 // Instanced pointsprite emulation requires ViewCoords to be defined in the
425 // the vertex shader.
426 mVertex.viewCoords[0] = mPixel.viewCoords[0];
427 mVertex.viewCoords[1] = mPixel.viewCoords[1];
428 mVertex.viewCoords[2] = mPixel.viewCoords[2];
429 mVertex.viewCoords[3] = mPixel.viewCoords[3];
430
431 const float zNear = dxViewport.MinDepth;
432 const float zFar = dxViewport.MaxDepth;
433
434 mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
435 mPixel.depthFront[1] = (zNear + zFar) * 0.5f;
436
437 mVertex.depthRange[0] = zNear;
438 mVertex.depthRange[1] = zFar;
439 mVertex.depthRange[2] = zFar - zNear;
440
441 mPixel.depthRange[0] = zNear;
442 mPixel.depthRange[1] = zFar;
443 mPixel.depthRange[2] = zFar - zNear;
444
445 mPixel.viewScale[0] = 1.0f;
446 mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
447 // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw
448 // framebuffer's layout is changed.
449
450 mVertex.viewScale[0] = mPixel.viewScale[0];
451 mVertex.viewScale[1] = mPixel.viewScale[1];
452 }
453
onSamplerChange(gl::ShaderType shaderType,unsigned int samplerIndex,const gl::Texture & texture)454 void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
455 unsigned int samplerIndex,
456 const gl::Texture &texture)
457 {
458 switch (shaderType)
459 {
460 case gl::SHADER_VERTEX:
461 if (updateSamplerMetadata(&mSamplerMetadataVS[samplerIndex], texture))
462 {
463 mSamplerMetadataVSDirty = true;
464 }
465 break;
466 case gl::SHADER_FRAGMENT:
467 if (updateSamplerMetadata(&mSamplerMetadataPS[samplerIndex], texture))
468 {
469 mSamplerMetadataPSDirty = true;
470 }
471 break;
472 case gl::SHADER_COMPUTE:
473 if (updateSamplerMetadata(&mSamplerMetadataCS[samplerIndex], texture))
474 {
475 mSamplerMetadataCSDirty = true;
476 }
477 break;
478 default:
479 UNREACHABLE();
480 break;
481 }
482 }
483
updateBuffer(Renderer11 * renderer,gl::ShaderType shaderType,const ProgramD3D & programD3D,const d3d11::Buffer & driverConstantBuffer)484 gl::Error ShaderConstants11::updateBuffer(Renderer11 *renderer,
485 gl::ShaderType shaderType,
486 const ProgramD3D &programD3D,
487 const d3d11::Buffer &driverConstantBuffer)
488 {
489 bool dirty = false;
490 size_t dataSize = 0;
491 const uint8_t *data = nullptr;
492 const uint8_t *samplerData = nullptr;
493
494 switch (shaderType)
495 {
496 case gl::SHADER_VERTEX:
497 dirty = mVertexDirty || mSamplerMetadataVSDirty;
498 dataSize = sizeof(Vertex);
499 data = reinterpret_cast<const uint8_t *>(&mVertex);
500 samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataVS.data());
501 mVertexDirty = false;
502 mSamplerMetadataVSDirty = false;
503 break;
504 case gl::SHADER_FRAGMENT:
505 dirty = mPixelDirty || mSamplerMetadataPSDirty;
506 dataSize = sizeof(Pixel);
507 data = reinterpret_cast<const uint8_t *>(&mPixel);
508 samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataPS.data());
509 mPixelDirty = false;
510 mSamplerMetadataPSDirty = false;
511 break;
512 case gl::SHADER_COMPUTE:
513 dirty = mComputeDirty || mSamplerMetadataCSDirty;
514 dataSize = sizeof(Compute);
515 data = reinterpret_cast<const uint8_t *>(&mCompute);
516 samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataCS.data());
517 mComputeDirty = false;
518 mSamplerMetadataCSDirty = false;
519 break;
520 default:
521 UNREACHABLE();
522 break;
523 }
524
525 ASSERT(driverConstantBuffer.valid());
526
527 if (!dirty)
528 {
529 return gl::NoError();
530 }
531
532 // Previous buffer contents are discarded, so we need to refresh the whole buffer.
533 D3D11_MAPPED_SUBRESOURCE mapping = {0};
534 ANGLE_TRY(
535 renderer->mapResource(driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping));
536
537 size_t samplerDataBytes = sizeof(SamplerMetadata) * programD3D.getUsedSamplerRange(shaderType);
538
539 memcpy(mapping.pData, data, dataSize);
540 memcpy(reinterpret_cast<uint8_t *>(mapping.pData) + dataSize, samplerData, samplerDataBytes);
541
542 renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0);
543
544 return gl::NoError();
545 }
546
547 static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
548 GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT,
549 GL_COMMANDS_COMPLETED_CHROMIUM};
550
StateManager11(Renderer11 * renderer)551 StateManager11::StateManager11(Renderer11 *renderer)
552 : mRenderer(renderer),
553 mInternalDirtyBits(),
554 mCurBlendColor(0, 0, 0, 0),
555 mCurSampleMask(0),
556 mCurStencilRef(0),
557 mCurStencilBackRef(0),
558 mCurStencilSize(0),
559 mCurScissorEnabled(false),
560 mCurScissorRect(),
561 mCurViewport(),
562 mCurNear(0.0f),
563 mCurFar(0.0f),
564 mViewportBounds(),
565 mRenderTargetIsDirty(true),
566 mCurPresentPathFastEnabled(false),
567 mCurPresentPathFastColorBufferHeight(0),
568 mDirtyCurrentValueAttribs(),
569 mCurrentValueAttribs(),
570 mCurrentInputLayout(),
571 mInputLayoutIsDirty(false),
572 mVertexAttribsNeedTranslation(false),
573 mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0),
574 mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED),
575 mDirtySwizzles(false),
576 mAppliedIB(nullptr),
577 mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
578 mAppliedIBOffset(0),
579 mIndexBufferIsDirty(false),
580 mVertexDataManager(renderer),
581 mIndexDataManager(renderer),
582 mIsMultiviewEnabled(false),
583 mEmptySerial(mRenderer->generateSerial()),
584 mIsTransformFeedbackCurrentlyActiveUnpaused(false)
585 {
586 mCurBlendState.blend = false;
587 mCurBlendState.sourceBlendRGB = GL_ONE;
588 mCurBlendState.destBlendRGB = GL_ZERO;
589 mCurBlendState.sourceBlendAlpha = GL_ONE;
590 mCurBlendState.destBlendAlpha = GL_ZERO;
591 mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
592 mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
593 mCurBlendState.colorMaskRed = true;
594 mCurBlendState.colorMaskBlue = true;
595 mCurBlendState.colorMaskGreen = true;
596 mCurBlendState.colorMaskAlpha = true;
597 mCurBlendState.sampleAlphaToCoverage = false;
598 mCurBlendState.dither = false;
599
600 mCurDepthStencilState.depthTest = false;
601 mCurDepthStencilState.depthFunc = GL_LESS;
602 mCurDepthStencilState.depthMask = true;
603 mCurDepthStencilState.stencilTest = false;
604 mCurDepthStencilState.stencilMask = true;
605 mCurDepthStencilState.stencilFail = GL_KEEP;
606 mCurDepthStencilState.stencilPassDepthFail = GL_KEEP;
607 mCurDepthStencilState.stencilPassDepthPass = GL_KEEP;
608 mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1);
609 mCurDepthStencilState.stencilBackFunc = GL_ALWAYS;
610 mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1);
611 mCurDepthStencilState.stencilBackFail = GL_KEEP;
612 mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
613 mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
614 mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1);
615
616 mCurRasterState.rasterizerDiscard = false;
617 mCurRasterState.cullFace = false;
618 mCurRasterState.cullMode = gl::CullFaceMode::Back;
619 mCurRasterState.frontFace = GL_CCW;
620 mCurRasterState.polygonOffsetFill = false;
621 mCurRasterState.polygonOffsetFactor = 0.0f;
622 mCurRasterState.polygonOffsetUnits = 0.0f;
623 mCurRasterState.pointDrawMode = false;
624 mCurRasterState.multiSample = false;
625
626 // Start with all internal dirty bits set.
627 mInternalDirtyBits.set();
628
629 // Initially all current value attributes must be updated on first use.
630 mDirtyCurrentValueAttribs.set();
631
632 mCurrentVertexBuffers.fill(nullptr);
633 mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
634 mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
635 }
636
~StateManager11()637 StateManager11::~StateManager11()
638 {
639 }
640
641 template <typename SRVType>
setShaderResourceInternal(gl::ShaderType shaderType,UINT resourceSlot,const SRVType * srv)642 void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType,
643 UINT resourceSlot,
644 const SRVType *srv)
645 {
646 auto *currentSRVs = getSRVCache(shaderType);
647 ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs->size());
648 const ViewRecord<D3D11_SHADER_RESOURCE_VIEW_DESC> &record = (*currentSRVs)[resourceSlot];
649
650 if (record.view != reinterpret_cast<uintptr_t>(srv))
651 {
652 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
653 ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr;
654 switch (shaderType)
655 {
656 case gl::SHADER_VERTEX:
657 deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr);
658 break;
659 case gl::SHADER_FRAGMENT:
660 deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr);
661 break;
662 case gl::SHADER_COMPUTE:
663 deviceContext->CSSetShaderResources(resourceSlot, 1, &srvPtr);
664 break;
665 default:
666 UNREACHABLE();
667 }
668
669 currentSRVs->update(resourceSlot, srvPtr);
670 }
671 }
672
673 template <typename UAVType>
setUnorderedAccessViewInternal(gl::ShaderType shaderType,UINT resourceSlot,const UAVType * uav)674 void StateManager11::setUnorderedAccessViewInternal(gl::ShaderType shaderType,
675 UINT resourceSlot,
676 const UAVType *uav)
677 {
678 ASSERT(shaderType == gl::SHADER_COMPUTE);
679 ASSERT(static_cast<size_t>(resourceSlot) < mCurComputeUAVs.size());
680 const ViewRecord<D3D11_UNORDERED_ACCESS_VIEW_DESC> &record = mCurComputeUAVs[resourceSlot];
681
682 if (record.view != reinterpret_cast<uintptr_t>(uav))
683 {
684 auto deviceContext = mRenderer->getDeviceContext();
685 ID3D11UnorderedAccessView *uavPtr = uav ? uav->get() : nullptr;
686 deviceContext->CSSetUnorderedAccessViews(resourceSlot, 1, &uavPtr, nullptr);
687
688 mCurComputeUAVs.update(resourceSlot, uavPtr);
689 }
690 }
691
updateStencilSizeIfChanged(bool depthStencilInitialized,unsigned int stencilSize)692 void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
693 unsigned int stencilSize)
694 {
695 if (!depthStencilInitialized || stencilSize != mCurStencilSize)
696 {
697 mCurStencilSize = stencilSize;
698 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
699 }
700 }
701
checkPresentPath(const gl::Context * context)702 void StateManager11::checkPresentPath(const gl::Context *context)
703 {
704 if (!mRenderer->presentPathFastEnabled())
705 return;
706
707 const auto *framebuffer = context->getGLState().getDrawFramebuffer();
708 const auto *firstColorAttachment = framebuffer->getFirstColorbuffer();
709 const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment);
710
711 const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0;
712
713 if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
714 (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
715 {
716 mCurPresentPathFastEnabled = presentPathFastActive;
717 mCurPresentPathFastColorBufferHeight = colorBufferHeight;
718
719 // Scissor rect may need to be vertically inverted
720 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
721
722 // Cull Mode may need to be inverted
723 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
724
725 // Viewport may need to be vertically inverted
726 invalidateViewport(context);
727 }
728 }
729
updateStateForCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)730 gl::Error StateManager11::updateStateForCompute(const gl::Context *context,
731 GLuint numGroupsX,
732 GLuint numGroupsY,
733 GLuint numGroupsZ)
734 {
735 mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
736
737 // TODO(jmadill): Use dirty bits.
738 const auto &glState = context->getGLState();
739 auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
740 programD3D->updateSamplerMapping();
741
742 // TODO(jmadill): Use dirty bits.
743 ANGLE_TRY(generateSwizzlesForShader(context, gl::SHADER_COMPUTE));
744
745 // TODO(jmadill): More complete implementation.
746 ANGLE_TRY(syncTexturesForCompute(context));
747
748 // TODO(Xinghua): applyUniformBuffers for compute shader.
749
750 return gl::NoError();
751 }
752
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits)753 void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
754 {
755 if (!dirtyBits.any())
756 {
757 return;
758 }
759
760 const auto &state = context->getGLState();
761
762 for (auto dirtyBit : dirtyBits)
763 {
764 switch (dirtyBit)
765 {
766 case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
767 {
768 const gl::BlendState &blendState = state.getBlendState();
769 if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
770 blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
771 {
772 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
773 }
774 break;
775 }
776 case gl::State::DIRTY_BIT_BLEND_FUNCS:
777 {
778 const gl::BlendState &blendState = state.getBlendState();
779 if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
780 blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
781 blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
782 blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
783 {
784 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
785 }
786 break;
787 }
788 case gl::State::DIRTY_BIT_BLEND_ENABLED:
789 if (state.getBlendState().blend != mCurBlendState.blend)
790 {
791 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
792 }
793 break;
794 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
795 if (state.getBlendState().sampleAlphaToCoverage !=
796 mCurBlendState.sampleAlphaToCoverage)
797 {
798 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
799 }
800 break;
801 case gl::State::DIRTY_BIT_DITHER_ENABLED:
802 if (state.getBlendState().dither != mCurBlendState.dither)
803 {
804 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
805 }
806 break;
807 case gl::State::DIRTY_BIT_COLOR_MASK:
808 {
809 const gl::BlendState &blendState = state.getBlendState();
810 if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
811 blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
812 blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
813 blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
814 {
815 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
816 }
817 break;
818 }
819 case gl::State::DIRTY_BIT_BLEND_COLOR:
820 if (state.getBlendColor() != mCurBlendColor)
821 {
822 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
823 }
824 break;
825 case gl::State::DIRTY_BIT_DEPTH_MASK:
826 if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
827 {
828 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
829 }
830 break;
831 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
832 if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
833 {
834 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
835 }
836 break;
837 case gl::State::DIRTY_BIT_DEPTH_FUNC:
838 if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
839 {
840 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
841 }
842 break;
843 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
844 if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
845 {
846 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
847 }
848 break;
849 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
850 {
851 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
852 if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
853 depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
854 state.getStencilRef() != mCurStencilRef)
855 {
856 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
857 }
858 break;
859 }
860 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
861 {
862 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
863 if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
864 depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
865 state.getStencilBackRef() != mCurStencilBackRef)
866 {
867 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
868 }
869 break;
870 }
871 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
872 if (state.getDepthStencilState().stencilWritemask !=
873 mCurDepthStencilState.stencilWritemask)
874 {
875 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
876 }
877 break;
878 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
879 if (state.getDepthStencilState().stencilBackWritemask !=
880 mCurDepthStencilState.stencilBackWritemask)
881 {
882 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
883 }
884 break;
885 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
886 {
887 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
888 if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
889 depthStencil.stencilPassDepthFail !=
890 mCurDepthStencilState.stencilPassDepthFail ||
891 depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
892 {
893 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
894 }
895 break;
896 }
897 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
898 {
899 const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
900 if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
901 depthStencil.stencilBackPassDepthFail !=
902 mCurDepthStencilState.stencilBackPassDepthFail ||
903 depthStencil.stencilBackPassDepthPass !=
904 mCurDepthStencilState.stencilBackPassDepthPass)
905 {
906 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
907 }
908 break;
909 }
910 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
911 if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
912 {
913 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
914 }
915 break;
916 case gl::State::DIRTY_BIT_CULL_FACE:
917 if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
918 {
919 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
920 }
921 break;
922 case gl::State::DIRTY_BIT_FRONT_FACE:
923 if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
924 {
925 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
926 }
927 break;
928 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
929 if (state.getRasterizerState().polygonOffsetFill !=
930 mCurRasterState.polygonOffsetFill)
931 {
932 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
933 }
934 break;
935 case gl::State::DIRTY_BIT_POLYGON_OFFSET:
936 {
937 const gl::RasterizerState &rasterState = state.getRasterizerState();
938 if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
939 rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
940 {
941 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
942 }
943 break;
944 }
945 case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
946 if (state.getRasterizerState().rasterizerDiscard !=
947 mCurRasterState.rasterizerDiscard)
948 {
949 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
950
951 // Enabling/disabling rasterizer discard affects the pixel shader.
952 invalidateShaders();
953 }
954 break;
955 case gl::State::DIRTY_BIT_SCISSOR:
956 if (state.getScissor() != mCurScissorRect)
957 {
958 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
959 }
960 break;
961 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
962 if (state.isScissorTestEnabled() != mCurScissorEnabled)
963 {
964 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
965 // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
966 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
967 }
968 break;
969 case gl::State::DIRTY_BIT_DEPTH_RANGE:
970 if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
971 {
972 invalidateViewport(context);
973 }
974 break;
975 case gl::State::DIRTY_BIT_VIEWPORT:
976 if (state.getViewport() != mCurViewport)
977 {
978 invalidateViewport(context);
979 }
980 break;
981 case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
982 invalidateRenderTarget();
983 if (mIsMultiviewEnabled)
984 {
985 handleMultiviewDrawFramebufferChange(context);
986 }
987 break;
988 case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
989 invalidateVertexBuffer();
990 // Force invalidate the current value attributes, since the VertexArray11 keeps an
991 // internal cache of TranslatedAttributes, and they CurrentValue attributes are
992 // owned by the StateManager11/Context.
993 mDirtyCurrentValueAttribs.set();
994 // Invalidate the cached index buffer.
995 mIndexBufferIsDirty = true;
996 break;
997 case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
998 invalidateProgramUniformBuffers();
999 break;
1000 case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
1001 invalidateTexturesAndSamplers();
1002 break;
1003 case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
1004 invalidateTexturesAndSamplers();
1005 break;
1006 case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
1007 {
1008 mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
1009 invalidateVertexBuffer();
1010 invalidateRenderTarget();
1011 invalidateTexturesAndSamplers();
1012 invalidateProgramUniforms();
1013 invalidateProgramUniformBuffers();
1014 gl::VertexArray *vao = state.getVertexArray();
1015 if (mIsMultiviewEnabled && vao != nullptr)
1016 {
1017 // If ANGLE_multiview is enabled, the attribute divisor has to be updated for
1018 // each binding.
1019 VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
1020 const gl::Program *program = state.getProgram();
1021 int numViews = 1;
1022 if (program != nullptr && program->usesMultiview())
1023 {
1024 numViews = program->getNumViews();
1025 }
1026 vao11->markAllAttributeDivisorsForAdjustment(numViews);
1027 }
1028 break;
1029 }
1030 case gl::State::DIRTY_BIT_CURRENT_VALUES:
1031 {
1032 for (auto attribIndex : state.getAndResetDirtyCurrentValues())
1033 {
1034 invalidateCurrentValueAttrib(attribIndex);
1035 }
1036 break;
1037 }
1038 default:
1039 break;
1040 }
1041 }
1042
1043 // TODO(jmadill): Input layout and vertex buffer state.
1044 }
1045
handleMultiviewDrawFramebufferChange(const gl::Context * context)1046 void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context)
1047 {
1048 const auto &glState = context->getGLState();
1049 const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1050 ASSERT(drawFramebuffer != nullptr);
1051
1052 // Update viewport offsets.
1053 const std::vector<gl::Offset> *attachmentViewportOffsets =
1054 drawFramebuffer->getViewportOffsets();
1055 const std::vector<gl::Offset> &viewportOffsets =
1056 attachmentViewportOffsets != nullptr
1057 ? *attachmentViewportOffsets
1058 : gl::FramebufferAttachment::GetDefaultViewportOffsetVector();
1059 if (mViewportOffsets != viewportOffsets)
1060 {
1061 mViewportOffsets = viewportOffsets;
1062
1063 // Because new viewport offsets are to be applied, we have to mark the internal viewport and
1064 // scissor state as dirty.
1065 invalidateViewport(context);
1066 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
1067 }
1068 switch (drawFramebuffer->getMultiviewLayout())
1069 {
1070 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
1071 mShaderConstants.setMultiviewWriteToViewportIndex(1.0f);
1072 break;
1073 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
1074 // Because the base view index is applied as an offset to the 2D texture array when the
1075 // RTV is created, we just have to pass a boolean to select which code path is to be
1076 // used.
1077 mShaderConstants.setMultiviewWriteToViewportIndex(0.0f);
1078 break;
1079 default:
1080 // There is no need to update the value in the constant buffer if the active framebuffer
1081 // object does not have a multiview layout.
1082 break;
1083 }
1084 }
1085
syncBlendState(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::BlendState & blendState,const gl::ColorF & blendColor,unsigned int sampleMask)1086 gl::Error StateManager11::syncBlendState(const gl::Context *context,
1087 const gl::Framebuffer *framebuffer,
1088 const gl::BlendState &blendState,
1089 const gl::ColorF &blendColor,
1090 unsigned int sampleMask)
1091 {
1092 const d3d11::BlendState *dxBlendState = nullptr;
1093 const d3d11::BlendStateKey &key =
1094 RenderStateCache::GetBlendStateKey(context, framebuffer, blendState);
1095
1096 ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState));
1097
1098 ASSERT(dxBlendState != nullptr);
1099
1100 float blendColors[4] = {0.0f};
1101 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
1102 blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1103 blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
1104 blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1105 {
1106 blendColors[0] = blendColor.red;
1107 blendColors[1] = blendColor.green;
1108 blendColors[2] = blendColor.blue;
1109 blendColors[3] = blendColor.alpha;
1110 }
1111 else
1112 {
1113 blendColors[0] = blendColor.alpha;
1114 blendColors[1] = blendColor.alpha;
1115 blendColors[2] = blendColor.alpha;
1116 blendColors[3] = blendColor.alpha;
1117 }
1118
1119 mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask);
1120
1121 mCurBlendState = blendState;
1122 mCurBlendColor = blendColor;
1123 mCurSampleMask = sampleMask;
1124
1125 return gl::NoError();
1126 }
1127
syncDepthStencilState(const gl::State & glState)1128 gl::Error StateManager11::syncDepthStencilState(const gl::State &glState)
1129 {
1130 mCurDepthStencilState = glState.getDepthStencilState();
1131 mCurStencilRef = glState.getStencilRef();
1132 mCurStencilBackRef = glState.getStencilBackRef();
1133
1134 // get the maximum size of the stencil ref
1135 unsigned int maxStencil = 0;
1136 if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
1137 {
1138 maxStencil = (1 << mCurStencilSize) - 1;
1139 }
1140 ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
1141 (mCurDepthStencilState.stencilBackWritemask & maxStencil));
1142 ASSERT(mCurStencilRef == mCurStencilBackRef);
1143 ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
1144 (mCurDepthStencilState.stencilBackMask & maxStencil));
1145
1146 gl::DepthStencilState modifiedGLState = glState.getDepthStencilState();
1147
1148 ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid());
1149
1150 if (mCurDisableDepth.value())
1151 {
1152 modifiedGLState.depthTest = false;
1153 modifiedGLState.depthMask = false;
1154 }
1155
1156 if (mCurDisableStencil.value())
1157 {
1158 modifiedGLState.stencilWritemask = 0;
1159 modifiedGLState.stencilBackWritemask = 0;
1160 modifiedGLState.stencilTest = false;
1161 }
1162
1163 const d3d11::DepthStencilState *d3dState = nullptr;
1164 ANGLE_TRY(mRenderer->getDepthStencilState(modifiedGLState, &d3dState));
1165 ASSERT(d3dState);
1166
1167 // Max D3D11 stencil reference value is 0xFF,
1168 // corresponding to the max 8 bits in a stencil buffer
1169 // GL specifies we should clamp the ref value to the
1170 // nearest bit depth when doing stencil ops
1171 static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
1172 "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
1173 static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
1174 "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
1175 UINT dxStencilRef = std::min<UINT>(mCurStencilRef, 0xFFu);
1176
1177 mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef);
1178
1179 return gl::NoError();
1180 }
1181
syncRasterizerState(const gl::Context * context,bool pointDrawMode)1182 gl::Error StateManager11::syncRasterizerState(const gl::Context *context, bool pointDrawMode)
1183 {
1184 // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
1185 gl::RasterizerState rasterState = context->getGLState().getRasterizerState();
1186 rasterState.pointDrawMode = pointDrawMode;
1187 rasterState.multiSample = mCurRasterState.multiSample;
1188
1189 ID3D11RasterizerState *dxRasterState = nullptr;
1190
1191 if (mCurPresentPathFastEnabled)
1192 {
1193 gl::RasterizerState modifiedRasterState = rasterState;
1194
1195 // If prseent path fast is active then we need invert the front face state.
1196 // This ensures that both gl_FrontFacing is correct, and front/back culling
1197 // is performed correctly.
1198 if (modifiedRasterState.frontFace == GL_CCW)
1199 {
1200 modifiedRasterState.frontFace = GL_CW;
1201 }
1202 else
1203 {
1204 ASSERT(modifiedRasterState.frontFace == GL_CW);
1205 modifiedRasterState.frontFace = GL_CCW;
1206 }
1207
1208 ANGLE_TRY(
1209 mRenderer->getRasterizerState(modifiedRasterState, mCurScissorEnabled, &dxRasterState));
1210 }
1211 else
1212 {
1213 ANGLE_TRY(mRenderer->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState));
1214 }
1215
1216 mRenderer->getDeviceContext()->RSSetState(dxRasterState);
1217
1218 mCurRasterState = rasterState;
1219
1220 return gl::NoError();
1221 }
1222
syncScissorRectangle(const gl::Rectangle & scissor,bool enabled)1223 void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled)
1224 {
1225 int modifiedScissorY = scissor.y;
1226 if (mCurPresentPathFastEnabled)
1227 {
1228 modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
1229 }
1230
1231 if (enabled)
1232 {
1233 std::array<D3D11_RECT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> rectangles;
1234 const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size());
1235 for (UINT i = 0u; i < numRectangles; ++i)
1236 {
1237 D3D11_RECT &rect = rectangles[i];
1238 int x = scissor.x + mViewportOffsets[i].x;
1239 int y = modifiedScissorY + mViewportOffsets[i].y;
1240 rect.left = std::max(0, x);
1241 rect.top = std::max(0, y);
1242 rect.right = x + std::max(0, scissor.width);
1243 rect.bottom = y + std::max(0, scissor.height);
1244 }
1245 mRenderer->getDeviceContext()->RSSetScissorRects(numRectangles, rectangles.data());
1246 }
1247
1248 mCurScissorRect = scissor;
1249 mCurScissorEnabled = enabled;
1250 }
1251
syncViewport(const gl::Context * context)1252 void StateManager11::syncViewport(const gl::Context *context)
1253 {
1254 const auto &glState = context->getGLState();
1255 gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
1256 float actualZNear = gl::clamp01(glState.getNearPlane());
1257 float actualZFar = gl::clamp01(glState.getFarPlane());
1258
1259 const auto &caps = context->getCaps();
1260 int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
1261 int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
1262 int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
1263 int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
1264
1265 bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3;
1266
1267 if (is9_3)
1268 {
1269 // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
1270 dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
1271 dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
1272 dxMinViewportBoundsX = 0;
1273 dxMinViewportBoundsY = 0;
1274 }
1275
1276 const auto &viewport = glState.getViewport();
1277 std::array<D3D11_VIEWPORT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> dxViewports;
1278 const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size());
1279
1280 int dxViewportTopLeftX = 0;
1281 int dxViewportTopLeftY = 0;
1282 int dxViewportWidth = 0;
1283 int dxViewportHeight = 0;
1284
1285 for (UINT i = 0u; i < numRectangles; ++i)
1286 {
1287 dxViewportTopLeftX = gl::clamp(viewport.x + mViewportOffsets[i].x, dxMinViewportBoundsX,
1288 dxMaxViewportBoundsX);
1289 dxViewportTopLeftY = gl::clamp(viewport.y + mViewportOffsets[i].y, dxMinViewportBoundsY,
1290 dxMaxViewportBoundsY);
1291 dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
1292 dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
1293
1294 D3D11_VIEWPORT &dxViewport = dxViewports[i];
1295 dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
1296 if (mCurPresentPathFastEnabled)
1297 {
1298 // When present path fast is active and we're rendering to framebuffer 0, we must invert
1299 // the viewport in Y-axis.
1300 // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
1301 // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
1302 // unaltered dxViewportTopLeftY value.
1303 dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
1304 dxViewportTopLeftY - dxViewportHeight);
1305 }
1306 else
1307 {
1308 dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
1309 }
1310
1311 // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering
1312 // will be limited to a rectangle having a lower left of (0, 0) and an upper right of
1313 // (width, height), where width and height are the framebuffer object's default width
1314 // and height." See http://anglebug.com/1594
1315 // If the Framebuffer has no color attachment and the default width or height is smaller
1316 // than the current viewport, use the smaller of the two sizes.
1317 // If framebuffer default width or height is 0, the params should not set.
1318 if (!framebuffer->getFirstNonNullAttachment() &&
1319 (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight()))
1320 {
1321 dxViewport.Width =
1322 static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth()));
1323 dxViewport.Height =
1324 static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight()));
1325 }
1326 else
1327 {
1328 dxViewport.Width = static_cast<float>(dxViewportWidth);
1329 dxViewport.Height = static_cast<float>(dxViewportHeight);
1330 }
1331 dxViewport.MinDepth = actualZNear;
1332 dxViewport.MaxDepth = actualZFar;
1333 }
1334
1335 mRenderer->getDeviceContext()->RSSetViewports(numRectangles, dxViewports.data());
1336
1337 mCurViewport = viewport;
1338 mCurNear = actualZNear;
1339 mCurFar = actualZFar;
1340
1341 const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX),
1342 static_cast<FLOAT>(dxViewportTopLeftY),
1343 static_cast<FLOAT>(dxViewportWidth),
1344 static_cast<FLOAT>(dxViewportHeight),
1345 actualZNear,
1346 actualZFar};
1347 mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled);
1348 }
1349
invalidateRenderTarget()1350 void StateManager11::invalidateRenderTarget()
1351 {
1352 mRenderTargetIsDirty = true;
1353 }
1354
processFramebufferInvalidation(const gl::Context * context)1355 void StateManager11::processFramebufferInvalidation(const gl::Context *context)
1356 {
1357 if (!mRenderTargetIsDirty)
1358 {
1359 return;
1360 }
1361
1362 ASSERT(context);
1363
1364 mRenderTargetIsDirty = false;
1365 mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1366
1367 // The pixel shader is dependent on the output layout.
1368 invalidateShaders();
1369
1370 // The D3D11 blend state is heavily dependent on the current render target.
1371 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
1372
1373 gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
1374 ASSERT(fbo);
1375
1376 // Disable the depth test/depth write if we are using a stencil-only attachment.
1377 // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
1378 // nor write to the unused depth part of this emulated texture.
1379 bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil());
1380
1381 // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
1382 bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil());
1383
1384 if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() ||
1385 !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value())
1386 {
1387 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
1388 mCurDisableDepth = disableDepth;
1389 mCurDisableStencil = disableStencil;
1390 }
1391
1392 bool multiSample = (fbo->getCachedSamples(context) != 0);
1393 if (multiSample != mCurRasterState.multiSample)
1394 {
1395 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1396 mCurRasterState.multiSample = multiSample;
1397 }
1398
1399 checkPresentPath(context);
1400
1401 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
1402 {
1403 const auto *firstAttachment = fbo->getFirstNonNullAttachment();
1404 if (firstAttachment)
1405 {
1406 const auto &size = firstAttachment->getSize();
1407 if (mViewportBounds.width != size.width || mViewportBounds.height != size.height)
1408 {
1409 mViewportBounds = gl::Extents(size.width, size.height, 1);
1410 invalidateViewport(context);
1411 }
1412 }
1413 }
1414 }
1415
invalidateBoundViews()1416 void StateManager11::invalidateBoundViews()
1417 {
1418 mCurVertexSRVs.clear();
1419 mCurPixelSRVs.clear();
1420
1421 invalidateRenderTarget();
1422 }
1423
invalidateVertexBuffer()1424 void StateManager11::invalidateVertexBuffer()
1425 {
1426 unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
1427 gl::MAX_VERTEX_ATTRIBS);
1428 mDirtyVertexBufferRange = gl::RangeUI(0, limit);
1429 mInputLayoutIsDirty = true;
1430 mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
1431 invalidateVertexAttributeTranslation();
1432 }
1433
invalidateViewport(const gl::Context * context)1434 void StateManager11::invalidateViewport(const gl::Context *context)
1435 {
1436 mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
1437
1438 // Viewport affects the driver constants.
1439 invalidateDriverUniforms();
1440 }
1441
invalidateTexturesAndSamplers()1442 void StateManager11::invalidateTexturesAndSamplers()
1443 {
1444 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
1445 invalidateSwizzles();
1446
1447 // Texture state affects the driver uniforms (base level, etc).
1448 invalidateDriverUniforms();
1449 }
1450
invalidateSwizzles()1451 void StateManager11::invalidateSwizzles()
1452 {
1453 mDirtySwizzles = true;
1454 }
1455
invalidateProgramUniforms()1456 void StateManager11::invalidateProgramUniforms()
1457 {
1458 mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
1459 }
1460
invalidateDriverUniforms()1461 void StateManager11::invalidateDriverUniforms()
1462 {
1463 mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
1464 }
1465
invalidateProgramUniformBuffers()1466 void StateManager11::invalidateProgramUniformBuffers()
1467 {
1468 mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
1469 }
1470
invalidateConstantBuffer(unsigned int slot)1471 void StateManager11::invalidateConstantBuffer(unsigned int slot)
1472 {
1473 if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
1474 {
1475 invalidateDriverUniforms();
1476 }
1477 else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK)
1478 {
1479 invalidateProgramUniforms();
1480 }
1481 else
1482 {
1483 invalidateProgramUniformBuffers();
1484 }
1485 }
1486
invalidateShaders()1487 void StateManager11::invalidateShaders()
1488 {
1489 mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
1490 }
1491
setRenderTarget(ID3D11RenderTargetView * rtv,ID3D11DepthStencilView * dsv)1492 void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv)
1493 {
1494 if ((rtv && unsetConflictingView(rtv)) || (dsv && unsetConflictingView(dsv)))
1495 {
1496 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
1497 }
1498
1499 mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
1500 mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1501 }
1502
setRenderTargets(ID3D11RenderTargetView ** rtvs,UINT numRTVs,ID3D11DepthStencilView * dsv)1503 void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs,
1504 UINT numRTVs,
1505 ID3D11DepthStencilView *dsv)
1506 {
1507 bool anyDirty = false;
1508
1509 for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex)
1510 {
1511 anyDirty = anyDirty || unsetConflictingView(rtvs[rtvIndex]);
1512 }
1513
1514 if (dsv)
1515 {
1516 anyDirty = anyDirty || unsetConflictingView(dsv);
1517 }
1518
1519 if (anyDirty)
1520 {
1521 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
1522 }
1523
1524 mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv);
1525 mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
1526 }
1527
invalidateVertexAttributeTranslation()1528 void StateManager11::invalidateVertexAttributeTranslation()
1529 {
1530 mVertexAttribsNeedTranslation = true;
1531 }
1532
onBeginQuery(Query11 * query)1533 void StateManager11::onBeginQuery(Query11 *query)
1534 {
1535 mCurrentQueries.insert(query);
1536 }
1537
onDeleteQueryObject(Query11 * query)1538 void StateManager11::onDeleteQueryObject(Query11 *query)
1539 {
1540 mCurrentQueries.erase(query);
1541 }
1542
onMakeCurrent(const gl::Context * context)1543 gl::Error StateManager11::onMakeCurrent(const gl::Context *context)
1544 {
1545 const gl::State &state = context->getGLState();
1546
1547 for (Query11 *query : mCurrentQueries)
1548 {
1549 ANGLE_TRY(query->pause());
1550 }
1551 mCurrentQueries.clear();
1552
1553 for (GLenum queryType : QueryTypes)
1554 {
1555 gl::Query *query = state.getActiveQuery(queryType);
1556 if (query != nullptr)
1557 {
1558 Query11 *query11 = GetImplAs<Query11>(query);
1559 ANGLE_TRY(query11->resume());
1560 mCurrentQueries.insert(query11);
1561 }
1562 }
1563
1564 return gl::NoError();
1565 }
1566
clearSRVs(gl::ShaderType shaderType,size_t rangeStart,size_t rangeEnd)1567 gl::Error StateManager11::clearSRVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd)
1568 {
1569 if (rangeStart == rangeEnd)
1570 {
1571 return gl::NoError();
1572 }
1573
1574 auto *currentSRVs = getSRVCache(shaderType);
1575 gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, currentSRVs->highestUsed()));
1576 if (clearRange.empty())
1577 {
1578 return gl::NoError();
1579 }
1580
1581 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1582 switch (shaderType)
1583 {
1584 case gl::SHADER_VERTEX:
1585 deviceContext->VSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
1586 static_cast<unsigned int>(clearRange.length()),
1587 &mNullSRVs[0]);
1588 break;
1589 case gl::SHADER_FRAGMENT:
1590 deviceContext->PSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
1591 static_cast<unsigned int>(clearRange.length()),
1592 &mNullSRVs[0]);
1593 break;
1594 case gl::SHADER_COMPUTE:
1595 deviceContext->CSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
1596 static_cast<unsigned int>(clearRange.length()),
1597 &mNullSRVs[0]);
1598 break;
1599 default:
1600 UNREACHABLE();
1601 break;
1602 }
1603
1604 for (size_t samplerIndex : clearRange)
1605 {
1606 currentSRVs->update(samplerIndex, nullptr);
1607 }
1608
1609 return gl::NoError();
1610 }
1611
clearUAVs(gl::ShaderType shaderType,size_t rangeStart,size_t rangeEnd)1612 gl::Error StateManager11::clearUAVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd)
1613 {
1614 ASSERT(shaderType == gl::SHADER_COMPUTE);
1615 if (rangeStart == rangeEnd)
1616 {
1617 return gl::NoError();
1618 }
1619
1620 gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, mCurComputeUAVs.highestUsed()));
1621 if (clearRange.empty())
1622 {
1623 return gl::NoError();
1624 }
1625
1626 auto deviceContext = mRenderer->getDeviceContext();
1627 deviceContext->CSSetUnorderedAccessViews(static_cast<unsigned int>(clearRange.low()),
1628 static_cast<unsigned int>(clearRange.length()),
1629 &mNullUAVs[0], nullptr);
1630
1631 for (size_t index : clearRange)
1632 {
1633 mCurComputeUAVs.update(index, nullptr);
1634 }
1635
1636 return gl::NoError();
1637 }
1638
unsetConflictingView(ID3D11View * view)1639 bool StateManager11::unsetConflictingView(ID3D11View *view)
1640 {
1641 uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
1642 return unsetConflictingSRVs(gl::SHADER_VERTEX, resource, nullptr) ||
1643 unsetConflictingSRVs(gl::SHADER_FRAGMENT, resource, nullptr);
1644 }
1645
unsetConflictingSRVs(gl::ShaderType shaderType,uintptr_t resource,const gl::ImageIndex * index)1646 bool StateManager11::unsetConflictingSRVs(gl::ShaderType shaderType,
1647 uintptr_t resource,
1648 const gl::ImageIndex *index)
1649 {
1650 auto *currentSRVs = getSRVCache(shaderType);
1651
1652 bool foundOne = false;
1653
1654 for (size_t resourceIndex = 0; resourceIndex < currentSRVs->size(); ++resourceIndex)
1655 {
1656 auto &record = (*currentSRVs)[resourceIndex];
1657
1658 if (record.view && record.resource == resource &&
1659 (!index || ImageIndexConflictsWithSRV(*index, record.desc)))
1660 {
1661 setShaderResourceInternal<d3d11::ShaderResourceView>(
1662 shaderType, static_cast<UINT>(resourceIndex), nullptr);
1663 foundOne = true;
1664 }
1665 }
1666
1667 return foundOne;
1668 }
1669
unsetConflictingAttachmentResources(const gl::FramebufferAttachment * attachment,ID3D11Resource * resource)1670 void StateManager11::unsetConflictingAttachmentResources(
1671 const gl::FramebufferAttachment *attachment,
1672 ID3D11Resource *resource)
1673 {
1674 // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
1675 if (attachment->type() == GL_TEXTURE)
1676 {
1677 uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
1678 const gl::ImageIndex &index = attachment->getTextureImageIndex();
1679 // The index doesn't need to be corrected for the small compressed texture workaround
1680 // because a rendertarget is never compressed.
1681 unsetConflictingSRVs(gl::SHADER_VERTEX, resourcePtr, &index);
1682 unsetConflictingSRVs(gl::SHADER_FRAGMENT, resourcePtr, &index);
1683 }
1684 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
1685 {
1686 uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
1687 unsetConflictingSRVs(gl::SHADER_VERTEX, resourcePtr, nullptr);
1688 unsetConflictingSRVs(gl::SHADER_FRAGMENT, resourcePtr, nullptr);
1689 }
1690 }
1691
initialize(const gl::Caps & caps,const gl::Extensions & extensions)1692 gl::Error StateManager11::initialize(const gl::Caps &caps, const gl::Extensions &extensions)
1693 {
1694 mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
1695 mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
1696
1697 // TODO(xinghua.cao@intel.com): need to add compute shader texture image units.
1698 mCurComputeSRVs.initialize(caps.maxImageUnits);
1699
1700 mCurComputeUAVs.initialize(caps.maxImageUnits);
1701
1702 // Initialize cached NULL SRV block
1703 mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
1704
1705 mNullUAVs.resize(caps.maxImageUnits, nullptr);
1706
1707 mCurrentValueAttribs.resize(caps.maxVertexAttributes);
1708
1709 mForceSetVertexSamplerStates.resize(caps.maxVertexTextureImageUnits, true);
1710 mForceSetPixelSamplerStates.resize(caps.maxTextureImageUnits, true);
1711 mForceSetComputeSamplerStates.resize(caps.maxComputeTextureImageUnits, true);
1712
1713 mCurVertexSamplerStates.resize(caps.maxVertexTextureImageUnits);
1714 mCurPixelSamplerStates.resize(caps.maxTextureImageUnits);
1715 mCurComputeSamplerStates.resize(caps.maxComputeTextureImageUnits);
1716
1717 mShaderConstants.init(caps);
1718
1719 mIsMultiviewEnabled = extensions.multiview;
1720 mViewportOffsets.resize(1u);
1721
1722 ANGLE_TRY(mVertexDataManager.initialize());
1723
1724 mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
1725
1726 return gl::NoError();
1727 }
1728
deinitialize()1729 void StateManager11::deinitialize()
1730 {
1731 mCurrentValueAttribs.clear();
1732 mInputLayoutCache.clear();
1733 mVertexDataManager.deinitialize();
1734 mIndexDataManager.deinitialize();
1735
1736 mDriverConstantBufferVS.reset();
1737 mDriverConstantBufferPS.reset();
1738 mDriverConstantBufferCS.reset();
1739 }
1740
syncFramebuffer(const gl::Context * context,gl::Framebuffer * framebuffer)1741 gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer)
1742 {
1743 Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
1744
1745 // Applies the render target surface, depth stencil surface, viewport rectangle and
1746 // scissor rectangle to the renderer
1747 ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
1748
1749 // Check for zero-sized default framebuffer, which is a special case.
1750 // in this case we do not wish to modify any state and just silently return false.
1751 // this will not report any gl error but will cause the calling method to return.
1752 if (framebuffer->id() == 0)
1753 {
1754 ASSERT(!framebuffer11->hasAnyInternalDirtyBit());
1755 const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize();
1756 if (size.width == 0 || size.height == 0)
1757 {
1758 return gl::NoError();
1759 }
1760 }
1761
1762 RTVArray framebufferRTVs = {{}};
1763
1764 const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
1765
1766 size_t appliedRTIndex = 0;
1767 bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround;
1768 const auto &drawStates = framebuffer->getDrawBufferStates();
1769 gl::DrawBufferMask activeProgramOutputs =
1770 context->getContextState().getState().getProgram()->getActiveOutputVariables();
1771 UINT maxExistingRT = 0;
1772
1773 for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
1774 {
1775 const RenderTarget11 *renderTarget = colorRTs[rtIndex];
1776
1777 // Skip inactive rendertargets if the workaround is enabled.
1778 if (skipInactiveRTs &&
1779 (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
1780 {
1781 continue;
1782 }
1783
1784 if (renderTarget)
1785 {
1786 framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
1787 ASSERT(framebufferRTVs[appliedRTIndex]);
1788 maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
1789
1790 // Unset conflicting texture SRVs
1791 const auto *attachment = framebuffer->getColorbuffer(rtIndex);
1792 ASSERT(attachment);
1793 unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
1794 }
1795
1796 appliedRTIndex++;
1797 }
1798
1799 // Get the depth stencil buffers
1800 ID3D11DepthStencilView *framebufferDSV = nullptr;
1801 const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget();
1802 if (depthStencilRenderTarget)
1803 {
1804 framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
1805 ASSERT(framebufferDSV);
1806
1807 // Unset conflicting texture SRVs
1808 const auto *attachment = framebuffer->getDepthOrStencilbuffer();
1809 ASSERT(attachment);
1810 unsetConflictingAttachmentResources(attachment,
1811 depthStencilRenderTarget->getTexture().get());
1812 }
1813
1814 // TODO(jmadill): Use context caps?
1815 ASSERT(maxExistingRT <= static_cast<UINT>(mRenderer->getNativeCaps().maxDrawBuffers));
1816
1817 // Apply the render target and depth stencil
1818 mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
1819 framebufferDSV);
1820
1821 return gl::NoError();
1822 }
1823
invalidateCurrentValueAttrib(size_t attribIndex)1824 void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
1825 {
1826 mDirtyCurrentValueAttribs.set(attribIndex);
1827 mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
1828 }
1829
syncCurrentValueAttribs(const gl::State & glState)1830 gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState)
1831 {
1832 const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask();
1833 const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
1834
1835 if (!dirtyActiveAttribs.any())
1836 {
1837 return gl::NoError();
1838 }
1839
1840 const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes();
1841 const auto &vertexBindings = glState.getVertexArray()->getVertexBindings();
1842 mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
1843
1844 for (auto attribIndex : dirtyActiveAttribs)
1845 {
1846 if (vertexAttributes[attribIndex].enabled)
1847 continue;
1848
1849 const auto *attrib = &vertexAttributes[attribIndex];
1850 const auto ¤tValue = glState.getVertexAttribCurrentValue(attribIndex);
1851 TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
1852 currentValueAttrib->currentValueType = currentValue.Type;
1853 currentValueAttrib->attribute = attrib;
1854 currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex];
1855
1856 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
1857 mInputLayoutIsDirty = true;
1858
1859 ANGLE_TRY(mVertexDataManager.storeCurrentValue(currentValue, currentValueAttrib,
1860 static_cast<size_t>(attribIndex)));
1861 }
1862
1863 return gl::NoError();
1864 }
1865
setInputLayout(const d3d11::InputLayout * inputLayout)1866 void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
1867 {
1868 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1869 if (inputLayout == nullptr)
1870 {
1871 if (!mCurrentInputLayout.empty())
1872 {
1873 deviceContext->IASetInputLayout(nullptr);
1874 mCurrentInputLayout.clear();
1875 mInputLayoutIsDirty = true;
1876 }
1877 }
1878 else if (inputLayout->getSerial() != mCurrentInputLayout)
1879 {
1880 deviceContext->IASetInputLayout(inputLayout->get());
1881 mCurrentInputLayout = inputLayout->getSerial();
1882 mInputLayoutIsDirty = true;
1883 }
1884 }
1885
queueVertexBufferChange(size_t bufferIndex,ID3D11Buffer * buffer,UINT stride,UINT offset)1886 bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
1887 ID3D11Buffer *buffer,
1888 UINT stride,
1889 UINT offset)
1890 {
1891 if (buffer != mCurrentVertexBuffers[bufferIndex] ||
1892 stride != mCurrentVertexStrides[bufferIndex] ||
1893 offset != mCurrentVertexOffsets[bufferIndex])
1894 {
1895 mInputLayoutIsDirty = true;
1896 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
1897
1898 mCurrentVertexBuffers[bufferIndex] = buffer;
1899 mCurrentVertexStrides[bufferIndex] = stride;
1900 mCurrentVertexOffsets[bufferIndex] = offset;
1901 return true;
1902 }
1903
1904 return false;
1905 }
1906
queueVertexOffsetChange(size_t bufferIndex,UINT offsetOnly)1907 bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly)
1908 {
1909 if (offsetOnly != mCurrentVertexOffsets[bufferIndex])
1910 {
1911 mInputLayoutIsDirty = true;
1912 mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
1913 mCurrentVertexOffsets[bufferIndex] = offsetOnly;
1914 return true;
1915 }
1916 return false;
1917 }
1918
applyVertexBufferChanges()1919 void StateManager11::applyVertexBufferChanges()
1920 {
1921 if (mDirtyVertexBufferRange.empty())
1922 {
1923 return;
1924 }
1925
1926 ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
1927
1928 UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
1929
1930 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1931 deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
1932 &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
1933 &mCurrentVertexOffsets[start]);
1934
1935 mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
1936 }
1937
setSingleVertexBuffer(const d3d11::Buffer * buffer,UINT stride,UINT offset)1938 void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
1939 {
1940 ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
1941 if (queueVertexBufferChange(0, native, stride, offset))
1942 {
1943 applyVertexBufferChanges();
1944 }
1945 }
1946
updateState(const gl::Context * context,GLenum drawMode)1947 gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMode)
1948 {
1949 const auto &glState = context->getGLState();
1950 auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
1951
1952 // TODO(jmadill): Use dirty bits.
1953 processFramebufferInvalidation(context);
1954
1955 // TODO(jmadill): Use dirty bits.
1956 if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
1957 {
1958 invalidateTexturesAndSamplers();
1959 }
1960
1961 // TODO(jmadill): Use dirty bits.
1962 if (programD3D->areVertexUniformsDirty() || programD3D->areFragmentUniformsDirty())
1963 {
1964 mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
1965 }
1966
1967 // Transform feedback affects the stream-out geometry shader.
1968 // TODO(jmadill): Use dirty bits.
1969 if (glState.isTransformFeedbackActiveUnpaused() != mIsTransformFeedbackCurrentlyActiveUnpaused)
1970 {
1971 mIsTransformFeedbackCurrentlyActiveUnpaused = glState.isTransformFeedbackActiveUnpaused();
1972 invalidateShaders();
1973 }
1974
1975 // Swizzling can cause internal state changes with blit shaders.
1976 if (mDirtySwizzles)
1977 {
1978 ANGLE_TRY(generateSwizzles(context));
1979 mDirtySwizzles = false;
1980 }
1981
1982 gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
1983 Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
1984 ANGLE_TRY(framebuffer11->markAttachmentsDirty(context));
1985
1986 if (framebuffer11->hasAnyInternalDirtyBit())
1987 {
1988 ASSERT(framebuffer->id() != 0);
1989 framebuffer11->syncInternalState(context);
1990 }
1991
1992 bool pointDrawMode = (drawMode == GL_POINTS);
1993 if (pointDrawMode != mCurRasterState.pointDrawMode)
1994 {
1995 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
1996
1997 // Changing from points to not points (or vice-versa) affects the geometry shader.
1998 invalidateShaders();
1999 }
2000
2001 // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
2002 // state changes.
2003 RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget();
2004 int samples = (firstRT ? firstRT->getSamples() : 0);
2005 unsigned int sampleMask = GetBlendSampleMask(glState, samples);
2006 if (sampleMask != mCurSampleMask)
2007 {
2008 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2009 }
2010
2011 // Changing the vertex attribute state can affect the vertex shader.
2012 gl::VertexArray *vao = glState.getVertexArray();
2013 VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
2014 if (vao11->flushAttribUpdates(context))
2015 {
2016 mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
2017 }
2018
2019 auto dirtyBitsCopy = mInternalDirtyBits;
2020 mInternalDirtyBits.reset();
2021
2022 for (auto dirtyBit : dirtyBitsCopy)
2023 {
2024 switch (dirtyBit)
2025 {
2026 case DIRTY_BIT_RENDER_TARGET:
2027 ANGLE_TRY(syncFramebuffer(context, framebuffer));
2028 break;
2029 case DIRTY_BIT_VIEWPORT_STATE:
2030 syncViewport(context);
2031 break;
2032 case DIRTY_BIT_SCISSOR_STATE:
2033 syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
2034 break;
2035 case DIRTY_BIT_RASTERIZER_STATE:
2036 ANGLE_TRY(syncRasterizerState(context, pointDrawMode));
2037 break;
2038 case DIRTY_BIT_BLEND_STATE:
2039 ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(),
2040 glState.getBlendColor(), sampleMask));
2041 break;
2042 case DIRTY_BIT_DEPTH_STENCIL_STATE:
2043 ANGLE_TRY(syncDepthStencilState(glState));
2044 break;
2045 case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
2046 // TODO(jmadill): More fine-grained update.
2047 ANGLE_TRY(syncTextures(context));
2048 break;
2049 case DIRTY_BIT_PROGRAM_UNIFORMS:
2050 ANGLE_TRY(applyUniforms(programD3D));
2051 break;
2052 case DIRTY_BIT_DRIVER_UNIFORMS:
2053 // This must happen after viewport sync; the viewport affects builtin uniforms.
2054 ANGLE_TRY(applyDriverUniforms(*programD3D));
2055 break;
2056 case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
2057 ANGLE_TRY(syncUniformBuffers(context, programD3D));
2058 break;
2059 case DIRTY_BIT_SHADERS:
2060 ANGLE_TRY(syncProgram(context, drawMode));
2061 break;
2062 case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
2063 ANGLE_TRY(syncCurrentValueAttribs(glState));
2064 break;
2065 default:
2066 UNREACHABLE();
2067 break;
2068 }
2069 }
2070
2071 ANGLE_TRY(syncTransformFeedbackBuffers(context));
2072
2073 // Check that we haven't set any dirty bits in the flushing of the dirty bits loop.
2074 ASSERT(mInternalDirtyBits.none());
2075
2076 return gl::NoError();
2077 }
2078
setShaderResourceShared(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::SharedSRV * srv)2079 void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
2080 UINT resourceSlot,
2081 const d3d11::SharedSRV *srv)
2082 {
2083 setShaderResourceInternal(shaderType, resourceSlot, srv);
2084
2085 // TODO(jmadill): Narrower dirty region.
2086 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2087 }
2088
setShaderResource(gl::ShaderType shaderType,UINT resourceSlot,const d3d11::ShaderResourceView * srv)2089 void StateManager11::setShaderResource(gl::ShaderType shaderType,
2090 UINT resourceSlot,
2091 const d3d11::ShaderResourceView *srv)
2092 {
2093 setShaderResourceInternal(shaderType, resourceSlot, srv);
2094
2095 // TODO(jmadill): Narrower dirty region.
2096 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2097 }
2098
setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)2099 void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
2100 {
2101 if (primitiveTopology != mCurrentPrimitiveTopology)
2102 {
2103 mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
2104 mCurrentPrimitiveTopology = primitiveTopology;
2105 }
2106 }
2107
setDrawShaders(const d3d11::VertexShader * vertexShader,const d3d11::GeometryShader * geometryShader,const d3d11::PixelShader * pixelShader)2108 void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
2109 const d3d11::GeometryShader *geometryShader,
2110 const d3d11::PixelShader *pixelShader)
2111 {
2112 setVertexShader(vertexShader);
2113 setGeometryShader(geometryShader);
2114 setPixelShader(pixelShader);
2115 }
2116
setVertexShader(const d3d11::VertexShader * shader)2117 void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
2118 {
2119 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2120
2121 if (serial != mAppliedVertexShader)
2122 {
2123 ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
2124 mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
2125 mAppliedVertexShader = serial;
2126 invalidateShaders();
2127 }
2128 }
2129
setGeometryShader(const d3d11::GeometryShader * shader)2130 void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
2131 {
2132 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2133
2134 if (serial != mAppliedGeometryShader)
2135 {
2136 ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
2137 mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
2138 mAppliedGeometryShader = serial;
2139 invalidateShaders();
2140 }
2141 }
2142
setPixelShader(const d3d11::PixelShader * shader)2143 void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
2144 {
2145 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2146
2147 if (serial != mAppliedPixelShader)
2148 {
2149 ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
2150 mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
2151 mAppliedPixelShader = serial;
2152 invalidateShaders();
2153 }
2154 }
2155
setComputeShader(const d3d11::ComputeShader * shader)2156 void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
2157 {
2158 ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
2159
2160 if (serial != mAppliedComputeShader)
2161 {
2162 ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
2163 mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
2164 mAppliedComputeShader = serial;
2165 // TODO(jmadill): Dirty bits for compute.
2166 }
2167 }
2168
setVertexConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2169 void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2170 {
2171 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2172 auto ¤tSerial = mCurrentConstantBufferVS[slot];
2173
2174 mCurrentConstantBufferVSOffset[slot] = 0;
2175 mCurrentConstantBufferVSSize[slot] = 0;
2176
2177 if (buffer)
2178 {
2179 if (currentSerial != buffer->getSerial())
2180 {
2181 deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
2182 currentSerial = buffer->getSerial();
2183 invalidateConstantBuffer(slot);
2184 }
2185 }
2186 else
2187 {
2188 if (!currentSerial.empty())
2189 {
2190 ID3D11Buffer *nullBuffer = nullptr;
2191 deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
2192 currentSerial.clear();
2193 invalidateConstantBuffer(slot);
2194 }
2195 }
2196 }
2197
setPixelConstantBuffer(unsigned int slot,const d3d11::Buffer * buffer)2198 void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
2199 {
2200 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2201 auto ¤tSerial = mCurrentConstantBufferPS[slot];
2202
2203 mCurrentConstantBufferPSOffset[slot] = 0;
2204 mCurrentConstantBufferPSSize[slot] = 0;
2205
2206 if (buffer)
2207 {
2208 if (currentSerial != buffer->getSerial())
2209 {
2210 deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
2211 currentSerial = buffer->getSerial();
2212 invalidateConstantBuffer(slot);
2213 }
2214 }
2215 else
2216 {
2217 if (!currentSerial.empty())
2218 {
2219 ID3D11Buffer *nullBuffer = nullptr;
2220 deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
2221 currentSerial.clear();
2222 invalidateConstantBuffer(slot);
2223 }
2224 }
2225 }
2226
setDepthStencilState(const d3d11::DepthStencilState * depthStencilState,UINT stencilRef)2227 void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
2228 UINT stencilRef)
2229 {
2230 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2231
2232 if (depthStencilState)
2233 {
2234 deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
2235 }
2236 else
2237 {
2238 deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
2239 }
2240
2241 mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
2242 }
2243
setSimpleBlendState(const d3d11::BlendState * blendState)2244 void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
2245 {
2246 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2247
2248 if (blendState)
2249 {
2250 deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
2251 }
2252 else
2253 {
2254 deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
2255 }
2256
2257 mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
2258 }
2259
setRasterizerState(const d3d11::RasterizerState * rasterizerState)2260 void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
2261 {
2262 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2263
2264 if (rasterizerState)
2265 {
2266 deviceContext->RSSetState(rasterizerState->get());
2267 }
2268 else
2269 {
2270 deviceContext->RSSetState(nullptr);
2271 }
2272
2273 mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
2274 }
2275
setSimpleViewport(const gl::Extents & extents)2276 void StateManager11::setSimpleViewport(const gl::Extents &extents)
2277 {
2278 setSimpleViewport(extents.width, extents.height);
2279 }
2280
setSimpleViewport(int width,int height)2281 void StateManager11::setSimpleViewport(int width, int height)
2282 {
2283 D3D11_VIEWPORT viewport;
2284 viewport.TopLeftX = 0;
2285 viewport.TopLeftY = 0;
2286 viewport.Width = static_cast<FLOAT>(width);
2287 viewport.Height = static_cast<FLOAT>(height);
2288 viewport.MinDepth = 0.0f;
2289 viewport.MaxDepth = 1.0f;
2290
2291 mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
2292 mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
2293 }
2294
setSimplePixelTextureAndSampler(const d3d11::SharedSRV & srv,const d3d11::SamplerState & samplerState)2295 void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
2296 const d3d11::SamplerState &samplerState)
2297 {
2298 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2299
2300 setShaderResourceInternal(gl::SHADER_FRAGMENT, 0, &srv);
2301 deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
2302
2303 mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
2304 mForceSetPixelSamplerStates[0] = true;
2305 }
2306
setSimpleScissorRect(const gl::Rectangle & glRect)2307 void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
2308 {
2309 D3D11_RECT scissorRect;
2310 scissorRect.left = glRect.x;
2311 scissorRect.right = glRect.x + glRect.width;
2312 scissorRect.top = glRect.y;
2313 scissorRect.bottom = glRect.y + glRect.height;
2314 setScissorRectD3D(scissorRect);
2315 }
2316
setScissorRectD3D(const D3D11_RECT & d3dRect)2317 void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
2318 {
2319 mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
2320 mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
2321 }
2322
2323 // For each Direct3D sampler of either the pixel or vertex stage,
2324 // looks up the corresponding OpenGL texture image unit and texture type,
2325 // and sets the texture and its addressing/filtering state (or NULL when inactive).
2326 // Sampler mapping needs to be up-to-date on the program object before this is called.
applyTextures(const gl::Context * context,gl::ShaderType shaderType)2327 gl::Error StateManager11::applyTextures(const gl::Context *context, gl::ShaderType shaderType)
2328 {
2329 ASSERT(shaderType != gl::SHADER_COMPUTE);
2330 const auto &glState = context->getGLState();
2331 const auto &caps = context->getCaps();
2332 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
2333
2334 ASSERT(!programD3D->isSamplerMappingDirty());
2335
2336 // TODO(jmadill): Use the Program's sampler bindings.
2337 const auto &completeTextures = glState.getCompleteTextureCache();
2338
2339 unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
2340 for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
2341 {
2342 GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
2343 ASSERT(textureUnit != -1);
2344 gl::Texture *texture = completeTextures[textureUnit];
2345
2346 // A nullptr texture indicates incomplete.
2347 if (texture)
2348 {
2349 gl::Sampler *samplerObject = glState.getSampler(textureUnit);
2350
2351 const gl::SamplerState &samplerState =
2352 samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
2353
2354 ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
2355 ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
2356 }
2357 else
2358 {
2359 GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
2360
2361 // Texture is not sampler complete or it is in use by the framebuffer. Bind the
2362 // incomplete texture.
2363 gl::Texture *incompleteTexture = nullptr;
2364 ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
2365 ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
2366 incompleteTexture->getSamplerState()));
2367 ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
2368 }
2369 }
2370
2371 // Set all the remaining textures to NULL
2372 size_t samplerCount = (shaderType == gl::SHADER_FRAGMENT) ? caps.maxTextureImageUnits
2373 : caps.maxVertexTextureImageUnits;
2374 ANGLE_TRY(clearSRVs(shaderType, samplerRange, samplerCount));
2375
2376 return gl::NoError();
2377 }
2378
syncTextures(const gl::Context * context)2379 gl::Error StateManager11::syncTextures(const gl::Context *context)
2380 {
2381 ANGLE_TRY(applyTextures(context, gl::SHADER_VERTEX));
2382 ANGLE_TRY(applyTextures(context, gl::SHADER_FRAGMENT));
2383 return gl::NoError();
2384 }
2385
setSamplerState(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & samplerState)2386 gl::Error StateManager11::setSamplerState(const gl::Context *context,
2387 gl::ShaderType type,
2388 int index,
2389 gl::Texture *texture,
2390 const gl::SamplerState &samplerState)
2391 {
2392 #if !defined(NDEBUG)
2393 // Storage should exist, texture should be complete. Only verified in Debug.
2394 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
2395 TextureStorage *storage = nullptr;
2396 ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
2397 ASSERT(storage);
2398 #endif // !defined(NDEBUG)
2399
2400 auto *deviceContext = mRenderer->getDeviceContext();
2401
2402 if (type == gl::SHADER_FRAGMENT)
2403 {
2404 ASSERT(static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits);
2405
2406 if (mForceSetPixelSamplerStates[index] ||
2407 memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
2408 {
2409 ID3D11SamplerState *dxSamplerState = nullptr;
2410 ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
2411
2412 ASSERT(dxSamplerState != nullptr);
2413 deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
2414
2415 mCurPixelSamplerStates[index] = samplerState;
2416 }
2417
2418 mForceSetPixelSamplerStates[index] = false;
2419 }
2420 else if (type == gl::SHADER_VERTEX)
2421 {
2422 ASSERT(static_cast<unsigned int>(index) <
2423 mRenderer->getNativeCaps().maxVertexTextureImageUnits);
2424
2425 if (mForceSetVertexSamplerStates[index] ||
2426 memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
2427 {
2428 ID3D11SamplerState *dxSamplerState = nullptr;
2429 ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
2430
2431 ASSERT(dxSamplerState != nullptr);
2432 deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
2433
2434 mCurVertexSamplerStates[index] = samplerState;
2435 }
2436
2437 mForceSetVertexSamplerStates[index] = false;
2438 }
2439 else if (type == gl::SHADER_COMPUTE)
2440 {
2441 ASSERT(static_cast<unsigned int>(index) <
2442 mRenderer->getNativeCaps().maxComputeTextureImageUnits);
2443
2444 if (mForceSetComputeSamplerStates[index] ||
2445 memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0)
2446 {
2447 ID3D11SamplerState *dxSamplerState = nullptr;
2448 ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
2449
2450 ASSERT(dxSamplerState != nullptr);
2451 deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
2452
2453 mCurComputeSamplerStates[index] = samplerState;
2454 }
2455
2456 mForceSetComputeSamplerStates[index] = false;
2457 }
2458 else
2459 UNREACHABLE();
2460
2461 // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
2462 // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
2463 // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers.
2464 mShaderConstants.onSamplerChange(type, index, *texture);
2465
2466 return gl::NoError();
2467 }
2468
setTexture(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture)2469 gl::Error StateManager11::setTexture(const gl::Context *context,
2470 gl::ShaderType type,
2471 int index,
2472 gl::Texture *texture)
2473 {
2474 ASSERT(type != gl::SHADER_COMPUTE);
2475 const d3d11::SharedSRV *textureSRV = nullptr;
2476
2477 if (texture)
2478 {
2479 TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
2480
2481 TextureStorage *texStorage = nullptr;
2482 ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2483
2484 // Texture should be complete and have a storage
2485 ASSERT(texStorage);
2486
2487 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2488
2489 ANGLE_TRY(storage11->getSRVForSampler(context, texture->getTextureState(), &textureSRV));
2490
2491 // If we get an invalid SRV here, something went wrong in the texture class and we're
2492 // unexpectedly missing the shader resource view.
2493 ASSERT(textureSRV->valid());
2494
2495 textureImpl->resetDirty();
2496 }
2497
2498 ASSERT(
2499 (type == gl::SHADER_FRAGMENT &&
2500 static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits) ||
2501 (type == gl::SHADER_VERTEX &&
2502 static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxVertexTextureImageUnits));
2503
2504 setShaderResourceInternal(type, index, textureSRV);
2505 return gl::NoError();
2506 }
2507
syncTexturesForCompute(const gl::Context * context)2508 gl::Error StateManager11::syncTexturesForCompute(const gl::Context *context)
2509 {
2510 const auto &glState = context->getGLState();
2511 const auto &caps = context->getCaps();
2512 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
2513
2514 // TODO(xinghua.cao@intel.com): Implement sampler feature in compute shader.
2515 unsigned int readonlyImageRange = programD3D->getUsedImageRange(gl::SHADER_COMPUTE, true);
2516 for (unsigned int readonlyImageIndex = 0; readonlyImageIndex < readonlyImageRange;
2517 readonlyImageIndex++)
2518 {
2519 GLint imageUnitIndex =
2520 programD3D->getImageMapping(gl::SHADER_COMPUTE, readonlyImageIndex, true, caps);
2521 ASSERT(imageUnitIndex != -1);
2522 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2523 ANGLE_TRY(
2524 setTextureForImage(context, gl::SHADER_COMPUTE, readonlyImageIndex, true, imageUnit));
2525 }
2526
2527 unsigned int imageRange = programD3D->getUsedImageRange(gl::SHADER_COMPUTE, false);
2528 for (unsigned int imageIndex = 0; imageIndex < imageRange; imageIndex++)
2529 {
2530 GLint imageUnitIndex =
2531 programD3D->getImageMapping(gl::SHADER_COMPUTE, imageIndex, false, caps);
2532 ASSERT(imageUnitIndex != -1);
2533 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
2534 ANGLE_TRY(setTextureForImage(context, gl::SHADER_COMPUTE, imageIndex, false, imageUnit));
2535 }
2536
2537 // Set all the remaining textures to NULL
2538 size_t readonlyImageCount = caps.maxImageUnits;
2539 size_t imageCount = caps.maxImageUnits;
2540 ANGLE_TRY(clearSRVs(gl::SHADER_COMPUTE, readonlyImageRange, readonlyImageCount));
2541 ANGLE_TRY(clearUAVs(gl::SHADER_COMPUTE, imageRange, imageCount));
2542
2543 return gl::NoError();
2544 }
2545
setTextureForImage(const gl::Context * context,gl::ShaderType type,int index,bool readonly,const gl::ImageUnit & imageUnit)2546 gl::Error StateManager11::setTextureForImage(const gl::Context *context,
2547 gl::ShaderType type,
2548 int index,
2549 bool readonly,
2550 const gl::ImageUnit &imageUnit)
2551 {
2552 TextureD3D *textureImpl = nullptr;
2553 if (!imageUnit.texture.get())
2554 {
2555 return gl::NoError();
2556 }
2557
2558 textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
2559 TextureStorage *texStorage = nullptr;
2560 ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
2561 // Texture should be complete and have a storage
2562 ASSERT(texStorage);
2563 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2564
2565 if (readonly)
2566 {
2567 const d3d11::SharedSRV *textureSRV = nullptr;
2568 ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
2569 // If we get an invalid SRV here, something went wrong in the texture class and we're
2570 // unexpectedly missing the shader resource view.
2571 ASSERT(textureSRV->valid());
2572 ASSERT((static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxImageUnits));
2573 setShaderResourceInternal(type, index, textureSRV);
2574 }
2575 else
2576 {
2577 const d3d11::SharedUAV *textureUAV = nullptr;
2578 ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
2579 // If we get an invalid UAV here, something went wrong in the texture class and we're
2580 // unexpectedly missing the unordered access view.
2581 ASSERT(textureUAV->valid());
2582 ASSERT((static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxImageUnits));
2583 setUnorderedAccessViewInternal(type, index, textureUAV);
2584 }
2585
2586 textureImpl->resetDirty();
2587 return gl::NoError();
2588 }
2589
2590 // Things that affect a program's dirtyness:
2591 // 1. Directly changing the program executable -> triggered in StateManager11::syncState.
2592 // 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal.
2593 // 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal.
2594 // 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState.
2595 // 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState.
2596 // 6. An internal shader was used. -> triggered in StateManager11::set*Shader.
2597 // 7. Drawing with/without point sprites. -> checked in StateManager11::updateState.
2598 // TODO(jmadill): Use dirty bits for transform feedback.
syncProgram(const gl::Context * context,GLenum drawMode)2599 gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMode)
2600 {
2601 Context11 *context11 = GetImplAs<Context11>(context);
2602 ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
2603
2604 const auto &glState = context->getGLState();
2605 const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray());
2606 auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
2607
2608 programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
2609
2610 // Binaries must be compiled before the sync.
2611 ASSERT(programD3D->hasVertexExecutableForCachedInputLayout());
2612 ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode));
2613 ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout());
2614
2615 ShaderExecutableD3D *vertexExe = nullptr;
2616 ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr));
2617
2618 ShaderExecutableD3D *pixelExe = nullptr;
2619 ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
2620
2621 ShaderExecutableD3D *geometryExe = nullptr;
2622 ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
2623 nullptr));
2624
2625 const d3d11::VertexShader *vertexShader =
2626 (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
2627
2628 // Skip pixel shader if we're doing rasterizer discard.
2629 const d3d11::PixelShader *pixelShader = nullptr;
2630 if (!glState.getRasterizerState().rasterizerDiscard)
2631 {
2632 pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
2633 }
2634
2635 const d3d11::GeometryShader *geometryShader = nullptr;
2636 if (glState.isTransformFeedbackActiveUnpaused())
2637 {
2638 geometryShader =
2639 (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
2640 }
2641 else
2642 {
2643 geometryShader =
2644 (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
2645 }
2646
2647 setDrawShaders(vertexShader, geometryShader, pixelShader);
2648
2649 // Explicitly clear the shaders dirty bit.
2650 mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
2651
2652 return gl::NoError();
2653 }
2654
applyVertexBuffer(const gl::Context * context,GLenum mode,const DrawCallVertexParams & vertexParams,bool isIndexedRendering)2655 gl::Error StateManager11::applyVertexBuffer(const gl::Context *context,
2656 GLenum mode,
2657 const DrawCallVertexParams &vertexParams,
2658 bool isIndexedRendering)
2659 {
2660 const auto &state = context->getGLState();
2661 const gl::VertexArray *vertexArray = state.getVertexArray();
2662 VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
2663
2664 if (mVertexAttribsNeedTranslation)
2665 {
2666 ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, &mVertexDataManager,
2667 vertexParams));
2668 mInputLayoutIsDirty = true;
2669
2670 // Determine if we need to update attribs on the next draw.
2671 mVertexAttribsNeedTranslation = (vertexArray11->hasActiveDynamicAttrib(context));
2672 }
2673
2674 if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != vertexParams.firstVertex())
2675 {
2676 mLastFirstVertex = vertexParams.firstVertex();
2677 mInputLayoutIsDirty = true;
2678 }
2679
2680 if (!mInputLayoutIsDirty)
2681 {
2682 return gl::NoError();
2683 }
2684
2685 const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs();
2686 gl::Program *program = state.getProgram();
2687
2688 // Sort the attributes according to ensure we re-use similar input layouts.
2689 AttribIndexArray sortedSemanticIndices;
2690 SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs,
2691 &sortedSemanticIndices, &mCurrentAttributes);
2692
2693 auto featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
2694
2695 // If we are using FL 9_3, make sure the first attribute is not instanced
2696 if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
2697 {
2698 if (mCurrentAttributes[0]->divisor > 0)
2699 {
2700 Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
2701 if (firstNonInstancedIndex.valid())
2702 {
2703 size_t index = firstNonInstancedIndex.value();
2704 std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
2705 std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
2706 }
2707 }
2708 }
2709
2710 // Update the applied input layout by querying the cache.
2711 ANGLE_TRY(mInputLayoutCache.updateInputLayout(mRenderer, state, mCurrentAttributes, mode,
2712 sortedSemanticIndices, vertexParams));
2713
2714 // Update the applied vertex buffers.
2715 ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(context, mCurrentAttributes, mode,
2716 vertexParams.firstVertex(), isIndexedRendering));
2717
2718 // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
2719 // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
2720 // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
2721 // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
2722 // update on the second draw call.
2723 // Hence we clear the flags here, after we've applied vertex data, since we know everything
2724 // is clean. This is a bit of a hack.
2725 vertexArray11->clearDirtyAndPromoteDynamicAttribs(context, vertexParams);
2726
2727 mInputLayoutIsDirty = false;
2728 return gl::NoError();
2729 }
2730
applyIndexBuffer(const gl::Context * context,const void * indices,GLsizei count,GLenum type,const gl::HasIndexRange & lazyIndexRange,bool usePrimitiveRestartWorkaround)2731 gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
2732 const void *indices,
2733 GLsizei count,
2734 GLenum type,
2735 const gl::HasIndexRange &lazyIndexRange,
2736 bool usePrimitiveRestartWorkaround)
2737 {
2738 const auto &glState = context->getGLState();
2739 gl::VertexArray *vao = glState.getVertexArray();
2740 VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
2741
2742 GLenum destElementType =
2743 GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround);
2744
2745 if (!vao11->updateElementArrayStorage(context, type, destElementType, indices) &&
2746 !mIndexBufferIsDirty)
2747 {
2748 // No streaming or index buffer application necessary.
2749 return gl::NoError();
2750 }
2751
2752 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
2753
2754 TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo();
2755 ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, destElementType, count,
2756 elementArrayBuffer, indices, indexInfo));
2757
2758 ID3D11Buffer *buffer = nullptr;
2759 DXGI_FORMAT bufferFormat =
2760 (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
2761
2762 if (indexInfo->storage)
2763 {
2764 Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
2765 ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDEX), buffer);
2766 }
2767 else
2768 {
2769 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
2770 buffer = indexBuffer->getBuffer().get();
2771 }
2772
2773 // Track dirty indices in the index range cache.
2774 indexInfo->srcIndexData.srcIndicesChanged =
2775 syncIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
2776
2777 mIndexBufferIsDirty = false;
2778
2779 vao11->setCachedIndexInfoValid();
2780 return gl::NoError();
2781 }
2782
setIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)2783 void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
2784 DXGI_FORMAT indexFormat,
2785 unsigned int offset)
2786 {
2787 if (syncIndexBuffer(buffer, indexFormat, offset))
2788 {
2789 mIndexBufferIsDirty = true;
2790 }
2791 }
2792
syncIndexBuffer(ID3D11Buffer * buffer,DXGI_FORMAT indexFormat,unsigned int offset)2793 bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
2794 DXGI_FORMAT indexFormat,
2795 unsigned int offset)
2796 {
2797 if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
2798 {
2799 mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
2800
2801 mAppliedIB = buffer;
2802 mAppliedIBFormat = indexFormat;
2803 mAppliedIBOffset = offset;
2804 return true;
2805 }
2806
2807 return false;
2808 }
2809
2810 // Vertex buffer is invalidated outside this function.
updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,GLsizei emulatedInstanceId)2811 gl::Error StateManager11::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
2812 GLsizei emulatedInstanceId)
2813 {
2814 return mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(
2815 mRenderer, mCurrentAttributes, startVertex, emulatedInstanceId);
2816 }
2817
generateSwizzle(const gl::Context * context,gl::Texture * texture)2818 gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
2819 {
2820 if (!texture)
2821 {
2822 return gl::NoError();
2823 }
2824
2825 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
2826 ASSERT(textureD3D);
2827
2828 TextureStorage *texStorage = nullptr;
2829 ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
2830
2831 if (texStorage)
2832 {
2833 TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
2834 const gl::TextureState &textureState = texture->getTextureState();
2835 ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState()));
2836 }
2837
2838 return gl::NoError();
2839 }
2840
generateSwizzlesForShader(const gl::Context * context,gl::ShaderType type)2841 gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type)
2842 {
2843 const auto &glState = context->getGLState();
2844 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
2845
2846 unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
2847
2848 for (unsigned int i = 0; i < samplerRange; i++)
2849 {
2850 GLenum textureType = programD3D->getSamplerTextureType(type, i);
2851 GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps());
2852 if (textureUnit != -1)
2853 {
2854 gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
2855 ASSERT(texture);
2856 if (texture->getTextureState().swizzleRequired())
2857 {
2858 ANGLE_TRY(generateSwizzle(context, texture));
2859 }
2860 }
2861 }
2862
2863 return gl::NoError();
2864 }
2865
generateSwizzles(const gl::Context * context)2866 gl::Error StateManager11::generateSwizzles(const gl::Context *context)
2867 {
2868 ANGLE_TRY(generateSwizzlesForShader(context, gl::SHADER_VERTEX));
2869 ANGLE_TRY(generateSwizzlesForShader(context, gl::SHADER_FRAGMENT));
2870 return gl::NoError();
2871 }
2872
applyUniforms(ProgramD3D * programD3D)2873 gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D)
2874 {
2875 UniformStorage11 *vertexUniformStorage =
2876 GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage());
2877 UniformStorage11 *fragmentUniformStorage =
2878 GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage());
2879 ASSERT(vertexUniformStorage);
2880 ASSERT(fragmentUniformStorage);
2881
2882 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2883
2884 const d3d11::Buffer *vertexConstantBuffer = nullptr;
2885 ANGLE_TRY(vertexUniformStorage->getConstantBuffer(mRenderer, &vertexConstantBuffer));
2886 const d3d11::Buffer *pixelConstantBuffer = nullptr;
2887 ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer));
2888
2889 if (vertexUniformStorage->size() > 0 && programD3D->areVertexUniformsDirty())
2890 {
2891 UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer);
2892 }
2893
2894 if (fragmentUniformStorage->size() > 0 && programD3D->areFragmentUniformsDirty())
2895 {
2896 UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer);
2897 }
2898
2899 unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
2900
2901 if (mCurrentConstantBufferVS[slot] != vertexConstantBuffer->getSerial())
2902 {
2903 deviceContext->VSSetConstantBuffers(slot, 1, vertexConstantBuffer->getPointer());
2904 mCurrentConstantBufferVS[slot] = vertexConstantBuffer->getSerial();
2905 mCurrentConstantBufferVSOffset[slot] = 0;
2906 mCurrentConstantBufferVSSize[slot] = 0;
2907 }
2908
2909 if (mCurrentConstantBufferPS[slot] != pixelConstantBuffer->getSerial())
2910 {
2911 deviceContext->PSSetConstantBuffers(slot, 1, pixelConstantBuffer->getPointer());
2912 mCurrentConstantBufferPS[slot] = pixelConstantBuffer->getSerial();
2913 mCurrentConstantBufferPSOffset[slot] = 0;
2914 mCurrentConstantBufferPSSize[slot] = 0;
2915 }
2916
2917 programD3D->markUniformsClean();
2918
2919 return gl::NoError();
2920 }
2921
applyDriverUniforms(const ProgramD3D & programD3D)2922 gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D)
2923 {
2924 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2925
2926 if (!mDriverConstantBufferVS.valid())
2927 {
2928 size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SHADER_VERTEX);
2929
2930 D3D11_BUFFER_DESC constantBufferDescription = {0};
2931 d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
2932 ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferVS));
2933
2934 ID3D11Buffer *driverVSConstants = mDriverConstantBufferVS.get();
2935 deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
2936 &driverVSConstants);
2937 }
2938
2939 if (!mDriverConstantBufferPS.valid())
2940 {
2941 size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SHADER_FRAGMENT);
2942
2943 D3D11_BUFFER_DESC constantBufferDescription = {0};
2944 d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
2945 ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferPS));
2946
2947 ID3D11Buffer *driverVSConstants = mDriverConstantBufferPS.get();
2948 deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
2949 &driverVSConstants);
2950 }
2951
2952 // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve
2953 // constant buffer slots. We update both in the constant buffer if needed.
2954 ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::SHADER_VERTEX, programD3D,
2955 mDriverConstantBufferVS));
2956 ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::SHADER_FRAGMENT, programD3D,
2957 mDriverConstantBufferPS));
2958
2959 // needed for the point sprite geometry shader
2960 // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
2961 if (mRenderer->isES3Capable())
2962 {
2963 if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS.getSerial())
2964 {
2965 ASSERT(mDriverConstantBufferPS.valid());
2966 deviceContext->GSSetConstantBuffers(0, 1, mDriverConstantBufferPS.getPointer());
2967 mCurrentGeometryConstantBuffer = mDriverConstantBufferPS.getSerial();
2968 }
2969 }
2970
2971 return gl::NoError();
2972 }
2973
applyComputeUniforms(ProgramD3D * programD3D)2974 gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D)
2975 {
2976 UniformStorage11 *computeUniformStorage =
2977 GetAs<UniformStorage11>(&programD3D->getComputeUniformStorage());
2978 ASSERT(computeUniformStorage);
2979
2980 const d3d11::Buffer *constantBuffer = nullptr;
2981 ANGLE_TRY(computeUniformStorage->getConstantBuffer(mRenderer, &constantBuffer));
2982
2983 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2984
2985 if (computeUniformStorage->size() > 0 && programD3D->areComputeUniformsDirty())
2986 {
2987 UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
2988 programD3D->markUniformsClean();
2989 }
2990
2991 if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
2992 {
2993 deviceContext->CSSetConstantBuffers(
2994 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
2995 constantBuffer->getPointer());
2996 mCurrentComputeConstantBuffer = constantBuffer->getSerial();
2997 }
2998
2999 if (!mDriverConstantBufferCS.valid())
3000 {
3001 size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SHADER_COMPUTE);
3002
3003 D3D11_BUFFER_DESC constantBufferDescription = {0};
3004 d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
3005 ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferCS));
3006 ID3D11Buffer *buffer = mDriverConstantBufferCS.get();
3007 deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
3008 &buffer);
3009 }
3010
3011 ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::SHADER_COMPUTE, *programD3D,
3012 mDriverConstantBufferCS));
3013
3014 return gl::NoError();
3015 }
3016
syncUniformBuffers(const gl::Context * context,ProgramD3D * programD3D)3017 gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D)
3018 {
3019 unsigned int reservedVertex = mRenderer->getReservedVertexUniformBuffers();
3020 unsigned int reservedFragment = mRenderer->getReservedFragmentUniformBuffers();
3021
3022 programD3D->updateUniformBufferCache(context->getCaps(), reservedVertex, reservedFragment);
3023
3024 const auto &vertexUniformBuffers = programD3D->getVertexUniformBufferCache();
3025 const auto &fragmentUniformBuffers = programD3D->getFragmentUniformBufferCache();
3026 const auto &glState = context->getGLState();
3027 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3028 ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
3029
3030 mOnConstantBufferDirtyReceiver.reset();
3031
3032 for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++)
3033 {
3034 GLint binding = vertexUniformBuffers[bufferIndex];
3035
3036 if (binding == -1)
3037 {
3038 continue;
3039 }
3040
3041 const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
3042 GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3043 GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
3044
3045 if (uniformBuffer.get() == nullptr)
3046 {
3047 continue;
3048 }
3049
3050 Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
3051 const d3d11::Buffer *constantBuffer = nullptr;
3052 UINT firstConstant = 0;
3053 UINT numConstants = 0;
3054
3055 ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
3056 uniformBufferSize, &constantBuffer,
3057 &firstConstant, &numConstants));
3058
3059 ASSERT(constantBuffer);
3060
3061 if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() &&
3062 mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset &&
3063 mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize)
3064 {
3065 continue;
3066 }
3067
3068 unsigned int appliedIndex = reservedVertex + static_cast<unsigned int>(bufferIndex);
3069
3070 if (firstConstant != 0 && uniformBufferSize != 0)
3071 {
3072 ASSERT(numConstants != 0);
3073 deviceContext1->VSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(),
3074 &firstConstant, &numConstants);
3075 }
3076 else
3077 {
3078 deviceContext->VSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer());
3079 }
3080
3081 mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial();
3082 mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset;
3083 mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize;
3084
3085 mOnConstantBufferDirtyReceiver.bindVS(bufferIndex, bufferStorage);
3086 }
3087
3088 for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++)
3089 {
3090 GLint binding = fragmentUniformBuffers[bufferIndex];
3091
3092 if (binding == -1)
3093 {
3094 continue;
3095 }
3096
3097 const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
3098 GLintptr uniformBufferOffset = uniformBuffer.getOffset();
3099 GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
3100
3101 if (uniformBuffer.get() == nullptr)
3102 {
3103 continue;
3104 }
3105
3106 Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
3107 const d3d11::Buffer *constantBuffer = nullptr;
3108 UINT firstConstant = 0;
3109 UINT numConstants = 0;
3110
3111 ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
3112 uniformBufferSize, &constantBuffer,
3113 &firstConstant, &numConstants));
3114
3115 ASSERT(constantBuffer);
3116
3117 if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() &&
3118 mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset &&
3119 mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize)
3120 {
3121 continue;
3122 }
3123
3124 unsigned int appliedIndex = reservedFragment + static_cast<unsigned int>(bufferIndex);
3125
3126 if (firstConstant != 0 && uniformBufferSize != 0)
3127 {
3128 deviceContext1->PSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(),
3129 &firstConstant, &numConstants);
3130 }
3131 else
3132 {
3133 deviceContext->PSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer());
3134 }
3135
3136 mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial();
3137 mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset;
3138 mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize;
3139
3140 mOnConstantBufferDirtyReceiver.bindPS(bufferIndex, bufferStorage);
3141 }
3142
3143 return gl::NoError();
3144 }
3145
syncTransformFeedbackBuffers(const gl::Context * context)3146 gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
3147 {
3148 const auto &glState = context->getGLState();
3149
3150 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
3151
3152 // If transform feedback is not active, unbind all buffers
3153 if (!glState.isTransformFeedbackActiveUnpaused())
3154 {
3155 if (mAppliedTFSerial != mEmptySerial)
3156 {
3157 deviceContext->SOSetTargets(0, nullptr, nullptr);
3158 mAppliedTFSerial = mEmptySerial;
3159 }
3160 return gl::NoError();
3161 }
3162
3163 gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
3164 TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback);
3165 if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
3166 {
3167 return gl::NoError();
3168 }
3169
3170 const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
3171 ANGLE_TRY_RESULT(tf11->getSOBuffers(context), soBuffers);
3172 const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
3173
3174 deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
3175
3176 mAppliedTFSerial = tf11->getSerial();
3177 tf11->onApply();
3178
3179 return gl::NoError();
3180 }
3181
3182 // DrawCallVertexParams implementation.
DrawCallVertexParams(GLint firstVertex,GLsizei vertexCount,GLsizei instances)3183 DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex,
3184 GLsizei vertexCount,
3185 GLsizei instances)
3186 : mHasIndexRange(nullptr),
3187 mFirstVertex(firstVertex),
3188 mVertexCount(vertexCount),
3189 mInstances(instances),
3190 mBaseVertex(0)
3191 {
3192 }
3193
3194 // Use when in a drawElements call.
DrawCallVertexParams(bool firstVertexDefinitelyZero,const gl::HasIndexRange & hasIndexRange,GLint baseVertex,GLsizei instances)3195 DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero,
3196 const gl::HasIndexRange &hasIndexRange,
3197 GLint baseVertex,
3198 GLsizei instances)
3199 : mHasIndexRange(&hasIndexRange),
3200 mFirstVertex(),
3201 mVertexCount(0),
3202 mInstances(instances),
3203 mBaseVertex(baseVertex)
3204 {
3205 if (firstVertexDefinitelyZero)
3206 {
3207 mFirstVertex = baseVertex;
3208 }
3209 }
3210
firstVertex() const3211 GLint DrawCallVertexParams::firstVertex() const
3212 {
3213 if (!mFirstVertex.valid())
3214 {
3215 ensureResolved();
3216 ASSERT(mFirstVertex.valid());
3217 }
3218 return mFirstVertex.value();
3219 }
3220
vertexCount() const3221 GLsizei DrawCallVertexParams::vertexCount() const
3222 {
3223 ensureResolved();
3224 return mVertexCount;
3225 }
3226
instances() const3227 GLsizei DrawCallVertexParams::instances() const
3228 {
3229 return mInstances;
3230 }
3231
ensureResolved() const3232 void DrawCallVertexParams::ensureResolved() const
3233 {
3234 if (mHasIndexRange)
3235 {
3236 ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex);
3237
3238 // Resolve the index range now if we need to.
3239 const auto &indexRange = mHasIndexRange->getIndexRange().value();
3240 mFirstVertex = mBaseVertex + static_cast<GLint>(indexRange.start);
3241 mVertexCount = static_cast<GLsizei>(indexRange.vertexCount());
3242 mHasIndexRange = nullptr;
3243 }
3244 }
3245
3246 // OnConstantBufferDirtyReceiver implementation.
OnConstantBufferDirtyReceiver()3247 StateManager11::OnConstantBufferDirtyReceiver::OnConstantBufferDirtyReceiver()
3248 {
3249 for (size_t vsIndex = 0; vsIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS;
3250 ++vsIndex)
3251 {
3252 mBindingsVS.emplace_back(this, vsIndex);
3253 }
3254
3255 for (size_t fsIndex = 0; fsIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS;
3256 ++fsIndex)
3257 {
3258 mBindingsPS.emplace_back(this, fsIndex);
3259 }
3260 }
3261
~OnConstantBufferDirtyReceiver()3262 StateManager11::OnConstantBufferDirtyReceiver::~OnConstantBufferDirtyReceiver()
3263 {
3264 }
3265
onSubjectStateChange(const gl::Context * context,angle::SubjectIndex index,angle::SubjectMessage message)3266 void StateManager11::OnConstantBufferDirtyReceiver::onSubjectStateChange(
3267 const gl::Context *context,
3268 angle::SubjectIndex index,
3269 angle::SubjectMessage message)
3270 {
3271 StateManager11 *stateManager = GetImplAs<Context11>(context)->getRenderer()->getStateManager();
3272 stateManager->invalidateProgramUniformBuffers();
3273 }
3274
bindVS(size_t index,Buffer11 * buffer)3275 void StateManager11::OnConstantBufferDirtyReceiver::bindVS(size_t index, Buffer11 *buffer)
3276 {
3277 ASSERT(buffer);
3278 ASSERT(index < mBindingsVS.size());
3279 mBindingsVS[index].bind(buffer->getDirectSubject());
3280 }
3281
bindPS(size_t index,Buffer11 * buffer)3282 void StateManager11::OnConstantBufferDirtyReceiver::bindPS(size_t index, Buffer11 *buffer)
3283 {
3284 ASSERT(buffer);
3285 ASSERT(index < mBindingsPS.size());
3286 mBindingsPS[index].bind(buffer->getDirectSubject());
3287 }
3288
reset()3289 void StateManager11::OnConstantBufferDirtyReceiver::reset()
3290 {
3291 for (angle::ObserverBinding &vsBinding : mBindingsVS)
3292 {
3293 vsBinding.bind(nullptr);
3294 }
3295
3296 for (angle::ObserverBinding &psBinding : mBindingsPS)
3297 {
3298 psBinding.bind(nullptr);
3299 }
3300 }
3301
3302 } // namespace rx
3303