Renderer11.cpp (174895B)
1 // 2 // Copyright 2012 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 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. 8 9 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" 10 11 #include <EGL/eglext.h> 12 #include <versionhelpers.h> 13 #include <sstream> 14 15 #include "anglebase/no_destructor.h" 16 #include "common/tls.h" 17 #include "common/utilities.h" 18 #include "libANGLE/Buffer.h" 19 #include "libANGLE/Context.h" 20 #include "libANGLE/Display.h" 21 #include "libANGLE/Framebuffer.h" 22 #include "libANGLE/FramebufferAttachment.h" 23 #include "libANGLE/Program.h" 24 #include "libANGLE/State.h" 25 #include "libANGLE/Surface.h" 26 #include "libANGLE/formatutils.h" 27 #include "libANGLE/histogram_macros.h" 28 #include "libANGLE/renderer/d3d/CompilerD3D.h" 29 #include "libANGLE/renderer/d3d/DeviceD3D.h" 30 #include "libANGLE/renderer/d3d/DisplayD3D.h" 31 #include "libANGLE/renderer/d3d/FramebufferD3D.h" 32 #include "libANGLE/renderer/d3d/IndexDataManager.h" 33 #include "libANGLE/renderer/d3d/RenderbufferD3D.h" 34 #include "libANGLE/renderer/d3d/ShaderD3D.h" 35 #include "libANGLE/renderer/d3d/SurfaceD3D.h" 36 #include "libANGLE/renderer/d3d/TextureD3D.h" 37 #include "libANGLE/renderer/d3d/VertexDataManager.h" 38 #include "libANGLE/renderer/d3d/d3d11/Blit11.h" 39 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" 40 #include "libANGLE/renderer/d3d/d3d11/Clear11.h" 41 #include "libANGLE/renderer/d3d/d3d11/Context11.h" 42 #include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h" 43 #include "libANGLE/renderer/d3d/d3d11/Fence11.h" 44 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" 45 #include "libANGLE/renderer/d3d/d3d11/Image11.h" 46 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" 47 #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" 48 #include "libANGLE/renderer/d3d/d3d11/Program11.h" 49 #include "libANGLE/renderer/d3d/d3d11/Query11.h" 50 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" 51 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" 52 #include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h" 53 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" 54 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" 55 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" 56 #include "libANGLE/renderer/d3d/d3d11/Trim11.h" 57 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" 58 #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" 59 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" 60 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 61 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" 62 #include "libANGLE/renderer/d3d/driver_utils_d3d.h" 63 #include "libANGLE/renderer/driver_utils.h" 64 #include "libANGLE/renderer/dxgi_support_table.h" 65 #include "libANGLE/renderer/renderer_utils.h" 66 #include "libANGLE/trace.h" 67 68 #ifdef ANGLE_ENABLE_WINDOWS_UWP 69 # include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h" 70 #else 71 # include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" 72 #endif 73 74 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW 75 # include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h" 76 #endif 77 78 // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process 79 // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. 80 #ifndef ANGLE_SKIP_DXGI_1_2_CHECK 81 # define ANGLE_SKIP_DXGI_1_2_CHECK 0 82 #endif 83 84 namespace rx 85 { 86 87 namespace 88 { 89 90 enum 91 { 92 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 93 }; 94 95 enum ANGLEFeatureLevel 96 { 97 ANGLE_FEATURE_LEVEL_INVALID, 98 ANGLE_FEATURE_LEVEL_9_3, 99 ANGLE_FEATURE_LEVEL_10_0, 100 ANGLE_FEATURE_LEVEL_10_1, 101 ANGLE_FEATURE_LEVEL_11_0, 102 ANGLE_FEATURE_LEVEL_11_1, 103 NUM_ANGLE_FEATURE_LEVELS 104 }; 105 106 ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) 107 { 108 switch (d3dFeatureLevel) 109 { 110 case D3D_FEATURE_LEVEL_9_3: 111 return ANGLE_FEATURE_LEVEL_9_3; 112 case D3D_FEATURE_LEVEL_10_0: 113 return ANGLE_FEATURE_LEVEL_10_0; 114 case D3D_FEATURE_LEVEL_10_1: 115 return ANGLE_FEATURE_LEVEL_10_1; 116 case D3D_FEATURE_LEVEL_11_0: 117 return ANGLE_FEATURE_LEVEL_11_0; 118 case D3D_FEATURE_LEVEL_11_1: 119 return ANGLE_FEATURE_LEVEL_11_1; 120 default: 121 return ANGLE_FEATURE_LEVEL_INVALID; 122 } 123 } 124 125 void SetLineLoopIndices(GLuint *dest, size_t count) 126 { 127 for (size_t i = 0; i < count; i++) 128 { 129 dest[i] = static_cast<GLuint>(i); 130 } 131 dest[count] = 0; 132 } 133 134 template <typename T> 135 void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count) 136 { 137 const T *srcPtr = static_cast<const T *>(indices); 138 for (size_t i = 0; i < count; ++i) 139 { 140 dest[i] = static_cast<GLuint>(srcPtr[i]); 141 } 142 dest[count] = static_cast<GLuint>(srcPtr[0]); 143 } 144 145 void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) 146 { 147 for (size_t i = 0; i < numTris; i++) 148 { 149 destPtr[i * 3 + 0] = 0; 150 destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1; 151 destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2; 152 } 153 } 154 155 void GetLineLoopIndices(const void *indices, 156 gl::DrawElementsType indexType, 157 GLuint count, 158 bool usePrimitiveRestartFixedIndex, 159 std::vector<GLuint> *bufferOut) 160 { 161 if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex) 162 { 163 size_t indexCount = GetLineLoopWithRestartIndexCount(indexType, count, 164 static_cast<const uint8_t *>(indices)); 165 bufferOut->resize(indexCount); 166 switch (indexType) 167 { 168 case gl::DrawElementsType::UnsignedByte: 169 CopyLineLoopIndicesWithRestart<GLubyte, GLuint>( 170 count, static_cast<const uint8_t *>(indices), 171 reinterpret_cast<uint8_t *>(bufferOut->data())); 172 break; 173 case gl::DrawElementsType::UnsignedShort: 174 CopyLineLoopIndicesWithRestart<GLushort, GLuint>( 175 count, static_cast<const uint8_t *>(indices), 176 reinterpret_cast<uint8_t *>(bufferOut->data())); 177 break; 178 case gl::DrawElementsType::UnsignedInt: 179 CopyLineLoopIndicesWithRestart<GLuint, GLuint>( 180 count, static_cast<const uint8_t *>(indices), 181 reinterpret_cast<uint8_t *>(bufferOut->data())); 182 break; 183 default: 184 UNREACHABLE(); 185 break; 186 } 187 return; 188 } 189 190 // For non-primitive-restart draws, the index count is static. 191 bufferOut->resize(static_cast<size_t>(count) + 1); 192 193 switch (indexType) 194 { 195 // Non-indexed draw 196 case gl::DrawElementsType::InvalidEnum: 197 SetLineLoopIndices(&(*bufferOut)[0], count); 198 break; 199 case gl::DrawElementsType::UnsignedByte: 200 CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count); 201 break; 202 case gl::DrawElementsType::UnsignedShort: 203 CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count); 204 break; 205 case gl::DrawElementsType::UnsignedInt: 206 CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count); 207 break; 208 default: 209 UNREACHABLE(); 210 break; 211 } 212 } 213 214 template <typename T> 215 void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris) 216 { 217 const T *srcPtr = static_cast<const T *>(indices); 218 219 for (size_t i = 0; i < numTris; i++) 220 { 221 destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]); 222 destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]); 223 destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]); 224 } 225 } 226 227 template <typename T> 228 void CopyTriangleFanIndicesWithRestart(const void *indices, 229 GLuint indexCount, 230 gl::DrawElementsType indexType, 231 std::vector<GLuint> *bufferOut) 232 { 233 GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); 234 GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(gl::DrawElementsType::UnsignedInt); 235 const T *srcPtr = static_cast<const T *>(indices); 236 Optional<GLuint> vertexA; 237 Optional<GLuint> vertexB; 238 239 bufferOut->clear(); 240 241 for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx) 242 { 243 GLuint value = static_cast<GLuint>(srcPtr[indexIdx]); 244 245 if (value == restartIndex) 246 { 247 bufferOut->push_back(d3dRestartIndex); 248 vertexA.reset(); 249 vertexB.reset(); 250 } 251 else 252 { 253 if (!vertexA.valid()) 254 { 255 vertexA = value; 256 } 257 else if (!vertexB.valid()) 258 { 259 vertexB = value; 260 } 261 else 262 { 263 bufferOut->push_back(vertexA.value()); 264 bufferOut->push_back(vertexB.value()); 265 bufferOut->push_back(value); 266 vertexB = value; 267 } 268 } 269 } 270 } 271 272 void GetTriFanIndices(const void *indices, 273 gl::DrawElementsType indexType, 274 GLuint count, 275 bool usePrimitiveRestartFixedIndex, 276 std::vector<GLuint> *bufferOut) 277 { 278 if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex) 279 { 280 switch (indexType) 281 { 282 case gl::DrawElementsType::UnsignedByte: 283 CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut); 284 break; 285 case gl::DrawElementsType::UnsignedShort: 286 CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut); 287 break; 288 case gl::DrawElementsType::UnsignedInt: 289 CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut); 290 break; 291 default: 292 UNREACHABLE(); 293 break; 294 } 295 return; 296 } 297 298 // For non-primitive-restart draws, the index count is static. 299 GLuint numTris = count - 2; 300 bufferOut->resize(numTris * 3); 301 302 switch (indexType) 303 { 304 // Non-indexed draw 305 case gl::DrawElementsType::InvalidEnum: 306 SetTriangleFanIndices(&(*bufferOut)[0], numTris); 307 break; 308 case gl::DrawElementsType::UnsignedByte: 309 CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris); 310 break; 311 case gl::DrawElementsType::UnsignedShort: 312 CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris); 313 break; 314 case gl::DrawElementsType::UnsignedInt: 315 CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris); 316 break; 317 default: 318 UNREACHABLE(); 319 break; 320 } 321 } 322 323 bool IsArrayRTV(ID3D11RenderTargetView *rtv) 324 { 325 D3D11_RENDER_TARGET_VIEW_DESC desc; 326 rtv->GetDesc(&desc); 327 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY && 328 desc.Texture1DArray.ArraySize > 1) 329 return true; 330 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY && 331 desc.Texture2DArray.ArraySize > 1) 332 return true; 333 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY && 334 desc.Texture2DMSArray.ArraySize > 1) 335 return true; 336 return false; 337 } 338 339 GLsizei GetAdjustedInstanceCount(const ProgramD3D *program, GLsizei instanceCount) 340 { 341 if (!program->getState().usesMultiview()) 342 { 343 return instanceCount; 344 } 345 if (instanceCount == 0) 346 { 347 return program->getState().getNumViews(); 348 } 349 return program->getState().getNumViews() * instanceCount; 350 } 351 352 const uint32_t ScratchMemoryBufferLifetime = 1000; 353 354 void PopulateFormatDeviceCaps(ID3D11Device *device, 355 DXGI_FORMAT format, 356 UINT *outSupport, 357 UINT *outMaxSamples) 358 { 359 if (FAILED(device->CheckFormatSupport(format, outSupport))) 360 { 361 *outSupport = 0; 362 } 363 364 *outMaxSamples = 0; 365 for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2) 366 { 367 UINT qualityCount = 0; 368 if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) || 369 qualityCount == 0) 370 { 371 break; 372 } 373 374 *outMaxSamples = sampleCount; 375 } 376 } 377 378 angle::Result GetTextureD3DResourceFromStorageOrImage(const gl::Context *context, 379 TextureD3D *texture, 380 const gl::ImageIndex &index, 381 const TextureHelper11 **outResource, 382 UINT *outSubresource) 383 { 384 // If the storage exists, use it. Otherwise, copy directly from the images to avoid 385 // allocating a new storage. 386 if (texture->hasStorage()) 387 { 388 TextureStorage *storage = nullptr; 389 ANGLE_TRY(texture->getNativeTexture(context, &storage)); 390 391 TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); 392 ANGLE_TRY(storage11->getResource(context, outResource)); 393 ANGLE_TRY(storage11->getSubresourceIndex(context, index, outSubresource)); 394 } 395 else 396 { 397 ImageD3D *image = texture->getImage(index); 398 Image11 *image11 = GetAs<Image11>(image); 399 ANGLE_TRY(image11->getStagingTexture(context, outResource, outSubresource)); 400 } 401 402 return angle::Result::Continue; 403 } 404 405 } // anonymous namespace 406 407 Renderer11DeviceCaps::Renderer11DeviceCaps() = default; 408 409 Renderer11::Renderer11(egl::Display *display) 410 : RendererD3D(display), 411 mCreateDebugDevice(false), 412 mStateCache(), 413 mStateManager(this), 414 mLastHistogramUpdateTime( 415 ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())), 416 mDebug(nullptr), 417 mScratchMemoryBuffer(ScratchMemoryBufferLifetime) 418 { 419 mLineLoopIB = nullptr; 420 mTriangleFanIB = nullptr; 421 422 mBlit = nullptr; 423 mPixelTransfer = nullptr; 424 425 mClear = nullptr; 426 427 mTrim = nullptr; 428 429 mRenderer11DeviceCaps.supportsClearView = false; 430 mRenderer11DeviceCaps.supportsConstantBufferOffsets = false; 431 mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false; 432 mRenderer11DeviceCaps.supportsDXGI1_2 = false; 433 mRenderer11DeviceCaps.allowES3OnFL10_0 = false; 434 mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats = false; 435 mRenderer11DeviceCaps.supportsRasterizerOrderViews = false; 436 mRenderer11DeviceCaps.B5G6R5support = 0; 437 mRenderer11DeviceCaps.B4G4R4A4support = 0; 438 mRenderer11DeviceCaps.B5G5R5A1support = 0; 439 440 mD3d11Module = nullptr; 441 mD3d12Module = nullptr; 442 mDxgiModule = nullptr; 443 mDCompModule = nullptr; 444 mCreatedWithDeviceEXT = false; 445 446 mDevice = nullptr; 447 mDevice1 = nullptr; 448 mDeviceContext = nullptr; 449 mDeviceContext1 = nullptr; 450 mDeviceContext3 = nullptr; 451 mDxgiAdapter = nullptr; 452 mDxgiFactory = nullptr; 453 454 ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); 455 456 const auto &attributes = mDisplay->getAttributeMap(); 457 458 if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) 459 { 460 EGLint requestedMajorVersion = static_cast<EGLint>( 461 attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); 462 EGLint requestedMinorVersion = static_cast<EGLint>( 463 attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); 464 465 if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) 466 { 467 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) 468 { 469 // This could potentially lead to failed context creation if done on a system 470 // without the platform update which installs DXGI 1.2. Currently, for Chrome users 471 // D3D11 contexts are only created if the platform update is available, so this 472 // should not cause any issues. 473 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1); 474 } 475 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) 476 { 477 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); 478 } 479 } 480 481 if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) 482 { 483 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) 484 { 485 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); 486 } 487 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) 488 { 489 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); 490 } 491 } 492 493 if (requestedMajorVersion == 9 && requestedMinorVersion == 3) 494 { 495 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); 496 } 497 498 EGLint requestedDeviceType = static_cast<EGLint>(attributes.get( 499 EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE)); 500 switch (requestedDeviceType) 501 { 502 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: 503 mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE; 504 break; 505 506 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE: 507 mRequestedDriverType = D3D_DRIVER_TYPE_WARP; 508 break; 509 510 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE: 511 mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE; 512 break; 513 514 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: 515 mRequestedDriverType = D3D_DRIVER_TYPE_NULL; 516 break; 517 518 default: 519 UNREACHABLE(); 520 } 521 522 mCreateDebugDevice = ShouldUseDebugLayers(attributes); 523 } 524 else if (mDisplay->getPlatform() == EGL_PLATFORM_DEVICE_EXT) 525 { 526 ASSERT(mDisplay->getDevice() != nullptr); 527 mCreatedWithDeviceEXT = true; 528 529 // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE 530 // mAvailableFeatureLevels defaults to empty 531 mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; 532 } 533 534 const EGLenum presentPath = static_cast<EGLenum>(attributes.get( 535 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE)); 536 mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE); 537 } 538 539 Renderer11::~Renderer11() 540 { 541 release(); 542 } 543 544 #ifndef __d3d11_1_h__ 545 # define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) 546 #endif 547 548 egl::Error Renderer11::initialize() 549 { 550 HRESULT result = S_OK; 551 552 ANGLE_TRY(initializeD3DDevice()); 553 554 #if !defined(ANGLE_ENABLE_WINDOWS_UWP) 555 # if !ANGLE_SKIP_DXGI_1_2_CHECK 556 { 557 ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)"); 558 // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is 559 // required. 560 // The easiest way to check is to query for a IDXGIDevice2. 561 bool requireDXGI1_2 = false; 562 HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); 563 if (hwnd) 564 { 565 DWORD currentProcessId = GetCurrentProcessId(); 566 DWORD wndProcessId; 567 GetWindowThreadProcessId(hwnd, &wndProcessId); 568 requireDXGI1_2 = (currentProcessId != wndProcessId); 569 } 570 else 571 { 572 requireDXGI1_2 = true; 573 } 574 575 if (requireDXGI1_2) 576 { 577 IDXGIDevice2 *dxgiDevice2 = nullptr; 578 result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2); 579 if (FAILED(result)) 580 { 581 return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI) 582 << "DXGI 1.2 required to present to HWNDs owned by another process."; 583 } 584 SafeRelease(dxgiDevice2); 585 } 586 } 587 # endif 588 #endif 589 590 { 591 ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); 592 // Cast the DeviceContext to a DeviceContext1 and DeviceContext3. 593 // This could fail on Windows 7 without the Platform Update. 594 // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3. 595 mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext); 596 mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext); 597 598 IDXGIDevice *dxgiDevice = nullptr; 599 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice); 600 601 if (FAILED(result)) 602 { 603 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device."; 604 } 605 606 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter); 607 608 if (FAILED(result)) 609 { 610 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) 611 << "Could not retrieve DXGI adapter"; 612 } 613 614 SafeRelease(dxgiDevice); 615 616 IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter); 617 618 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the 619 // description string. 620 // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual 621 // hardware values. 622 if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr) 623 { 624 DXGI_ADAPTER_DESC2 adapterDesc2 = {}; 625 result = dxgiAdapter2->GetDesc2(&adapterDesc2); 626 if (SUCCEEDED(result)) 627 { 628 // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a 629 // DXGI_ADAPTER_DESC). 630 memcpy(mAdapterDescription.Description, adapterDesc2.Description, 631 sizeof(mAdapterDescription.Description)); 632 mAdapterDescription.VendorId = adapterDesc2.VendorId; 633 mAdapterDescription.DeviceId = adapterDesc2.DeviceId; 634 mAdapterDescription.SubSysId = adapterDesc2.SubSysId; 635 mAdapterDescription.Revision = adapterDesc2.Revision; 636 mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory; 637 mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory; 638 mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; 639 mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; 640 } 641 } 642 else 643 { 644 result = mDxgiAdapter->GetDesc(&mAdapterDescription); 645 } 646 647 SafeRelease(dxgiAdapter2); 648 649 if (FAILED(result)) 650 { 651 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) 652 << "Could not read DXGI adaptor description."; 653 } 654 655 memset(mDescription, 0, sizeof(mDescription)); 656 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); 657 658 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory); 659 660 if (!mDxgiFactory || FAILED(result)) 661 { 662 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) 663 << "Could not create DXGI factory."; 664 } 665 } 666 667 // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log 668 if (mCreateDebugDevice) 669 { 670 ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)"); 671 ID3D11InfoQueue *infoQueue; 672 result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); 673 674 if (SUCCEEDED(result)) 675 { 676 D3D11_MESSAGE_ID hideMessages[] = { 677 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET, 678 679 // Robust access behaviour makes out of bounds messages safe 680 D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL, 681 }; 682 683 D3D11_INFO_QUEUE_FILTER filter = {}; 684 filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages)); 685 filter.DenyList.pIDList = hideMessages; 686 687 infoQueue->AddStorageFilterEntries(&filter); 688 SafeRelease(infoQueue); 689 } 690 } 691 692 #if !defined(NDEBUG) 693 mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice); 694 #endif 695 696 ANGLE_TRY(initializeDevice()); 697 698 return egl::NoError(); 699 } 700 701 HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug) 702 { 703 angle::ComPtr<IDXGIAdapter> adapter; 704 705 const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); 706 // Check EGL_ANGLE_platform_angle_d3d_luid 707 long high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0)); 708 unsigned long low = 709 static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0)); 710 // Check EGL_ANGLE_platform_angle_device_id 711 if (high == 0 && low == 0) 712 { 713 high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0)); 714 low = static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0)); 715 } 716 if (high != 0 || low != 0) 717 { 718 angle::ComPtr<IDXGIFactory1> factory; 719 if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) 720 { 721 angle::ComPtr<IDXGIAdapter> temp; 722 for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++) 723 { 724 DXGI_ADAPTER_DESC desc; 725 if (SUCCEEDED(temp->GetDesc(&desc))) 726 { 727 // EGL_ANGLE_platform_angle_d3d_luid 728 if (desc.AdapterLuid.HighPart == high && desc.AdapterLuid.LowPart == low) 729 { 730 adapter = temp; 731 break; 732 } 733 734 // EGL_ANGLE_platform_angle_device_id 735 // NOTE: If there are multiple GPUs with the same PCI 736 // vendor and device IDs, this will arbitrarily choose one 737 // of them. To select a specific GPU, use the LUID instead. 738 if ((high == 0 || desc.VendorId == static_cast<UINT>(high)) && 739 (low == 0 || desc.DeviceId == static_cast<UINT>(low))) 740 { 741 adapter = temp; 742 break; 743 } 744 } 745 } 746 } 747 } 748 749 // If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or 750 // D3D11CreateDevice will return E_INVALIDARG. 751 return createDevice( 752 adapter.Get(), adapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr, 753 debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(), 754 static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice, 755 &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); 756 } 757 758 HRESULT Renderer11::callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12, 759 PFN_D3D11ON12_CREATE_DEVICE createDevice11on12, 760 bool debug) 761 { 762 angle::ComPtr<IDXGIFactory4> factory; 763 HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); 764 if (FAILED(result)) 765 { 766 return result; 767 } 768 769 if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) 770 { 771 angle::ComPtr<IDXGIAdapter> warpAdapter; 772 result = factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)); 773 if (SUCCEEDED(result)) 774 { 775 result = createDevice12(warpAdapter.Get(), mAvailableFeatureLevels[0], 776 IID_PPV_ARGS(&mDevice12)); 777 } 778 } 779 else 780 { 781 // Passing nullptr into pAdapter chooses the default adapter which will be the hardware 782 // adapter if it exists. 783 result = createDevice12(nullptr, mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12)); 784 } 785 786 if (SUCCEEDED(result)) 787 { 788 D3D12_COMMAND_QUEUE_DESC queueDesc = {}; 789 queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; 790 queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; 791 result = mDevice12->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)); 792 } 793 794 if (SUCCEEDED(result)) 795 { 796 result = createDevice11on12( 797 mDevice12.Get(), debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(), 798 static_cast<unsigned int>(mAvailableFeatureLevels.size()), 799 reinterpret_cast<IUnknown **>(mCommandQueue.GetAddressOf()), 1 /* NumQueues */, 800 0 /* NodeMask */, &mDevice, &mDeviceContext, &(mRenderer11DeviceCaps.featureLevel)); 801 } 802 803 return result; 804 } 805 806 egl::Error Renderer11::initializeD3DDevice() 807 { 808 HRESULT result = S_OK; 809 bool createD3D11on12Device = false; 810 811 if (!mCreatedWithDeviceEXT) 812 { 813 #if !defined(ANGLE_ENABLE_WINDOWS_UWP) 814 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; 815 PFN_D3D12_CREATE_DEVICE D3D12CreateDevice = nullptr; 816 PFN_D3D11ON12_CREATE_DEVICE D3D11On12CreateDevice = nullptr; 817 { 818 ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); 819 mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); 820 mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); 821 mDCompModule = LoadLibrary(TEXT("dcomp.dll")); 822 823 // create the D3D11 device 824 ASSERT(mDevice == nullptr); 825 826 const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); 827 createD3D11on12Device = 828 attributes.get(EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE, EGL_FALSE) == EGL_TRUE; 829 830 if (createD3D11on12Device) 831 { 832 mD3d12Module = LoadLibrary(TEXT("d3d12.dll")); 833 if (mD3d12Module == nullptr) 834 { 835 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) 836 << "Could not load D3D12 library."; 837 } 838 839 D3D12CreateDevice = reinterpret_cast<PFN_D3D12_CREATE_DEVICE>( 840 GetProcAddress(mD3d12Module, "D3D12CreateDevice")); 841 if (D3D12CreateDevice == nullptr) 842 { 843 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) 844 << "Could not retrieve D3D12CreateDevice address."; 845 } 846 847 D3D11On12CreateDevice = reinterpret_cast<PFN_D3D11ON12_CREATE_DEVICE>( 848 GetProcAddress(mD3d11Module, "D3D11On12CreateDevice")); 849 if (D3D11On12CreateDevice == nullptr) 850 { 851 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) 852 << "Could not retrieve D3D11On12CreateDevice address."; 853 } 854 } 855 else 856 { 857 if (mD3d11Module == nullptr || mDxgiModule == nullptr) 858 { 859 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) 860 << "Could not load D3D11 or DXGI library."; 861 } 862 863 D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>( 864 GetProcAddress(mD3d11Module, "D3D11CreateDevice")); 865 866 if (D3D11CreateDevice == nullptr) 867 { 868 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) 869 << "Could not retrieve D3D11CreateDevice address."; 870 } 871 } 872 } 873 #endif 874 875 if (mCreateDebugDevice) 876 { 877 ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)"); 878 if (createD3D11on12Device) 879 { 880 result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true); 881 } 882 else 883 { 884 result = callD3D11CreateDevice(D3D11CreateDevice, true); 885 } 886 887 if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && 888 mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) 889 { 890 // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. 891 // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature 892 // levels to fall back on. 893 mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); 894 if (createD3D11on12Device) 895 { 896 result = 897 callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true); 898 } 899 else 900 { 901 result = callD3D11CreateDevice(D3D11CreateDevice, true); 902 } 903 } 904 905 if (!mDevice || FAILED(result)) 906 { 907 WARN() << "Failed creating Debug D3D11 device - falling back to release runtime."; 908 } 909 } 910 911 if (!mDevice || FAILED(result)) 912 { 913 ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice"); 914 if (createD3D11on12Device) 915 { 916 result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false); 917 } 918 else 919 { 920 result = callD3D11CreateDevice(D3D11CreateDevice, false); 921 } 922 923 if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && 924 mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) 925 { 926 // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. 927 // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature 928 // levels to fall back on. 929 mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); 930 if (createD3D11on12Device) 931 { 932 result = 933 callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false); 934 } 935 else 936 { 937 result = callD3D11CreateDevice(D3D11CreateDevice, false); 938 } 939 } 940 941 // Cleanup done by destructor 942 if (!mDevice || FAILED(result)) 943 { 944 ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", 945 static_cast<int>(result)); 946 return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR) 947 << "Could not create D3D11 device."; 948 } 949 } 950 } 951 else 952 { 953 DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice()); 954 ASSERT(deviceD3D != nullptr); 955 956 // We should use the inputted D3D11 device instead 957 void *device = nullptr; 958 ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device)); 959 960 ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device); 961 if (FAILED(d3dDevice->GetDeviceRemovedReason())) 962 { 963 return egl::EglNotInitialized() << "Inputted D3D11 device has been lost."; 964 } 965 966 if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3) 967 { 968 return egl::EglNotInitialized() 969 << "Inputted D3D11 device must be Feature Level 9_3 or greater."; 970 } 971 972 // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. 973 mDevice = d3dDevice; 974 mDevice->AddRef(); 975 mDevice->GetImmediateContext(&mDeviceContext); 976 mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); 977 } 978 979 mResourceManager11.setAllocationsInitialized(mCreateDebugDevice); 980 981 d3d11::SetDebugName(mDeviceContext, "DeviceContext", nullptr); 982 983 mAnnotatorContext.initialize(mDeviceContext); 984 985 mDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void **>(&mDevice1)); 986 987 return egl::NoError(); 988 } 989 990 void Renderer11::setGlobalDebugAnnotator() 991 { 992 static angle::base::NoDestructor<std::mutex> gMutex; 993 static angle::base::NoDestructor<DebugAnnotator11> gGlobalAnnotator; 994 995 std::lock_guard<std::mutex> lg(*gMutex); 996 gl::InitializeDebugAnnotations(gGlobalAnnotator.get()); 997 } 998 999 // do any one-time device initialization 1000 // NOTE: this is also needed after a device lost/reset 1001 // to reset the scene status and ensure the default states are reset. 1002 egl::Error Renderer11::initializeDevice() 1003 { 1004 ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice"); 1005 1006 populateRenderer11DeviceCaps(); 1007 1008 mStateCache.clear(); 1009 1010 ASSERT(!mBlit); 1011 mBlit = new Blit11(this); 1012 1013 ASSERT(!mClear); 1014 mClear = new Clear11(this); 1015 1016 const auto &attributes = mDisplay->getAttributeMap(); 1017 // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application 1018 // automatically when an application is suspended by the OS. This feature is currently 1019 // only supported for Windows Store applications. 1020 EGLint enableAutoTrim = static_cast<EGLint>( 1021 attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE)); 1022 1023 if (enableAutoTrim == EGL_TRUE) 1024 { 1025 ASSERT(!mTrim); 1026 mTrim = new Trim11(this); 1027 } 1028 1029 ASSERT(!mPixelTransfer); 1030 mPixelTransfer = new PixelTransfer11(this); 1031 1032 // Gather stats on DXGI and D3D feature level 1033 ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); 1034 1035 ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel); 1036 1037 // We don't actually request a 11_1 device, because of complications with the platform 1038 // update. Instead we check if the mDeviceContext1 pointer cast succeeded. 1039 // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0 1040 // because the app can specify a lower version (such as 9_3) on Display creation. 1041 if (mDeviceContext1 != nullptr) 1042 { 1043 angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1; 1044 } 1045 1046 ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel, 1047 NUM_ANGLE_FEATURE_LEVELS); 1048 1049 return egl::NoError(); 1050 } 1051 1052 void Renderer11::populateRenderer11DeviceCaps() 1053 { 1054 HRESULT hr = S_OK; 1055 1056 LARGE_INTEGER version; 1057 hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); 1058 if (FAILED(hr)) 1059 { 1060 mRenderer11DeviceCaps.driverVersion.reset(); 1061 ERR() << "Error querying driver version from DXGI Adapter."; 1062 } 1063 else 1064 { 1065 mRenderer11DeviceCaps.driverVersion = version; 1066 } 1067 1068 if (mDeviceContext1) 1069 { 1070 D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; 1071 HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, 1072 sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); 1073 if (SUCCEEDED(result)) 1074 { 1075 mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE); 1076 mRenderer11DeviceCaps.supportsConstantBufferOffsets = 1077 (d3d11Options.ConstantBufferOffsetting != FALSE); 1078 } 1079 } 1080 1081 if (mDeviceContext3) 1082 { 1083 D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3; 1084 HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3, 1085 sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3)); 1086 if (SUCCEEDED(result)) 1087 { 1088 mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = 1089 (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE); 1090 } 1091 D3D11_FEATURE_DATA_D3D11_OPTIONS2 d3d11Options2; 1092 result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &d3d11Options2, 1093 sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS2)); 1094 if (SUCCEEDED(result)) 1095 { 1096 mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats = 1097 d3d11Options2.TypedUAVLoadAdditionalFormats; 1098 if (!getFeatures().disableRasterizerOrderViews.enabled) 1099 { 1100 mRenderer11DeviceCaps.supportsRasterizerOrderViews = d3d11Options2.ROVsSupported; 1101 } 1102 } 1103 } 1104 1105 mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs = 1106 mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0; 1107 1108 if (getFeatures().disableB5G6R5Support.enabled) 1109 { 1110 mRenderer11DeviceCaps.B5G6R5support = 0; 1111 mRenderer11DeviceCaps.B5G6R5maxSamples = 0; 1112 } 1113 else 1114 { 1115 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM, 1116 &mRenderer11DeviceCaps.B5G6R5support, 1117 &mRenderer11DeviceCaps.B5G6R5maxSamples); 1118 } 1119 1120 if (getFeatures().allowES3OnFL100.enabled) 1121 { 1122 mRenderer11DeviceCaps.allowES3OnFL10_0 = true; 1123 } 1124 1125 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM, 1126 &mRenderer11DeviceCaps.B4G4R4A4support, 1127 &mRenderer11DeviceCaps.B4G4R4A4maxSamples); 1128 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM, 1129 &mRenderer11DeviceCaps.B5G5R5A1support, 1130 &mRenderer11DeviceCaps.B5G5R5A1maxSamples); 1131 1132 IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter); 1133 mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); 1134 SafeRelease(dxgiAdapter2); 1135 } 1136 1137 gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig( 1138 const gl::TextureCaps &colorBufferFormatCaps, 1139 const gl::TextureCaps &depthStencilBufferFormatCaps) const 1140 { 1141 gl::SupportedSampleSet sampleCounts; 1142 1143 // Generate a new set from the set intersection of sample counts between the color and depth 1144 // format caps. 1145 std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(), 1146 colorBufferFormatCaps.sampleCounts.end(), 1147 depthStencilBufferFormatCaps.sampleCounts.begin(), 1148 depthStencilBufferFormatCaps.sampleCounts.end(), 1149 std::inserter(sampleCounts, sampleCounts.begin())); 1150 1151 // Format of GL_NONE results in no supported sample counts. 1152 // Add back the color sample counts to the supported sample set. 1153 if (depthStencilBufferFormatCaps.sampleCounts.empty()) 1154 { 1155 sampleCounts = colorBufferFormatCaps.sampleCounts; 1156 } 1157 else if (colorBufferFormatCaps.sampleCounts.empty()) 1158 { 1159 // Likewise, add back the depth sample counts to the supported sample set. 1160 sampleCounts = depthStencilBufferFormatCaps.sampleCounts; 1161 } 1162 1163 // Always support 0 samples 1164 sampleCounts.insert(0); 1165 1166 return sampleCounts; 1167 } 1168 1169 egl::ConfigSet Renderer11::generateConfigs() 1170 { 1171 std::vector<GLenum> colorBufferFormats; 1172 1173 // 32-bit supported formats 1174 colorBufferFormats.push_back(GL_BGRA8_EXT); 1175 colorBufferFormats.push_back(GL_RGBA8_OES); 1176 1177 // 24-bit supported formats 1178 colorBufferFormats.push_back(GL_RGB8_OES); 1179 1180 if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) 1181 { 1182 // Additional high bit depth formats added in D3D 10.0 1183 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx 1184 colorBufferFormats.push_back(GL_RGBA16F); 1185 colorBufferFormats.push_back(GL_RGB10_A2); 1186 } 1187 1188 if (!mPresentPathFastEnabled) 1189 { 1190 // 16-bit supported formats 1191 // These aren't valid D3D11 swapchain formats, so don't expose them as configs 1192 // if present path fast is active 1193 colorBufferFormats.push_back(GL_RGBA4); 1194 colorBufferFormats.push_back(GL_RGB5_A1); 1195 colorBufferFormats.push_back(GL_RGB565); 1196 } 1197 1198 static const GLenum depthStencilBufferFormats[] = { 1199 GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, 1200 GL_STENCIL_INDEX8, 1201 }; 1202 1203 const gl::Caps &rendererCaps = getNativeCaps(); 1204 const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); 1205 1206 const EGLint optimalSurfaceOrientation = 1207 mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; 1208 1209 egl::ConfigSet configs; 1210 for (GLenum colorBufferInternalFormat : colorBufferFormats) 1211 { 1212 const gl::TextureCaps &colorBufferFormatCaps = 1213 rendererTextureCaps.get(colorBufferInternalFormat); 1214 if (!colorBufferFormatCaps.renderbuffer) 1215 { 1216 ASSERT(!colorBufferFormatCaps.textureAttachment); 1217 continue; 1218 } 1219 1220 for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats) 1221 { 1222 const gl::TextureCaps &depthStencilBufferFormatCaps = 1223 rendererTextureCaps.get(depthStencilBufferInternalFormat); 1224 if (!depthStencilBufferFormatCaps.renderbuffer && 1225 depthStencilBufferInternalFormat != GL_NONE) 1226 { 1227 ASSERT(!depthStencilBufferFormatCaps.textureAttachment); 1228 continue; 1229 } 1230 1231 const gl::InternalFormat &colorBufferFormatInfo = 1232 gl::GetSizedInternalFormatInfo(colorBufferInternalFormat); 1233 const gl::InternalFormat &depthStencilBufferFormatInfo = 1234 gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat); 1235 const gl::Version &maxVersion = getMaxSupportedESVersion(); 1236 1237 const gl::SupportedSampleSet sampleCounts = 1238 generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps); 1239 1240 for (GLuint sampleCount : sampleCounts) 1241 { 1242 egl::Config config; 1243 config.renderTargetFormat = colorBufferInternalFormat; 1244 config.depthStencilFormat = depthStencilBufferInternalFormat; 1245 config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; 1246 config.redSize = colorBufferFormatInfo.redBits; 1247 config.greenSize = colorBufferFormatInfo.greenBits; 1248 config.blueSize = colorBufferFormatInfo.blueBits; 1249 config.luminanceSize = colorBufferFormatInfo.luminanceBits; 1250 config.alphaSize = colorBufferFormatInfo.alphaBits; 1251 config.alphaMaskSize = 0; 1252 config.bindToTextureRGB = 1253 ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1)); 1254 config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) || 1255 (colorBufferFormatInfo.format == GL_BGRA_EXT)) && 1256 (sampleCount <= 1)); 1257 config.colorBufferType = EGL_RGB_BUFFER; 1258 config.configCaveat = EGL_NONE; 1259 config.configID = static_cast<EGLint>(configs.size() + 1); 1260 1261 // PresentPathFast may not be conformant 1262 config.conformant = 0; 1263 if (!mPresentPathFastEnabled) 1264 { 1265 // Can only support a conformant ES2 with feature level greater than 10.0. 1266 if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) 1267 { 1268 config.conformant |= EGL_OPENGL_ES2_BIT; 1269 } 1270 1271 // We can only support conformant ES3 on FL 10.1+ 1272 if (maxVersion.major >= 3) 1273 { 1274 config.conformant |= EGL_OPENGL_ES3_BIT_KHR; 1275 } 1276 } 1277 1278 config.depthSize = depthStencilBufferFormatInfo.depthBits; 1279 config.level = 0; 1280 config.matchNativePixmap = EGL_NONE; 1281 config.maxPBufferWidth = rendererCaps.max2DTextureSize; 1282 config.maxPBufferHeight = rendererCaps.max2DTextureSize; 1283 config.maxPBufferPixels = 1284 rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; 1285 config.maxSwapInterval = 4; 1286 config.minSwapInterval = 0; 1287 config.nativeRenderable = EGL_FALSE; 1288 config.nativeVisualID = 0; 1289 config.nativeVisualType = EGL_NONE; 1290 1291 // Can't support ES3 at all without feature level 10.1 1292 config.renderableType = EGL_OPENGL_ES2_BIT; 1293 if (maxVersion.major >= 3) 1294 { 1295 config.renderableType |= EGL_OPENGL_ES3_BIT_KHR; 1296 } 1297 1298 config.sampleBuffers = (sampleCount == 0) ? 0 : 1; 1299 config.samples = sampleCount; 1300 config.stencilSize = depthStencilBufferFormatInfo.stencilBits; 1301 config.surfaceType = 1302 EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 1303 config.transparentType = EGL_NONE; 1304 config.transparentRedValue = 0; 1305 config.transparentGreenValue = 0; 1306 config.transparentBlueValue = 0; 1307 config.optimalOrientation = optimalSurfaceOrientation; 1308 config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType( 1309 colorBufferFormatInfo.componentType); 1310 1311 configs.add(config); 1312 } 1313 } 1314 } 1315 1316 ASSERT(configs.size() > 0); 1317 return configs; 1318 } 1319 1320 void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const 1321 { 1322 outExtensions->createContextRobustness = true; 1323 1324 if (getShareHandleSupport()) 1325 { 1326 outExtensions->d3dShareHandleClientBuffer = true; 1327 outExtensions->surfaceD3DTexture2DShareHandle = true; 1328 } 1329 outExtensions->d3dTextureClientBuffer = true; 1330 outExtensions->imageD3D11Texture = true; 1331 1332 outExtensions->keyedMutex = true; 1333 outExtensions->querySurfacePointer = true; 1334 outExtensions->windowFixedSize = true; 1335 1336 // If present path fast is active then the surface orientation extension isn't supported 1337 outExtensions->surfaceOrientation = !mPresentPathFastEnabled; 1338 1339 // D3D11 does not support present with dirty rectangles until DXGI 1.2. 1340 outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; 1341 1342 outExtensions->image = true; 1343 outExtensions->imageBase = true; 1344 outExtensions->glTexture2DImage = true; 1345 outExtensions->glTextureCubemapImage = true; 1346 outExtensions->glRenderbufferImage = true; 1347 1348 outExtensions->stream = true; 1349 outExtensions->streamConsumerGLTexture = true; 1350 outExtensions->streamConsumerGLTextureYUV = true; 1351 outExtensions->streamProducerD3DTexture = true; 1352 1353 outExtensions->noConfigContext = true; 1354 outExtensions->directComposition = !!mDCompModule; 1355 1356 // Contexts are virtualized so textures and semaphores can be shared globally 1357 outExtensions->displayTextureShareGroup = true; 1358 outExtensions->displaySemaphoreShareGroup = true; 1359 1360 // syncControlCHROMIUM requires direct composition. 1361 outExtensions->syncControlCHROMIUM = outExtensions->directComposition; 1362 1363 // D3D11 can be used without a swap chain 1364 outExtensions->surfacelessContext = true; 1365 1366 // All D3D feature levels support robust resource init 1367 outExtensions->robustResourceInitializationANGLE = true; 1368 1369 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW 1370 // Compositor Native Window capabilies require WinVer >= 1803 1371 if (CompositorNativeWindow11::IsSupportedWinRelease()) 1372 { 1373 outExtensions->windowsUIComposition = true; 1374 } 1375 #endif 1376 } 1377 1378 angle::Result Renderer11::flush(Context11 *context11) 1379 { 1380 mDeviceContext->Flush(); 1381 return angle::Result::Continue; 1382 } 1383 1384 angle::Result Renderer11::finish(Context11 *context11) 1385 { 1386 if (!mSyncQuery.valid()) 1387 { 1388 D3D11_QUERY_DESC queryDesc; 1389 queryDesc.Query = D3D11_QUERY_EVENT; 1390 queryDesc.MiscFlags = 0; 1391 1392 ANGLE_TRY(allocateResource(context11, queryDesc, &mSyncQuery)); 1393 } 1394 1395 mDeviceContext->End(mSyncQuery.get()); 1396 1397 HRESULT result = S_OK; 1398 unsigned int attempt = 0; 1399 do 1400 { 1401 unsigned int flushFrequency = 100; 1402 UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH; 1403 attempt++; 1404 1405 result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags); 1406 ANGLE_TRY_HR(context11, result, "Failed to get event query data"); 1407 1408 if (result == S_FALSE) 1409 { 1410 // Keep polling, but allow other threads to do something useful first 1411 ScheduleYield(); 1412 } 1413 1414 // Attempt is incremented before checking if we should test for device loss so that device 1415 // loss is not checked on the first iteration 1416 bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0; 1417 if (checkDeviceLost && testDeviceLost()) 1418 { 1419 mDisplay->notifyDeviceLost(); 1420 ANGLE_CHECK(context11, false, "Device was lost while waiting for sync.", 1421 GL_OUT_OF_MEMORY); 1422 } 1423 } while (result == S_FALSE); 1424 1425 return angle::Result::Continue; 1426 } 1427 1428 bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const 1429 { 1430 #if defined(ANGLE_ENABLE_WINDOWS_UWP) 1431 if (NativeWindow11WinRT::IsValidNativeWindow(window)) 1432 { 1433 return true; 1434 } 1435 #else 1436 if (NativeWindow11Win32::IsValidNativeWindow(window)) 1437 { 1438 return true; 1439 } 1440 #endif 1441 1442 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW 1443 static_assert(sizeof(ABI::Windows::UI::Composition::SpriteVisual *) == sizeof(HWND), 1444 "Pointer size must match Window Handle size"); 1445 if (CompositorNativeWindow11::IsValidNativeWindow(window)) 1446 { 1447 return true; 1448 } 1449 #endif 1450 1451 return false; 1452 } 1453 1454 NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window, 1455 const egl::Config *config, 1456 const egl::AttributeMap &attribs) const 1457 { 1458 #if defined(ANGLE_ENABLE_WINDOWS_UWP) 1459 if (window == nullptr || NativeWindow11WinRT::IsValidNativeWindow(window)) 1460 { 1461 return new NativeWindow11WinRT(window, config->alphaSize > 0); 1462 } 1463 #else 1464 if (window == nullptr || NativeWindow11Win32::IsValidNativeWindow(window)) 1465 { 1466 return new NativeWindow11Win32( 1467 window, config->alphaSize > 0, 1468 attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE); 1469 } 1470 #endif 1471 1472 #ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW 1473 if (CompositorNativeWindow11::IsValidNativeWindow(window)) 1474 { 1475 return new CompositorNativeWindow11(window, config->alphaSize > 0); 1476 } 1477 #endif 1478 1479 UNREACHABLE(); 1480 return nullptr; 1481 } 1482 1483 egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, 1484 IUnknown *texture, 1485 const egl::AttributeMap &attribs, 1486 EGLint *width, 1487 EGLint *height, 1488 GLsizei *samples, 1489 gl::Format *glFormat, 1490 const angle::Format **angleFormat, 1491 UINT *arraySlice) const 1492 { 1493 angle::ComPtr<ID3D11Texture2D> d3dTexture = 1494 d3d11::DynamicCastComObjectToComPtr<ID3D11Texture2D>(texture); 1495 if (d3dTexture == nullptr) 1496 { 1497 return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D"; 1498 } 1499 1500 angle::ComPtr<ID3D11Device> textureDevice; 1501 d3dTexture->GetDevice(&textureDevice); 1502 if (textureDevice.Get() != mDevice) 1503 { 1504 return egl::EglBadParameter() << "Texture's device does not match."; 1505 } 1506 1507 D3D11_TEXTURE2D_DESC desc = {}; 1508 d3dTexture->GetDesc(&desc); 1509 1510 EGLint imageWidth = static_cast<EGLint>(desc.Width); 1511 EGLint imageHeight = static_cast<EGLint>(desc.Height); 1512 1513 GLsizei sampleCount = static_cast<GLsizei>(desc.SampleDesc.Count); 1514 if (configuration && (configuration->samples != sampleCount)) 1515 { 1516 // Both the texture and EGL config sample count may not be the same when multi-sampling 1517 // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore, 1518 // we must only check for a invalid match when the EGL config is non-zero or the texture is 1519 // not one. 1520 if (configuration->samples != 0 || sampleCount != 1) 1521 { 1522 return egl::EglBadParameter() << "Texture's sample count does not match."; 1523 } 1524 } 1525 1526 const angle::Format *textureAngleFormat = nullptr; 1527 GLenum sizedInternalFormat = GL_NONE; 1528 1529 // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. 1530 if (desc.Format == DXGI_FORMAT_NV12 || desc.Format == DXGI_FORMAT_P010 || 1531 desc.Format == DXGI_FORMAT_P016) 1532 { 1533 if (!attribs.contains(EGL_D3D11_TEXTURE_PLANE_ANGLE)) 1534 { 1535 return egl::EglBadParameter() 1536 << "EGL_D3D11_TEXTURE_PLANE_ANGLE must be specified for YUV textures."; 1537 } 1538 1539 EGLint plane = attribs.getAsInt(EGL_D3D11_TEXTURE_PLANE_ANGLE); 1540 1541 // P010 and P016 have the same memory layout, SRV/RTV format, etc. 1542 const bool isNV12 = (desc.Format == DXGI_FORMAT_NV12); 1543 if (plane == 0) 1544 { 1545 textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8_UNORM) 1546 : &angle::Format::Get(angle::FormatID::R16_UNORM); 1547 } 1548 else if (plane == 1) 1549 { 1550 textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8G8_UNORM) 1551 : &angle::Format::Get(angle::FormatID::R16G16_UNORM); 1552 imageWidth /= 2; 1553 imageHeight /= 2; 1554 } 1555 else 1556 { 1557 return egl::EglBadParameter() << "Invalid client buffer texture plane: " << plane; 1558 } 1559 1560 ASSERT(textureAngleFormat); 1561 sizedInternalFormat = textureAngleFormat->glInternalFormat; 1562 } 1563 else 1564 { 1565 switch (desc.Format) 1566 { 1567 case DXGI_FORMAT_R8G8B8A8_UNORM: 1568 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: 1569 case DXGI_FORMAT_R8G8B8A8_TYPELESS: 1570 case DXGI_FORMAT_B8G8R8A8_UNORM: 1571 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: 1572 case DXGI_FORMAT_B8G8R8A8_TYPELESS: 1573 case DXGI_FORMAT_R16G16B16A16_FLOAT: 1574 case DXGI_FORMAT_R32G32B32A32_FLOAT: 1575 case DXGI_FORMAT_R10G10B10A2_UNORM: 1576 case DXGI_FORMAT_R8_UNORM: 1577 case DXGI_FORMAT_R8G8_UNORM: 1578 case DXGI_FORMAT_R16_UNORM: 1579 case DXGI_FORMAT_R16G16_UNORM: 1580 break; 1581 1582 default: 1583 return egl::EglBadParameter() 1584 << "Invalid client buffer texture format: " << desc.Format; 1585 } 1586 1587 textureAngleFormat = &d3d11_angle::GetFormat(desc.Format); 1588 ASSERT(textureAngleFormat); 1589 1590 sizedInternalFormat = textureAngleFormat->glInternalFormat; 1591 1592 if (attribs.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE)) 1593 { 1594 const GLenum internalFormat = 1595 static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE)); 1596 switch (internalFormat) 1597 { 1598 case GL_RGBA: 1599 case GL_BGRA_EXT: 1600 case GL_RGB: 1601 case GL_RED_EXT: 1602 case GL_RG_EXT: 1603 case GL_RGB10_A2_EXT: 1604 case GL_R16_EXT: 1605 case GL_RG16_EXT: 1606 break; 1607 default: 1608 return egl::EglBadParameter() 1609 << "Invalid client buffer texture internal format: " << std::hex 1610 << internalFormat; 1611 } 1612 1613 const GLenum type = gl::GetSizedInternalFormatInfo(sizedInternalFormat).type; 1614 1615 const auto format = gl::Format(internalFormat, type); 1616 if (!format.valid()) 1617 { 1618 return egl::EglBadParameter() 1619 << "Invalid client buffer texture internal format: " << std::hex 1620 << internalFormat; 1621 } 1622 1623 sizedInternalFormat = format.info->sizedInternalFormat; 1624 } 1625 } 1626 1627 UINT textureArraySlice = 1628 static_cast<UINT>(attribs.getAsInt(EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, 0)); 1629 if (textureArraySlice >= desc.ArraySize) 1630 { 1631 return egl::EglBadParameter() 1632 << "Invalid client buffer texture array slice: " << textureArraySlice; 1633 } 1634 1635 if (width) 1636 { 1637 *width = imageWidth; 1638 } 1639 if (height) 1640 { 1641 *height = imageHeight; 1642 } 1643 1644 if (samples) 1645 { 1646 // EGL samples 0 corresponds to D3D11 sample count 1. 1647 *samples = sampleCount != 1 ? sampleCount : 0; 1648 } 1649 1650 if (glFormat) 1651 { 1652 *glFormat = gl::Format(sizedInternalFormat); 1653 } 1654 1655 if (angleFormat) 1656 { 1657 *angleFormat = textureAngleFormat; 1658 } 1659 1660 if (arraySlice) 1661 { 1662 *arraySlice = textureArraySlice; 1663 } 1664 1665 return egl::NoError(); 1666 } 1667 1668 egl::Error Renderer11::validateShareHandle(const egl::Config *config, 1669 HANDLE shareHandle, 1670 const egl::AttributeMap &attribs) const 1671 { 1672 if (shareHandle == nullptr) 1673 { 1674 return egl::EglBadParameter() << "NULL share handle."; 1675 } 1676 1677 ID3D11Resource *tempResource11 = nullptr; 1678 HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), 1679 (void **)&tempResource11); 1680 if (FAILED(result) && mDevice1) 1681 { 1682 result = mDevice1->OpenSharedResource1(shareHandle, __uuidof(ID3D11Resource), 1683 (void **)&tempResource11); 1684 } 1685 1686 if (FAILED(result)) 1687 { 1688 return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result); 1689 } 1690 1691 ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11); 1692 SafeRelease(tempResource11); 1693 1694 if (texture2D == nullptr) 1695 { 1696 return egl::EglBadParameter() 1697 << "Failed to query ID3D11Texture2D object from share handle."; 1698 } 1699 1700 D3D11_TEXTURE2D_DESC desc = {}; 1701 texture2D->GetDesc(&desc); 1702 SafeRelease(texture2D); 1703 1704 EGLint width = attribs.getAsInt(EGL_WIDTH, 0); 1705 EGLint height = attribs.getAsInt(EGL_HEIGHT, 0); 1706 ASSERT(width != 0 && height != 0); 1707 1708 const d3d11::Format &backbufferFormatInfo = 1709 d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps()); 1710 1711 if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) || 1712 desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1) 1713 { 1714 return egl::EglBadParameter() << "Invalid texture parameters in share handle texture."; 1715 } 1716 1717 return egl::NoError(); 1718 } 1719 1720 SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow, 1721 HANDLE shareHandle, 1722 IUnknown *d3dTexture, 1723 GLenum backBufferFormat, 1724 GLenum depthBufferFormat, 1725 EGLint orientation, 1726 EGLint samples) 1727 { 1728 return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture, 1729 backBufferFormat, depthBufferFormat, orientation, samples); 1730 } 1731 1732 void *Renderer11::getD3DDevice() 1733 { 1734 return mDevice; 1735 } 1736 1737 angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 *context11, 1738 gl::PrimitiveMode mode, 1739 UINT instanceCount, 1740 UINT vertexCount) 1741 { 1742 const gl::State &glState = context11->getState(); 1743 ProgramD3D *programD3D = mStateManager.getProgramD3D(); 1744 1745 // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback 1746 // won't get the correct output. To work around this, draw with *only* the stream out 1747 // first (no pixel shader) to feed the stream out buffers and then draw again with the 1748 // geometry shader + pixel shader to rasterize the primitives. 1749 mStateManager.setPixelShader(nullptr); 1750 1751 if (instanceCount > 0) 1752 { 1753 mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0); 1754 } 1755 else 1756 { 1757 mDeviceContext->Draw(vertexCount, 0); 1758 } 1759 1760 rx::ShaderExecutableD3D *pixelExe = nullptr; 1761 ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr)); 1762 1763 // Skip the draw call if rasterizer discard is enabled (or no fragment shader). 1764 if (!pixelExe || glState.getRasterizerState().rasterizerDiscard) 1765 { 1766 return angle::Result::Continue; 1767 } 1768 1769 mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader()); 1770 1771 // Retrieve the geometry shader. 1772 rx::ShaderExecutableD3D *geometryExe = nullptr; 1773 ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context11, glState, mode, 1774 &geometryExe, nullptr)); 1775 1776 mStateManager.setGeometryShader(&GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader()); 1777 1778 if (instanceCount > 0) 1779 { 1780 mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0); 1781 } 1782 else 1783 { 1784 mDeviceContext->Draw(vertexCount, 0); 1785 } 1786 1787 return angle::Result::Continue; 1788 } 1789 1790 angle::Result Renderer11::drawArrays(const gl::Context *context, 1791 gl::PrimitiveMode mode, 1792 GLint firstVertex, 1793 GLsizei vertexCount, 1794 GLsizei instanceCount, 1795 GLuint baseInstance, 1796 bool isInstancedDraw) 1797 { 1798 if (mStateManager.getCullEverything()) 1799 { 1800 return angle::Result::Continue; 1801 } 1802 1803 ANGLE_TRY(markRawBufferUsage(context)); 1804 1805 ProgramD3D *programD3D = mStateManager.getProgramD3D(); 1806 GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount); 1807 1808 // Note: vertex indexes can be arbitrarily large. 1809 UINT clampedVertexCount = gl::GetClampedVertexCount<UINT>(vertexCount); 1810 1811 const auto &glState = context->getState(); 1812 if (glState.getCurrentTransformFeedback() && glState.isTransformFeedbackActiveUnpaused()) 1813 { 1814 ANGLE_TRY(markTransformFeedbackUsage(context)); 1815 1816 if (programD3D->usesGeometryShader(glState, mode)) 1817 { 1818 return drawWithGeometryShaderAndTransformFeedback( 1819 GetImplAs<Context11>(context), mode, adjustedInstanceCount, clampedVertexCount); 1820 } 1821 } 1822 1823 switch (mode) 1824 { 1825 case gl::PrimitiveMode::LineLoop: 1826 return drawLineLoop(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum, 1827 nullptr, 0, adjustedInstanceCount); 1828 case gl::PrimitiveMode::TriangleFan: 1829 return drawTriangleFan(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum, 1830 nullptr, 0, adjustedInstanceCount); 1831 case gl::PrimitiveMode::Points: 1832 if (getFeatures().useInstancedPointSpriteEmulation.enabled) 1833 { 1834 // This code should not be reachable by multi-view programs. 1835 ASSERT(programD3D->getState().usesMultiview() == false); 1836 1837 // If the shader is writing to gl_PointSize, then pointsprites are being rendered. 1838 // Emulating instanced point sprites for FL9_3 requires the topology to be 1839 // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. 1840 if (adjustedInstanceCount == 0) 1841 { 1842 mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance); 1843 return angle::Result::Continue; 1844 } 1845 1846 // If pointsprite emulation is used with glDrawArraysInstanced then we need to take 1847 // a less efficent code path. Instanced rendering of emulated pointsprites requires 1848 // a loop to draw each batch of points. An offset into the instanced data buffer is 1849 // calculated and applied on each iteration to ensure all instances are rendered 1850 // correctly. Each instance being rendered requires the inputlayout cache to reapply 1851 // buffers and offsets. 1852 for (GLsizei i = 0; i < instanceCount; i++) 1853 { 1854 ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation( 1855 context, firstVertex, i)); 1856 mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance); 1857 } 1858 1859 // This required by updateVertexOffsets... above but is outside of the loop for 1860 // speed. 1861 mStateManager.invalidateVertexBuffer(); 1862 return angle::Result::Continue; 1863 } 1864 break; 1865 default: 1866 break; 1867 } 1868 1869 // "Normal" draw case. 1870 if (!isInstancedDraw && adjustedInstanceCount == 0) 1871 { 1872 mDeviceContext->Draw(clampedVertexCount, 0); 1873 } 1874 else 1875 { 1876 mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, baseInstance); 1877 } 1878 return angle::Result::Continue; 1879 } 1880 1881 angle::Result Renderer11::drawElements(const gl::Context *context, 1882 gl::PrimitiveMode mode, 1883 GLint startVertex, 1884 GLsizei indexCount, 1885 gl::DrawElementsType indexType, 1886 const void *indices, 1887 GLsizei instanceCount, 1888 GLint baseVertex, 1889 GLuint baseInstance, 1890 bool isInstancedDraw) 1891 { 1892 if (mStateManager.getCullEverything()) 1893 { 1894 return angle::Result::Continue; 1895 } 1896 1897 ANGLE_TRY(markRawBufferUsage(context)); 1898 1899 // Transform feedback is not allowed for DrawElements, this error should have been caught at the 1900 // API validation layer. 1901 const gl::State &glState = context->getState(); 1902 ASSERT(!glState.isTransformFeedbackActiveUnpaused()); 1903 1904 // If this draw call is coming from an indirect call, offset by the indirect call's base vertex. 1905 GLint baseVertexAdjusted = baseVertex - startVertex; 1906 1907 const ProgramD3D *programD3D = mStateManager.getProgramD3D(); 1908 GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount); 1909 1910 if (mode == gl::PrimitiveMode::LineLoop) 1911 { 1912 return drawLineLoop(context, indexCount, indexType, indices, baseVertexAdjusted, 1913 adjustedInstanceCount); 1914 } 1915 1916 if (mode == gl::PrimitiveMode::TriangleFan) 1917 { 1918 return drawTriangleFan(context, indexCount, indexType, indices, baseVertexAdjusted, 1919 adjustedInstanceCount); 1920 } 1921 1922 if (mode != gl::PrimitiveMode::Points || !programD3D->usesInstancedPointSpriteEmulation()) 1923 { 1924 if (!isInstancedDraw && adjustedInstanceCount == 0) 1925 { 1926 mDeviceContext->DrawIndexed(indexCount, 0, baseVertexAdjusted); 1927 } 1928 else 1929 { 1930 mDeviceContext->DrawIndexedInstanced(indexCount, adjustedInstanceCount, 0, 1931 baseVertexAdjusted, baseInstance); 1932 } 1933 return angle::Result::Continue; 1934 } 1935 1936 // This code should not be reachable by multi-view programs. 1937 ASSERT(programD3D->getState().usesMultiview() == false); 1938 1939 // If the shader is writing to gl_PointSize, then pointsprites are being rendered. 1940 // Emulating instanced point sprites for FL9_3 requires the topology to be 1941 // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. 1942 // 1943 // The count parameter passed to drawElements represents the total number of instances to be 1944 // rendered. Each instance is referenced by the bound index buffer from the the caller. 1945 // 1946 // Indexed pointsprite emulation replicates data for duplicate entries found in the index 1947 // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers 1948 // that do not support geometry shaders. 1949 if (instanceCount == 0) 1950 { 1951 mDeviceContext->DrawIndexedInstanced(6, indexCount, 0, baseVertexAdjusted, baseInstance); 1952 return angle::Result::Continue; 1953 } 1954 1955 // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less 1956 // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each 1957 // batch of points. An offset into the instanced data buffer is calculated and applied on each 1958 // iteration to ensure all instances are rendered correctly. 1959 gl::IndexRange indexRange; 1960 ANGLE_TRY(glState.getVertexArray()->getIndexRange(context, indexType, indexCount, indices, 1961 &indexRange)); 1962 1963 UINT clampedVertexCount = gl::clampCast<UINT>(indexRange.vertexCount()); 1964 1965 // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets. 1966 for (GLsizei i = 0; i < instanceCount; i++) 1967 { 1968 ANGLE_TRY( 1969 mStateManager.updateVertexOffsetsForPointSpritesEmulation(context, startVertex, i)); 1970 mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, baseVertexAdjusted, 1971 baseInstance); 1972 } 1973 mStateManager.invalidateVertexBuffer(); 1974 return angle::Result::Continue; 1975 } 1976 1977 angle::Result Renderer11::drawArraysIndirect(const gl::Context *context, const void *indirect) 1978 { 1979 if (mStateManager.getCullEverything()) 1980 { 1981 return angle::Result::Continue; 1982 } 1983 1984 ANGLE_TRY(markRawBufferUsage(context)); 1985 1986 const gl::State &glState = context->getState(); 1987 ASSERT(!glState.isTransformFeedbackActiveUnpaused()); 1988 1989 gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); 1990 ASSERT(drawIndirectBuffer); 1991 Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); 1992 1993 uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); 1994 1995 ID3D11Buffer *buffer = nullptr; 1996 ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); 1997 mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset)); 1998 return angle::Result::Continue; 1999 } 2000 2001 angle::Result Renderer11::drawElementsIndirect(const gl::Context *context, const void *indirect) 2002 { 2003 if (mStateManager.getCullEverything()) 2004 { 2005 return angle::Result::Continue; 2006 } 2007 2008 ANGLE_TRY(markRawBufferUsage(context)); 2009 2010 const gl::State &glState = context->getState(); 2011 ASSERT(!glState.isTransformFeedbackActiveUnpaused()); 2012 2013 gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); 2014 ASSERT(drawIndirectBuffer); 2015 Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); 2016 uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); 2017 2018 ID3D11Buffer *buffer = nullptr; 2019 ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); 2020 mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset)); 2021 return angle::Result::Continue; 2022 } 2023 2024 angle::Result Renderer11::drawLineLoop(const gl::Context *context, 2025 GLuint count, 2026 gl::DrawElementsType type, 2027 const void *indexPointer, 2028 int baseVertex, 2029 int instances) 2030 { 2031 const gl::State &glState = context->getState(); 2032 gl::VertexArray *vao = glState.getVertexArray(); 2033 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); 2034 2035 const void *indices = indexPointer; 2036 2037 // Get the raw indices for an indexed draw 2038 if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer) 2039 { 2040 BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); 2041 intptr_t offset = reinterpret_cast<intptr_t>(indices); 2042 2043 const uint8_t *bufferData = nullptr; 2044 ANGLE_TRY(storage->getData(context, &bufferData)); 2045 2046 indices = bufferData + offset; 2047 } 2048 2049 if (!mLineLoopIB) 2050 { 2051 mLineLoopIB = new StreamingIndexBufferInterface(this); 2052 ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE, 2053 gl::DrawElementsType::UnsignedInt)); 2054 } 2055 2056 // Checked by Renderer11::applyPrimitiveType 2057 bool indexCheck = static_cast<unsigned int>(count) + 1 > 2058 (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)); 2059 ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck, 2060 "Failed to create a 32-bit looping index buffer for " 2061 "GL_LINE_LOOP, too many indices required.", 2062 GL_OUT_OF_MEMORY); 2063 2064 GetLineLoopIndices(indices, type, static_cast<GLuint>(count), 2065 glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); 2066 2067 unsigned int spaceNeeded = 2068 static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size()); 2069 ANGLE_TRY( 2070 mLineLoopIB->reserveBufferSpace(context, spaceNeeded, gl::DrawElementsType::UnsignedInt)); 2071 2072 void *mappedMemory = nullptr; 2073 unsigned int offset; 2074 ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset)); 2075 2076 // Copy over the converted index data. 2077 memcpy(mappedMemory, &mScratchIndexDataBuffer[0], 2078 sizeof(GLuint) * mScratchIndexDataBuffer.size()); 2079 2080 ANGLE_TRY(mLineLoopIB->unmapBuffer(context)); 2081 2082 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer()); 2083 const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer(); 2084 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); 2085 2086 mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset); 2087 2088 UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); 2089 2090 if (instances > 0) 2091 { 2092 mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); 2093 } 2094 else 2095 { 2096 mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); 2097 } 2098 2099 return angle::Result::Continue; 2100 } 2101 2102 angle::Result Renderer11::drawTriangleFan(const gl::Context *context, 2103 GLuint count, 2104 gl::DrawElementsType type, 2105 const void *indices, 2106 int baseVertex, 2107 int instances) 2108 { 2109 const gl::State &glState = context->getState(); 2110 gl::VertexArray *vao = glState.getVertexArray(); 2111 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); 2112 2113 const void *indexPointer = indices; 2114 2115 // Get the raw indices for an indexed draw 2116 if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer) 2117 { 2118 BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); 2119 intptr_t offset = reinterpret_cast<intptr_t>(indices); 2120 2121 const uint8_t *bufferData = nullptr; 2122 ANGLE_TRY(storage->getData(context, &bufferData)); 2123 2124 indexPointer = bufferData + offset; 2125 } 2126 2127 if (!mTriangleFanIB) 2128 { 2129 mTriangleFanIB = new StreamingIndexBufferInterface(this); 2130 ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE, 2131 gl::DrawElementsType::UnsignedInt)); 2132 } 2133 2134 // Checked by Renderer11::applyPrimitiveType 2135 ASSERT(count >= 3); 2136 2137 const GLuint numTris = count - 2; 2138 2139 bool indexCheck = 2140 (numTris > std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)); 2141 ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck, 2142 "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, " 2143 "too many indices required.", 2144 GL_OUT_OF_MEMORY); 2145 2146 GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(), 2147 &mScratchIndexDataBuffer); 2148 2149 const unsigned int spaceNeeded = 2150 static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); 2151 ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, spaceNeeded, 2152 gl::DrawElementsType::UnsignedInt)); 2153 2154 void *mappedMemory = nullptr; 2155 unsigned int offset; 2156 ANGLE_TRY(mTriangleFanIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset)); 2157 2158 memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); 2159 2160 ANGLE_TRY(mTriangleFanIB->unmapBuffer(context)); 2161 2162 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer()); 2163 const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer(); 2164 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); 2165 2166 mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset); 2167 2168 UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size()); 2169 2170 if (instances > 0) 2171 { 2172 mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); 2173 } 2174 else 2175 { 2176 mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); 2177 } 2178 2179 return angle::Result::Continue; 2180 } 2181 2182 void Renderer11::releaseDeviceResources() 2183 { 2184 mStateManager.deinitialize(); 2185 mStateCache.clear(); 2186 2187 SafeDelete(mLineLoopIB); 2188 SafeDelete(mTriangleFanIB); 2189 SafeDelete(mBlit); 2190 SafeDelete(mClear); 2191 SafeDelete(mTrim); 2192 SafeDelete(mPixelTransfer); 2193 2194 mSyncQuery.reset(); 2195 2196 mCachedResolveTexture.reset(); 2197 } 2198 2199 // set notify to true to broadcast a message to all contexts of the device loss 2200 bool Renderer11::testDeviceLost() 2201 { 2202 if (!mDevice) 2203 { 2204 return true; 2205 } 2206 2207 // GetRemovedReason is used to test if the device is removed 2208 HRESULT result = mDevice->GetDeviceRemovedReason(); 2209 bool isLost = FAILED(result); 2210 2211 if (isLost) 2212 { 2213 ERR() << "The D3D11 device was removed, " << gl::FmtHR(result); 2214 } 2215 2216 return isLost; 2217 } 2218 2219 bool Renderer11::testDeviceResettable() 2220 { 2221 // determine if the device is resettable by creating a mock device 2222 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = 2223 (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); 2224 2225 if (D3D11CreateDevice == nullptr) 2226 { 2227 return false; 2228 } 2229 2230 ID3D11Device *mockDevice; 2231 D3D_FEATURE_LEVEL mockFeatureLevel; 2232 ID3D11DeviceContext *mockContext; 2233 UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0); 2234 2235 ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN); 2236 HRESULT result = D3D11CreateDevice( 2237 nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(), 2238 static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mockDevice, 2239 &mockFeatureLevel, &mockContext); 2240 2241 if (!mDevice || FAILED(result)) 2242 { 2243 return false; 2244 } 2245 2246 SafeRelease(mockContext); 2247 SafeRelease(mockDevice); 2248 2249 return true; 2250 } 2251 2252 void Renderer11::release() 2253 { 2254 mScratchMemoryBuffer.clear(); 2255 2256 mAnnotatorContext.release(); 2257 gl::UninitializeDebugAnnotations(); 2258 2259 releaseDeviceResources(); 2260 2261 SafeRelease(mDxgiFactory); 2262 SafeRelease(mDxgiAdapter); 2263 2264 SafeRelease(mDeviceContext3); 2265 SafeRelease(mDeviceContext1); 2266 2267 if (mDeviceContext) 2268 { 2269 mDeviceContext->ClearState(); 2270 mDeviceContext->Flush(); 2271 SafeRelease(mDeviceContext); 2272 } 2273 2274 SafeRelease(mDevice); 2275 SafeRelease(mDevice1); 2276 SafeRelease(mDebug); 2277 2278 if (mD3d11Module) 2279 { 2280 FreeLibrary(mD3d11Module); 2281 mD3d11Module = nullptr; 2282 } 2283 2284 if (mDxgiModule) 2285 { 2286 FreeLibrary(mDxgiModule); 2287 mDxgiModule = nullptr; 2288 } 2289 2290 if (mDCompModule) 2291 { 2292 FreeLibrary(mDCompModule); 2293 mDCompModule = nullptr; 2294 } 2295 2296 mDevice12.Reset(); 2297 mCommandQueue.Reset(); 2298 2299 if (mD3d12Module) 2300 { 2301 FreeLibrary(mD3d12Module); 2302 mD3d12Module = nullptr; 2303 } 2304 2305 mCompiler.release(); 2306 2307 mSupportsShareHandles.reset(); 2308 } 2309 2310 bool Renderer11::resetDevice() 2311 { 2312 // recreate everything 2313 release(); 2314 egl::Error result = initialize(); 2315 2316 if (result.isError()) 2317 { 2318 ERR() << "Could not reinitialize D3D11 device: " << result; 2319 return false; 2320 } 2321 2322 return true; 2323 } 2324 2325 std::string Renderer11::getRendererDescription() const 2326 { 2327 std::ostringstream rendererString; 2328 2329 rendererString << mDescription; 2330 rendererString << " Direct3D11"; 2331 2332 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() 2333 << getShaderModelSuffix(); 2334 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() 2335 << getShaderModelSuffix(); 2336 2337 return rendererString.str(); 2338 } 2339 2340 DeviceIdentifier Renderer11::getAdapterIdentifier() const 2341 { 2342 // Don't use the AdapterLuid here, since that doesn't persist across reboot. 2343 DeviceIdentifier deviceIdentifier = {}; 2344 deviceIdentifier.VendorId = mAdapterDescription.VendorId; 2345 deviceIdentifier.DeviceId = mAdapterDescription.DeviceId; 2346 deviceIdentifier.SubSysId = mAdapterDescription.SubSysId; 2347 deviceIdentifier.Revision = mAdapterDescription.Revision; 2348 deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel); 2349 2350 return deviceIdentifier; 2351 } 2352 2353 unsigned int Renderer11::getReservedVertexUniformVectors() const 2354 { 2355 // Driver uniforms are stored in a separate constant buffer 2356 return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel); 2357 } 2358 2359 unsigned int Renderer11::getReservedFragmentUniformVectors() const 2360 { 2361 // Driver uniforms are stored in a separate constant buffer 2362 return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel); 2363 } 2364 2365 gl::ShaderMap<unsigned int> Renderer11::getReservedShaderUniformBuffers() const 2366 { 2367 gl::ShaderMap<unsigned int> shaderReservedUniformBuffers = {}; 2368 2369 // we reserve one buffer for the application uniforms, and one for driver uniforms 2370 shaderReservedUniformBuffers[gl::ShaderType::Vertex] = 2; 2371 shaderReservedUniformBuffers[gl::ShaderType::Fragment] = 2; 2372 2373 return shaderReservedUniformBuffers; 2374 } 2375 2376 d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const 2377 { 2378 if (mCreatedWithDeviceEXT) 2379 { 2380 return d3d11::GetDeviceType(mDevice); 2381 } 2382 2383 if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) || 2384 (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) || 2385 (mRequestedDriverType == D3D_DRIVER_TYPE_NULL)) 2386 { 2387 return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL; 2388 } 2389 2390 if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) 2391 { 2392 return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP; 2393 } 2394 2395 return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE; 2396 } 2397 2398 bool Renderer11::getShareHandleSupport() const 2399 { 2400 if (mSupportsShareHandles.valid()) 2401 { 2402 return mSupportsShareHandles.value(); 2403 } 2404 2405 // We only currently support share handles with BGRA surfaces, because 2406 // chrome needs BGRA. Once chrome fixes this, we should always support them. 2407 if (!getNativeExtensions().textureFormatBGRA8888EXT) 2408 { 2409 mSupportsShareHandles = false; 2410 return false; 2411 } 2412 2413 // PIX doesn't seem to support using share handles, so disable them. 2414 if (mAnnotatorContext.getStatus()) 2415 { 2416 mSupportsShareHandles = false; 2417 return false; 2418 } 2419 2420 // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on 2421 // RGBA8 textures/swapchains. 2422 if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) 2423 { 2424 mSupportsShareHandles = false; 2425 return false; 2426 } 2427 2428 // Find out which type of D3D11 device the Renderer11 is using 2429 d3d11::ANGLED3D11DeviceType deviceType = getDeviceType(); 2430 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN) 2431 { 2432 mSupportsShareHandles = false; 2433 return false; 2434 } 2435 2436 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL) 2437 { 2438 // Software/Reference/NULL devices don't support share handles 2439 mSupportsShareHandles = false; 2440 return false; 2441 } 2442 2443 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP) 2444 { 2445 #if !defined(ANGLE_ENABLE_WINDOWS_UWP) 2446 if (!IsWindows8OrGreater()) 2447 { 2448 // WARP on Windows 7 doesn't support shared handles 2449 mSupportsShareHandles = false; 2450 return false; 2451 } 2452 #endif // !defined(ANGLE_ENABLE_WINDOWS_UWP) 2453 2454 // WARP on Windows 8.0+ supports shared handles when shared with another WARP device 2455 // TODO: allow applications to query for HARDWARE or WARP-specific share handles, 2456 // to prevent them trying to use a WARP share handle with an a HW device (or 2457 // vice-versa) 2458 // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE 2459 mSupportsShareHandles = true; 2460 return true; 2461 } 2462 2463 ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE); 2464 mSupportsShareHandles = true; 2465 return true; 2466 } 2467 2468 int Renderer11::getMajorShaderModel() const 2469 { 2470 switch (mRenderer11DeviceCaps.featureLevel) 2471 { 2472 case D3D_FEATURE_LEVEL_11_1: 2473 case D3D_FEATURE_LEVEL_11_0: 2474 return D3D11_SHADER_MAJOR_VERSION; // 5 2475 case D3D_FEATURE_LEVEL_10_1: 2476 return D3D10_1_SHADER_MAJOR_VERSION; // 4 2477 case D3D_FEATURE_LEVEL_10_0: 2478 return D3D10_SHADER_MAJOR_VERSION; // 4 2479 case D3D_FEATURE_LEVEL_9_3: 2480 return D3D10_SHADER_MAJOR_VERSION; // 4 2481 default: 2482 UNREACHABLE(); 2483 return 0; 2484 } 2485 } 2486 2487 int Renderer11::getMinorShaderModel() const 2488 { 2489 switch (mRenderer11DeviceCaps.featureLevel) 2490 { 2491 case D3D_FEATURE_LEVEL_11_1: 2492 case D3D_FEATURE_LEVEL_11_0: 2493 return D3D11_SHADER_MINOR_VERSION; // 0 2494 case D3D_FEATURE_LEVEL_10_1: 2495 return D3D10_1_SHADER_MINOR_VERSION; // 1 2496 case D3D_FEATURE_LEVEL_10_0: 2497 return D3D10_SHADER_MINOR_VERSION; // 0 2498 case D3D_FEATURE_LEVEL_9_3: 2499 return D3D10_SHADER_MINOR_VERSION; // 0 2500 default: 2501 UNREACHABLE(); 2502 return 0; 2503 } 2504 } 2505 2506 std::string Renderer11::getShaderModelSuffix() const 2507 { 2508 switch (mRenderer11DeviceCaps.featureLevel) 2509 { 2510 case D3D_FEATURE_LEVEL_11_1: 2511 case D3D_FEATURE_LEVEL_11_0: 2512 return ""; 2513 case D3D_FEATURE_LEVEL_10_1: 2514 return ""; 2515 case D3D_FEATURE_LEVEL_10_0: 2516 return ""; 2517 case D3D_FEATURE_LEVEL_9_3: 2518 return "_level_9_3"; 2519 default: 2520 UNREACHABLE(); 2521 return ""; 2522 } 2523 } 2524 2525 angle::Result Renderer11::copyImageInternal(const gl::Context *context, 2526 const gl::Framebuffer *framebuffer, 2527 const gl::Rectangle &sourceRect, 2528 GLenum destFormat, 2529 const gl::Offset &destOffset, 2530 RenderTargetD3D *destRenderTarget) 2531 { 2532 const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorAttachment(); 2533 ASSERT(colorAttachment); 2534 2535 RenderTarget11 *sourceRenderTarget = nullptr; 2536 ANGLE_TRY(colorAttachment->getRenderTarget(context, 0, &sourceRenderTarget)); 2537 ASSERT(sourceRenderTarget); 2538 2539 const d3d11::RenderTargetView &dest = 2540 GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); 2541 ASSERT(dest.valid()); 2542 2543 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); 2544 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); 2545 2546 const bool invertSource = UsePresentPathFast(this, colorAttachment); 2547 if (invertSource) 2548 { 2549 sourceArea.y = sourceSize.height - sourceRect.y; 2550 sourceArea.height = -sourceArea.height; 2551 } 2552 2553 gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); 2554 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); 2555 2556 // Use nearest filtering because source and destination are the same size for the direct copy. 2557 // Convert to the unsized format before calling copyTexture. 2558 GLenum sourceFormat = colorAttachment->getFormat().info->format; 2559 if (sourceRenderTarget->getTexture().is2D() && sourceRenderTarget->isMultisampled()) 2560 { 2561 TextureHelper11 tex; 2562 ANGLE_TRY(resolveMultisampledTexture(context, sourceRenderTarget, 2563 colorAttachment->getDepthSize() > 0, 2564 colorAttachment->getStencilSize() > 0, &tex)); 2565 2566 D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; 2567 viewDesc.Format = sourceRenderTarget->getFormatSet().srvFormat; 2568 viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 2569 viewDesc.Texture2D.MipLevels = 1; 2570 viewDesc.Texture2D.MostDetailedMip = 0; 2571 2572 d3d11::SharedSRV readSRV; 2573 ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, tex.get(), &readSRV)); 2574 ASSERT(readSRV.valid()); 2575 2576 ANGLE_TRY(mBlit->copyTexture(context, readSRV, sourceArea, sourceSize, sourceFormat, dest, 2577 destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat), 2578 GL_NONE, GL_NEAREST, false, false, false)); 2579 2580 return angle::Result::Continue; 2581 } 2582 2583 ASSERT(!sourceRenderTarget->isMultisampled()); 2584 2585 const d3d11::SharedSRV *source; 2586 ANGLE_TRY(sourceRenderTarget->getBlitShaderResourceView(context, &source)); 2587 ASSERT(source->valid()); 2588 2589 ANGLE_TRY(mBlit->copyTexture(context, *source, sourceArea, sourceSize, sourceFormat, dest, 2590 destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat), 2591 GL_NONE, GL_NEAREST, false, false, false)); 2592 2593 return angle::Result::Continue; 2594 } 2595 2596 angle::Result Renderer11::copyImage2D(const gl::Context *context, 2597 const gl::Framebuffer *framebuffer, 2598 const gl::Rectangle &sourceRect, 2599 GLenum destFormat, 2600 const gl::Offset &destOffset, 2601 TextureStorage *storage, 2602 GLint level) 2603 { 2604 TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage); 2605 ASSERT(storage11); 2606 2607 gl::ImageIndex index = gl::ImageIndex::Make2D(level); 2608 RenderTargetD3D *destRenderTarget = nullptr; 2609 ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), 2610 &destRenderTarget)); 2611 ASSERT(destRenderTarget); 2612 2613 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, 2614 destRenderTarget)); 2615 2616 storage11->markLevelDirty(level); 2617 2618 return angle::Result::Continue; 2619 } 2620 2621 angle::Result Renderer11::copyImageCube(const gl::Context *context, 2622 const gl::Framebuffer *framebuffer, 2623 const gl::Rectangle &sourceRect, 2624 GLenum destFormat, 2625 const gl::Offset &destOffset, 2626 TextureStorage *storage, 2627 gl::TextureTarget target, 2628 GLint level) 2629 { 2630 TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage); 2631 ASSERT(storage11); 2632 2633 gl::ImageIndex index = gl::ImageIndex::MakeCubeMapFace(target, level); 2634 RenderTargetD3D *destRenderTarget = nullptr; 2635 ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), 2636 &destRenderTarget)); 2637 ASSERT(destRenderTarget); 2638 2639 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, 2640 destRenderTarget)); 2641 2642 storage11->markLevelDirty(level); 2643 2644 return angle::Result::Continue; 2645 } 2646 2647 angle::Result Renderer11::copyImage3D(const gl::Context *context, 2648 const gl::Framebuffer *framebuffer, 2649 const gl::Rectangle &sourceRect, 2650 GLenum destFormat, 2651 const gl::Offset &destOffset, 2652 TextureStorage *storage, 2653 GLint level) 2654 { 2655 TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage); 2656 ASSERT(storage11); 2657 2658 gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); 2659 RenderTargetD3D *destRenderTarget = nullptr; 2660 ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), 2661 &destRenderTarget)); 2662 ASSERT(destRenderTarget); 2663 2664 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, 2665 destRenderTarget)); 2666 2667 storage11->markLevelDirty(level); 2668 2669 return angle::Result::Continue; 2670 } 2671 2672 angle::Result Renderer11::copyImage2DArray(const gl::Context *context, 2673 const gl::Framebuffer *framebuffer, 2674 const gl::Rectangle &sourceRect, 2675 GLenum destFormat, 2676 const gl::Offset &destOffset, 2677 TextureStorage *storage, 2678 GLint level) 2679 { 2680 TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage); 2681 ASSERT(storage11); 2682 2683 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); 2684 RenderTargetD3D *destRenderTarget = nullptr; 2685 ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(), 2686 &destRenderTarget)); 2687 ASSERT(destRenderTarget); 2688 2689 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, 2690 destRenderTarget)); 2691 storage11->markLevelDirty(level); 2692 2693 return angle::Result::Continue; 2694 } 2695 2696 angle::Result Renderer11::copyTexture(const gl::Context *context, 2697 const gl::Texture *source, 2698 GLint sourceLevel, 2699 gl::TextureTarget srcTarget, 2700 const gl::Box &sourceBox, 2701 GLenum destFormat, 2702 GLenum destType, 2703 const gl::Offset &destOffset, 2704 TextureStorage *storage, 2705 gl::TextureTarget destTarget, 2706 GLint destLevel, 2707 bool unpackFlipY, 2708 bool unpackPremultiplyAlpha, 2709 bool unpackUnmultiplyAlpha) 2710 { 2711 2712 TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); 2713 const gl::ImageDesc &sourceImageDesc = source->getTextureState().getImageDesc( 2714 NonCubeTextureTypeToTarget(source->getType()), sourceLevel); 2715 2716 TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage); 2717 ASSERT(destStorage11); 2718 2719 // Check for fast path where a CopySubresourceRegion can be used. 2720 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY && 2721 sourceImageDesc.format.info->sizedInternalFormat == 2722 destStorage11->getFormatSet().internalFormat) 2723 { 2724 const TextureHelper11 *destResource = nullptr; 2725 ANGLE_TRY(destStorage11->getResource(context, &destResource)); 2726 2727 if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D) 2728 { 2729 gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel, 1); 2730 const TextureHelper11 *sourceResource = nullptr; 2731 UINT sourceSubresource = 0; 2732 ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage(context, sourceD3D, sourceIndex, 2733 &sourceResource, &sourceSubresource)); 2734 2735 gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1); 2736 2737 UINT destSubresource = 0; 2738 ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource)); 2739 2740 D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x), 2741 static_cast<UINT>(sourceBox.y), 2742 static_cast<UINT>(sourceBox.z), 2743 static_cast<UINT>(sourceBox.x + sourceBox.width), 2744 static_cast<UINT>(sourceBox.y + sourceBox.height), 2745 static_cast<UINT>(sourceBox.z + sourceBox.depth)}; 2746 2747 mDeviceContext->CopySubresourceRegion( 2748 destResource->get(), destSubresource, destOffset.x, destOffset.y, destOffset.z, 2749 sourceResource->get(), sourceSubresource, &d3dBox); 2750 } 2751 else if (srcTarget == gl::TextureTarget::_2DArray) 2752 { 2753 D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x), 2754 static_cast<UINT>(sourceBox.y), 2755 0, 2756 static_cast<UINT>(sourceBox.x + sourceBox.width), 2757 static_cast<UINT>(sourceBox.y + sourceBox.height), 2758 1u}; 2759 2760 for (int i = 0; i < sourceBox.depth; i++) 2761 { 2762 gl::ImageIndex sourceIndex = 2763 gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z); 2764 const TextureHelper11 *sourceResource = nullptr; 2765 UINT sourceSubresource = 0; 2766 ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage( 2767 context, sourceD3D, sourceIndex, &sourceResource, &sourceSubresource)); 2768 2769 gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z); 2770 UINT destSubresource = 0; 2771 ANGLE_TRY(destStorage11->getSubresourceIndex(context, dIndex, &destSubresource)); 2772 2773 mDeviceContext->CopySubresourceRegion( 2774 destResource->get(), destSubresource, destOffset.x, destOffset.y, 0, 2775 sourceResource->get(), sourceSubresource, &d3dBox); 2776 } 2777 } 2778 else 2779 { 2780 UNREACHABLE(); 2781 } 2782 } 2783 else 2784 { 2785 TextureStorage *sourceStorage = nullptr; 2786 ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); 2787 2788 TextureStorage11 *sourceStorage11 = GetAs<TextureStorage11>(sourceStorage); 2789 ASSERT(sourceStorage11); 2790 2791 const d3d11::SharedSRV *sourceSRV = nullptr; 2792 ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV)); 2793 2794 gl::ImageIndex destIndex; 2795 if (destTarget == gl::TextureTarget::_2D || destTarget == gl::TextureTarget::_3D || 2796 gl::IsCubeMapFaceTarget(destTarget)) 2797 { 2798 destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1); 2799 } 2800 else if (destTarget == gl::TextureTarget::_2DArray) 2801 { 2802 destIndex = gl::ImageIndex::Make2DArrayRange(destLevel, 0, sourceImageDesc.size.depth); 2803 } 2804 else 2805 { 2806 UNREACHABLE(); 2807 } 2808 2809 RenderTargetD3D *destRenderTargetD3D = nullptr; 2810 ANGLE_TRY(destStorage11->getRenderTarget( 2811 context, destIndex, destStorage11->getRenderToTextureSamples(), &destRenderTargetD3D)); 2812 2813 RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D); 2814 2815 const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView(); 2816 ASSERT(destRTV.valid()); 2817 2818 gl::Box sourceArea(sourceBox.x, sourceBox.y, sourceBox.z, sourceBox.width, sourceBox.height, 2819 sourceBox.depth); 2820 2821 if (unpackFlipY) 2822 { 2823 sourceArea.y += sourceArea.height; 2824 sourceArea.height = -sourceArea.height; 2825 } 2826 2827 gl::Box destArea(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, 2828 sourceBox.height, sourceBox.depth); 2829 2830 gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 2831 sourceBox.depth); 2832 2833 // Use nearest filtering because source and destination are the same size for the direct 2834 // copy 2835 GLenum sourceFormat = source->getFormat(srcTarget, sourceLevel).info->format; 2836 ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceImageDesc.size, 2837 sourceFormat, destRTV, destArea, destSize, nullptr, destFormat, 2838 destType, GL_NEAREST, false, unpackPremultiplyAlpha, 2839 unpackUnmultiplyAlpha)); 2840 } 2841 2842 destStorage11->markLevelDirty(destLevel); 2843 2844 return angle::Result::Continue; 2845 } 2846 2847 angle::Result Renderer11::copyCompressedTexture(const gl::Context *context, 2848 const gl::Texture *source, 2849 GLint sourceLevel, 2850 TextureStorage *storage, 2851 GLint destLevel) 2852 { 2853 TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage); 2854 ASSERT(destStorage11); 2855 2856 const TextureHelper11 *destResource = nullptr; 2857 ANGLE_TRY(destStorage11->getResource(context, &destResource)); 2858 2859 gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); 2860 UINT destSubresource = 0; 2861 ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource)); 2862 2863 TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); 2864 ASSERT(sourceD3D); 2865 2866 TextureStorage *sourceStorage = nullptr; 2867 ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); 2868 2869 TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage); 2870 ASSERT(sourceStorage11); 2871 2872 const TextureHelper11 *sourceResource = nullptr; 2873 ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); 2874 2875 gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); 2876 UINT sourceSubresource = 0; 2877 ANGLE_TRY(sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource)); 2878 2879 mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0, 2880 sourceResource->get(), sourceSubresource, nullptr); 2881 2882 return angle::Result::Continue; 2883 } 2884 2885 angle::Result Renderer11::createRenderTarget(const gl::Context *context, 2886 int width, 2887 int height, 2888 GLenum format, 2889 GLsizei samples, 2890 RenderTargetD3D **outRT) 2891 { 2892 const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps); 2893 2894 const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); 2895 GLuint supportedSamples = textureCaps.getNearestSamples(samples); 2896 2897 Context11 *context11 = GetImplAs<Context11>(context); 2898 2899 if (width > 0 && height > 0) 2900 { 2901 // Create texture resource 2902 D3D11_TEXTURE2D_DESC desc; 2903 desc.Width = width; 2904 desc.Height = height; 2905 desc.MipLevels = 1; 2906 desc.ArraySize = 1; 2907 desc.Format = formatInfo.texFormat; 2908 desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; 2909 desc.SampleDesc.Quality = getSampleDescQuality(supportedSamples); 2910 desc.Usage = D3D11_USAGE_DEFAULT; 2911 desc.CPUAccessFlags = 0; 2912 desc.MiscFlags = 0; 2913 2914 // If a rendertarget or depthstencil format exists for this texture format, 2915 // we'll flag it to allow binding that way. Shader resource views are a little 2916 // more complicated. 2917 bool bindRTV = false, bindDSV = false, bindSRV = false; 2918 bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); 2919 bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); 2920 bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN); 2921 2922 bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1; 2923 if (isMultisampledDepthStencil && 2924 !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs) 2925 { 2926 bindSRV = false; 2927 } 2928 2929 desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | 2930 (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | 2931 (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); 2932 2933 // The format must be either an RTV or a DSV 2934 ASSERT(bindRTV != bindDSV); 2935 2936 TextureHelper11 texture; 2937 ANGLE_TRY(allocateTexture(context11, desc, formatInfo, &texture)); 2938 texture.setInternalName("createRenderTarget.Texture"); 2939 2940 d3d11::SharedSRV srv; 2941 d3d11::SharedSRV blitSRV; 2942 if (bindSRV) 2943 { 2944 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 2945 srvDesc.Format = formatInfo.srvFormat; 2946 srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D 2947 : D3D11_SRV_DIMENSION_TEXTURE2DMS; 2948 srvDesc.Texture2D.MostDetailedMip = 0; 2949 srvDesc.Texture2D.MipLevels = 1; 2950 2951 ANGLE_TRY(allocateResource(context11, srvDesc, texture.get(), &srv)); 2952 srv.setInternalName("createRenderTarget.SRV"); 2953 2954 if (formatInfo.blitSRVFormat != formatInfo.srvFormat) 2955 { 2956 D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc; 2957 blitSRVDesc.Format = formatInfo.blitSRVFormat; 2958 blitSRVDesc.ViewDimension = (supportedSamples == 0) 2959 ? D3D11_SRV_DIMENSION_TEXTURE2D 2960 : D3D11_SRV_DIMENSION_TEXTURE2DMS; 2961 blitSRVDesc.Texture2D.MostDetailedMip = 0; 2962 blitSRVDesc.Texture2D.MipLevels = 1; 2963 2964 ANGLE_TRY(allocateResource(context11, blitSRVDesc, texture.get(), &blitSRV)); 2965 blitSRV.setInternalName("createRenderTarget.BlitSRV"); 2966 } 2967 else 2968 { 2969 blitSRV = srv.makeCopy(); 2970 } 2971 } 2972 2973 if (bindDSV) 2974 { 2975 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 2976 dsvDesc.Format = formatInfo.dsvFormat; 2977 dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D 2978 : D3D11_DSV_DIMENSION_TEXTURE2DMS; 2979 dsvDesc.Texture2D.MipSlice = 0; 2980 dsvDesc.Flags = 0; 2981 2982 d3d11::DepthStencilView dsv; 2983 ANGLE_TRY(allocateResource(context11, dsvDesc, texture.get(), &dsv)); 2984 dsv.setInternalName("createRenderTarget.DSV"); 2985 2986 *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo, 2987 width, height, 1, supportedSamples); 2988 } 2989 else if (bindRTV) 2990 { 2991 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 2992 rtvDesc.Format = formatInfo.rtvFormat; 2993 rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D 2994 : D3D11_RTV_DIMENSION_TEXTURE2DMS; 2995 rtvDesc.Texture2D.MipSlice = 0; 2996 2997 d3d11::RenderTargetView rtv; 2998 ANGLE_TRY(allocateResource(context11, rtvDesc, texture.get(), &rtv)); 2999 rtv.setInternalName("createRenderTarget.RTV"); 3000 3001 if (formatInfo.dataInitializerFunction != nullptr) 3002 { 3003 const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f}; 3004 mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues); 3005 } 3006 3007 *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format, 3008 formatInfo, width, height, 1, supportedSamples); 3009 } 3010 else 3011 { 3012 UNREACHABLE(); 3013 } 3014 } 3015 else 3016 { 3017 *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(), 3018 d3d11::SharedSRV(), d3d11::SharedSRV(), format, 3019 d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), 3020 width, height, 1, supportedSamples); 3021 } 3022 3023 return angle::Result::Continue; 3024 } 3025 3026 angle::Result Renderer11::createRenderTargetCopy(const gl::Context *context, 3027 RenderTargetD3D *source, 3028 RenderTargetD3D **outRT) 3029 { 3030 ASSERT(source != nullptr); 3031 3032 RenderTargetD3D *newRT = nullptr; 3033 ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(), 3034 source->getInternalFormat(), source->getSamples(), &newRT)); 3035 3036 RenderTarget11 *source11 = GetAs<RenderTarget11>(source); 3037 RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT); 3038 3039 mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(), 3040 0, 0, 0, source11->getTexture().get(), 3041 source11->getSubresourceIndex(), nullptr); 3042 *outRT = newRT; 3043 return angle::Result::Continue; 3044 } 3045 3046 angle::Result Renderer11::loadExecutable(d3d::Context *context, 3047 const uint8_t *function, 3048 size_t length, 3049 gl::ShaderType type, 3050 const std::vector<D3DVarying> &streamOutVaryings, 3051 bool separatedOutputBuffers, 3052 ShaderExecutableD3D **outExecutable) 3053 { 3054 ShaderData shaderData(function, length); 3055 3056 switch (type) 3057 { 3058 case gl::ShaderType::Vertex: 3059 { 3060 d3d11::VertexShader vertexShader; 3061 d3d11::GeometryShader streamOutShader; 3062 ANGLE_TRY(allocateResource(context, shaderData, &vertexShader)); 3063 3064 if (!streamOutVaryings.empty()) 3065 { 3066 std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; 3067 soDeclaration.reserve(streamOutVaryings.size()); 3068 3069 for (const auto &streamOutVarying : streamOutVaryings) 3070 { 3071 D3D11_SO_DECLARATION_ENTRY entry = {}; 3072 entry.Stream = 0; 3073 entry.SemanticName = streamOutVarying.semanticName.c_str(); 3074 entry.SemanticIndex = streamOutVarying.semanticIndex; 3075 entry.StartComponent = 0; 3076 entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount); 3077 entry.OutputSlot = static_cast<BYTE>( 3078 (separatedOutputBuffers ? streamOutVarying.outputSlot : 0)); 3079 soDeclaration.push_back(entry); 3080 } 3081 3082 ANGLE_TRY(allocateResource(context, shaderData, &soDeclaration, &streamOutShader)); 3083 } 3084 3085 *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader), 3086 std::move(streamOutShader)); 3087 } 3088 break; 3089 case gl::ShaderType::Fragment: 3090 { 3091 d3d11::PixelShader pixelShader; 3092 ANGLE_TRY(allocateResource(context, shaderData, &pixelShader)); 3093 *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader)); 3094 } 3095 break; 3096 case gl::ShaderType::Geometry: 3097 { 3098 d3d11::GeometryShader geometryShader; 3099 ANGLE_TRY(allocateResource(context, shaderData, &geometryShader)); 3100 *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader)); 3101 } 3102 break; 3103 case gl::ShaderType::Compute: 3104 { 3105 d3d11::ComputeShader computeShader; 3106 ANGLE_TRY(allocateResource(context, shaderData, &computeShader)); 3107 *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader)); 3108 } 3109 break; 3110 default: 3111 ANGLE_HR_UNREACHABLE(context); 3112 } 3113 3114 return angle::Result::Continue; 3115 } 3116 3117 angle::Result Renderer11::compileToExecutable(d3d::Context *context, 3118 gl::InfoLog &infoLog, 3119 const std::string &shaderHLSL, 3120 gl::ShaderType type, 3121 const std::vector<D3DVarying> &streamOutVaryings, 3122 bool separatedOutputBuffers, 3123 const CompilerWorkaroundsD3D &workarounds, 3124 ShaderExecutableD3D **outExectuable) 3125 { 3126 std::stringstream profileStream; 3127 3128 switch (type) 3129 { 3130 case gl::ShaderType::Vertex: 3131 profileStream << "vs"; 3132 break; 3133 case gl::ShaderType::Fragment: 3134 profileStream << "ps"; 3135 break; 3136 case gl::ShaderType::Geometry: 3137 profileStream << "gs"; 3138 break; 3139 case gl::ShaderType::Compute: 3140 profileStream << "cs"; 3141 break; 3142 default: 3143 ANGLE_HR_UNREACHABLE(context); 3144 } 3145 3146 profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel() 3147 << getShaderModelSuffix(); 3148 std::string profile = profileStream.str(); 3149 3150 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; 3151 3152 #if defined(ANGLE_ENABLE_DEBUG_TRACE) 3153 # ifndef NDEBUG 3154 flags = D3DCOMPILE_SKIP_OPTIMIZATION; 3155 # endif // NDEBUG 3156 flags |= D3DCOMPILE_DEBUG; 3157 #endif // defined(ANGLE_ENABLE_DEBUG_TRACE) 3158 3159 if (workarounds.enableIEEEStrictness) 3160 flags |= D3DCOMPILE_IEEE_STRICTNESS; 3161 3162 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders 3163 // when it would otherwise pass with alternative options. 3164 // Try the default flags first and if compilation fails, try some alternatives. 3165 std::vector<CompileConfig> configs; 3166 configs.push_back(CompileConfig(flags, "default")); 3167 configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation")); 3168 configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); 3169 3170 if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "") 3171 { 3172 // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader". 3173 // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*. 3174 // Using the [unroll] directive works around this, as does this D3DCompile flag. 3175 configs.push_back( 3176 CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); 3177 } 3178 3179 D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}}; 3180 3181 // TODO(jmadill): Use ComPtr? 3182 ID3DBlob *binary = nullptr; 3183 std::string debugInfo; 3184 ANGLE_TRY(mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs, loopMacros, 3185 &binary, &debugInfo)); 3186 3187 // It's possible that binary is NULL if the compiler failed in all configurations. Set the 3188 // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the 3189 // internal state is still OK. 3190 if (!binary) 3191 { 3192 *outExectuable = nullptr; 3193 return angle::Result::Continue; 3194 } 3195 3196 angle::Result error = loadExecutable( 3197 context, static_cast<const uint8_t *>(binary->GetBufferPointer()), binary->GetBufferSize(), 3198 type, streamOutVaryings, separatedOutputBuffers, outExectuable); 3199 3200 SafeRelease(binary); 3201 if (error == angle::Result::Stop) 3202 { 3203 return error; 3204 } 3205 3206 if (!debugInfo.empty()) 3207 { 3208 (*outExectuable)->appendDebugInfo(debugInfo); 3209 } 3210 3211 return angle::Result::Continue; 3212 } 3213 3214 angle::Result Renderer11::ensureHLSLCompilerInitialized(d3d::Context *context) 3215 { 3216 return mCompiler.ensureInitialized(context); 3217 } 3218 3219 UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) 3220 { 3221 return new UniformStorage11(storageSize); 3222 } 3223 3224 VertexBuffer *Renderer11::createVertexBuffer() 3225 { 3226 return new VertexBuffer11(this); 3227 } 3228 3229 IndexBuffer *Renderer11::createIndexBuffer() 3230 { 3231 return new IndexBuffer11(this); 3232 } 3233 3234 StreamProducerImpl *Renderer11::createStreamProducerD3DTexture( 3235 egl::Stream::ConsumerType consumerType, 3236 const egl::AttributeMap &attribs) 3237 { 3238 return new StreamProducerD3DTexture(this); 3239 } 3240 3241 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const 3242 { 3243 ASSERT(getNativeExtensions().pixelBufferObjectNV); 3244 3245 const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); 3246 const d3d11::Format &d3d11FormatInfo = 3247 d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps); 3248 3249 // sRGB formats do not work with D3D11 buffer SRVs 3250 if (internalFormatInfo.colorEncoding == GL_SRGB) 3251 { 3252 return false; 3253 } 3254 3255 // We cannot support direct copies to non-color-renderable formats 3256 if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN) 3257 { 3258 return false; 3259 } 3260 3261 // We skip all 3-channel formats since sometimes format support is missing 3262 if (internalFormatInfo.componentCount == 3) 3263 { 3264 return false; 3265 } 3266 3267 // We don't support formats which we can't represent without conversion 3268 if (d3d11FormatInfo.format().glInternalFormat != internalFormat) 3269 { 3270 return false; 3271 } 3272 3273 // Buffer SRV creation for this format was not working on Windows 10. 3274 if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM) 3275 { 3276 return false; 3277 } 3278 3279 // This format is not supported as a buffer SRV. 3280 if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM) 3281 { 3282 return false; 3283 } 3284 3285 return true; 3286 } 3287 3288 angle::Result Renderer11::fastCopyBufferToTexture(const gl::Context *context, 3289 const gl::PixelUnpackState &unpack, 3290 gl::Buffer *unpackBuffer, 3291 unsigned int offset, 3292 RenderTargetD3D *destRenderTarget, 3293 GLenum destinationFormat, 3294 GLenum sourcePixelsType, 3295 const gl::Box &destArea) 3296 { 3297 ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); 3298 return mPixelTransfer->copyBufferToTexture(context, unpack, unpackBuffer, offset, 3299 destRenderTarget, destinationFormat, 3300 sourcePixelsType, destArea); 3301 } 3302 3303 ImageD3D *Renderer11::createImage() 3304 { 3305 return new Image11(this); 3306 } 3307 3308 ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Context *context, 3309 EGLenum target, 3310 EGLClientBuffer buffer, 3311 const egl::AttributeMap &attribs) 3312 { 3313 switch (target) 3314 { 3315 case EGL_D3D11_TEXTURE_ANGLE: 3316 return new ExternalImageSiblingImpl11(this, buffer, attribs); 3317 3318 default: 3319 UNREACHABLE(); 3320 return nullptr; 3321 } 3322 } 3323 3324 angle::Result Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src) 3325 { 3326 Image11 *dest11 = GetAs<Image11>(dest); 3327 Image11 *src11 = GetAs<Image11>(src); 3328 return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps); 3329 } 3330 3331 angle::Result Renderer11::generateMipmapUsingD3D(const gl::Context *context, 3332 TextureStorage *storage, 3333 const gl::TextureState &textureState) 3334 { 3335 TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); 3336 3337 ASSERT(storage11->isRenderTarget()); 3338 ASSERT(storage11->supportsNativeMipmapFunction()); 3339 3340 const d3d11::SharedSRV *srv = nullptr; 3341 ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(), 3342 textureState.getEffectiveMaxLevel(), &srv)); 3343 3344 mDeviceContext->GenerateMips(srv->get()); 3345 3346 return angle::Result::Continue; 3347 } 3348 3349 angle::Result Renderer11::copyImage(const gl::Context *context, 3350 ImageD3D *dest, 3351 ImageD3D *source, 3352 const gl::Box &sourceBox, 3353 const gl::Offset &destOffset, 3354 bool unpackFlipY, 3355 bool unpackPremultiplyAlpha, 3356 bool unpackUnmultiplyAlpha) 3357 { 3358 Image11 *dest11 = GetAs<Image11>(dest); 3359 Image11 *src11 = GetAs<Image11>(source); 3360 return Image11::CopyImage(context, dest11, src11, sourceBox, destOffset, unpackFlipY, 3361 unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps); 3362 } 3363 3364 TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain, 3365 const std::string &label) 3366 { 3367 SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain); 3368 return new TextureStorage11_2D(this, swapChain11, label); 3369 } 3370 3371 TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage, 3372 RenderTargetD3D *renderTargetD3D, 3373 const std::string &label) 3374 { 3375 return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D), 3376 label); 3377 } 3378 3379 TextureStorage *Renderer11::createTextureStorageExternal( 3380 egl::Stream *stream, 3381 const egl::Stream::GLTextureDescription &desc, 3382 const std::string &label) 3383 { 3384 return new TextureStorage11_External(this, stream, desc, label); 3385 } 3386 3387 TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, 3388 BindFlags bindFlags, 3389 GLsizei width, 3390 GLsizei height, 3391 int levels, 3392 const std::string &label, 3393 bool hintLevelZeroOnly) 3394 { 3395 return new TextureStorage11_2D(this, internalformat, bindFlags, width, height, levels, label, 3396 hintLevelZeroOnly); 3397 } 3398 3399 TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, 3400 BindFlags bindFlags, 3401 int size, 3402 int levels, 3403 bool hintLevelZeroOnly, 3404 const std::string &label) 3405 { 3406 return new TextureStorage11_Cube(this, internalformat, bindFlags, size, levels, 3407 hintLevelZeroOnly, label); 3408 } 3409 3410 TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, 3411 BindFlags bindFlags, 3412 GLsizei width, 3413 GLsizei height, 3414 GLsizei depth, 3415 int levels, 3416 const std::string &label) 3417 { 3418 return new TextureStorage11_3D(this, internalformat, bindFlags, width, height, depth, levels, 3419 label); 3420 } 3421 3422 TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, 3423 BindFlags bindFlags, 3424 GLsizei width, 3425 GLsizei height, 3426 GLsizei depth, 3427 int levels, 3428 const std::string &label) 3429 { 3430 return new TextureStorage11_2DArray(this, internalformat, bindFlags, width, height, depth, 3431 levels, label); 3432 } 3433 3434 TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat, 3435 GLsizei width, 3436 GLsizei height, 3437 int levels, 3438 int samples, 3439 bool fixedSampleLocations, 3440 const std::string &label) 3441 { 3442 return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples, 3443 fixedSampleLocations, label); 3444 } 3445 3446 TextureStorage *Renderer11::createTextureStorageBuffer( 3447 const gl::OffsetBindingPointer<gl::Buffer> &buffer, 3448 GLenum internalFormat, 3449 const std::string &label) 3450 { 3451 return new TextureStorage11_Buffer(this, buffer, internalFormat, label); 3452 } 3453 3454 TextureStorage *Renderer11::createTextureStorage2DMultisampleArray(GLenum internalformat, 3455 GLsizei width, 3456 GLsizei height, 3457 GLsizei depth, 3458 int levels, 3459 int samples, 3460 bool fixedSampleLocations, 3461 const std::string &label) 3462 { 3463 return new TextureStorage11_2DMultisampleArray(this, internalformat, width, height, depth, 3464 levels, samples, fixedSampleLocations, label); 3465 } 3466 3467 angle::Result Renderer11::readFromAttachment(const gl::Context *context, 3468 const gl::FramebufferAttachment &srcAttachment, 3469 const gl::Rectangle &sourceArea, 3470 GLenum format, 3471 GLenum type, 3472 GLuint outputPitch, 3473 const gl::PixelPackState &pack, 3474 uint8_t *pixelsOut) 3475 { 3476 ASSERT(sourceArea.width >= 0); 3477 ASSERT(sourceArea.height >= 0); 3478 3479 const bool invertTexture = UsePresentPathFast(this, &srcAttachment); 3480 3481 RenderTarget11 *rt11 = nullptr; 3482 ANGLE_TRY(srcAttachment.getRenderTarget(context, 0, &rt11)); 3483 ASSERT(rt11->getTexture().valid()); 3484 3485 const TextureHelper11 &textureHelper = rt11->getTexture(); 3486 unsigned int sourceSubResource = rt11->getSubresourceIndex(); 3487 3488 const gl::Extents &texSize = textureHelper.getExtents(); 3489 3490 gl::Rectangle actualArea = sourceArea; 3491 bool reverseRowOrder = pack.reverseRowOrder; 3492 if (invertTexture) 3493 { 3494 actualArea.y = texSize.height - actualArea.y - actualArea.height; 3495 reverseRowOrder = !reverseRowOrder; 3496 } 3497 3498 // Clamp read region to the defined texture boundaries, preventing out of bounds reads 3499 // and reads of uninitialized data. 3500 gl::Rectangle safeArea; 3501 safeArea.x = gl::clamp(actualArea.x, 0, texSize.width); 3502 safeArea.y = gl::clamp(actualArea.y, 0, texSize.height); 3503 safeArea.width = 3504 gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x); 3505 safeArea.height = 3506 gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y); 3507 3508 ASSERT(safeArea.x >= 0 && safeArea.y >= 0); 3509 ASSERT(safeArea.x + safeArea.width <= texSize.width); 3510 ASSERT(safeArea.y + safeArea.height <= texSize.height); 3511 3512 if (safeArea.width == 0 || safeArea.height == 0) 3513 { 3514 // no work to do 3515 return angle::Result::Continue; 3516 } 3517 3518 gl::Extents safeSize(safeArea.width, safeArea.height, 1); 3519 TextureHelper11 stagingHelper; 3520 ANGLE_TRY(createStagingTexture(context, textureHelper.getTextureType(), 3521 textureHelper.getFormatSet(), safeSize, StagingAccess::READ, 3522 &stagingHelper)); 3523 stagingHelper.setInternalName("readFromAttachment::stagingHelper"); 3524 3525 TextureHelper11 resolvedTextureHelper; 3526 3527 // "srcTexture" usually points to the source texture. 3528 // For 2D multisampled textures, it points to the multisampled resolve texture. 3529 const TextureHelper11 *srcTexture = &textureHelper; 3530 3531 if (textureHelper.is2D() && textureHelper.getSampleCount() > 1) 3532 { 3533 D3D11_TEXTURE2D_DESC resolveDesc; 3534 resolveDesc.Width = static_cast<UINT>(texSize.width); 3535 resolveDesc.Height = static_cast<UINT>(texSize.height); 3536 resolveDesc.MipLevels = 1; 3537 resolveDesc.ArraySize = 1; 3538 resolveDesc.Format = textureHelper.getFormat(); 3539 resolveDesc.SampleDesc.Count = 1; 3540 resolveDesc.SampleDesc.Quality = 0; 3541 resolveDesc.Usage = D3D11_USAGE_DEFAULT; 3542 resolveDesc.BindFlags = 0; 3543 resolveDesc.CPUAccessFlags = 0; 3544 resolveDesc.MiscFlags = 0; 3545 3546 ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc, 3547 textureHelper.getFormatSet(), &resolvedTextureHelper)); 3548 resolvedTextureHelper.setInternalName("readFromAttachment::resolvedTextureHelper"); 3549 3550 mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(), 3551 sourceSubResource, textureHelper.getFormat()); 3552 3553 sourceSubResource = 0; 3554 srcTexture = &resolvedTextureHelper; 3555 } 3556 3557 D3D11_BOX srcBox; 3558 srcBox.left = static_cast<UINT>(safeArea.x); 3559 srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width); 3560 srcBox.top = static_cast<UINT>(safeArea.y); 3561 srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height); 3562 3563 // Select the correct layer from a 3D attachment 3564 srcBox.front = 0; 3565 if (textureHelper.is3D()) 3566 { 3567 srcBox.front = static_cast<UINT>(srcAttachment.layer()); 3568 } 3569 srcBox.back = srcBox.front + 1; 3570 3571 mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(), 3572 sourceSubResource, &srcBox); 3573 3574 const angle::Format &angleFormat = GetFormatFromFormatType(format, type); 3575 gl::Buffer *packBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelPack); 3576 3577 PackPixelsParams packParams(safeArea, angleFormat, outputPitch, reverseRowOrder, packBuffer, 0); 3578 return packPixels(context, stagingHelper, packParams, pixelsOut); 3579 } 3580 3581 angle::Result Renderer11::packPixels(const gl::Context *context, 3582 const TextureHelper11 &textureHelper, 3583 const PackPixelsParams ¶ms, 3584 uint8_t *pixelsOut) 3585 { 3586 ID3D11Resource *readResource = textureHelper.get(); 3587 3588 D3D11_MAPPED_SUBRESOURCE mapping; 3589 ANGLE_TRY(mapResource(context, readResource, 0, D3D11_MAP_READ, 0, &mapping)); 3590 3591 uint8_t *source = static_cast<uint8_t *>(mapping.pData); 3592 int inputPitch = static_cast<int>(mapping.RowPitch); 3593 3594 const auto &formatInfo = textureHelper.getFormatSet(); 3595 ASSERT(formatInfo.format().glInternalFormat != GL_NONE); 3596 3597 PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut); 3598 3599 mDeviceContext->Unmap(readResource, 0); 3600 3601 return angle::Result::Continue; 3602 } 3603 3604 angle::Result Renderer11::blitRenderbufferRect(const gl::Context *context, 3605 const gl::Rectangle &readRectIn, 3606 const gl::Rectangle &drawRectIn, 3607 UINT readLayer, 3608 UINT drawLayer, 3609 RenderTargetD3D *readRenderTarget, 3610 RenderTargetD3D *drawRenderTarget, 3611 GLenum filter, 3612 const gl::Rectangle *scissor, 3613 bool colorBlit, 3614 bool depthBlit, 3615 bool stencilBlit) 3616 { 3617 // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, 3618 // it should never be the case that both color and depth/stencil need to be blitted at 3619 // at the same time. 3620 ASSERT(colorBlit != (depthBlit || stencilBlit)); 3621 3622 RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget); 3623 ASSERT(drawRenderTarget11); 3624 3625 const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture(); 3626 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); 3627 3628 RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget); 3629 ASSERT(readRenderTarget11); 3630 3631 const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); 3632 const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); 3633 3634 // From the spec: 3635 // "The actual region taken from the read framebuffer is limited to the intersection of the 3636 // source buffers being transferred, which may include the color buffer selected by the read 3637 // buffer, the depth buffer, and / or the stencil buffer depending on mask." 3638 // This means negative x and y are out of bounds, and not to be read from. We handle this here 3639 // by internally scaling the read and draw rectangles. 3640 3641 // Remove reversal from readRect to simplify further operations. 3642 gl::Rectangle readRect = readRectIn; 3643 gl::Rectangle drawRect = drawRectIn; 3644 if (readRect.isReversedX()) 3645 { 3646 readRect.x = readRect.x + readRect.width; 3647 readRect.width = -readRect.width; 3648 drawRect.x = drawRect.x + drawRect.width; 3649 drawRect.width = -drawRect.width; 3650 } 3651 if (readRect.isReversedY()) 3652 { 3653 readRect.y = readRect.y + readRect.height; 3654 readRect.height = -readRect.height; 3655 drawRect.y = drawRect.y + drawRect.height; 3656 drawRect.height = -drawRect.height; 3657 } 3658 3659 gl::Rectangle readBounds(0, 0, readSize.width, readSize.height); 3660 gl::Rectangle inBoundsReadRect; 3661 if (!gl::ClipRectangle(readRect, readBounds, &inBoundsReadRect)) 3662 { 3663 return angle::Result::Continue; 3664 } 3665 3666 { 3667 // Calculate the drawRect that corresponds to inBoundsReadRect. 3668 auto readToDrawX = [&drawRect, &readRect](int readOffset) { 3669 double readToDrawScale = 3670 static_cast<double>(drawRect.width) / static_cast<double>(readRect.width); 3671 return static_cast<int>( 3672 round(static_cast<double>(readOffset - readRect.x) * readToDrawScale) + drawRect.x); 3673 }; 3674 auto readToDrawY = [&drawRect, &readRect](int readOffset) { 3675 double readToDrawScale = 3676 static_cast<double>(drawRect.height) / static_cast<double>(readRect.height); 3677 return static_cast<int>( 3678 round(static_cast<double>(readOffset - readRect.y) * readToDrawScale) + drawRect.y); 3679 }; 3680 3681 gl::Rectangle drawRectMatchingInBoundsReadRect; 3682 drawRectMatchingInBoundsReadRect.x = readToDrawX(inBoundsReadRect.x); 3683 drawRectMatchingInBoundsReadRect.y = readToDrawY(inBoundsReadRect.y); 3684 drawRectMatchingInBoundsReadRect.width = 3685 readToDrawX(inBoundsReadRect.x1()) - drawRectMatchingInBoundsReadRect.x; 3686 drawRectMatchingInBoundsReadRect.height = 3687 readToDrawY(inBoundsReadRect.y1()) - drawRectMatchingInBoundsReadRect.y; 3688 drawRect = drawRectMatchingInBoundsReadRect; 3689 readRect = inBoundsReadRect; 3690 } 3691 3692 bool scissorNeeded = false; 3693 if (scissor) 3694 { 3695 gl::Rectangle scissoredDrawRect; 3696 if (!gl::ClipRectangle(drawRect, *scissor, &scissoredDrawRect)) 3697 { 3698 return angle::Result::Continue; 3699 } 3700 scissorNeeded = scissoredDrawRect != drawRect; 3701 } 3702 3703 const auto &destFormatInfo = 3704 gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat()); 3705 const auto &srcFormatInfo = 3706 gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat()); 3707 const auto &formatSet = drawRenderTarget11->getFormatSet(); 3708 const auto &nativeFormat = formatSet.format(); 3709 3710 // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we 3711 // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy. 3712 3713 gl::Color<bool> colorMask; 3714 colorMask.red = 3715 (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0); 3716 colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && 3717 (nativeFormat.greenBits > 0); 3718 colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && 3719 (nativeFormat.blueBits > 0); 3720 colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && 3721 (nativeFormat.alphaBits > 0); 3722 3723 // We only currently support masking off the alpha channel. 3724 bool colorMaskingNeeded = colorMask.alpha; 3725 ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue); 3726 3727 bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 && 3728 readRect.width == readSize.width && readRect.y == 0 && 3729 readRect.height == readSize.height && drawRect.x == 0 && 3730 drawRect.width == drawSize.width && drawRect.y == 0 && 3731 drawRect.height == drawSize.height; 3732 3733 bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; 3734 3735 ASSERT(!readRect.isReversedX() && !readRect.isReversedY()); 3736 bool reversalRequired = drawRect.isReversedX() || drawRect.isReversedY(); 3737 3738 bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || 3739 readRect.y < 0 || readRect.y + readRect.height > readSize.height || 3740 drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || 3741 drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; 3742 3743 bool partialDSBlit = 3744 (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit); 3745 3746 const bool canCopySubresource = 3747 drawRenderTarget->getSamples() == readRenderTarget->getSamples() && 3748 readRenderTarget11->getFormatSet().formatID == 3749 drawRenderTarget11->getFormatSet().formatID && 3750 !stretchRequired && !outOfBounds && !reversalRequired && !partialDSBlit && 3751 !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy); 3752 3753 TextureHelper11 readTexture; 3754 unsigned int readSubresource = 0; 3755 d3d11::SharedSRV readSRV; 3756 3757 if (readRenderTarget->isMultisampled()) 3758 { 3759 ANGLE_TRY(resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit, 3760 &readTexture)); 3761 3762 if (!stencilBlit && !canCopySubresource) 3763 { 3764 const auto &readFormatSet = readTexture.getFormatSet(); 3765 3766 D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; 3767 viewDesc.Format = readFormatSet.srvFormat; 3768 viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 3769 viewDesc.Texture2D.MipLevels = 1; 3770 viewDesc.Texture2D.MostDetailedMip = 0; 3771 3772 ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, readTexture.get(), 3773 &readSRV)); 3774 } 3775 } 3776 else 3777 { 3778 ASSERT(readRenderTarget11); 3779 readTexture = readRenderTarget11->getTexture(); 3780 readSubresource = readRenderTarget11->getSubresourceIndex(); 3781 if (!canCopySubresource) 3782 { 3783 const d3d11::SharedSRV *blitSRV; 3784 ANGLE_TRY(readRenderTarget11->getBlitShaderResourceView(context, &blitSRV)); 3785 readSRV = blitSRV->makeCopy(); 3786 if (!readSRV.valid()) 3787 { 3788 ASSERT(depthBlit || stencilBlit); 3789 const d3d11::SharedSRV *srv; 3790 ANGLE_TRY(readRenderTarget11->getShaderResourceView(context, &srv)); 3791 readSRV = srv->makeCopy(); 3792 } 3793 ASSERT(readSRV.valid()); 3794 } 3795 } 3796 3797 if (canCopySubresource) 3798 { 3799 UINT dstX = drawRect.x; 3800 UINT dstY = drawRect.y; 3801 UINT dstZ = drawLayer; 3802 3803 D3D11_BOX readBox; 3804 readBox.left = readRect.x; 3805 readBox.right = readRect.x + readRect.width; 3806 readBox.top = readRect.y; 3807 readBox.bottom = readRect.y + readRect.height; 3808 readBox.front = readLayer; 3809 readBox.back = readLayer + 1; 3810 3811 if (scissorNeeded) 3812 { 3813 // drawRect is guaranteed to have positive width and height because stretchRequired is 3814 // false. 3815 ASSERT(drawRect.width >= 0 || drawRect.height >= 0); 3816 3817 if (drawRect.x < scissor->x) 3818 { 3819 dstX = scissor->x; 3820 readBox.left += (scissor->x - drawRect.x); 3821 } 3822 if (drawRect.y < scissor->y) 3823 { 3824 dstY = scissor->y; 3825 readBox.top += (scissor->y - drawRect.y); 3826 } 3827 if (drawRect.x + drawRect.width > scissor->x + scissor->width) 3828 { 3829 readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); 3830 } 3831 if (drawRect.y + drawRect.height > scissor->y + scissor->height) 3832 { 3833 readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); 3834 } 3835 } 3836 3837 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox 3838 // We also require complete framebuffer copies for depth-stencil blit. 3839 D3D11_BOX *pSrcBox = wholeBufferCopy && readLayer == 0 ? nullptr : &readBox; 3840 3841 mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, dstZ, 3842 readTexture.get(), readSubresource, pSrcBox); 3843 } 3844 else 3845 { 3846 gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); 3847 gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); 3848 3849 if (depthBlit && stencilBlit) 3850 { 3851 ANGLE_TRY(mBlit->copyDepthStencil(context, readTexture, readSubresource, readArea, 3852 readSize, drawTexture, drawSubresource, drawArea, 3853 drawSize, scissor)); 3854 } 3855 else if (depthBlit) 3856 { 3857 const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView(); 3858 ASSERT(readSRV.valid()); 3859 ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea, 3860 drawSize, scissor)); 3861 } 3862 else if (stencilBlit) 3863 { 3864 ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize, 3865 drawTexture, drawSubresource, drawArea, drawSize, 3866 scissor)); 3867 } 3868 else 3869 { 3870 const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView(); 3871 3872 // We don't currently support masking off any other channel than alpha 3873 bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha; 3874 ASSERT(readSRV.valid()); 3875 ANGLE_TRY(mBlit->copyTexture(context, readSRV, readArea, readSize, srcFormatInfo.format, 3876 drawRTV, drawArea, drawSize, scissor, 3877 destFormatInfo.format, GL_NONE, filter, maskOffAlpha, 3878 false, false)); 3879 } 3880 } 3881 3882 return angle::Result::Continue; 3883 } 3884 3885 bool Renderer11::isES3Capable() const 3886 { 3887 return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps).major > 2); 3888 } 3889 3890 RendererClass Renderer11::getRendererClass() const 3891 { 3892 return RENDERER_D3D11; 3893 } 3894 3895 void Renderer11::onSwap() 3896 { 3897 // Send histogram updates every half hour 3898 const double kHistogramUpdateInterval = 30 * 60; 3899 3900 auto *platform = ANGLEPlatformCurrent(); 3901 const double currentTime = platform->monotonicallyIncreasingTime(platform); 3902 const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; 3903 3904 if (timeSinceLastUpdate > kHistogramUpdateInterval) 3905 { 3906 updateHistograms(); 3907 mLastHistogramUpdateTime = currentTime; 3908 } 3909 } 3910 3911 void Renderer11::updateHistograms() 3912 { 3913 // Update the buffer CPU memory histogram 3914 { 3915 size_t sizeSum = 0; 3916 for (const Buffer11 *buffer : mAliveBuffers) 3917 { 3918 sizeSum += buffer->getTotalCPUBufferMemoryBytes(); 3919 } 3920 const int kOneMegaByte = 1024 * 1024; 3921 ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB", 3922 static_cast<int>(sizeSum) / kOneMegaByte); 3923 } 3924 } 3925 3926 void Renderer11::onBufferCreate(const Buffer11 *created) 3927 { 3928 mAliveBuffers.insert(created); 3929 } 3930 3931 void Renderer11::onBufferDelete(const Buffer11 *deleted) 3932 { 3933 mAliveBuffers.erase(deleted); 3934 } 3935 3936 angle::Result Renderer11::resolveMultisampledTexture(const gl::Context *context, 3937 RenderTarget11 *renderTarget, 3938 bool depth, 3939 bool stencil, 3940 TextureHelper11 *textureOut) 3941 { 3942 if (depth && !stencil) 3943 { 3944 return mBlit->resolveDepth(context, renderTarget, textureOut); 3945 } 3946 3947 if (stencil) 3948 { 3949 return mBlit->resolveStencil(context, renderTarget, depth, textureOut); 3950 } 3951 3952 const auto &formatSet = renderTarget->getFormatSet(); 3953 3954 ASSERT(renderTarget->isMultisampled()); 3955 const d3d11::SharedSRV *sourceSRV; 3956 ANGLE_TRY(renderTarget->getShaderResourceView(context, &sourceSRV)); 3957 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; 3958 sourceSRV->get()->GetDesc(&sourceSRVDesc); 3959 ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS || 3960 sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMSARRAY); 3961 3962 if (!mCachedResolveTexture.valid() || 3963 mCachedResolveTexture.getExtents().width != renderTarget->getWidth() || 3964 mCachedResolveTexture.getExtents().height != renderTarget->getHeight() || 3965 mCachedResolveTexture.getFormat() != formatSet.texFormat) 3966 { 3967 D3D11_TEXTURE2D_DESC resolveDesc; 3968 resolveDesc.Width = renderTarget->getWidth(); 3969 resolveDesc.Height = renderTarget->getHeight(); 3970 resolveDesc.MipLevels = 1; 3971 resolveDesc.ArraySize = 1; 3972 resolveDesc.Format = formatSet.texFormat; 3973 resolveDesc.SampleDesc.Count = 1; 3974 resolveDesc.SampleDesc.Quality = 0; 3975 resolveDesc.Usage = D3D11_USAGE_DEFAULT; 3976 resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 3977 resolveDesc.CPUAccessFlags = 0; 3978 resolveDesc.MiscFlags = 0; 3979 3980 ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc, formatSet, 3981 &mCachedResolveTexture)); 3982 } 3983 3984 mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0, 3985 renderTarget->getTexture().get(), 3986 renderTarget->getSubresourceIndex(), formatSet.texFormat); 3987 *textureOut = mCachedResolveTexture; 3988 return angle::Result::Continue; 3989 } 3990 3991 bool Renderer11::getLUID(LUID *adapterLuid) const 3992 { 3993 adapterLuid->HighPart = 0; 3994 adapterLuid->LowPart = 0; 3995 3996 if (!mDxgiAdapter) 3997 { 3998 return false; 3999 } 4000 4001 DXGI_ADAPTER_DESC adapterDesc; 4002 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) 4003 { 4004 return false; 4005 } 4006 4007 *adapterLuid = adapterDesc.AdapterLuid; 4008 return true; 4009 } 4010 4011 VertexConversionType Renderer11::getVertexConversionType(angle::FormatID vertexFormatID) const 4012 { 4013 return d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel) 4014 .conversionType; 4015 } 4016 4017 GLenum Renderer11::getVertexComponentType(angle::FormatID vertexFormatID) const 4018 { 4019 const auto &format = 4020 d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel); 4021 return d3d11::GetComponentType(format.nativeFormat); 4022 } 4023 4024 angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context, 4025 const gl::VertexAttribute &attrib, 4026 const gl::VertexBinding &binding, 4027 size_t count, 4028 GLsizei instances, 4029 GLuint baseInstance, 4030 unsigned int *bytesRequiredOut) const 4031 { 4032 if (!attrib.enabled) 4033 { 4034 *bytesRequiredOut = 16u; 4035 return angle::Result::Continue; 4036 } 4037 4038 unsigned int elementCount = 0; 4039 const unsigned int divisor = binding.getDivisor(); 4040 if (instances == 0 || divisor == 0) 4041 { 4042 // This could be a clipped cast. 4043 elementCount = gl::clampCast<unsigned int>(count); 4044 } 4045 else 4046 { 4047 // Round up to divisor, if possible 4048 elementCount = 4049 UnsignedCeilDivide(static_cast<unsigned int>(instances + baseInstance), divisor); 4050 } 4051 4052 ASSERT(elementCount > 0); 4053 4054 const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel; 4055 const d3d11::VertexFormat &vertexFormatInfo = 4056 d3d11::GetVertexFormatInfo(attrib.format->id, featureLevel); 4057 const d3d11::DXGIFormatSize &dxgiFormatInfo = 4058 d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat); 4059 unsigned int elementSize = dxgiFormatInfo.pixelBytes; 4060 bool check = (elementSize > std::numeric_limits<unsigned int>::max() / elementCount); 4061 ANGLE_CHECK(GetImplAs<Context11>(context), !check, 4062 "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY); 4063 4064 *bytesRequiredOut = elementSize * elementCount; 4065 return angle::Result::Continue; 4066 } 4067 4068 void Renderer11::generateCaps(gl::Caps *outCaps, 4069 gl::TextureCapsMap *outTextureCaps, 4070 gl::Extensions *outExtensions, 4071 gl::Limitations *outLimitations) const 4072 { 4073 d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, getFeatures(), 4074 mDescription, outCaps, outTextureCaps, outExtensions, outLimitations); 4075 } 4076 4077 void Renderer11::initializeFeatures(angle::FeaturesD3D *features) const 4078 { 4079 if (!mDisplay->getState().featuresAllDisabled) 4080 { 4081 d3d11::InitializeFeatures(mRenderer11DeviceCaps, mAdapterDescription, features); 4082 } 4083 ApplyFeatureOverrides(features, mDisplay->getState()); 4084 } 4085 4086 void Renderer11::initializeFrontendFeatures(angle::FrontendFeatures *features) const 4087 { 4088 if (!mDisplay->getState().featuresAllDisabled) 4089 { 4090 d3d11::InitializeFrontendFeatures(mAdapterDescription, features); 4091 } 4092 ApplyFeatureOverrides(features, mDisplay->getState()); 4093 } 4094 4095 DeviceImpl *Renderer11::createEGLDevice() 4096 { 4097 return new DeviceD3D(EGL_D3D11_DEVICE_ANGLE, mDevice); 4098 } 4099 4100 ContextImpl *Renderer11::createContext(const gl::State &state, gl::ErrorSet *errorSet) 4101 { 4102 return new Context11(state, errorSet, this); 4103 } 4104 4105 FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state) 4106 { 4107 return new Framebuffer11(state, this); 4108 } 4109 4110 angle::Result Renderer11::getScratchMemoryBuffer(Context11 *context11, 4111 size_t requestedSize, 4112 angle::MemoryBuffer **bufferOut) 4113 { 4114 ANGLE_CHECK_GL_ALLOC(context11, mScratchMemoryBuffer.get(requestedSize, bufferOut)); 4115 return angle::Result::Continue; 4116 } 4117 4118 gl::Version Renderer11::getMaxSupportedESVersion() const 4119 { 4120 return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps); 4121 } 4122 4123 gl::Version Renderer11::getMaxConformantESVersion() const 4124 { 4125 // 3.1 support is in progress. 4126 return std::min(getMaxSupportedESVersion(), gl::Version(3, 0)); 4127 } 4128 4129 DebugAnnotatorContext11 *Renderer11::getDebugAnnotatorContext() 4130 { 4131 return &mAnnotatorContext; 4132 } 4133 4134 angle::Result Renderer11::dispatchCompute(const gl::Context *context, 4135 GLuint numGroupsX, 4136 GLuint numGroupsY, 4137 GLuint numGroupsZ) 4138 { 4139 const gl::State &glState = context->getState(); 4140 const gl::Program *program = glState.getProgram(); 4141 if (program->getActiveShaderStorageBlockCount() > 0 || 4142 program->getActiveAtomicCounterBufferCount() > 0) 4143 { 4144 ANGLE_TRY(markRawBufferUsage(context)); 4145 } 4146 ANGLE_TRY(markTypedBufferUsage(context)); 4147 ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); 4148 mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); 4149 4150 return angle::Result::Continue; 4151 } 4152 angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) 4153 { 4154 const auto &glState = context->getState(); 4155 const gl::Program *program = glState.getProgram(); 4156 if (program->getActiveShaderStorageBlockCount() > 0 || 4157 program->getActiveAtomicCounterBufferCount() > 0) 4158 { 4159 ANGLE_TRY(markRawBufferUsage(context)); 4160 } 4161 4162 auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect); 4163 ASSERT(dispatchIndirectBuffer); 4164 4165 Buffer11 *storage = GetImplAs<Buffer11>(dispatchIndirectBuffer); 4166 const uint8_t *bufferData = nullptr; 4167 // TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant 4168 // buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization 4169 // to use GPU->GPU copy instead. 4170 // http://anglebug.com/2807 4171 ANGLE_TRY(storage->getData(context, &bufferData)); 4172 const GLuint *groups = reinterpret_cast<const GLuint *>(bufferData + indirect); 4173 ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2])); 4174 4175 ID3D11Buffer *buffer = nullptr; 4176 ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); 4177 4178 mDeviceContext->DispatchIndirect(buffer, static_cast<UINT>(indirect)); 4179 return angle::Result::Continue; 4180 } 4181 4182 angle::Result Renderer11::createStagingTexture(const gl::Context *context, 4183 ResourceType textureType, 4184 const d3d11::Format &formatSet, 4185 const gl::Extents &size, 4186 StagingAccess readAndWriteAccess, 4187 TextureHelper11 *textureOut) 4188 { 4189 Context11 *context11 = GetImplAs<Context11>(context); 4190 4191 if (textureType == ResourceType::Texture2D) 4192 { 4193 D3D11_TEXTURE2D_DESC stagingDesc; 4194 stagingDesc.Width = size.width; 4195 stagingDesc.Height = size.height; 4196 stagingDesc.MipLevels = 1; 4197 stagingDesc.ArraySize = 1; 4198 stagingDesc.Format = formatSet.texFormat; 4199 stagingDesc.SampleDesc.Count = 1; 4200 stagingDesc.SampleDesc.Quality = 0; 4201 stagingDesc.Usage = D3D11_USAGE_STAGING; 4202 stagingDesc.BindFlags = 0; 4203 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 4204 stagingDesc.MiscFlags = 0; 4205 4206 if (readAndWriteAccess == StagingAccess::READ_WRITE) 4207 { 4208 stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE; 4209 } 4210 4211 ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut)); 4212 return angle::Result::Continue; 4213 } 4214 ASSERT(textureType == ResourceType::Texture3D); 4215 4216 D3D11_TEXTURE3D_DESC stagingDesc; 4217 stagingDesc.Width = size.width; 4218 stagingDesc.Height = size.height; 4219 stagingDesc.Depth = 1; 4220 stagingDesc.MipLevels = 1; 4221 stagingDesc.Format = formatSet.texFormat; 4222 stagingDesc.Usage = D3D11_USAGE_STAGING; 4223 stagingDesc.BindFlags = 0; 4224 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 4225 stagingDesc.MiscFlags = 0; 4226 4227 ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut)); 4228 return angle::Result::Continue; 4229 } 4230 4231 angle::Result Renderer11::allocateTexture(d3d::Context *context, 4232 const D3D11_TEXTURE2D_DESC &desc, 4233 const d3d11::Format &format, 4234 const D3D11_SUBRESOURCE_DATA *initData, 4235 TextureHelper11 *textureOut) 4236 { 4237 d3d11::Texture2D texture; 4238 ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture)); 4239 textureOut->init(std::move(texture), desc, format); 4240 return angle::Result::Continue; 4241 } 4242 4243 angle::Result Renderer11::allocateTexture(d3d::Context *context, 4244 const D3D11_TEXTURE3D_DESC &desc, 4245 const d3d11::Format &format, 4246 const D3D11_SUBRESOURCE_DATA *initData, 4247 TextureHelper11 *textureOut) 4248 { 4249 d3d11::Texture3D texture; 4250 ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture)); 4251 textureOut->init(std::move(texture), desc, format); 4252 return angle::Result::Continue; 4253 } 4254 4255 angle::Result Renderer11::getBlendState(const gl::Context *context, 4256 const d3d11::BlendStateKey &key, 4257 const d3d11::BlendState **outBlendState) 4258 { 4259 return mStateCache.getBlendState(context, this, key, outBlendState); 4260 } 4261 4262 angle::Result Renderer11::getRasterizerState(const gl::Context *context, 4263 const gl::RasterizerState &rasterState, 4264 bool scissorEnabled, 4265 ID3D11RasterizerState **outRasterizerState) 4266 { 4267 return mStateCache.getRasterizerState(context, this, rasterState, scissorEnabled, 4268 outRasterizerState); 4269 } 4270 4271 angle::Result Renderer11::getDepthStencilState(const gl::Context *context, 4272 const gl::DepthStencilState &dsState, 4273 const d3d11::DepthStencilState **outDSState) 4274 { 4275 return mStateCache.getDepthStencilState(context, this, dsState, outDSState); 4276 } 4277 4278 angle::Result Renderer11::getSamplerState(const gl::Context *context, 4279 const gl::SamplerState &samplerState, 4280 ID3D11SamplerState **outSamplerState) 4281 { 4282 return mStateCache.getSamplerState(context, this, samplerState, outSamplerState); 4283 } 4284 4285 UINT Renderer11::getSampleDescQuality(GLuint supportedSamples) const 4286 { 4287 // Per the documentation on 4288 // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels 4289 // applications can only request the standard multisample pattern on 4290 // feature levels 10_1 and above. 4291 if (supportedSamples > 0 && mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_1) 4292 { 4293 return D3D11_STANDARD_MULTISAMPLE_PATTERN; 4294 } 4295 return 0; 4296 } 4297 4298 angle::Result Renderer11::clearRenderTarget(const gl::Context *context, 4299 RenderTargetD3D *renderTarget, 4300 const gl::ColorF &clearColorValue, 4301 const float clearDepthValue, 4302 const unsigned int clearStencilValue) 4303 { 4304 RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget); 4305 4306 if (rt11->getFormatSet().dsvFormat != DXGI_FORMAT_UNKNOWN) 4307 { 4308 ASSERT(rt11->getDepthStencilView().valid()); 4309 4310 const auto &format = rt11->getFormatSet(); 4311 const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) | 4312 (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0); 4313 mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags, 4314 clearDepthValue, 4315 static_cast<UINT8>(clearStencilValue)); 4316 return angle::Result::Continue; 4317 } 4318 4319 ASSERT(rt11->getRenderTargetView().valid()); 4320 ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get(); 4321 4322 // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView. 4323 // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx 4324 ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv)); 4325 4326 const auto &d3d11Format = rt11->getFormatSet(); 4327 const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat()); 4328 4329 gl::ColorF safeClearColor = clearColorValue; 4330 4331 if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0) 4332 { 4333 safeClearColor.alpha = 1.0f; 4334 } 4335 4336 mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red); 4337 return angle::Result::Continue; 4338 } 4339 4340 bool Renderer11::canSelectViewInVertexShader() const 4341 { 4342 return !getFeatures().selectViewInGeometryShader.enabled && 4343 getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader; 4344 } 4345 4346 angle::Result Renderer11::mapResource(const gl::Context *context, 4347 ID3D11Resource *resource, 4348 UINT subResource, 4349 D3D11_MAP mapType, 4350 UINT mapFlags, 4351 D3D11_MAPPED_SUBRESOURCE *mappedResource) 4352 { 4353 HRESULT hr = mDeviceContext->Map(resource, subResource, mapType, mapFlags, mappedResource); 4354 ANGLE_TRY_HR(GetImplAs<Context11>(context), hr, "Failed to map D3D11 resource."); 4355 return angle::Result::Continue; 4356 } 4357 4358 angle::Result Renderer11::markTypedBufferUsage(const gl::Context *context) 4359 { 4360 const gl::State &glState = context->getState(); 4361 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); 4362 gl::RangeUI imageRange = programD3D->getUsedImageRange(gl::ShaderType::Compute, false); 4363 for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++) 4364 { 4365 GLint imageUnitIndex = programD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, 4366 false, context->getCaps()); 4367 ASSERT(imageUnitIndex != -1); 4368 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); 4369 if (imageUnit.texture.get()->getType() == gl::TextureType::Buffer) 4370 { 4371 Buffer11 *buffer11 = GetImplAs<Buffer11>(imageUnit.texture.get()->getBuffer().get()); 4372 ANGLE_TRY(buffer11->markTypedBufferUsage(context)); 4373 } 4374 } 4375 return angle::Result::Continue; 4376 } 4377 4378 angle::Result Renderer11::markRawBufferUsage(const gl::Context *context) 4379 { 4380 const gl::State &glState = context->getState(); 4381 const gl::Program *program = glState.getProgram(); 4382 for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount(); 4383 blockIndex++) 4384 { 4385 GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex)); 4386 const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding); 4387 if (shaderStorageBuffer.get() != nullptr) 4388 { 4389 Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get()); 4390 ANGLE_TRY(bufferStorage->markRawBufferUsage(context)); 4391 } 4392 } 4393 4394 for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers()) 4395 { 4396 GLuint binding = atomicCounterBuffer.binding; 4397 const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding); 4398 4399 if (buffer.get() != nullptr) 4400 { 4401 Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get()); 4402 ANGLE_TRY(bufferStorage->markRawBufferUsage(context)); 4403 } 4404 } 4405 return angle::Result::Continue; 4406 } 4407 4408 angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context) 4409 { 4410 const gl::State &glState = context->getState(); 4411 const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); 4412 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) 4413 { 4414 const gl::OffsetBindingPointer<gl::Buffer> &binding = 4415 transformFeedback->getIndexedBuffer(i); 4416 if (binding.get() != nullptr) 4417 { 4418 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get()); 4419 ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context)); 4420 } 4421 } 4422 4423 return angle::Result::Continue; 4424 } 4425 4426 angle::Result Renderer11::getIncompleteTexture(const gl::Context *context, 4427 gl::TextureType type, 4428 gl::Texture **textureOut) 4429 { 4430 return GetImplAs<Context11>(context)->getIncompleteTexture(context, type, textureOut); 4431 } 4432 4433 std::string Renderer11::getVendorString() const 4434 { 4435 return GetVendorString(mAdapterDescription.VendorId); 4436 } 4437 4438 std::string Renderer11::getVersionString(bool includeFullVersion) const 4439 { 4440 std::ostringstream versionString; 4441 versionString << "D3D11"; 4442 if (includeFullVersion && mRenderer11DeviceCaps.driverVersion.valid()) 4443 { 4444 versionString << "-" << GetDriverVersionString(mRenderer11DeviceCaps.driverVersion.value()); 4445 } 4446 return versionString.str(); 4447 } 4448 4449 RendererD3D *CreateRenderer11(egl::Display *display) 4450 { 4451 return new Renderer11(display); 4452 } 4453 4454 } // namespace rx