gfx/angle/src/libGLESv2/renderer/Renderer11.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial