1 #include "precompiled.h" 2 // 3 // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. 9 10 #include "libGLESv2/main.h" 11 #include "common/utilities.h" 12 #include "libGLESv2/Buffer.h" 13 #include "libGLESv2/ProgramBinary.h" 14 #include "libGLESv2/Framebuffer.h" 15 #include "libGLESv2/RenderBuffer.h" 16 #include "libGLESv2/renderer/d3d11/Renderer11.h" 17 #include "libGLESv2/renderer/d3d11/RenderTarget11.h" 18 #include "libGLESv2/renderer/d3d11/renderer11_utils.h" 19 #include "libGLESv2/renderer/d3d11/formatutils11.h" 20 #include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" 21 #include "libGLESv2/renderer/d3d11/SwapChain11.h" 22 #include "libGLESv2/renderer/d3d11/Image11.h" 23 #include "libGLESv2/renderer/d3d11/VertexBuffer11.h" 24 #include "libGLESv2/renderer/d3d11/IndexBuffer11.h" 25 #include "libGLESv2/renderer/d3d11/BufferStorage11.h" 26 #include "libGLESv2/renderer/VertexDataManager.h" 27 #include "libGLESv2/renderer/IndexDataManager.h" 28 #include "libGLESv2/renderer/d3d11/TextureStorage11.h" 29 #include "libGLESv2/renderer/d3d11/Query11.h" 30 #include "libGLESv2/renderer/d3d11/Fence11.h" 31 #include "libGLESv2/renderer/d3d11/Blit11.h" 32 #include "libGLESv2/renderer/d3d11/Clear11.h" 33 #include "libGLESv2/renderer/d3d11/PixelTransfer11.h" 34 #include "libEGL/Display.h" 35 36 // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process 37 // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. 38 #ifndef ANGLE_SKIP_DXGI_1_2_CHECK 39 #define ANGLE_SKIP_DXGI_1_2_CHECK 0 40 #endif 41 42 #ifdef _DEBUG 43 // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples 44 // and conformance tests. to enable all warnings, remove this define. 45 #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 46 #endif 47 48 namespace rx 49 { 50 static const DXGI_FORMAT RenderTargetFormats[] = 51 { 52 DXGI_FORMAT_B8G8R8A8_UNORM, 53 DXGI_FORMAT_R8G8B8A8_UNORM 54 }; 55 56 static const DXGI_FORMAT DepthStencilFormats[] = 57 { 58 DXGI_FORMAT_UNKNOWN, 59 DXGI_FORMAT_D24_UNORM_S8_UINT, 60 DXGI_FORMAT_D16_UNORM 61 }; 62 63 enum 64 { 65 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 66 }; 67 68 Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) 69 { 70 mVertexDataManager = NULL; 71 mIndexDataManager = NULL; 72 73 mLineLoopIB = NULL; 74 mTriangleFanIB = NULL; 75 76 mBlit = NULL; 77 mPixelTransfer = NULL; 78 79 mClear = NULL; 80 81 mSyncQuery = NULL; 82 83 mD3d11Module = NULL; 84 mDxgiModule = NULL; 85 86 mDeviceLost = false; 87 88 mMaxSupportedSamples = 0; 89 90 mDevice = NULL; 91 mDeviceContext = NULL; 92 mDxgiAdapter = NULL; 93 mDxgiFactory = NULL; 94 95 mDriverConstantBufferVS = NULL; 96 mDriverConstantBufferPS = NULL; 97 98 mBGRATextureSupport = false; 99 100 mAppliedVertexShader = NULL; 101 mAppliedGeometryShader = NULL; 102 mCurPointGeometryShader = NULL; 103 mAppliedPixelShader = NULL; 104 } 105 106 Renderer11::~Renderer11() 107 { 108 release(); 109 } 110 111 Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) 112 { 113 ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); 114 return static_cast<rx::Renderer11*>(renderer); 115 } 116 117 #ifndef __d3d11_1_h__ 118 #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) 119 #endif 120 121 EGLint Renderer11::initialize() 122 { 123 if (!mCompiler.initialize()) 124 { 125 return EGL_NOT_INITIALIZED; 126 } 127 128 mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); 129 mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); 130 131 if (mD3d11Module == NULL || mDxgiModule == NULL) 132 { 133 ERR("Could not load D3D11 or DXGI library - aborting!\n"); 134 return EGL_NOT_INITIALIZED; 135 } 136 137 // create the D3D11 device 138 ASSERT(mDevice == NULL); 139 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); 140 141 if (D3D11CreateDevice == NULL) 142 { 143 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); 144 return EGL_NOT_INITIALIZED; 145 } 146 147 D3D_FEATURE_LEVEL featureLevels[] = 148 { 149 D3D_FEATURE_LEVEL_11_0, 150 D3D_FEATURE_LEVEL_10_1, 151 D3D_FEATURE_LEVEL_10_0, 152 }; 153 154 HRESULT result = S_OK; 155 156 #ifdef _DEBUG 157 result = D3D11CreateDevice(NULL, 158 D3D_DRIVER_TYPE_HARDWARE, 159 NULL, 160 D3D11_CREATE_DEVICE_DEBUG, 161 featureLevels, 162 ArraySize(featureLevels), 163 D3D11_SDK_VERSION, 164 &mDevice, 165 &mFeatureLevel, 166 &mDeviceContext); 167 168 if (!mDevice || FAILED(result)) 169 { 170 ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); 171 } 172 173 if (!mDevice || FAILED(result)) 174 #endif 175 { 176 result = D3D11CreateDevice(NULL, 177 D3D_DRIVER_TYPE_HARDWARE, 178 NULL, 179 0, 180 featureLevels, 181 ArraySize(featureLevels), 182 D3D11_SDK_VERSION, 183 &mDevice, 184 &mFeatureLevel, 185 &mDeviceContext); 186 187 if (!mDevice || FAILED(result)) 188 { 189 ERR("Could not create D3D11 device - aborting!\n"); 190 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer 191 } 192 } 193 194 #if !ANGLE_SKIP_DXGI_1_2_CHECK 195 // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. 196 // The easiest way to check is to query for a IDXGIDevice2. 197 bool requireDXGI1_2 = false; 198 HWND hwnd = WindowFromDC(mDc); 199 if (hwnd) 200 { 201 DWORD currentProcessId = GetCurrentProcessId(); 202 DWORD wndProcessId; 203 GetWindowThreadProcessId(hwnd, &wndProcessId); 204 requireDXGI1_2 = (currentProcessId != wndProcessId); 205 } 206 else 207 { 208 requireDXGI1_2 = true; 209 } 210 211 if (requireDXGI1_2) 212 { 213 IDXGIDevice2 *dxgiDevice2 = NULL; 214 result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); 215 if (FAILED(result)) 216 { 217 ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n"); 218 return EGL_NOT_INITIALIZED; 219 } 220 SafeRelease(dxgiDevice2); 221 } 222 #endif 223 224 IDXGIDevice *dxgiDevice = NULL; 225 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); 226 227 if (FAILED(result)) 228 { 229 ERR("Could not query DXGI device - aborting!\n"); 230 return EGL_NOT_INITIALIZED; 231 } 232 233 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); 234 235 if (FAILED(result)) 236 { 237 ERR("Could not retrieve DXGI adapter - aborting!\n"); 238 return EGL_NOT_INITIALIZED; 239 } 240 241 SafeRelease(dxgiDevice); 242 243 mDxgiAdapter->GetDesc(&mAdapterDescription); 244 memset(mDescription, 0, sizeof(mDescription)); 245 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); 246 247 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); 248 249 if (!mDxgiFactory || FAILED(result)) 250 { 251 ERR("Could not create DXGI factory - aborting!\n"); 252 return EGL_NOT_INITIALIZED; 253 } 254 255 // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log 256 #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) 257 ID3D11InfoQueue *infoQueue; 258 result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); 259 260 if (SUCCEEDED(result)) 261 { 262 D3D11_MESSAGE_ID hideMessages[] = 263 { 264 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET 265 }; 266 267 D3D11_INFO_QUEUE_FILTER filter = {0}; 268 filter.DenyList.NumIDs = ArraySize(hideMessages); 269 filter.DenyList.pIDList = hideMessages; 270 271 infoQueue->AddStorageFilterEntries(&filter); 272 SafeRelease(infoQueue); 273 } 274 #endif 275 276 mMaxSupportedSamples = 0; 277 278 const d3d11::DXGIFormatSet &dxgiFormats = d3d11::GetAllUsedDXGIFormats(); 279 for (d3d11::DXGIFormatSet::const_iterator i = dxgiFormats.begin(); i != dxgiFormats.end(); ++i) 280 { 281 MultisampleSupportInfo support = getMultisampleSupportInfo(*i); 282 mMultisampleSupportMap.insert(std::make_pair(*i, support)); 283 mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); 284 } 285 286 initializeDevice(); 287 288 // BGRA texture support is optional in feature levels 10 and 10_1 289 UINT formatSupport; 290 result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); 291 if (FAILED(result)) 292 { 293 ERR("Error checking BGRA format support: 0x%08X", result); 294 } 295 else 296 { 297 const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); 298 mBGRATextureSupport = (formatSupport & flags) == flags; 299 } 300 301 // Check floating point texture support 302 static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; 303 static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; 304 static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; 305 306 DXGI_FORMAT float16Formats[] = 307 { 308 DXGI_FORMAT_R16_FLOAT, 309 DXGI_FORMAT_R16G16_FLOAT, 310 DXGI_FORMAT_R16G16B16A16_FLOAT, 311 }; 312 313 DXGI_FORMAT float32Formats[] = 314 { 315 DXGI_FORMAT_R32_FLOAT, 316 DXGI_FORMAT_R32G32_FLOAT, 317 DXGI_FORMAT_R32G32B32A32_FLOAT, 318 }; 319 320 mFloat16TextureSupport = true; 321 mFloat16FilterSupport = true; 322 mFloat16RenderSupport = true; 323 for (unsigned int i = 0; i < ArraySize(float16Formats); i++) 324 { 325 if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) 326 { 327 mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; 328 mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; 329 mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; 330 } 331 else 332 { 333 mFloat16TextureSupport = false; 334 mFloat16RenderSupport = false; 335 mFloat16FilterSupport = false; 336 } 337 } 338 339 mFloat32TextureSupport = true; 340 mFloat32FilterSupport = true; 341 mFloat32RenderSupport = true; 342 for (unsigned int i = 0; i < ArraySize(float32Formats); i++) 343 { 344 if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) 345 { 346 mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; 347 mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; 348 mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; 349 } 350 else 351 { 352 mFloat32TextureSupport = false; 353 mFloat32FilterSupport = false; 354 mFloat32RenderSupport = false; 355 } 356 } 357 358 DXGI_FORMAT rgTextureFormats[] = 359 { 360 DXGI_FORMAT_R8_UNORM, 361 DXGI_FORMAT_R8G8_UNORM, 362 DXGI_FORMAT_R16_FLOAT, 363 DXGI_FORMAT_R16G16_FLOAT, 364 DXGI_FORMAT_R32_FLOAT, 365 DXGI_FORMAT_R32G32_FLOAT, 366 }; 367 368 mRGTextureSupport = true; 369 for (unsigned int i = 0; i < ArraySize(rgTextureFormats); i++) 370 { 371 if (SUCCEEDED(mDevice->CheckFormatSupport(rgTextureFormats[i], &formatSupport))) 372 { 373 mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; 374 mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; 375 mRGTextureSupport = mRGTextureSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; 376 } 377 else 378 { 379 mRGTextureSupport = false; 380 } 381 } 382 383 // Check compressed texture support 384 const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; 385 386 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) 387 { 388 mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 389 } 390 else 391 { 392 mDXT1TextureSupport = false; 393 } 394 395 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) 396 { 397 mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 398 } 399 else 400 { 401 mDXT3TextureSupport = false; 402 } 403 404 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) 405 { 406 mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 407 } 408 else 409 { 410 mDXT5TextureSupport = false; 411 } 412 413 // Check depth texture support 414 DXGI_FORMAT depthTextureFormats[] = 415 { 416 DXGI_FORMAT_D16_UNORM, 417 DXGI_FORMAT_D24_UNORM_S8_UINT, 418 }; 419 420 static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | 421 D3D11_FORMAT_SUPPORT_TEXTURE2D; 422 423 mDepthTextureSupport = true; 424 for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) 425 { 426 if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) 427 { 428 mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); 429 } 430 else 431 { 432 mDepthTextureSupport = false; 433 } 434 } 435 436 return EGL_SUCCESS; 437 } 438 439 // do any one-time device initialization 440 // NOTE: this is also needed after a device lost/reset 441 // to reset the scene status and ensure the default states are reset. 442 void Renderer11::initializeDevice() 443 { 444 mStateCache.initialize(mDevice); 445 mInputLayoutCache.initialize(mDevice, mDeviceContext); 446 447 ASSERT(!mVertexDataManager && !mIndexDataManager); 448 mVertexDataManager = new VertexDataManager(this); 449 mIndexDataManager = new IndexDataManager(this); 450 451 ASSERT(!mBlit); 452 mBlit = new Blit11(this); 453 454 ASSERT(!mClear); 455 mClear = new Clear11(this); 456 457 ASSERT(!mPixelTransfer); 458 mPixelTransfer = new PixelTransfer11(this); 459 460 markAllStateDirty(); 461 } 462 463 int Renderer11::generateConfigs(ConfigDesc **configDescList) 464 { 465 unsigned int numRenderFormats = ArraySize(RenderTargetFormats); 466 unsigned int numDepthFormats = ArraySize(DepthStencilFormats); 467 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; 468 int numConfigs = 0; 469 470 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) 471 { 472 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) 473 { 474 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; 475 476 UINT formatSupport = 0; 477 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); 478 479 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) 480 { 481 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; 482 483 bool depthStencilFormatOK = true; 484 485 if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) 486 { 487 UINT depthStencilSupport = 0; 488 result = mDevice->CheckFormatSupport(depthStencilFormat, &depthStencilSupport); 489 depthStencilFormatOK = SUCCEEDED(result) && (depthStencilSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); 490 } 491 492 if (depthStencilFormatOK) 493 { 494 // FIXME: parse types from context version 495 ASSERT(d3d11_gl::GetInternalFormat(renderTargetFormat, 2) == d3d11_gl::GetInternalFormat(renderTargetFormat, 3)); 496 ASSERT(d3d11_gl::GetInternalFormat(depthStencilFormat, 2) == d3d11_gl::GetInternalFormat(depthStencilFormat, 3)); 497 498 ConfigDesc newConfig; 499 newConfig.renderTargetFormat = d3d11_gl::GetInternalFormat(renderTargetFormat, getCurrentClientVersion()); 500 newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat, getCurrentClientVersion()); 501 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling 502 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast 503 newConfig.es3Capable = true; 504 505 (*configDescList)[numConfigs++] = newConfig; 506 } 507 } 508 } 509 } 510 511 return numConfigs; 512 } 513 514 void Renderer11::deleteConfigs(ConfigDesc *configDescList) 515 { 516 delete [] (configDescList); 517 } 518 519 void Renderer11::sync(bool block) 520 { 521 if (block) 522 { 523 HRESULT result; 524 525 if (!mSyncQuery) 526 { 527 D3D11_QUERY_DESC queryDesc; 528 queryDesc.Query = D3D11_QUERY_EVENT; 529 queryDesc.MiscFlags = 0; 530 531 result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); 532 ASSERT(SUCCEEDED(result)); 533 } 534 535 mDeviceContext->End(mSyncQuery); 536 mDeviceContext->Flush(); 537 538 do 539 { 540 result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); 541 542 // Keep polling, but allow other threads to do something useful first 543 Sleep(0); 544 545 if (testDeviceLost(true)) 546 { 547 return; 548 } 549 } 550 while (result == S_FALSE); 551 } 552 else 553 { 554 mDeviceContext->Flush(); 555 } 556 } 557 558 SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) 559 { 560 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); 561 } 562 563 void Renderer11::generateSwizzle(gl::Texture *texture) 564 { 565 if (texture) 566 { 567 TextureStorageInterface *texStorage = texture->getNativeTexture(); 568 if (texStorage) 569 { 570 TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); 571 572 storage11->generateSwizzles(texture->getSwizzleRed(), texture->getSwizzleGreen(), texture->getSwizzleBlue(), 573 texture->getSwizzleAlpha()); 574 } 575 } 576 } 577 578 void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) 579 { 580 if (type == gl::SAMPLER_PIXEL) 581 { 582 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) 583 { 584 ERR("Pixel shader sampler index %i is not valid.", index); 585 return; 586 } 587 588 if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) 589 { 590 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); 591 592 if (!dxSamplerState) 593 { 594 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" 595 "sampler state for pixel shaders at slot %i.", index); 596 } 597 598 mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); 599 600 mCurPixelSamplerStates[index] = samplerState; 601 } 602 603 mForceSetPixelSamplerStates[index] = false; 604 } 605 else if (type == gl::SAMPLER_VERTEX) 606 { 607 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) 608 { 609 ERR("Vertex shader sampler index %i is not valid.", index); 610 return; 611 } 612 613 if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) 614 { 615 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); 616 617 if (!dxSamplerState) 618 { 619 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" 620 "sampler state for vertex shaders at slot %i.", index); 621 } 622 623 mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); 624 625 mCurVertexSamplerStates[index] = samplerState; 626 } 627 628 mForceSetVertexSamplerStates[index] = false; 629 } 630 else UNREACHABLE(); 631 } 632 633 void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) 634 { 635 ID3D11ShaderResourceView *textureSRV = NULL; 636 bool forceSetTexture = false; 637 638 if (texture) 639 { 640 TextureStorageInterface *texStorage = texture->getNativeTexture(); 641 if (texStorage) 642 { 643 TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); 644 gl::SamplerState samplerState; 645 texture->getSamplerState(&samplerState); 646 textureSRV = storage11->getSRV(samplerState); 647 } 648 649 // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly 650 // missing the shader resource view 651 ASSERT(textureSRV != NULL); 652 653 forceSetTexture = texture->hasDirtyImages(); 654 } 655 656 if (type == gl::SAMPLER_PIXEL) 657 { 658 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) 659 { 660 ERR("Pixel shader sampler index %i is not valid.", index); 661 return; 662 } 663 664 if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) 665 { 666 mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); 667 } 668 669 mCurPixelSRVs[index] = textureSRV; 670 } 671 else if (type == gl::SAMPLER_VERTEX) 672 { 673 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) 674 { 675 ERR("Vertex shader sampler index %i is not valid.", index); 676 return; 677 } 678 679 if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) 680 { 681 mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); 682 } 683 684 mCurVertexSRVs[index] = textureSRV; 685 } 686 else UNREACHABLE(); 687 } 688 689 bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) 690 { 691 for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) 692 { 693 const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; 694 if (uniformBuffer) 695 { 696 BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage()); 697 ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); 698 699 if (!constantBuffer) 700 { 701 return false; 702 } 703 704 if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) 705 { 706 mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, 707 1, &constantBuffer); 708 mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); 709 } 710 } 711 } 712 713 for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) 714 { 715 const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; 716 if (uniformBuffer) 717 { 718 BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage()); 719 ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); 720 721 if (!constantBuffer) 722 { 723 return false; 724 } 725 726 if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) 727 { 728 mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, 729 1, &constantBuffer); 730 mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); 731 } 732 } 733 } 734 735 return true; 736 } 737 738 void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) 739 { 740 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) 741 { 742 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled); 743 if (!dxRasterState) 744 { 745 ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" 746 "rasterizer state."); 747 } 748 749 mDeviceContext->RSSetState(dxRasterState); 750 751 mCurRasterState = rasterState; 752 } 753 754 mForceSetRasterState = false; 755 } 756 757 void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, 758 unsigned int sampleMask) 759 { 760 if (mForceSetBlendState || 761 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || 762 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || 763 sampleMask != mCurSampleMask) 764 { 765 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState); 766 if (!dxBlendState) 767 { 768 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " 769 "blend state."); 770 } 771 772 float blendColors[4] = {0.0f}; 773 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 774 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 775 { 776 blendColors[0] = blendColor.red; 777 blendColors[1] = blendColor.green; 778 blendColors[2] = blendColor.blue; 779 blendColors[3] = blendColor.alpha; 780 } 781 else 782 { 783 blendColors[0] = blendColor.alpha; 784 blendColors[1] = blendColor.alpha; 785 blendColors[2] = blendColor.alpha; 786 blendColors[3] = blendColor.alpha; 787 } 788 789 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); 790 791 mCurBlendState = blendState; 792 mCurBlendColor = blendColor; 793 mCurSampleMask = sampleMask; 794 } 795 796 mForceSetBlendState = false; 797 } 798 799 void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, 800 int stencilBackRef, bool frontFaceCCW) 801 { 802 if (mForceSetDepthStencilState || 803 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || 804 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) 805 { 806 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || 807 stencilRef != stencilBackRef || 808 depthStencilState.stencilMask != depthStencilState.stencilBackMask) 809 { 810 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " 811 "invalid under WebGL."); 812 return gl::error(GL_INVALID_OPERATION); 813 } 814 815 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); 816 if (!dxDepthStencilState) 817 { 818 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " 819 "setting the default depth stencil state."); 820 } 821 822 // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer 823 // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops 824 META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF); 825 META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF); 826 UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); 827 828 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); 829 830 mCurDepthStencilState = depthStencilState; 831 mCurStencilRef = stencilRef; 832 mCurStencilBackRef = stencilBackRef; 833 } 834 835 mForceSetDepthStencilState = false; 836 } 837 838 void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) 839 { 840 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || 841 enabled != mScissorEnabled) 842 { 843 if (enabled) 844 { 845 D3D11_RECT rect; 846 rect.left = std::max(0, scissor.x); 847 rect.top = std::max(0, scissor.y); 848 rect.right = scissor.x + std::max(0, scissor.width); 849 rect.bottom = scissor.y + std::max(0, scissor.height); 850 851 mDeviceContext->RSSetScissorRects(1, &rect); 852 } 853 854 if (enabled != mScissorEnabled) 855 { 856 mForceSetRasterState = true; 857 } 858 859 mCurScissor = scissor; 860 mScissorEnabled = enabled; 861 } 862 863 mForceSetScissor = false; 864 } 865 866 bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, 867 bool ignoreViewport) 868 { 869 gl::Rectangle actualViewport = viewport; 870 float actualZNear = gl::clamp01(zNear); 871 float actualZFar = gl::clamp01(zFar); 872 if (ignoreViewport) 873 { 874 actualViewport.x = 0; 875 actualViewport.y = 0; 876 actualViewport.width = mRenderTargetDesc.width; 877 actualViewport.height = mRenderTargetDesc.height; 878 actualZNear = 0.0f; 879 actualZFar = 1.0f; 880 } 881 882 // Get D3D viewport bounds, which depends on the feature level 883 const Range& viewportBounds = getViewportBounds(); 884 885 // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds 886 D3D11_VIEWPORT dxViewport; 887 dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); 888 dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); 889 dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); 890 dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); 891 dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX)); 892 dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY)); 893 dxViewport.MinDepth = actualZNear; 894 dxViewport.MaxDepth = actualZFar; 895 896 if (dxViewport.Width <= 0 || dxViewport.Height <= 0) 897 { 898 return false; // Nothing to render 899 } 900 901 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || 902 actualZNear != mCurNear || actualZFar != mCurFar; 903 904 if (viewportChanged) 905 { 906 mDeviceContext->RSSetViewports(1, &dxViewport); 907 908 mCurViewport = actualViewport; 909 mCurNear = actualZNear; 910 mCurFar = actualZFar; 911 912 mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; 913 mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; 914 mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); 915 mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); 916 917 mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; 918 mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; 919 920 mVertexConstants.depthRange[0] = actualZNear; 921 mVertexConstants.depthRange[1] = actualZFar; 922 mVertexConstants.depthRange[2] = actualZFar - actualZNear; 923 924 mPixelConstants.depthRange[0] = actualZNear; 925 mPixelConstants.depthRange[1] = actualZFar; 926 mPixelConstants.depthRange[2] = actualZFar - actualZNear; 927 } 928 929 mForceSetViewport = false; 930 return true; 931 } 932 933 bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) 934 { 935 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; 936 937 GLsizei minCount = 0; 938 939 switch (mode) 940 { 941 case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; 942 case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; 943 case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; 944 case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; 945 case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; 946 case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; 947 // emulate fans via rewriting index buffer 948 case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; 949 default: 950 return gl::error(GL_INVALID_ENUM, false); 951 } 952 953 if (primitiveTopology != mCurrentPrimitiveTopology) 954 { 955 mDeviceContext->IASetPrimitiveTopology(primitiveTopology); 956 mCurrentPrimitiveTopology = primitiveTopology; 957 } 958 959 return count >= minCount; 960 } 961 962 bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) 963 { 964 // Get the color render buffer and serial 965 // Also extract the render target dimensions and view 966 unsigned int renderTargetWidth = 0; 967 unsigned int renderTargetHeight = 0; 968 GLenum renderTargetFormat = 0; 969 unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; 970 ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; 971 bool missingColorRenderTarget = true; 972 973 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 974 { 975 const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); 976 977 if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) 978 { 979 // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) 980 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); 981 982 gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(colorAttachment); 983 984 if (!colorbuffer) 985 { 986 ERR("render target pointer unexpectedly null."); 987 return false; 988 } 989 990 // check for zero-sized default framebuffer, which is a special case. 991 // in this case we do not wish to modify any state and just silently return false. 992 // this will not report any gl error but will cause the calling method to return. 993 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) 994 { 995 return false; 996 } 997 998 renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); 999 1000 // Extract the render target dimensions and view 1001 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 1002 if (!renderTarget) 1003 { 1004 ERR("render target pointer unexpectedly null."); 1005 return false; 1006 } 1007 1008 framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); 1009 if (!framebufferRTVs[colorAttachment]) 1010 { 1011 ERR("render target view pointer unexpectedly null."); 1012 return false; 1013 } 1014 1015 if (missingColorRenderTarget) 1016 { 1017 renderTargetWidth = colorbuffer->getWidth(); 1018 renderTargetHeight = colorbuffer->getHeight(); 1019 renderTargetFormat = colorbuffer->getActualFormat(); 1020 missingColorRenderTarget = false; 1021 } 1022 1023 // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent 1024 // D3D11 warnings. 1025 } 1026 } 1027 1028 // Get the depth stencil render buffer and serials 1029 gl::FramebufferAttachment *depthStencil = NULL; 1030 unsigned int depthbufferSerial = 0; 1031 unsigned int stencilbufferSerial = 0; 1032 if (framebuffer->getDepthbufferType() != GL_NONE) 1033 { 1034 depthStencil = framebuffer->getDepthbuffer(); 1035 if (!depthStencil) 1036 { 1037 ERR("Depth stencil pointer unexpectedly null."); 1038 SafeRelease(framebufferRTVs); 1039 return false; 1040 } 1041 1042 depthbufferSerial = depthStencil->getSerial(); 1043 } 1044 else if (framebuffer->getStencilbufferType() != GL_NONE) 1045 { 1046 depthStencil = framebuffer->getStencilbuffer(); 1047 if (!depthStencil) 1048 { 1049 ERR("Depth stencil pointer unexpectedly null."); 1050 SafeRelease(framebufferRTVs); 1051 return false; 1052 } 1053 1054 stencilbufferSerial = depthStencil->getSerial(); 1055 } 1056 1057 ID3D11DepthStencilView* framebufferDSV = NULL; 1058 if (depthStencil) 1059 { 1060 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); 1061 if (!depthStencilRenderTarget) 1062 { 1063 ERR("render target pointer unexpectedly null."); 1064 SafeRelease(framebufferRTVs); 1065 return false; 1066 } 1067 1068 framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); 1069 if (!framebufferDSV) 1070 { 1071 ERR("depth stencil view pointer unexpectedly null."); 1072 SafeRelease(framebufferRTVs); 1073 return false; 1074 } 1075 1076 // If there is no render buffer, the width, height and format values come from 1077 // the depth stencil 1078 if (missingColorRenderTarget) 1079 { 1080 renderTargetWidth = depthStencil->getWidth(); 1081 renderTargetHeight = depthStencil->getHeight(); 1082 renderTargetFormat = depthStencil->getActualFormat(); 1083 } 1084 } 1085 1086 // Apply the render target and depth stencil 1087 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || 1088 memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || 1089 depthbufferSerial != mAppliedDepthbufferSerial || 1090 stencilbufferSerial != mAppliedStencilbufferSerial) 1091 { 1092 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); 1093 1094 mRenderTargetDesc.width = renderTargetWidth; 1095 mRenderTargetDesc.height = renderTargetHeight; 1096 mRenderTargetDesc.format = renderTargetFormat; 1097 mForceSetViewport = true; 1098 mForceSetScissor = true; 1099 mForceSetBlendState = true; 1100 1101 if (!mDepthStencilInitialized) 1102 { 1103 mForceSetRasterState = true; 1104 } 1105 1106 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 1107 { 1108 mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; 1109 } 1110 mAppliedDepthbufferSerial = depthbufferSerial; 1111 mAppliedStencilbufferSerial = stencilbufferSerial; 1112 mRenderTargetDescInitialized = true; 1113 mDepthStencilInitialized = true; 1114 } 1115 1116 invalidateFramebufferSwizzles(framebuffer); 1117 1118 return true; 1119 } 1120 1121 GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[], 1122 GLint first, GLsizei count, GLsizei instances) 1123 { 1124 TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; 1125 GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); 1126 if (err != GL_NO_ERROR) 1127 { 1128 return err; 1129 } 1130 1131 return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); 1132 } 1133 1134 GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) 1135 { 1136 GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); 1137 1138 if (err == GL_NO_ERROR) 1139 { 1140 ID3D11Buffer *buffer = NULL; 1141 DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; 1142 1143 if (indexInfo->storage) 1144 { 1145 BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); 1146 buffer = storage->getBuffer(BUFFER_USAGE_INDEX); 1147 } 1148 else 1149 { 1150 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); 1151 buffer = indexBuffer->getBuffer(); 1152 } 1153 1154 if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) 1155 { 1156 mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); 1157 1158 mAppliedIB = buffer; 1159 mAppliedIBFormat = bufferFormat; 1160 mAppliedIBOffset = indexInfo->startOffset; 1161 } 1162 } 1163 1164 return err; 1165 } 1166 1167 void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) 1168 { 1169 ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; 1170 UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; 1171 bool requiresUpdate = false; 1172 for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) 1173 { 1174 if (transformFeedbackBuffers[i]) 1175 { 1176 BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(transformFeedbackBuffers[i]->getStorage()); 1177 ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); 1178 1179 d3dBuffers[i] = buffer; 1180 d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast<UINT>(offsets[i]) : -1; 1181 } 1182 else 1183 { 1184 d3dBuffers[i] = NULL; 1185 d3dOffsets[i] = 0; 1186 } 1187 1188 if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i]) 1189 { 1190 requiresUpdate = true; 1191 } 1192 } 1193 1194 if (requiresUpdate) 1195 { 1196 mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets); 1197 for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) 1198 { 1199 mAppliedTFBuffers[i] = d3dBuffers[i]; 1200 mAppliedTFOffsets[i] = offsets[i]; 1201 } 1202 } 1203 } 1204 1205 void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) 1206 { 1207 if (mode == GL_POINTS && transformFeedbackActive) 1208 { 1209 // Since point sprites are generated with a geometry shader, too many vertices will 1210 // be written if transform feedback is active. To work around this, draw only the points 1211 // with the stream out shader and no pixel shader to feed the stream out buffers and then 1212 // draw again with the point sprite geometry shader to rasterize the point sprites. 1213 1214 mDeviceContext->PSSetShader(NULL, NULL, 0); 1215 1216 if (instances > 0) 1217 { 1218 mDeviceContext->DrawInstanced(count, instances, 0, 0); 1219 } 1220 else 1221 { 1222 mDeviceContext->Draw(count, 0); 1223 } 1224 1225 mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0); 1226 mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0); 1227 1228 if (instances > 0) 1229 { 1230 mDeviceContext->DrawInstanced(count, instances, 0, 0); 1231 } 1232 else 1233 { 1234 mDeviceContext->Draw(count, 0); 1235 } 1236 1237 mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); 1238 } 1239 else if (mode == GL_LINE_LOOP) 1240 { 1241 drawLineLoop(count, GL_NONE, NULL, 0, NULL); 1242 } 1243 else if (mode == GL_TRIANGLE_FAN) 1244 { 1245 drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); 1246 } 1247 else if (instances > 0) 1248 { 1249 mDeviceContext->DrawInstanced(count, instances, 0, 0); 1250 } 1251 else 1252 { 1253 mDeviceContext->Draw(count, 0); 1254 } 1255 } 1256 1257 void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, 1258 gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) 1259 { 1260 if (mode == GL_LINE_LOOP) 1261 { 1262 drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); 1263 } 1264 else if (mode == GL_TRIANGLE_FAN) 1265 { 1266 drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); 1267 } 1268 else if (instances > 0) 1269 { 1270 mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0); 1271 } 1272 else 1273 { 1274 mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex)); 1275 } 1276 } 1277 1278 void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) 1279 { 1280 // Get the raw indices for an indexed draw 1281 if (type != GL_NONE && elementArrayBuffer) 1282 { 1283 gl::Buffer *indexBuffer = elementArrayBuffer; 1284 BufferStorage *storage = indexBuffer->getStorage(); 1285 intptr_t offset = reinterpret_cast<intptr_t>(indices); 1286 indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1287 } 1288 1289 if (!mLineLoopIB) 1290 { 1291 mLineLoopIB = new StreamingIndexBufferInterface(this); 1292 if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) 1293 { 1294 delete mLineLoopIB; 1295 mLineLoopIB = NULL; 1296 1297 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); 1298 return gl::error(GL_OUT_OF_MEMORY); 1299 } 1300 } 1301 1302 // Checked by Renderer11::applyPrimitiveType 1303 ASSERT(count >= 0); 1304 1305 if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) 1306 { 1307 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1308 return gl::error(GL_OUT_OF_MEMORY); 1309 } 1310 1311 const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); 1312 if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) 1313 { 1314 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1315 return gl::error(GL_OUT_OF_MEMORY); 1316 } 1317 1318 void* mappedMemory = NULL; 1319 unsigned int offset; 1320 if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1321 { 1322 ERR("Could not map index buffer for GL_LINE_LOOP."); 1323 return gl::error(GL_OUT_OF_MEMORY); 1324 } 1325 1326 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1327 unsigned int indexBufferOffset = offset; 1328 1329 switch (type) 1330 { 1331 case GL_NONE: // Non-indexed draw 1332 for (int i = 0; i < count; i++) 1333 { 1334 data[i] = i; 1335 } 1336 data[count] = 0; 1337 break; 1338 case GL_UNSIGNED_BYTE: 1339 for (int i = 0; i < count; i++) 1340 { 1341 data[i] = static_cast<const GLubyte*>(indices)[i]; 1342 } 1343 data[count] = static_cast<const GLubyte*>(indices)[0]; 1344 break; 1345 case GL_UNSIGNED_SHORT: 1346 for (int i = 0; i < count; i++) 1347 { 1348 data[i] = static_cast<const GLushort*>(indices)[i]; 1349 } 1350 data[count] = static_cast<const GLushort*>(indices)[0]; 1351 break; 1352 case GL_UNSIGNED_INT: 1353 for (int i = 0; i < count; i++) 1354 { 1355 data[i] = static_cast<const GLuint*>(indices)[i]; 1356 } 1357 data[count] = static_cast<const GLuint*>(indices)[0]; 1358 break; 1359 default: UNREACHABLE(); 1360 } 1361 1362 if (!mLineLoopIB->unmapBuffer()) 1363 { 1364 ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1365 return gl::error(GL_OUT_OF_MEMORY); 1366 } 1367 1368 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); 1369 ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); 1370 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); 1371 1372 if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) 1373 { 1374 mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); 1375 mAppliedIB = d3dIndexBuffer; 1376 mAppliedIBFormat = indexFormat; 1377 mAppliedIBOffset = indexBufferOffset; 1378 } 1379 1380 mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); 1381 } 1382 1383 void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) 1384 { 1385 // Get the raw indices for an indexed draw 1386 if (type != GL_NONE && elementArrayBuffer) 1387 { 1388 gl::Buffer *indexBuffer = elementArrayBuffer; 1389 BufferStorage *storage = indexBuffer->getStorage(); 1390 intptr_t offset = reinterpret_cast<intptr_t>(indices); 1391 indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1392 } 1393 1394 if (!mTriangleFanIB) 1395 { 1396 mTriangleFanIB = new StreamingIndexBufferInterface(this); 1397 if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) 1398 { 1399 delete mTriangleFanIB; 1400 mTriangleFanIB = NULL; 1401 1402 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); 1403 return gl::error(GL_OUT_OF_MEMORY); 1404 } 1405 } 1406 1407 // Checked by Renderer11::applyPrimitiveType 1408 ASSERT(count >= 3); 1409 1410 const unsigned int numTris = count - 2; 1411 1412 if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) 1413 { 1414 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); 1415 return gl::error(GL_OUT_OF_MEMORY); 1416 } 1417 1418 const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); 1419 if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) 1420 { 1421 ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); 1422 return gl::error(GL_OUT_OF_MEMORY); 1423 } 1424 1425 void* mappedMemory = NULL; 1426 unsigned int offset; 1427 if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1428 { 1429 ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); 1430 return gl::error(GL_OUT_OF_MEMORY); 1431 } 1432 1433 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1434 unsigned int indexBufferOffset = offset; 1435 1436 switch (type) 1437 { 1438 case GL_NONE: // Non-indexed draw 1439 for (unsigned int i = 0; i < numTris; i++) 1440 { 1441 data[i*3 + 0] = 0; 1442 data[i*3 + 1] = i + 1; 1443 data[i*3 + 2] = i + 2; 1444 } 1445 break; 1446 case GL_UNSIGNED_BYTE: 1447 for (unsigned int i = 0; i < numTris; i++) 1448 { 1449 data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0]; 1450 data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1]; 1451 data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2]; 1452 } 1453 break; 1454 case GL_UNSIGNED_SHORT: 1455 for (unsigned int i = 0; i < numTris; i++) 1456 { 1457 data[i*3 + 0] = static_cast<const GLushort*>(indices)[0]; 1458 data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1]; 1459 data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2]; 1460 } 1461 break; 1462 case GL_UNSIGNED_INT: 1463 for (unsigned int i = 0; i < numTris; i++) 1464 { 1465 data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; 1466 data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; 1467 data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2]; 1468 } 1469 break; 1470 default: UNREACHABLE(); 1471 } 1472 1473 if (!mTriangleFanIB->unmapBuffer()) 1474 { 1475 ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); 1476 return gl::error(GL_OUT_OF_MEMORY); 1477 } 1478 1479 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); 1480 ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); 1481 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); 1482 1483 if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) 1484 { 1485 mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); 1486 mAppliedIB = d3dIndexBuffer; 1487 mAppliedIBFormat = indexFormat; 1488 mAppliedIBOffset = indexBufferOffset; 1489 } 1490 1491 if (instances > 0) 1492 { 1493 mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); 1494 } 1495 else 1496 { 1497 mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); 1498 } 1499 } 1500 1501 void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]) 1502 { 1503 ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); 1504 ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); 1505 ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); 1506 1507 ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); 1508 1509 ID3D11PixelShader *pixelShader = NULL; 1510 // Skip pixel shader if we're doing rasterizer discard. 1511 if (!rasterizerDiscard) 1512 { 1513 pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); 1514 } 1515 1516 ID3D11GeometryShader *geometryShader = NULL; 1517 if (transformFeedbackActive) 1518 { 1519 geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); 1520 } 1521 else if (mCurRasterState.pointDrawMode) 1522 { 1523 geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); 1524 } 1525 1526 bool dirtyUniforms = false; 1527 1528 if (vertexShader != mAppliedVertexShader) 1529 { 1530 mDeviceContext->VSSetShader(vertexShader, NULL, 0); 1531 mAppliedVertexShader = vertexShader; 1532 dirtyUniforms = true; 1533 } 1534 1535 if (geometryShader != mAppliedGeometryShader) 1536 { 1537 mDeviceContext->GSSetShader(geometryShader, NULL, 0); 1538 mAppliedGeometryShader = geometryShader; 1539 dirtyUniforms = true; 1540 } 1541 1542 if (geometryExe && mCurRasterState.pointDrawMode) 1543 { 1544 mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); 1545 } 1546 else 1547 { 1548 mCurPointGeometryShader = NULL; 1549 } 1550 1551 if (pixelShader != mAppliedPixelShader) 1552 { 1553 mDeviceContext->PSSetShader(pixelShader, NULL, 0); 1554 mAppliedPixelShader = pixelShader; 1555 dirtyUniforms = true; 1556 } 1557 1558 if (dirtyUniforms) 1559 { 1560 programBinary->dirtyAllUniforms(); 1561 } 1562 } 1563 1564 void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) 1565 { 1566 const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms(); 1567 1568 unsigned int totalRegisterCountVS = 0; 1569 unsigned int totalRegisterCountPS = 0; 1570 1571 bool vertexUniformsDirty = false; 1572 bool pixelUniformsDirty = false; 1573 1574 for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) 1575 { 1576 const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; 1577 1578 if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) 1579 { 1580 totalRegisterCountVS += uniform.registerCount; 1581 vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); 1582 } 1583 1584 if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) 1585 { 1586 totalRegisterCountPS += uniform.registerCount; 1587 pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); 1588 } 1589 } 1590 1591 const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getVertexUniformStorage()); 1592 const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getFragmentUniformStorage()); 1593 ASSERT(vertexUniformStorage); 1594 ASSERT(fragmentUniformStorage); 1595 1596 ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); 1597 ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); 1598 1599 float (*mapVS)[4] = NULL; 1600 float (*mapPS)[4] = NULL; 1601 1602 if (totalRegisterCountVS > 0 && vertexUniformsDirty) 1603 { 1604 D3D11_MAPPED_SUBRESOURCE map = {0}; 1605 HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); 1606 UNUSED_ASSERTION_VARIABLE(result); 1607 ASSERT(SUCCEEDED(result)); 1608 mapVS = (float(*)[4])map.pData; 1609 } 1610 1611 if (totalRegisterCountPS > 0 && pixelUniformsDirty) 1612 { 1613 D3D11_MAPPED_SUBRESOURCE map = {0}; 1614 HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); 1615 UNUSED_ASSERTION_VARIABLE(result); 1616 ASSERT(SUCCEEDED(result)); 1617 mapPS = (float(*)[4])map.pData; 1618 } 1619 1620 for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) 1621 { 1622 gl::LinkedUniform *uniform = uniformArray[uniformIndex]; 1623 1624 if (!uniform->isSampler()) 1625 { 1626 unsigned int componentCount = (4 - uniform->registerElement); 1627 1628 // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would 1629 // overwrite previously written regions of memory. 1630 1631 if (uniform->isReferencedByVertexShader() && mapVS) 1632 { 1633 memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); 1634 } 1635 1636 if (uniform->isReferencedByFragmentShader() && mapPS) 1637 { 1638 memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); 1639 } 1640 } 1641 } 1642 1643 if (mapVS) 1644 { 1645 mDeviceContext->Unmap(vertexConstantBuffer, 0); 1646 } 1647 1648 if (mapPS) 1649 { 1650 mDeviceContext->Unmap(pixelConstantBuffer, 0); 1651 } 1652 1653 if (mCurrentVertexConstantBuffer != vertexConstantBuffer) 1654 { 1655 mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); 1656 mCurrentVertexConstantBuffer = vertexConstantBuffer; 1657 } 1658 1659 if (mCurrentPixelConstantBuffer != pixelConstantBuffer) 1660 { 1661 mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); 1662 mCurrentPixelConstantBuffer = pixelConstantBuffer; 1663 } 1664 1665 // Driver uniforms 1666 if (!mDriverConstantBufferVS) 1667 { 1668 D3D11_BUFFER_DESC constantBufferDescription = {0}; 1669 constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); 1670 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; 1671 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 1672 constantBufferDescription.CPUAccessFlags = 0; 1673 constantBufferDescription.MiscFlags = 0; 1674 constantBufferDescription.StructureByteStride = 0; 1675 1676 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); 1677 UNUSED_ASSERTION_VARIABLE(result); 1678 ASSERT(SUCCEEDED(result)); 1679 1680 mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); 1681 } 1682 1683 if (!mDriverConstantBufferPS) 1684 { 1685 D3D11_BUFFER_DESC constantBufferDescription = {0}; 1686 constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); 1687 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; 1688 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 1689 constantBufferDescription.CPUAccessFlags = 0; 1690 constantBufferDescription.MiscFlags = 0; 1691 constantBufferDescription.StructureByteStride = 0; 1692 1693 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); 1694 UNUSED_ASSERTION_VARIABLE(result); 1695 ASSERT(SUCCEEDED(result)); 1696 1697 mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); 1698 } 1699 1700 if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) 1701 { 1702 mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); 1703 memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); 1704 } 1705 1706 if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) 1707 { 1708 mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); 1709 memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); 1710 } 1711 1712 // needed for the point sprite geometry shader 1713 if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) 1714 { 1715 mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); 1716 mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; 1717 } 1718 } 1719 1720 void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) 1721 { 1722 mClear->clearFramebuffer(clearParams, frameBuffer); 1723 invalidateFramebufferSwizzles(frameBuffer); 1724 } 1725 1726 void Renderer11::markAllStateDirty() 1727 { 1728 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 1729 { 1730 mAppliedRenderTargetSerials[rtIndex] = 0; 1731 } 1732 mAppliedDepthbufferSerial = 0; 1733 mAppliedStencilbufferSerial = 0; 1734 mDepthStencilInitialized = false; 1735 mRenderTargetDescInitialized = false; 1736 1737 for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) 1738 { 1739 mForceSetVertexSamplerStates[i] = true; 1740 mCurVertexSRVs[i] = NULL; 1741 } 1742 for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) 1743 { 1744 mForceSetPixelSamplerStates[i] = true; 1745 mCurPixelSRVs[i] = NULL; 1746 } 1747 1748 mForceSetBlendState = true; 1749 mForceSetRasterState = true; 1750 mForceSetDepthStencilState = true; 1751 mForceSetScissor = true; 1752 mForceSetViewport = true; 1753 1754 mAppliedIB = NULL; 1755 mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; 1756 mAppliedIBOffset = 0; 1757 1758 mAppliedVertexShader = NULL; 1759 mAppliedGeometryShader = NULL; 1760 mCurPointGeometryShader = NULL; 1761 mAppliedPixelShader = NULL; 1762 1763 for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) 1764 { 1765 mAppliedTFBuffers[i] = NULL; 1766 mAppliedTFOffsets[i] = 0; 1767 } 1768 1769 memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); 1770 memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); 1771 1772 mInputLayoutCache.markDirty(); 1773 1774 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) 1775 { 1776 mCurrentConstantBufferVS[i] = -1; 1777 mCurrentConstantBufferPS[i] = -1; 1778 } 1779 1780 mCurrentVertexConstantBuffer = NULL; 1781 mCurrentPixelConstantBuffer = NULL; 1782 mCurrentGeometryConstantBuffer = NULL; 1783 1784 mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; 1785 } 1786 1787 void Renderer11::releaseDeviceResources() 1788 { 1789 mStateCache.clear(); 1790 mInputLayoutCache.clear(); 1791 1792 SafeDelete(mVertexDataManager); 1793 SafeDelete(mIndexDataManager); 1794 SafeDelete(mLineLoopIB); 1795 SafeDelete(mTriangleFanIB); 1796 SafeDelete(mBlit); 1797 SafeDelete(mClear); 1798 SafeDelete(mPixelTransfer); 1799 1800 SafeRelease(mDriverConstantBufferVS); 1801 SafeRelease(mDriverConstantBufferPS); 1802 SafeRelease(mSyncQuery); 1803 } 1804 1805 void Renderer11::notifyDeviceLost() 1806 { 1807 mDeviceLost = true; 1808 mDisplay->notifyDeviceLost(); 1809 } 1810 1811 bool Renderer11::isDeviceLost() 1812 { 1813 return mDeviceLost; 1814 } 1815 1816 // set notify to true to broadcast a message to all contexts of the device loss 1817 bool Renderer11::testDeviceLost(bool notify) 1818 { 1819 bool isLost = false; 1820 1821 // GetRemovedReason is used to test if the device is removed 1822 HRESULT result = mDevice->GetDeviceRemovedReason(); 1823 isLost = d3d11::isDeviceLostError(result); 1824 1825 if (isLost) 1826 { 1827 // Log error if this is a new device lost event 1828 if (mDeviceLost == false) 1829 { 1830 ERR("The D3D11 device was removed: 0x%08X", result); 1831 } 1832 1833 // ensure we note the device loss -- 1834 // we'll probably get this done again by notifyDeviceLost 1835 // but best to remember it! 1836 // Note that we don't want to clear the device loss status here 1837 // -- this needs to be done by resetDevice 1838 mDeviceLost = true; 1839 if (notify) 1840 { 1841 notifyDeviceLost(); 1842 } 1843 } 1844 1845 return isLost; 1846 } 1847 1848 bool Renderer11::testDeviceResettable() 1849 { 1850 // determine if the device is resettable by creating a dummy device 1851 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); 1852 1853 if (D3D11CreateDevice == NULL) 1854 { 1855 return false; 1856 } 1857 1858 D3D_FEATURE_LEVEL featureLevels[] = 1859 { 1860 D3D_FEATURE_LEVEL_11_0, 1861 D3D_FEATURE_LEVEL_10_1, 1862 D3D_FEATURE_LEVEL_10_0, 1863 }; 1864 1865 ID3D11Device* dummyDevice; 1866 D3D_FEATURE_LEVEL dummyFeatureLevel; 1867 ID3D11DeviceContext* dummyContext; 1868 1869 HRESULT result = D3D11CreateDevice(NULL, 1870 D3D_DRIVER_TYPE_HARDWARE, 1871 NULL, 1872 #if defined(_DEBUG) 1873 D3D11_CREATE_DEVICE_DEBUG, 1874 #else 1875 0, 1876 #endif 1877 featureLevels, 1878 ArraySize(featureLevels), 1879 D3D11_SDK_VERSION, 1880 &dummyDevice, 1881 &dummyFeatureLevel, 1882 &dummyContext); 1883 1884 if (!mDevice || FAILED(result)) 1885 { 1886 return false; 1887 } 1888 1889 SafeRelease(dummyContext); 1890 SafeRelease(dummyDevice); 1891 1892 return true; 1893 } 1894 1895 void Renderer11::release() 1896 { 1897 releaseDeviceResources(); 1898 1899 SafeRelease(mDxgiFactory); 1900 SafeRelease(mDxgiAdapter); 1901 1902 if (mDeviceContext) 1903 { 1904 mDeviceContext->ClearState(); 1905 mDeviceContext->Flush(); 1906 SafeRelease(mDeviceContext); 1907 } 1908 1909 SafeRelease(mDevice); 1910 1911 if (mD3d11Module) 1912 { 1913 FreeLibrary(mD3d11Module); 1914 mD3d11Module = NULL; 1915 } 1916 1917 if (mDxgiModule) 1918 { 1919 FreeLibrary(mDxgiModule); 1920 mDxgiModule = NULL; 1921 } 1922 1923 mCompiler.release(); 1924 } 1925 1926 bool Renderer11::resetDevice() 1927 { 1928 // recreate everything 1929 release(); 1930 EGLint result = initialize(); 1931 1932 if (result != EGL_SUCCESS) 1933 { 1934 ERR("Could not reinitialize D3D11 device: %08X", result); 1935 return false; 1936 } 1937 1938 mDeviceLost = false; 1939 1940 return true; 1941 } 1942 1943 DWORD Renderer11::getAdapterVendor() const 1944 { 1945 return mAdapterDescription.VendorId; 1946 } 1947 1948 std::string Renderer11::getRendererDescription() const 1949 { 1950 std::ostringstream rendererString; 1951 1952 rendererString << mDescription; 1953 rendererString << " Direct3D11"; 1954 1955 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); 1956 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); 1957 1958 return rendererString.str(); 1959 } 1960 1961 GUID Renderer11::getAdapterIdentifier() const 1962 { 1963 // Use the adapter LUID as our adapter ID 1964 // This number is local to a machine is only guaranteed to be unique between restarts 1965 META_ASSERT(sizeof(LUID) <= sizeof(GUID)); 1966 GUID adapterId = {0}; 1967 memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); 1968 return adapterId; 1969 } 1970 1971 bool Renderer11::getBGRATextureSupport() const 1972 { 1973 return mBGRATextureSupport; 1974 } 1975 1976 bool Renderer11::getDXT1TextureSupport() const 1977 { 1978 return mDXT1TextureSupport; 1979 } 1980 1981 bool Renderer11::getDXT3TextureSupport() const 1982 { 1983 return mDXT3TextureSupport; 1984 } 1985 1986 bool Renderer11::getDXT5TextureSupport() const 1987 { 1988 return mDXT5TextureSupport; 1989 } 1990 1991 bool Renderer11::getDepthTextureSupport() const 1992 { 1993 return mDepthTextureSupport; 1994 } 1995 1996 bool Renderer11::getFloat32TextureSupport() const 1997 { 1998 return mFloat32TextureSupport; 1999 } 2000 2001 bool Renderer11::getFloat32TextureFilteringSupport() const 2002 { 2003 return mFloat32FilterSupport; 2004 } 2005 2006 bool Renderer11::getFloat32TextureRenderingSupport() const 2007 { 2008 return mFloat32RenderSupport; 2009 } 2010 2011 bool Renderer11::getFloat16TextureSupport() const 2012 { 2013 return mFloat16TextureSupport; 2014 } 2015 2016 bool Renderer11::getFloat16TextureFilteringSupport() const 2017 { 2018 return mFloat16FilterSupport; 2019 } 2020 2021 bool Renderer11::getFloat16TextureRenderingSupport() const 2022 { 2023 return mFloat16RenderSupport; 2024 } 2025 2026 bool Renderer11::getRGB565TextureSupport() const 2027 { 2028 return false; 2029 } 2030 2031 bool Renderer11::getLuminanceTextureSupport() const 2032 { 2033 return false; 2034 } 2035 2036 bool Renderer11::getLuminanceAlphaTextureSupport() const 2037 { 2038 return false; 2039 } 2040 2041 bool Renderer11::getRGTextureSupport() const 2042 { 2043 return mRGTextureSupport; 2044 } 2045 2046 bool Renderer11::getTextureFilterAnisotropySupport() const 2047 { 2048 return true; 2049 } 2050 2051 bool Renderer11::getPBOSupport() const 2052 { 2053 return true; 2054 } 2055 2056 float Renderer11::getTextureMaxAnisotropy() const 2057 { 2058 switch (mFeatureLevel) 2059 { 2060 case D3D_FEATURE_LEVEL_11_0: 2061 return D3D11_MAX_MAXANISOTROPY; 2062 case D3D_FEATURE_LEVEL_10_1: 2063 case D3D_FEATURE_LEVEL_10_0: 2064 return D3D10_MAX_MAXANISOTROPY; 2065 default: UNREACHABLE(); 2066 return 0; 2067 } 2068 } 2069 2070 bool Renderer11::getEventQuerySupport() const 2071 { 2072 return true; 2073 } 2074 2075 Range Renderer11::getViewportBounds() const 2076 { 2077 switch (mFeatureLevel) 2078 { 2079 case D3D_FEATURE_LEVEL_11_0: 2080 return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); 2081 case D3D_FEATURE_LEVEL_10_1: 2082 case D3D_FEATURE_LEVEL_10_0: 2083 return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); 2084 default: UNREACHABLE(); 2085 return Range(0, 0); 2086 } 2087 } 2088 2089 unsigned int Renderer11::getMaxVertexTextureImageUnits() const 2090 { 2091 META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); 2092 switch (mFeatureLevel) 2093 { 2094 case D3D_FEATURE_LEVEL_11_0: 2095 case D3D_FEATURE_LEVEL_10_1: 2096 case D3D_FEATURE_LEVEL_10_0: 2097 return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; 2098 default: UNREACHABLE(); 2099 return 0; 2100 } 2101 } 2102 2103 unsigned int Renderer11::getMaxCombinedTextureImageUnits() const 2104 { 2105 return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); 2106 } 2107 2108 unsigned int Renderer11::getReservedVertexUniformVectors() const 2109 { 2110 return 0; // Driver uniforms are stored in a separate constant buffer 2111 } 2112 2113 unsigned int Renderer11::getReservedFragmentUniformVectors() const 2114 { 2115 return 0; // Driver uniforms are stored in a separate constant buffer 2116 } 2117 2118 unsigned int Renderer11::getMaxVertexUniformVectors() const 2119 { 2120 META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); 2121 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); 2122 return MAX_VERTEX_UNIFORM_VECTORS_D3D11; 2123 } 2124 2125 unsigned int Renderer11::getMaxFragmentUniformVectors() const 2126 { 2127 META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); 2128 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); 2129 return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; 2130 } 2131 2132 unsigned int Renderer11::getMaxVaryingVectors() const 2133 { 2134 META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); 2135 META_ASSERT(D3D11_VS_OUTPUT_REGISTER_COUNT <= D3D11_PS_INPUT_REGISTER_COUNT); 2136 META_ASSERT(D3D10_VS_OUTPUT_REGISTER_COUNT <= D3D10_PS_INPUT_REGISTER_COUNT); 2137 switch (mFeatureLevel) 2138 { 2139 case D3D_FEATURE_LEVEL_11_0: 2140 return D3D11_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); 2141 case D3D_FEATURE_LEVEL_10_1: 2142 return D3D10_1_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); 2143 case D3D_FEATURE_LEVEL_10_0: 2144 return D3D10_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); 2145 default: UNREACHABLE(); 2146 return 0; 2147 } 2148 } 2149 2150 unsigned int Renderer11::getMaxVertexShaderUniformBuffers() const 2151 { 2152 META_ASSERT(gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && 2153 gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); 2154 2155 switch (mFeatureLevel) 2156 { 2157 case D3D_FEATURE_LEVEL_11_0: 2158 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); 2159 case D3D_FEATURE_LEVEL_10_1: 2160 case D3D_FEATURE_LEVEL_10_0: 2161 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); 2162 default: UNREACHABLE(); 2163 return 0; 2164 } 2165 } 2166 2167 unsigned int Renderer11::getMaxFragmentShaderUniformBuffers() const 2168 { 2169 META_ASSERT(gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && 2170 gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); 2171 2172 switch (mFeatureLevel) 2173 { 2174 case D3D_FEATURE_LEVEL_11_0: 2175 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); 2176 case D3D_FEATURE_LEVEL_10_1: 2177 case D3D_FEATURE_LEVEL_10_0: 2178 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); 2179 default: UNREACHABLE(); 2180 return 0; 2181 } 2182 } 2183 2184 unsigned int Renderer11::getReservedVertexUniformBuffers() const 2185 { 2186 // we reserve one buffer for the application uniforms, and one for driver uniforms 2187 return 2; 2188 } 2189 2190 unsigned int Renderer11::getReservedFragmentUniformBuffers() const 2191 { 2192 // we reserve one buffer for the application uniforms, and one for driver uniforms 2193 return 2; 2194 } 2195 2196 unsigned int Renderer11::getReservedVaryings() const 2197 { 2198 // We potentially reserve varyings for gl_Position, _dx_Position, gl_FragCoord and gl_PointSize 2199 return 4; 2200 } 2201 2202 2203 unsigned int Renderer11::getMaxTransformFeedbackBuffers() const 2204 { 2205 META_ASSERT(gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D11_SO_BUFFER_SLOT_COUNT && 2206 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D10_SO_BUFFER_SLOT_COUNT); 2207 2208 switch (mFeatureLevel) 2209 { 2210 case D3D_FEATURE_LEVEL_11_0: 2211 return D3D11_SO_BUFFER_SLOT_COUNT; 2212 case D3D_FEATURE_LEVEL_10_1: 2213 return D3D10_1_SO_BUFFER_SLOT_COUNT; 2214 case D3D_FEATURE_LEVEL_10_0: 2215 return D3D10_SO_BUFFER_SLOT_COUNT; 2216 default: UNREACHABLE(); 2217 return 0; 2218 } 2219 } 2220 2221 unsigned int Renderer11::getMaxTransformFeedbackSeparateComponents() const 2222 { 2223 switch (mFeatureLevel) 2224 { 2225 case D3D_FEATURE_LEVEL_11_0: 2226 return getMaxTransformFeedbackInterleavedComponents() / getMaxTransformFeedbackBuffers(); 2227 case D3D_FEATURE_LEVEL_10_1: 2228 case D3D_FEATURE_LEVEL_10_0: 2229 // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero 2230 // is used. 2231 return 4; 2232 default: UNREACHABLE(); 2233 return 0; 2234 } 2235 } 2236 2237 unsigned int Renderer11::getMaxTransformFeedbackInterleavedComponents() const 2238 { 2239 return (getMaxVaryingVectors() * 4); 2240 } 2241 2242 unsigned int Renderer11::getMaxUniformBufferSize() const 2243 { 2244 // Each component is a 4-element vector of 4-byte units (floats) 2245 const unsigned int bytesPerComponent = 4 * sizeof(float); 2246 2247 switch (mFeatureLevel) 2248 { 2249 case D3D_FEATURE_LEVEL_11_0: 2250 return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; 2251 case D3D_FEATURE_LEVEL_10_1: 2252 case D3D_FEATURE_LEVEL_10_0: 2253 return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; 2254 default: UNREACHABLE(); 2255 return 0; 2256 } 2257 } 2258 2259 bool Renderer11::getNonPower2TextureSupport() const 2260 { 2261 switch (mFeatureLevel) 2262 { 2263 case D3D_FEATURE_LEVEL_11_0: 2264 case D3D_FEATURE_LEVEL_10_1: 2265 case D3D_FEATURE_LEVEL_10_0: 2266 return true; 2267 default: UNREACHABLE(); 2268 return false; 2269 } 2270 } 2271 2272 bool Renderer11::getOcclusionQuerySupport() const 2273 { 2274 switch (mFeatureLevel) 2275 { 2276 case D3D_FEATURE_LEVEL_11_0: 2277 case D3D_FEATURE_LEVEL_10_1: 2278 case D3D_FEATURE_LEVEL_10_0: 2279 return true; 2280 default: UNREACHABLE(); 2281 return false; 2282 } 2283 } 2284 2285 bool Renderer11::getInstancingSupport() const 2286 { 2287 switch (mFeatureLevel) 2288 { 2289 case D3D_FEATURE_LEVEL_11_0: 2290 case D3D_FEATURE_LEVEL_10_1: 2291 case D3D_FEATURE_LEVEL_10_0: 2292 return true; 2293 default: UNREACHABLE(); 2294 return false; 2295 } 2296 } 2297 2298 bool Renderer11::getShareHandleSupport() const 2299 { 2300 // We only currently support share handles with BGRA surfaces, because 2301 // chrome needs BGRA. Once chrome fixes this, we should always support them. 2302 // PIX doesn't seem to support using share handles, so disable them. 2303 return getBGRATextureSupport() && !gl::perfActive(); 2304 } 2305 2306 bool Renderer11::getDerivativeInstructionSupport() const 2307 { 2308 switch (mFeatureLevel) 2309 { 2310 case D3D_FEATURE_LEVEL_11_0: 2311 case D3D_FEATURE_LEVEL_10_1: 2312 case D3D_FEATURE_LEVEL_10_0: 2313 return true; 2314 default: UNREACHABLE(); 2315 return false; 2316 } 2317 } 2318 2319 bool Renderer11::getPostSubBufferSupport() const 2320 { 2321 // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. 2322 return false; 2323 } 2324 2325 int Renderer11::getMaxRecommendedElementsIndices() const 2326 { 2327 META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); 2328 META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); 2329 2330 // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. 2331 return std::numeric_limits<GLint>::max(); 2332 } 2333 2334 int Renderer11::getMaxRecommendedElementsVertices() const 2335 { 2336 META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); 2337 META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); 2338 2339 // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. 2340 return std::numeric_limits<GLint>::max(); 2341 } 2342 2343 int Renderer11::getMajorShaderModel() const 2344 { 2345 switch (mFeatureLevel) 2346 { 2347 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 2348 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 2349 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 2350 default: UNREACHABLE(); return 0; 2351 } 2352 } 2353 2354 int Renderer11::getMinorShaderModel() const 2355 { 2356 switch (mFeatureLevel) 2357 { 2358 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 2359 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 2360 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 2361 default: UNREACHABLE(); return 0; 2362 } 2363 } 2364 2365 float Renderer11::getMaxPointSize() const 2366 { 2367 // choose a reasonable maximum. we enforce this in the shader. 2368 // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) 2369 return 1024.0f; 2370 } 2371 2372 int Renderer11::getMaxViewportDimension() const 2373 { 2374 // Maximum viewport size must be at least as large as the largest render buffer (or larger). 2375 // In our case return the maximum texture size, which is the maximum render buffer size. 2376 META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); 2377 META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); 2378 2379 switch (mFeatureLevel) 2380 { 2381 case D3D_FEATURE_LEVEL_11_0: 2382 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 2383 case D3D_FEATURE_LEVEL_10_1: 2384 case D3D_FEATURE_LEVEL_10_0: 2385 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 2386 default: UNREACHABLE(); 2387 return 0; 2388 } 2389 } 2390 2391 int Renderer11::getMaxTextureWidth() const 2392 { 2393 switch (mFeatureLevel) 2394 { 2395 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 2396 case D3D_FEATURE_LEVEL_10_1: 2397 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 2398 default: UNREACHABLE(); return 0; 2399 } 2400 } 2401 2402 int Renderer11::getMaxTextureHeight() const 2403 { 2404 switch (mFeatureLevel) 2405 { 2406 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 2407 case D3D_FEATURE_LEVEL_10_1: 2408 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 2409 default: UNREACHABLE(); return 0; 2410 } 2411 } 2412 2413 int Renderer11::getMaxTextureDepth() const 2414 { 2415 switch (mFeatureLevel) 2416 { 2417 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048 2418 case D3D_FEATURE_LEVEL_10_1: 2419 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048 2420 default: UNREACHABLE(); return 0; 2421 } 2422 } 2423 2424 int Renderer11::getMaxTextureArrayLayers() const 2425 { 2426 switch (mFeatureLevel) 2427 { 2428 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 2048 2429 case D3D_FEATURE_LEVEL_10_1: 2430 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 512 2431 default: UNREACHABLE(); return 0; 2432 } 2433 } 2434 2435 bool Renderer11::get32BitIndexSupport() const 2436 { 2437 switch (mFeatureLevel) 2438 { 2439 case D3D_FEATURE_LEVEL_11_0: 2440 case D3D_FEATURE_LEVEL_10_1: 2441 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true 2442 default: UNREACHABLE(); return false; 2443 } 2444 } 2445 2446 int Renderer11::getMinSwapInterval() const 2447 { 2448 return 0; 2449 } 2450 2451 int Renderer11::getMaxSwapInterval() const 2452 { 2453 return 4; 2454 } 2455 2456 int Renderer11::getMaxSupportedSamples() const 2457 { 2458 return mMaxSupportedSamples; 2459 } 2460 2461 GLsizei Renderer11::getMaxSupportedFormatSamples(GLenum internalFormat) const 2462 { 2463 DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); 2464 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); 2465 return (iter != mMultisampleSupportMap.end()) ? iter->second.maxSupportedSamples : 0; 2466 } 2467 2468 GLsizei Renderer11::getNumSampleCounts(GLenum internalFormat) const 2469 { 2470 unsigned int numCounts = 0; 2471 2472 // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not 2473 GLenum componentType = gl::GetComponentType(internalFormat, getCurrentClientVersion()); 2474 if (componentType != GL_INT && componentType != GL_UNSIGNED_INT) 2475 { 2476 DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); 2477 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); 2478 2479 if (iter != mMultisampleSupportMap.end()) 2480 { 2481 const MultisampleSupportInfo& info = iter->second; 2482 for (int i = 0; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) 2483 { 2484 if (info.qualityLevels[i] > 0) 2485 { 2486 numCounts++; 2487 } 2488 } 2489 } 2490 } 2491 2492 return numCounts; 2493 } 2494 2495 void Renderer11::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const 2496 { 2497 // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not 2498 GLenum componentType = gl::GetComponentType(internalFormat, getCurrentClientVersion()); 2499 if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) 2500 { 2501 return; 2502 } 2503 2504 DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat, getCurrentClientVersion()); 2505 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); 2506 2507 if (iter != mMultisampleSupportMap.end()) 2508 { 2509 const MultisampleSupportInfo& info = iter->second; 2510 int bufPos = 0; 2511 for (int i = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT - 1; i >= 0 && bufPos < bufSize; i--) 2512 { 2513 if (info.qualityLevels[i] > 0) 2514 { 2515 params[bufPos++] = i + 1; 2516 } 2517 } 2518 } 2519 } 2520 2521 int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const 2522 { 2523 if (requested == 0) 2524 { 2525 return 0; 2526 } 2527 2528 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); 2529 if (iter != mMultisampleSupportMap.end()) 2530 { 2531 const MultisampleSupportInfo& info = iter->second; 2532 for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) 2533 { 2534 if (info.qualityLevels[i] > 0) 2535 { 2536 return i + 1; 2537 } 2538 } 2539 } 2540 2541 return -1; 2542 } 2543 2544 unsigned int Renderer11::getMaxRenderTargets() const 2545 { 2546 META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); 2547 META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); 2548 2549 switch (mFeatureLevel) 2550 { 2551 case D3D_FEATURE_LEVEL_11_0: 2552 return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 2553 case D3D_FEATURE_LEVEL_10_1: 2554 case D3D_FEATURE_LEVEL_10_0: 2555 // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader 2556 // outputs to multiple RTs that are not bound. 2557 // TODO: Remove pixel shader outputs for render targets that are not bound. 2558 return 1; 2559 default: 2560 UNREACHABLE(); 2561 return 1; 2562 } 2563 } 2564 2565 bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) 2566 { 2567 if (source && dest) 2568 { 2569 TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); 2570 TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); 2571 2572 mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); 2573 2574 dest11->invalidateSwizzleCache(); 2575 2576 return true; 2577 } 2578 2579 return false; 2580 } 2581 2582 bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) 2583 { 2584 if (source && dest) 2585 { 2586 TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); 2587 TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); 2588 2589 mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); 2590 2591 dest11->invalidateSwizzleCache(); 2592 2593 return true; 2594 } 2595 2596 return false; 2597 } 2598 2599 bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) 2600 { 2601 if (source && dest) 2602 { 2603 TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source->getStorageInstance()); 2604 TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest->getStorageInstance()); 2605 2606 mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); 2607 2608 dest11->invalidateSwizzleCache(); 2609 2610 return true; 2611 } 2612 2613 return false; 2614 } 2615 2616 bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) 2617 { 2618 if (source && dest) 2619 { 2620 TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source->getStorageInstance()); 2621 TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest->getStorageInstance()); 2622 2623 mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); 2624 2625 dest11->invalidateSwizzleCache(); 2626 2627 return true; 2628 } 2629 2630 return false; 2631 } 2632 2633 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2634 GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) 2635 { 2636 gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); 2637 if (!colorbuffer) 2638 { 2639 ERR("Failed to retrieve the color buffer from the frame buffer."); 2640 return gl::error(GL_OUT_OF_MEMORY, false); 2641 } 2642 2643 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 2644 if (!sourceRenderTarget) 2645 { 2646 ERR("Failed to retrieve the render target from the frame buffer."); 2647 return gl::error(GL_OUT_OF_MEMORY, false); 2648 } 2649 2650 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 2651 if (!source) 2652 { 2653 ERR("Failed to retrieve the render target view from the render target."); 2654 return gl::error(GL_OUT_OF_MEMORY, false); 2655 } 2656 2657 TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); 2658 if (!storage11) 2659 { 2660 ERR("Failed to retrieve the texture storage from the destination."); 2661 return gl::error(GL_OUT_OF_MEMORY, false); 2662 } 2663 2664 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); 2665 if (!destRenderTarget) 2666 { 2667 ERR("Failed to retrieve the render target from the destination storage."); 2668 return gl::error(GL_OUT_OF_MEMORY, false); 2669 } 2670 2671 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 2672 if (!dest) 2673 { 2674 ERR("Failed to retrieve the render target view from the destination render target."); 2675 return gl::error(GL_OUT_OF_MEMORY, false); 2676 } 2677 2678 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); 2679 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); 2680 2681 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); 2682 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); 2683 2684 // Use nearest filtering because source and destination are the same size for the direct 2685 // copy 2686 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, 2687 destFormat, GL_NEAREST); 2688 2689 storage11->invalidateSwizzleCacheLevel(level); 2690 2691 return ret; 2692 } 2693 2694 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2695 GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) 2696 { 2697 gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); 2698 if (!colorbuffer) 2699 { 2700 ERR("Failed to retrieve the color buffer from the frame buffer."); 2701 return gl::error(GL_OUT_OF_MEMORY, false); 2702 } 2703 2704 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 2705 if (!sourceRenderTarget) 2706 { 2707 ERR("Failed to retrieve the render target from the frame buffer."); 2708 return gl::error(GL_OUT_OF_MEMORY, false); 2709 } 2710 2711 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 2712 if (!source) 2713 { 2714 ERR("Failed to retrieve the render target view from the render target."); 2715 return gl::error(GL_OUT_OF_MEMORY, false); 2716 } 2717 2718 TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); 2719 if (!storage11) 2720 { 2721 ERR("Failed to retrieve the texture storage from the destination."); 2722 return gl::error(GL_OUT_OF_MEMORY, false); 2723 } 2724 2725 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetFace(target, level)); 2726 if (!destRenderTarget) 2727 { 2728 ERR("Failed to retrieve the render target from the destination storage."); 2729 return gl::error(GL_OUT_OF_MEMORY, false); 2730 } 2731 2732 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 2733 if (!dest) 2734 { 2735 ERR("Failed to retrieve the render target view from the destination render target."); 2736 return gl::error(GL_OUT_OF_MEMORY, false); 2737 } 2738 2739 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); 2740 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); 2741 2742 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); 2743 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); 2744 2745 // Use nearest filtering because source and destination are the same size for the direct 2746 // copy 2747 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, 2748 destFormat, GL_NEAREST); 2749 2750 storage11->invalidateSwizzleCacheLevel(level); 2751 2752 return ret; 2753 } 2754 2755 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2756 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) 2757 { 2758 gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); 2759 if (!colorbuffer) 2760 { 2761 ERR("Failed to retrieve the color buffer from the frame buffer."); 2762 return gl::error(GL_OUT_OF_MEMORY, false); 2763 } 2764 2765 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 2766 if (!sourceRenderTarget) 2767 { 2768 ERR("Failed to retrieve the render target from the frame buffer."); 2769 return gl::error(GL_OUT_OF_MEMORY, false); 2770 } 2771 2772 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 2773 if (!source) 2774 { 2775 ERR("Failed to retrieve the render target view from the render target."); 2776 return gl::error(GL_OUT_OF_MEMORY, false); 2777 } 2778 2779 TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); 2780 if (!storage11) 2781 { 2782 ERR("Failed to retrieve the texture storage from the destination."); 2783 return gl::error(GL_OUT_OF_MEMORY, false); 2784 } 2785 2786 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); 2787 if (!destRenderTarget) 2788 { 2789 ERR("Failed to retrieve the render target from the destination storage."); 2790 return gl::error(GL_OUT_OF_MEMORY, false); 2791 } 2792 2793 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 2794 if (!dest) 2795 { 2796 ERR("Failed to retrieve the render target view from the destination render target."); 2797 return gl::error(GL_OUT_OF_MEMORY, false); 2798 } 2799 2800 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); 2801 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); 2802 2803 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); 2804 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); 2805 2806 // Use nearest filtering because source and destination are the same size for the direct 2807 // copy 2808 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, 2809 destFormat, GL_NEAREST); 2810 2811 storage11->invalidateSwizzleCacheLevel(level); 2812 2813 return ret; 2814 } 2815 2816 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 2817 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) 2818 { 2819 gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); 2820 if (!colorbuffer) 2821 { 2822 ERR("Failed to retrieve the color buffer from the frame buffer."); 2823 return gl::error(GL_OUT_OF_MEMORY, false); 2824 } 2825 2826 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 2827 if (!sourceRenderTarget) 2828 { 2829 ERR("Failed to retrieve the render target from the frame buffer."); 2830 return gl::error(GL_OUT_OF_MEMORY, false); 2831 } 2832 2833 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 2834 if (!source) 2835 { 2836 ERR("Failed to retrieve the render target view from the render target."); 2837 return gl::error(GL_OUT_OF_MEMORY, false); 2838 } 2839 2840 TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); 2841 if (!storage11) 2842 { 2843 SafeRelease(source); 2844 ERR("Failed to retrieve the texture storage from the destination."); 2845 return gl::error(GL_OUT_OF_MEMORY, false); 2846 } 2847 2848 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); 2849 if (!destRenderTarget) 2850 { 2851 SafeRelease(source); 2852 ERR("Failed to retrieve the render target from the destination storage."); 2853 return gl::error(GL_OUT_OF_MEMORY, false); 2854 } 2855 2856 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 2857 if (!dest) 2858 { 2859 ERR("Failed to retrieve the render target view from the destination render target."); 2860 return gl::error(GL_OUT_OF_MEMORY, false); 2861 } 2862 2863 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); 2864 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); 2865 2866 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); 2867 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); 2868 2869 // Use nearest filtering because source and destination are the same size for the direct 2870 // copy 2871 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, 2872 destFormat, GL_NEAREST); 2873 2874 storage11->invalidateSwizzleCacheLevel(level); 2875 2876 return ret; 2877 } 2878 2879 void Renderer11::unapplyRenderTargets() 2880 { 2881 setOneTimeRenderTarget(NULL); 2882 } 2883 2884 void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) 2885 { 2886 ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; 2887 2888 rtvArray[0] = renderTargetView; 2889 2890 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); 2891 2892 // Do not preserve the serial for this one-time-use render target 2893 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 2894 { 2895 mAppliedRenderTargetSerials[rtIndex] = 0; 2896 } 2897 } 2898 2899 RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) 2900 { 2901 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); 2902 RenderTarget11 *renderTarget = NULL; 2903 2904 if (depth) 2905 { 2906 // Note: depth stencil may be NULL for 0 sized surfaces 2907 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), 2908 swapChain11->getDepthStencilTexture(), 2909 swapChain11->getDepthStencilShaderResource(), 2910 swapChain11->getWidth(), swapChain11->getHeight(), 1); 2911 } 2912 else 2913 { 2914 // Note: render target may be NULL for 0 sized surfaces 2915 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), 2916 swapChain11->getOffscreenTexture(), 2917 swapChain11->getRenderTargetShaderResource(), 2918 swapChain11->getWidth(), swapChain11->getHeight(), 1); 2919 } 2920 return renderTarget; 2921 } 2922 2923 RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples) 2924 { 2925 RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples); 2926 return renderTarget; 2927 } 2928 2929 ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, 2930 const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, 2931 bool separatedOutputBuffers) 2932 { 2933 ShaderExecutable11 *executable = NULL; 2934 HRESULT result; 2935 2936 switch (type) 2937 { 2938 case rx::SHADER_VERTEX: 2939 { 2940 ID3D11VertexShader *vertexShader = NULL; 2941 ID3D11GeometryShader *streamOutShader = NULL; 2942 2943 result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); 2944 ASSERT(SUCCEEDED(result)); 2945 2946 if (transformFeedbackVaryings.size() > 0) 2947 { 2948 std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; 2949 for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) 2950 { 2951 const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; 2952 for (size_t j = 0; j < varying.semanticIndexCount; j++) 2953 { 2954 D3D11_SO_DECLARATION_ENTRY entry = { 0 }; 2955 entry.Stream = 0; 2956 entry.SemanticName = varying.semanticName.c_str(); 2957 entry.SemanticIndex = varying.semanticIndex + j; 2958 entry.StartComponent = 0; 2959 entry.ComponentCount = gl::VariableRowCount(type); 2960 entry.OutputSlot = (separatedOutputBuffers ? i : 0); 2961 soDeclaration.push_back(entry); 2962 } 2963 } 2964 2965 result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), 2966 NULL, 0, 0, NULL, &streamOutShader); 2967 ASSERT(SUCCEEDED(result)); 2968 } 2969 2970 if (vertexShader) 2971 { 2972 executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); 2973 } 2974 } 2975 break; 2976 case rx::SHADER_PIXEL: 2977 { 2978 ID3D11PixelShader *pixelShader = NULL; 2979 2980 result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); 2981 ASSERT(SUCCEEDED(result)); 2982 2983 if (pixelShader) 2984 { 2985 executable = new ShaderExecutable11(function, length, pixelShader); 2986 } 2987 } 2988 break; 2989 case rx::SHADER_GEOMETRY: 2990 { 2991 ID3D11GeometryShader *geometryShader = NULL; 2992 2993 result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); 2994 ASSERT(SUCCEEDED(result)); 2995 2996 if (geometryShader) 2997 { 2998 executable = new ShaderExecutable11(function, length, geometryShader); 2999 } 3000 } 3001 break; 3002 default: 3003 UNREACHABLE(); 3004 break; 3005 } 3006 3007 return executable; 3008 } 3009 3010 ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, 3011 const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, 3012 bool separatedOutputBuffers, D3DWorkaroundType workaround) 3013 { 3014 const char *profileType = NULL; 3015 switch (type) 3016 { 3017 case rx::SHADER_VERTEX: 3018 profileType = "vs"; 3019 break; 3020 case rx::SHADER_PIXEL: 3021 profileType = "ps"; 3022 break; 3023 case rx::SHADER_GEOMETRY: 3024 profileType = "gs"; 3025 break; 3026 default: 3027 UNREACHABLE(); 3028 return NULL; 3029 } 3030 3031 const char *profileVersion = NULL; 3032 switch (mFeatureLevel) 3033 { 3034 case D3D_FEATURE_LEVEL_11_0: 3035 profileVersion = "5_0"; 3036 break; 3037 case D3D_FEATURE_LEVEL_10_1: 3038 profileVersion = "4_1"; 3039 break; 3040 case D3D_FEATURE_LEVEL_10_0: 3041 profileVersion = "4_0"; 3042 break; 3043 default: 3044 UNREACHABLE(); 3045 return NULL; 3046 } 3047 3048 char profile[32]; 3049 snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion); 3050 3051 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0; 3052 3053 if (gl::perfActive()) 3054 { 3055 #ifndef NDEBUG 3056 flags = D3DCOMPILE_SKIP_OPTIMIZATION; 3057 #endif 3058 3059 flags |= D3DCOMPILE_DEBUG; 3060 3061 std::string sourcePath = getTempPath(); 3062 std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); 3063 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); 3064 } 3065 3066 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. 3067 // Try the default flags first and if compilation fails, try some alternatives. 3068 const UINT extraFlags[] = 3069 { 3070 flags, 3071 flags | D3DCOMPILE_SKIP_VALIDATION, 3072 flags | D3DCOMPILE_SKIP_OPTIMIZATION 3073 }; 3074 3075 const static char *extraFlagNames[] = 3076 { 3077 "default", 3078 "skip validation", 3079 "skip optimization" 3080 }; 3081 3082 int attempts = ArraySize(extraFlags); 3083 3084 ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); 3085 if (!binary) 3086 { 3087 return NULL; 3088 } 3089 3090 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, 3091 transformFeedbackVaryings, separatedOutputBuffers); 3092 SafeRelease(binary); 3093 3094 return executable; 3095 } 3096 3097 rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize) 3098 { 3099 return new UniformStorage11(this, storageSize); 3100 } 3101 3102 VertexBuffer *Renderer11::createVertexBuffer() 3103 { 3104 return new VertexBuffer11(this); 3105 } 3106 3107 IndexBuffer *Renderer11::createIndexBuffer() 3108 { 3109 return new IndexBuffer11(this); 3110 } 3111 3112 BufferStorage *Renderer11::createBufferStorage() 3113 { 3114 return new BufferStorage11(this); 3115 } 3116 3117 QueryImpl *Renderer11::createQuery(GLenum type) 3118 { 3119 return new Query11(this, type); 3120 } 3121 3122 FenceImpl *Renderer11::createFence() 3123 { 3124 return new Fence11(this); 3125 } 3126 3127 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const 3128 { 3129 int clientVersion = getCurrentClientVersion(); 3130 3131 // We only support buffer to texture copies in ES3 3132 if (clientVersion <= 2) 3133 { 3134 return false; 3135 } 3136 3137 // sRGB formats do not work with D3D11 buffer SRVs 3138 if (gl::GetColorEncoding(internalFormat, clientVersion) == GL_SRGB) 3139 { 3140 return false; 3141 } 3142 3143 // We cannot support direct copies to non-color-renderable formats 3144 if (!gl::IsColorRenderingSupported(internalFormat, this)) 3145 { 3146 return false; 3147 } 3148 3149 // We skip all 3-channel formats since sometimes format support is missing 3150 if (gl::GetComponentCount(internalFormat, clientVersion) == 3) 3151 { 3152 return false; 3153 } 3154 3155 // We don't support formats which we can't represent without conversion 3156 if (getNativeTextureFormat(internalFormat) != internalFormat) 3157 { 3158 return false; 3159 } 3160 3161 return true; 3162 } 3163 3164 bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, 3165 GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) 3166 { 3167 ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); 3168 return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); 3169 } 3170 3171 bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) 3172 { 3173 ASSERT(colorbuffer != NULL); 3174 3175 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 3176 if (renderTarget) 3177 { 3178 *subresourceIndex = renderTarget->getSubresourceIndex(); 3179 3180 ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); 3181 if (colorBufferRTV) 3182 { 3183 ID3D11Resource *textureResource = NULL; 3184 colorBufferRTV->GetResource(&textureResource); 3185 3186 if (textureResource) 3187 { 3188 HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource); 3189 SafeRelease(textureResource); 3190 3191 if (SUCCEEDED(result)) 3192 { 3193 return true; 3194 } 3195 else 3196 { 3197 ERR("Failed to extract the ID3D11Texture2D from the render target resource, " 3198 "HRESULT: 0x%X.", result); 3199 } 3200 } 3201 } 3202 } 3203 3204 return false; 3205 } 3206 3207 bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, 3208 const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) 3209 { 3210 if (blitRenderTarget) 3211 { 3212 gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); 3213 3214 if (!readBuffer) 3215 { 3216 ERR("Failed to retrieve the read buffer from the read framebuffer."); 3217 return gl::error(GL_OUT_OF_MEMORY, false); 3218 } 3219 3220 RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); 3221 3222 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 3223 { 3224 if (drawTarget->isEnabledColorAttachment(colorAttachment)) 3225 { 3226 gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); 3227 3228 if (!drawBuffer) 3229 { 3230 ERR("Failed to retrieve the draw buffer from the draw framebuffer."); 3231 return gl::error(GL_OUT_OF_MEMORY, false); 3232 } 3233 3234 RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); 3235 3236 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, 3237 blitRenderTarget, false, false)) 3238 { 3239 return false; 3240 } 3241 } 3242 } 3243 } 3244 3245 if (blitDepth || blitStencil) 3246 { 3247 gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); 3248 gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); 3249 3250 if (!readBuffer) 3251 { 3252 ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); 3253 return gl::error(GL_OUT_OF_MEMORY, false); 3254 } 3255 3256 if (!drawBuffer) 3257 { 3258 ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); 3259 return gl::error(GL_OUT_OF_MEMORY, false); 3260 } 3261 3262 RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); 3263 RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); 3264 3265 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, 3266 false, blitDepth, blitStencil)) 3267 { 3268 return false; 3269 } 3270 } 3271 3272 invalidateFramebufferSwizzles(drawTarget); 3273 3274 return true; 3275 } 3276 3277 void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, 3278 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) 3279 { 3280 ID3D11Texture2D *colorBufferTexture = NULL; 3281 unsigned int subresourceIndex = 0; 3282 3283 gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); 3284 3285 if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) 3286 { 3287 gl::Rectangle area; 3288 area.x = x; 3289 area.y = y; 3290 area.width = width; 3291 area.height = height; 3292 3293 if (pack.pixelBuffer.get() != NULL) 3294 { 3295 rx::BufferStorage11 *packBufferStorage = BufferStorage11::makeBufferStorage11(pack.pixelBuffer.get()->getStorage()); 3296 PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels)); 3297 packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); 3298 } 3299 else 3300 { 3301 readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); 3302 } 3303 3304 SafeRelease(colorBufferTexture); 3305 } 3306 } 3307 3308 Image *Renderer11::createImage() 3309 { 3310 return new Image11(); 3311 } 3312 3313 void Renderer11::generateMipmap(Image *dest, Image *src) 3314 { 3315 Image11 *dest11 = Image11::makeImage11(dest); 3316 Image11 *src11 = Image11::makeImage11(src); 3317 Image11::generateMipmap(getCurrentClientVersion(), dest11, src11); 3318 } 3319 3320 TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) 3321 { 3322 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); 3323 return new TextureStorage11_2D(this, swapChain11); 3324 } 3325 3326 TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) 3327 { 3328 return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); 3329 } 3330 3331 TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) 3332 { 3333 return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels); 3334 } 3335 3336 TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) 3337 { 3338 return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); 3339 } 3340 3341 TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) 3342 { 3343 return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); 3344 } 3345 3346 void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, 3347 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) 3348 { 3349 ASSERT(area.width >= 0); 3350 ASSERT(area.height >= 0); 3351 3352 D3D11_TEXTURE2D_DESC textureDesc; 3353 texture->GetDesc(&textureDesc); 3354 3355 // Clamp read region to the defined texture boundaries, preventing out of bounds reads 3356 // and reads of uninitialized data. 3357 gl::Rectangle safeArea; 3358 safeArea.x = gl::clamp(area.x, 0, static_cast<int>(textureDesc.Width)); 3359 safeArea.y = gl::clamp(area.y, 0, static_cast<int>(textureDesc.Height)); 3360 safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, 3361 static_cast<int>(textureDesc.Width) - safeArea.x); 3362 safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, 3363 static_cast<int>(textureDesc.Height) - safeArea.y); 3364 3365 ASSERT(safeArea.x >= 0 && safeArea.y >= 0); 3366 ASSERT(safeArea.x + safeArea.width <= static_cast<int>(textureDesc.Width)); 3367 ASSERT(safeArea.y + safeArea.height <= static_cast<int>(textureDesc.Height)); 3368 3369 if (safeArea.width == 0 || safeArea.height == 0) 3370 { 3371 // no work to do 3372 return; 3373 } 3374 3375 D3D11_TEXTURE2D_DESC stagingDesc; 3376 stagingDesc.Width = safeArea.width; 3377 stagingDesc.Height = safeArea.height; 3378 stagingDesc.MipLevels = 1; 3379 stagingDesc.ArraySize = 1; 3380 stagingDesc.Format = textureDesc.Format; 3381 stagingDesc.SampleDesc.Count = 1; 3382 stagingDesc.SampleDesc.Quality = 0; 3383 stagingDesc.Usage = D3D11_USAGE_STAGING; 3384 stagingDesc.BindFlags = 0; 3385 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 3386 stagingDesc.MiscFlags = 0; 3387 3388 ID3D11Texture2D* stagingTex = NULL; 3389 HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); 3390 if (FAILED(result)) 3391 { 3392 ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); 3393 return; 3394 } 3395 3396 ID3D11Texture2D* srcTex = NULL; 3397 if (textureDesc.SampleDesc.Count > 1) 3398 { 3399 D3D11_TEXTURE2D_DESC resolveDesc; 3400 resolveDesc.Width = textureDesc.Width; 3401 resolveDesc.Height = textureDesc.Height; 3402 resolveDesc.MipLevels = 1; 3403 resolveDesc.ArraySize = 1; 3404 resolveDesc.Format = textureDesc.Format; 3405 resolveDesc.SampleDesc.Count = 1; 3406 resolveDesc.SampleDesc.Quality = 0; 3407 resolveDesc.Usage = D3D11_USAGE_DEFAULT; 3408 resolveDesc.BindFlags = 0; 3409 resolveDesc.CPUAccessFlags = 0; 3410 resolveDesc.MiscFlags = 0; 3411 3412 result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); 3413 if (FAILED(result)) 3414 { 3415 ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); 3416 SafeRelease(stagingTex); 3417 return; 3418 } 3419 3420 mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); 3421 subResource = 0; 3422 } 3423 else 3424 { 3425 srcTex = texture; 3426 srcTex->AddRef(); 3427 } 3428 3429 D3D11_BOX srcBox; 3430 srcBox.left = static_cast<UINT>(safeArea.x); 3431 srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width); 3432 srcBox.top = static_cast<UINT>(safeArea.y); 3433 srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height); 3434 srcBox.front = 0; 3435 srcBox.back = 1; 3436 3437 mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); 3438 3439 SafeRelease(srcTex); 3440 3441 PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); 3442 packPixels(stagingTex, packParams, pixels); 3443 3444 SafeRelease(stagingTex); 3445 } 3446 3447 void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut) 3448 { 3449 D3D11_TEXTURE2D_DESC textureDesc; 3450 readTexture->GetDesc(&textureDesc); 3451 3452 D3D11_MAPPED_SUBRESOURCE mapping; 3453 HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); 3454 UNUSED_ASSERTION_VARIABLE(hr); 3455 ASSERT(SUCCEEDED(hr)); 3456 3457 unsigned char *source; 3458 int inputPitch; 3459 if (params.pack.reverseRowOrder) 3460 { 3461 source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (params.area.height - 1); 3462 inputPitch = -static_cast<int>(mapping.RowPitch); 3463 } 3464 else 3465 { 3466 source = static_cast<unsigned char*>(mapping.pData); 3467 inputPitch = static_cast<int>(mapping.RowPitch); 3468 } 3469 3470 GLuint clientVersion = getCurrentClientVersion(); 3471 3472 GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format, clientVersion); 3473 GLenum sourceFormat = gl::GetFormat(sourceInternalFormat, clientVersion); 3474 GLenum sourceType = gl::GetType(sourceInternalFormat, clientVersion); 3475 3476 GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat, clientVersion); 3477 3478 if (sourceFormat == params.format && sourceType == params.type) 3479 { 3480 unsigned char *dest = static_cast<unsigned char*>(pixelsOut) + params.offset; 3481 for (int y = 0; y < params.area.height; y++) 3482 { 3483 memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourcePixelSize); 3484 } 3485 } 3486 else 3487 { 3488 GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type, clientVersion); 3489 GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat, clientVersion); 3490 3491 ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type); 3492 if (fastCopyFunc) 3493 { 3494 // Fast copy is possible through some special function 3495 for (int y = 0; y < params.area.height; y++) 3496 { 3497 for (int x = 0; x < params.area.width; x++) 3498 { 3499 void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; 3500 void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize; 3501 3502 fastCopyFunc(src, dest); 3503 } 3504 } 3505 } 3506 else 3507 { 3508 ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format); 3509 ColorWriteFunction writeFunc = gl::GetColorWriteFunction(params.format, params.type, clientVersion); 3510 3511 unsigned char temp[16]; // Maximum size of any Color<T> type used. 3512 META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && 3513 sizeof(temp) >= sizeof(gl::ColorUI) && 3514 sizeof(temp) >= sizeof(gl::ColorI)); 3515 3516 for (int y = 0; y < params.area.height; y++) 3517 { 3518 for (int x = 0; x < params.area.width; x++) 3519 { 3520 void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; 3521 void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize; 3522 3523 // readFunc and writeFunc will be using the same type of color, CopyTexImage 3524 // will not allow the copy otherwise. 3525 readFunc(src, temp); 3526 writeFunc(temp, dest); 3527 } 3528 } 3529 } 3530 } 3531 3532 mDeviceContext->Unmap(readTexture, 0); 3533 } 3534 3535 bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, 3536 RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, 3537 bool colorBlit, bool depthBlit, bool stencilBlit) 3538 { 3539 // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, 3540 // it should never be the case that both color and depth/stencil need to be blitted at 3541 // at the same time. 3542 ASSERT(colorBlit != (depthBlit || stencilBlit)); 3543 3544 bool result = true; 3545 3546 RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); 3547 if (!drawRenderTarget) 3548 { 3549 ERR("Failed to retrieve the draw render target from the draw framebuffer."); 3550 return gl::error(GL_OUT_OF_MEMORY, false); 3551 } 3552 3553 ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); 3554 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); 3555 ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); 3556 ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); 3557 3558 RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); 3559 if (!readRenderTarget) 3560 { 3561 ERR("Failed to retrieve the read render target from the read framebuffer."); 3562 return gl::error(GL_OUT_OF_MEMORY, false); 3563 } 3564 3565 ID3D11Resource *readTexture = NULL; 3566 ID3D11ShaderResourceView *readSRV = NULL; 3567 unsigned int readSubresource = 0; 3568 if (readRenderTarget->getSamples() > 0) 3569 { 3570 ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); 3571 ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource); 3572 3573 if (unresolvedTexture) 3574 { 3575 readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); 3576 readSubresource = 0; 3577 3578 SafeRelease(unresolvedTexture); 3579 3580 HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); 3581 if (FAILED(hresult)) 3582 { 3583 SafeRelease(readTexture); 3584 return gl::error(GL_OUT_OF_MEMORY, false); 3585 } 3586 } 3587 } 3588 else 3589 { 3590 readTexture = readRenderTarget11->getTexture(); 3591 readTexture->AddRef(); 3592 readSubresource = readRenderTarget11->getSubresourceIndex(); 3593 readSRV = readRenderTarget11->getShaderResourceView(); 3594 readSRV->AddRef(); 3595 } 3596 3597 if (!readTexture || !readSRV) 3598 { 3599 SafeRelease(readTexture); 3600 SafeRelease(readSRV); 3601 ERR("Failed to retrieve the read render target view from the read render target."); 3602 return gl::error(GL_OUT_OF_MEMORY, false); 3603 } 3604 3605 gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); 3606 gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); 3607 3608 bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); 3609 3610 bool wholeBufferCopy = !scissorNeeded && 3611 readRect.x == 0 && readRect.width == readSize.width && 3612 readRect.y == 0 && readRect.height == readSize.height && 3613 drawRect.x == 0 && drawRect.width == drawSize.width && 3614 drawRect.y == 0 && drawRect.height == drawSize.height; 3615 3616 bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; 3617 3618 bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; 3619 3620 bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || 3621 readRect.y < 0 || readRect.y + readRect.height > readSize.height || 3622 drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || 3623 drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; 3624 3625 bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0; 3626 bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0; 3627 bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit); 3628 3629 if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && 3630 !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && 3631 (!(depthBlit || stencilBlit) || wholeBufferCopy)) 3632 { 3633 UINT dstX = drawRect.x; 3634 UINT dstY = drawRect.y; 3635 3636 D3D11_BOX readBox; 3637 readBox.left = readRect.x; 3638 readBox.right = readRect.x + readRect.width; 3639 readBox.top = readRect.y; 3640 readBox.bottom = readRect.y + readRect.height; 3641 readBox.front = 0; 3642 readBox.back = 1; 3643 3644 if (scissorNeeded) 3645 { 3646 // drawRect is guaranteed to have positive width and height because stretchRequired is false. 3647 ASSERT(drawRect.width >= 0 || drawRect.height >= 0); 3648 3649 if (drawRect.x < scissor->x) 3650 { 3651 dstX = scissor->x; 3652 readBox.left += (scissor->x - drawRect.x); 3653 } 3654 if (drawRect.y < scissor->y) 3655 { 3656 dstY = scissor->y; 3657 readBox.top += (scissor->y - drawRect.y); 3658 } 3659 if (drawRect.x + drawRect.width > scissor->x + scissor->width) 3660 { 3661 readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); 3662 } 3663 if (drawRect.y + drawRect.height > scissor->y + scissor->height) 3664 { 3665 readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); 3666 } 3667 } 3668 3669 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox 3670 // We also require complete framebuffer copies for depth-stencil blit. 3671 D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; 3672 3673 mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, 3674 readTexture, readSubresource, pSrcBox); 3675 result = true; 3676 } 3677 else 3678 { 3679 gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); 3680 gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); 3681 3682 if (depthBlit && stencilBlit) 3683 { 3684 result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, 3685 drawTexture, drawSubresource, drawArea, drawSize, 3686 scissor); 3687 } 3688 else if (depthBlit) 3689 { 3690 result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, 3691 scissor); 3692 } 3693 else if (stencilBlit) 3694 { 3695 result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, 3696 drawTexture, drawSubresource, drawArea, drawSize, 3697 scissor); 3698 } 3699 else 3700 { 3701 GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat(), getCurrentClientVersion()); 3702 result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, 3703 scissor, format, filter); 3704 } 3705 } 3706 3707 SafeRelease(readTexture); 3708 SafeRelease(readSRV); 3709 3710 return result; 3711 } 3712 3713 ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) 3714 { 3715 D3D11_TEXTURE2D_DESC textureDesc; 3716 source->GetDesc(&textureDesc); 3717 3718 if (textureDesc.SampleDesc.Count > 1) 3719 { 3720 D3D11_TEXTURE2D_DESC resolveDesc; 3721 resolveDesc.Width = textureDesc.Width; 3722 resolveDesc.Height = textureDesc.Height; 3723 resolveDesc.MipLevels = 1; 3724 resolveDesc.ArraySize = 1; 3725 resolveDesc.Format = textureDesc.Format; 3726 resolveDesc.SampleDesc.Count = 1; 3727 resolveDesc.SampleDesc.Quality = 0; 3728 resolveDesc.Usage = textureDesc.Usage; 3729 resolveDesc.BindFlags = textureDesc.BindFlags; 3730 resolveDesc.CPUAccessFlags = 0; 3731 resolveDesc.MiscFlags = 0; 3732 3733 ID3D11Texture2D *resolveTexture = NULL; 3734 HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); 3735 if (FAILED(result)) 3736 { 3737 ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); 3738 return NULL; 3739 } 3740 3741 mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); 3742 return resolveTexture; 3743 } 3744 else 3745 { 3746 source->AddRef(); 3747 return source; 3748 } 3749 } 3750 3751 void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) 3752 { 3753 ASSERT(attachment->isTexture()); 3754 TextureStorage *texStorage = attachment->getTextureStorage(); 3755 if (texStorage) 3756 { 3757 TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); 3758 if (!texStorage11) 3759 { 3760 ERR("texture storage pointer unexpectedly null."); 3761 return; 3762 } 3763 3764 texStorage11->invalidateSwizzleCacheLevel(mipLevel); 3765 } 3766 } 3767 3768 void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer) 3769 { 3770 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 3771 { 3772 gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); 3773 if (attachment && attachment->isTexture()) 3774 { 3775 invalidateFBOAttachmentSwizzles(attachment, framebuffer->getColorbufferMipLevel(colorAttachment)); 3776 } 3777 } 3778 3779 gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); 3780 if (depthAttachment && depthAttachment->isTexture()) 3781 { 3782 invalidateFBOAttachmentSwizzles(depthAttachment, framebuffer->getDepthbufferMipLevel()); 3783 } 3784 3785 gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); 3786 if (stencilAttachment && stencilAttachment->isTexture()) 3787 { 3788 invalidateFBOAttachmentSwizzles(stencilAttachment, framebuffer->getStencilbufferMipLevel()); 3789 } 3790 } 3791 3792 bool Renderer11::getLUID(LUID *adapterLuid) const 3793 { 3794 adapterLuid->HighPart = 0; 3795 adapterLuid->LowPart = 0; 3796 3797 if (!mDxgiAdapter) 3798 { 3799 return false; 3800 } 3801 3802 DXGI_ADAPTER_DESC adapterDesc; 3803 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) 3804 { 3805 return false; 3806 } 3807 3808 *adapterLuid = adapterDesc.AdapterLuid; 3809 return true; 3810 } 3811 3812 GLenum Renderer11::getNativeTextureFormat(GLenum internalFormat) const 3813 { 3814 int clientVersion = getCurrentClientVersion(); 3815 return d3d11_gl::GetInternalFormat(gl_d3d11::GetTexFormat(internalFormat, clientVersion), clientVersion); 3816 } 3817 3818 rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const 3819 { 3820 return gl_d3d11::GetVertexConversionType(vertexFormat); 3821 } 3822 3823 GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const 3824 { 3825 return d3d11::GetComponentType(gl_d3d11::GetNativeVertexFormat(vertexFormat)); 3826 } 3827 3828 Renderer11::MultisampleSupportInfo Renderer11::getMultisampleSupportInfo(DXGI_FORMAT format) 3829 { 3830 MultisampleSupportInfo supportInfo = { 0 }; 3831 3832 UINT formatSupport; 3833 HRESULT result; 3834 3835 result = mDevice->CheckFormatSupport(format, &formatSupport); 3836 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) 3837 { 3838 for (unsigned int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) 3839 { 3840 result = mDevice->CheckMultisampleQualityLevels(format, i, &supportInfo.qualityLevels[i - 1]); 3841 if (SUCCEEDED(result) && supportInfo.qualityLevels[i - 1] > 0) 3842 { 3843 supportInfo.maxSupportedSamples = std::max(supportInfo.maxSupportedSamples, i); 3844 } 3845 else 3846 { 3847 supportInfo.qualityLevels[i - 1] = 0; 3848 } 3849 } 3850 } 3851 3852 return supportInfo; 3853 } 3854 3855 } 3856