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