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