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