1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/Renderer11.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3535 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. 1.12 + 1.13 +#include "libGLESv2/main.h" 1.14 +#include "libGLESv2/utilities.h" 1.15 +#include "libGLESv2/Buffer.h" 1.16 +#include "libGLESv2/ProgramBinary.h" 1.17 +#include "libGLESv2/Framebuffer.h" 1.18 +#include "libGLESv2/Renderbuffer.h" 1.19 +#include "libGLESv2/renderer/Renderer11.h" 1.20 +#include "libGLESv2/renderer/RenderTarget11.h" 1.21 +#include "libGLESv2/renderer/renderer11_utils.h" 1.22 +#include "libGLESv2/renderer/ShaderExecutable11.h" 1.23 +#include "libGLESv2/renderer/SwapChain11.h" 1.24 +#include "libGLESv2/renderer/Image11.h" 1.25 +#include "libGLESv2/renderer/VertexBuffer11.h" 1.26 +#include "libGLESv2/renderer/IndexBuffer11.h" 1.27 +#include "libGLESv2/renderer/BufferStorage11.h" 1.28 +#include "libGLESv2/renderer/VertexDataManager.h" 1.29 +#include "libGLESv2/renderer/IndexDataManager.h" 1.30 +#include "libGLESv2/renderer/TextureStorage11.h" 1.31 +#include "libGLESv2/renderer/Query11.h" 1.32 +#include "libGLESv2/renderer/Fence11.h" 1.33 + 1.34 +#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" 1.35 +#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" 1.36 +#include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h" 1.37 +#include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h" 1.38 +#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h" 1.39 + 1.40 +#include "libGLESv2/renderer/shaders/compiled/clear11vs.h" 1.41 +#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h" 1.42 +#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h" 1.43 + 1.44 +#include "libEGL/Display.h" 1.45 + 1.46 +#ifdef _DEBUG 1.47 +// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples 1.48 +// and conformance tests. to enable all warnings, remove this define. 1.49 +#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 1.50 +#endif 1.51 + 1.52 +namespace rx 1.53 +{ 1.54 +static const DXGI_FORMAT RenderTargetFormats[] = 1.55 + { 1.56 + DXGI_FORMAT_B8G8R8A8_UNORM, 1.57 + DXGI_FORMAT_R8G8B8A8_UNORM 1.58 + }; 1.59 + 1.60 +static const DXGI_FORMAT DepthStencilFormats[] = 1.61 + { 1.62 + DXGI_FORMAT_UNKNOWN, 1.63 + DXGI_FORMAT_D24_UNORM_S8_UINT, 1.64 + DXGI_FORMAT_D16_UNORM 1.65 + }; 1.66 + 1.67 +enum 1.68 +{ 1.69 + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 1.70 +}; 1.71 + 1.72 +Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) 1.73 +{ 1.74 + mVertexDataManager = NULL; 1.75 + mIndexDataManager = NULL; 1.76 + 1.77 + mLineLoopIB = NULL; 1.78 + mTriangleFanIB = NULL; 1.79 + 1.80 + mCopyResourcesInitialized = false; 1.81 + mCopyVB = NULL; 1.82 + mCopySampler = NULL; 1.83 + mCopyIL = NULL; 1.84 + mCopyVS = NULL; 1.85 + mCopyRGBAPS = NULL; 1.86 + mCopyRGBPS = NULL; 1.87 + mCopyLumPS = NULL; 1.88 + mCopyLumAlphaPS = NULL; 1.89 + 1.90 + mClearResourcesInitialized = false; 1.91 + mClearVB = NULL; 1.92 + mClearIL = NULL; 1.93 + mClearVS = NULL; 1.94 + mClearSinglePS = NULL; 1.95 + mClearMultiplePS = NULL; 1.96 + mClearScissorRS = NULL; 1.97 + mClearNoScissorRS = NULL; 1.98 + 1.99 + mSyncQuery = NULL; 1.100 + 1.101 + mD3d11Module = NULL; 1.102 + mDxgiModule = NULL; 1.103 + 1.104 + mDeviceLost = false; 1.105 + 1.106 + mMaxSupportedSamples = 0; 1.107 + 1.108 + mDevice = NULL; 1.109 + mDeviceContext = NULL; 1.110 + mDxgiAdapter = NULL; 1.111 + mDxgiFactory = NULL; 1.112 + 1.113 + mDriverConstantBufferVS = NULL; 1.114 + mDriverConstantBufferPS = NULL; 1.115 + 1.116 + mBGRATextureSupport = false; 1.117 + 1.118 + mIsGeometryShaderActive = false; 1.119 +} 1.120 + 1.121 +Renderer11::~Renderer11() 1.122 +{ 1.123 + release(); 1.124 +} 1.125 + 1.126 +Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) 1.127 +{ 1.128 + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); 1.129 + return static_cast<rx::Renderer11*>(renderer); 1.130 +} 1.131 + 1.132 +#ifndef __d3d11_1_h__ 1.133 +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) 1.134 +#endif 1.135 + 1.136 +EGLint Renderer11::initialize() 1.137 +{ 1.138 + if (!initializeCompiler()) 1.139 + { 1.140 + return EGL_NOT_INITIALIZED; 1.141 + } 1.142 + 1.143 + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); 1.144 + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); 1.145 + 1.146 + if (mD3d11Module == NULL || mDxgiModule == NULL) 1.147 + { 1.148 + ERR("Could not load D3D11 or DXGI library - aborting!\n"); 1.149 + return EGL_NOT_INITIALIZED; 1.150 + } 1.151 + 1.152 + // create the D3D11 device 1.153 + ASSERT(mDevice == NULL); 1.154 + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); 1.155 + 1.156 + if (D3D11CreateDevice == NULL) 1.157 + { 1.158 + ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); 1.159 + return EGL_NOT_INITIALIZED; 1.160 + } 1.161 + 1.162 + D3D_FEATURE_LEVEL featureLevels[] = 1.163 + { 1.164 + D3D_FEATURE_LEVEL_11_0, 1.165 + D3D_FEATURE_LEVEL_10_1, 1.166 + D3D_FEATURE_LEVEL_10_0, 1.167 + }; 1.168 + 1.169 + HRESULT result = S_OK; 1.170 + 1.171 +#ifdef _DEBUG 1.172 + result = D3D11CreateDevice(NULL, 1.173 + D3D_DRIVER_TYPE_HARDWARE, 1.174 + NULL, 1.175 + D3D11_CREATE_DEVICE_DEBUG, 1.176 + featureLevels, 1.177 + ArraySize(featureLevels), 1.178 + D3D11_SDK_VERSION, 1.179 + &mDevice, 1.180 + &mFeatureLevel, 1.181 + &mDeviceContext); 1.182 + 1.183 + if (!mDevice || FAILED(result)) 1.184 + { 1.185 + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); 1.186 + } 1.187 + 1.188 + if (!mDevice || FAILED(result)) 1.189 +#endif 1.190 + { 1.191 + result = D3D11CreateDevice(NULL, 1.192 + D3D_DRIVER_TYPE_HARDWARE, 1.193 + NULL, 1.194 + 0, 1.195 + featureLevels, 1.196 + ArraySize(featureLevels), 1.197 + D3D11_SDK_VERSION, 1.198 + &mDevice, 1.199 + &mFeatureLevel, 1.200 + &mDeviceContext); 1.201 + 1.202 + if (!mDevice || FAILED(result)) 1.203 + { 1.204 + ERR("Could not create D3D11 device - aborting!\n"); 1.205 + return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer 1.206 + } 1.207 + } 1.208 + 1.209 + IDXGIDevice *dxgiDevice = NULL; 1.210 + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); 1.211 + 1.212 + if (FAILED(result)) 1.213 + { 1.214 + ERR("Could not query DXGI device - aborting!\n"); 1.215 + return EGL_NOT_INITIALIZED; 1.216 + } 1.217 + 1.218 + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); 1.219 + 1.220 + if (FAILED(result)) 1.221 + { 1.222 + ERR("Could not retrieve DXGI adapter - aborting!\n"); 1.223 + return EGL_NOT_INITIALIZED; 1.224 + } 1.225 + 1.226 + dxgiDevice->Release(); 1.227 + 1.228 + mDxgiAdapter->GetDesc(&mAdapterDescription); 1.229 + memset(mDescription, 0, sizeof(mDescription)); 1.230 + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); 1.231 + 1.232 + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); 1.233 + 1.234 + if (!mDxgiFactory || FAILED(result)) 1.235 + { 1.236 + ERR("Could not create DXGI factory - aborting!\n"); 1.237 + return EGL_NOT_INITIALIZED; 1.238 + } 1.239 + 1.240 + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log 1.241 +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) 1.242 + ID3D11InfoQueue *infoQueue; 1.243 + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); 1.244 + 1.245 + if (SUCCEEDED(result)) 1.246 + { 1.247 + D3D11_MESSAGE_ID hideMessages[] = 1.248 + { 1.249 + D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD, 1.250 + D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD, 1.251 + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET 1.252 + }; 1.253 + 1.254 + D3D11_INFO_QUEUE_FILTER filter = {0}; 1.255 + filter.DenyList.NumIDs = ArraySize(hideMessages); 1.256 + filter.DenyList.pIDList = hideMessages; 1.257 + 1.258 + infoQueue->AddStorageFilterEntries(&filter); 1.259 + 1.260 + infoQueue->Release(); 1.261 + } 1.262 +#endif 1.263 + 1.264 + unsigned int maxSupportedSamples = 0; 1.265 + unsigned int rtFormatCount = ArraySize(RenderTargetFormats); 1.266 + unsigned int dsFormatCount = ArraySize(DepthStencilFormats); 1.267 + for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) 1.268 + { 1.269 + DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; 1.270 + if (format != DXGI_FORMAT_UNKNOWN) 1.271 + { 1.272 + UINT formatSupport; 1.273 + result = mDevice->CheckFormatSupport(format, &formatSupport); 1.274 + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) 1.275 + { 1.276 + MultisampleSupportInfo supportInfo; 1.277 + 1.278 + for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) 1.279 + { 1.280 + result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); 1.281 + if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) 1.282 + { 1.283 + maxSupportedSamples = std::max(j, maxSupportedSamples); 1.284 + } 1.285 + else 1.286 + { 1.287 + supportInfo.qualityLevels[j - 1] = 0; 1.288 + } 1.289 + } 1.290 + 1.291 + mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); 1.292 + } 1.293 + } 1.294 + } 1.295 + mMaxSupportedSamples = maxSupportedSamples; 1.296 + 1.297 + initializeDevice(); 1.298 + 1.299 + // BGRA texture support is optional in feature levels 10 and 10_1 1.300 + UINT formatSupport; 1.301 + result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); 1.302 + if (FAILED(result)) 1.303 + { 1.304 + ERR("Error checking BGRA format support: 0x%08X", result); 1.305 + } 1.306 + else 1.307 + { 1.308 + const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); 1.309 + mBGRATextureSupport = (formatSupport & flags) == flags; 1.310 + } 1.311 + 1.312 + // Check floating point texture support 1.313 + static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; 1.314 + static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; 1.315 + static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; 1.316 + 1.317 + DXGI_FORMAT float16Formats[] = 1.318 + { 1.319 + DXGI_FORMAT_R16_FLOAT, 1.320 + DXGI_FORMAT_R16G16_FLOAT, 1.321 + DXGI_FORMAT_R16G16B16A16_FLOAT, 1.322 + }; 1.323 + 1.324 + DXGI_FORMAT float32Formats[] = 1.325 + { 1.326 + DXGI_FORMAT_R32_FLOAT, 1.327 + DXGI_FORMAT_R32G32_FLOAT, 1.328 + DXGI_FORMAT_R32G32B32_FLOAT, 1.329 + DXGI_FORMAT_R32G32B32A32_FLOAT, 1.330 + }; 1.331 + 1.332 + mFloat16TextureSupport = true; 1.333 + mFloat16FilterSupport = true; 1.334 + mFloat16RenderSupport = true; 1.335 + for (unsigned int i = 0; i < ArraySize(float16Formats); i++) 1.336 + { 1.337 + if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) 1.338 + { 1.339 + mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; 1.340 + mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; 1.341 + mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; 1.342 + } 1.343 + else 1.344 + { 1.345 + mFloat16TextureSupport = false; 1.346 + mFloat16RenderSupport = false; 1.347 + mFloat16FilterSupport = false; 1.348 + } 1.349 + } 1.350 + 1.351 + mFloat32TextureSupport = true; 1.352 + mFloat32FilterSupport = true; 1.353 + mFloat32RenderSupport = true; 1.354 + for (unsigned int i = 0; i < ArraySize(float32Formats); i++) 1.355 + { 1.356 + if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) 1.357 + { 1.358 + mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; 1.359 + mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; 1.360 + mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; 1.361 + } 1.362 + else 1.363 + { 1.364 + mFloat32TextureSupport = false; 1.365 + mFloat32FilterSupport = false; 1.366 + mFloat32RenderSupport = false; 1.367 + } 1.368 + } 1.369 + 1.370 + // Check compressed texture support 1.371 + const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; 1.372 + 1.373 + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) 1.374 + { 1.375 + mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 1.376 + } 1.377 + else 1.378 + { 1.379 + mDXT1TextureSupport = false; 1.380 + } 1.381 + 1.382 + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) 1.383 + { 1.384 + mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 1.385 + } 1.386 + else 1.387 + { 1.388 + mDXT3TextureSupport = false; 1.389 + } 1.390 + 1.391 + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) 1.392 + { 1.393 + mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; 1.394 + } 1.395 + else 1.396 + { 1.397 + mDXT5TextureSupport = false; 1.398 + } 1.399 + 1.400 + // Check depth texture support 1.401 + DXGI_FORMAT depthTextureFormats[] = 1.402 + { 1.403 + DXGI_FORMAT_D16_UNORM, 1.404 + DXGI_FORMAT_D24_UNORM_S8_UINT, 1.405 + }; 1.406 + 1.407 + static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | 1.408 + D3D11_FORMAT_SUPPORT_TEXTURE2D; 1.409 + 1.410 + mDepthTextureSupport = true; 1.411 + for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) 1.412 + { 1.413 + if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) 1.414 + { 1.415 + mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); 1.416 + } 1.417 + else 1.418 + { 1.419 + mDepthTextureSupport = false; 1.420 + } 1.421 + } 1.422 + 1.423 + return EGL_SUCCESS; 1.424 +} 1.425 + 1.426 +// do any one-time device initialization 1.427 +// NOTE: this is also needed after a device lost/reset 1.428 +// to reset the scene status and ensure the default states are reset. 1.429 +void Renderer11::initializeDevice() 1.430 +{ 1.431 + mStateCache.initialize(mDevice); 1.432 + mInputLayoutCache.initialize(mDevice, mDeviceContext); 1.433 + 1.434 + ASSERT(!mVertexDataManager && !mIndexDataManager); 1.435 + mVertexDataManager = new VertexDataManager(this); 1.436 + mIndexDataManager = new IndexDataManager(this); 1.437 + 1.438 + markAllStateDirty(); 1.439 +} 1.440 + 1.441 +int Renderer11::generateConfigs(ConfigDesc **configDescList) 1.442 +{ 1.443 + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); 1.444 + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); 1.445 + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; 1.446 + int numConfigs = 0; 1.447 + 1.448 + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) 1.449 + { 1.450 + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) 1.451 + { 1.452 + DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; 1.453 + 1.454 + UINT formatSupport = 0; 1.455 + HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); 1.456 + 1.457 + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) 1.458 + { 1.459 + DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; 1.460 + 1.461 + bool depthStencilFormatOK = true; 1.462 + 1.463 + if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) 1.464 + { 1.465 + UINT formatSupport = 0; 1.466 + result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); 1.467 + depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); 1.468 + } 1.469 + 1.470 + if (depthStencilFormatOK) 1.471 + { 1.472 + ConfigDesc newConfig; 1.473 + newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); 1.474 + newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); 1.475 + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling 1.476 + newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast 1.477 + 1.478 + (*configDescList)[numConfigs++] = newConfig; 1.479 + } 1.480 + } 1.481 + } 1.482 + } 1.483 + 1.484 + return numConfigs; 1.485 +} 1.486 + 1.487 +void Renderer11::deleteConfigs(ConfigDesc *configDescList) 1.488 +{ 1.489 + delete [] (configDescList); 1.490 +} 1.491 + 1.492 +void Renderer11::sync(bool block) 1.493 +{ 1.494 + if (block) 1.495 + { 1.496 + HRESULT result; 1.497 + 1.498 + if (!mSyncQuery) 1.499 + { 1.500 + D3D11_QUERY_DESC queryDesc; 1.501 + queryDesc.Query = D3D11_QUERY_EVENT; 1.502 + queryDesc.MiscFlags = 0; 1.503 + 1.504 + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); 1.505 + ASSERT(SUCCEEDED(result)); 1.506 + } 1.507 + 1.508 + mDeviceContext->End(mSyncQuery); 1.509 + mDeviceContext->Flush(); 1.510 + 1.511 + do 1.512 + { 1.513 + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); 1.514 + 1.515 + // Keep polling, but allow other threads to do something useful first 1.516 + Sleep(0); 1.517 + 1.518 + if (testDeviceLost(true)) 1.519 + { 1.520 + return; 1.521 + } 1.522 + } 1.523 + while (result == S_FALSE); 1.524 + } 1.525 + else 1.526 + { 1.527 + mDeviceContext->Flush(); 1.528 + } 1.529 +} 1.530 + 1.531 +SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) 1.532 +{ 1.533 + return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); 1.534 +} 1.535 + 1.536 +void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) 1.537 +{ 1.538 + if (type == gl::SAMPLER_PIXEL) 1.539 + { 1.540 + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) 1.541 + { 1.542 + ERR("Pixel shader sampler index %i is not valid.", index); 1.543 + return; 1.544 + } 1.545 + 1.546 + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) 1.547 + { 1.548 + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); 1.549 + 1.550 + if (!dxSamplerState) 1.551 + { 1.552 + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" 1.553 + "sampler state for pixel shaders at slot %i.", index); 1.554 + } 1.555 + 1.556 + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); 1.557 + 1.558 + mCurPixelSamplerStates[index] = samplerState; 1.559 + } 1.560 + 1.561 + mForceSetPixelSamplerStates[index] = false; 1.562 + } 1.563 + else if (type == gl::SAMPLER_VERTEX) 1.564 + { 1.565 + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) 1.566 + { 1.567 + ERR("Vertex shader sampler index %i is not valid.", index); 1.568 + return; 1.569 + } 1.570 + 1.571 + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) 1.572 + { 1.573 + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); 1.574 + 1.575 + if (!dxSamplerState) 1.576 + { 1.577 + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" 1.578 + "sampler state for vertex shaders at slot %i.", index); 1.579 + } 1.580 + 1.581 + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); 1.582 + 1.583 + mCurVertexSamplerStates[index] = samplerState; 1.584 + } 1.585 + 1.586 + mForceSetVertexSamplerStates[index] = false; 1.587 + } 1.588 + else UNREACHABLE(); 1.589 +} 1.590 + 1.591 +void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) 1.592 +{ 1.593 + ID3D11ShaderResourceView *textureSRV = NULL; 1.594 + unsigned int serial = 0; 1.595 + bool forceSetTexture = false; 1.596 + 1.597 + if (texture) 1.598 + { 1.599 + TextureStorageInterface *texStorage = texture->getNativeTexture(); 1.600 + if (texStorage) 1.601 + { 1.602 + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); 1.603 + textureSRV = storage11->getSRV(); 1.604 + } 1.605 + 1.606 + // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly 1.607 + // missing the shader resource view 1.608 + ASSERT(textureSRV != NULL); 1.609 + 1.610 + serial = texture->getTextureSerial(); 1.611 + forceSetTexture = texture->hasDirtyImages(); 1.612 + } 1.613 + 1.614 + if (type == gl::SAMPLER_PIXEL) 1.615 + { 1.616 + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) 1.617 + { 1.618 + ERR("Pixel shader sampler index %i is not valid.", index); 1.619 + return; 1.620 + } 1.621 + 1.622 + if (forceSetTexture || mCurPixelTextureSerials[index] != serial) 1.623 + { 1.624 + mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); 1.625 + } 1.626 + 1.627 + mCurPixelTextureSerials[index] = serial; 1.628 + } 1.629 + else if (type == gl::SAMPLER_VERTEX) 1.630 + { 1.631 + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) 1.632 + { 1.633 + ERR("Vertex shader sampler index %i is not valid.", index); 1.634 + return; 1.635 + } 1.636 + 1.637 + if (forceSetTexture || mCurVertexTextureSerials[index] != serial) 1.638 + { 1.639 + mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); 1.640 + } 1.641 + 1.642 + mCurVertexTextureSerials[index] = serial; 1.643 + } 1.644 + else UNREACHABLE(); 1.645 +} 1.646 + 1.647 +void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) 1.648 +{ 1.649 + if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) 1.650 + { 1.651 + ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, 1.652 + mCurDepthSize); 1.653 + if (!dxRasterState) 1.654 + { 1.655 + ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" 1.656 + "rasterizer state."); 1.657 + } 1.658 + 1.659 + mDeviceContext->RSSetState(dxRasterState); 1.660 + 1.661 + mCurRasterState = rasterState; 1.662 + } 1.663 + 1.664 + mForceSetRasterState = false; 1.665 +} 1.666 + 1.667 +void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, 1.668 + unsigned int sampleMask) 1.669 +{ 1.670 + if (mForceSetBlendState || 1.671 + memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || 1.672 + memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || 1.673 + sampleMask != mCurSampleMask) 1.674 + { 1.675 + ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState); 1.676 + if (!dxBlendState) 1.677 + { 1.678 + ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " 1.679 + "blend state."); 1.680 + } 1.681 + 1.682 + float blendColors[4] = {0.0f}; 1.683 + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 1.684 + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 1.685 + { 1.686 + blendColors[0] = blendColor.red; 1.687 + blendColors[1] = blendColor.green; 1.688 + blendColors[2] = blendColor.blue; 1.689 + blendColors[3] = blendColor.alpha; 1.690 + } 1.691 + else 1.692 + { 1.693 + blendColors[0] = blendColor.alpha; 1.694 + blendColors[1] = blendColor.alpha; 1.695 + blendColors[2] = blendColor.alpha; 1.696 + blendColors[3] = blendColor.alpha; 1.697 + } 1.698 + 1.699 + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); 1.700 + 1.701 + mCurBlendState = blendState; 1.702 + mCurBlendColor = blendColor; 1.703 + mCurSampleMask = sampleMask; 1.704 + } 1.705 + 1.706 + mForceSetBlendState = false; 1.707 +} 1.708 + 1.709 +void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, 1.710 + int stencilBackRef, bool frontFaceCCW) 1.711 +{ 1.712 + if (mForceSetDepthStencilState || 1.713 + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || 1.714 + stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) 1.715 + { 1.716 + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || 1.717 + stencilRef != stencilBackRef || 1.718 + depthStencilState.stencilMask != depthStencilState.stencilBackMask) 1.719 + { 1.720 + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " 1.721 + "invalid under WebGL."); 1.722 + return gl::error(GL_INVALID_OPERATION); 1.723 + } 1.724 + 1.725 + ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); 1.726 + if (!dxDepthStencilState) 1.727 + { 1.728 + ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " 1.729 + "setting the default depth stencil state."); 1.730 + } 1.731 + 1.732 + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef)); 1.733 + 1.734 + mCurDepthStencilState = depthStencilState; 1.735 + mCurStencilRef = stencilRef; 1.736 + mCurStencilBackRef = stencilBackRef; 1.737 + } 1.738 + 1.739 + mForceSetDepthStencilState = false; 1.740 +} 1.741 + 1.742 +void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) 1.743 +{ 1.744 + if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || 1.745 + enabled != mScissorEnabled) 1.746 + { 1.747 + if (enabled) 1.748 + { 1.749 + D3D11_RECT rect; 1.750 + rect.left = std::max(0, scissor.x); 1.751 + rect.top = std::max(0, scissor.y); 1.752 + rect.right = scissor.x + std::max(0, scissor.width); 1.753 + rect.bottom = scissor.y + std::max(0, scissor.height); 1.754 + 1.755 + mDeviceContext->RSSetScissorRects(1, &rect); 1.756 + } 1.757 + 1.758 + if (enabled != mScissorEnabled) 1.759 + { 1.760 + mForceSetRasterState = true; 1.761 + } 1.762 + 1.763 + mCurScissor = scissor; 1.764 + mScissorEnabled = enabled; 1.765 + } 1.766 + 1.767 + mForceSetScissor = false; 1.768 +} 1.769 + 1.770 +bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, 1.771 + bool ignoreViewport) 1.772 +{ 1.773 + gl::Rectangle actualViewport = viewport; 1.774 + float actualZNear = gl::clamp01(zNear); 1.775 + float actualZFar = gl::clamp01(zFar); 1.776 + if (ignoreViewport) 1.777 + { 1.778 + actualViewport.x = 0; 1.779 + actualViewport.y = 0; 1.780 + actualViewport.width = mRenderTargetDesc.width; 1.781 + actualViewport.height = mRenderTargetDesc.height; 1.782 + actualZNear = 0.0f; 1.783 + actualZFar = 1.0f; 1.784 + } 1.785 + 1.786 + // Get D3D viewport bounds, which depends on the feature level 1.787 + const Range& viewportBounds = getViewportBounds(); 1.788 + 1.789 + // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds 1.790 + D3D11_VIEWPORT dxViewport; 1.791 + dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); 1.792 + dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); 1.793 + dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); 1.794 + dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); 1.795 + dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX)); 1.796 + dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY)); 1.797 + dxViewport.MinDepth = actualZNear; 1.798 + dxViewport.MaxDepth = actualZFar; 1.799 + 1.800 + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) 1.801 + { 1.802 + return false; // Nothing to render 1.803 + } 1.804 + 1.805 + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || 1.806 + actualZNear != mCurNear || actualZFar != mCurFar; 1.807 + 1.808 + if (viewportChanged) 1.809 + { 1.810 + mDeviceContext->RSSetViewports(1, &dxViewport); 1.811 + 1.812 + mCurViewport = actualViewport; 1.813 + mCurNear = actualZNear; 1.814 + mCurFar = actualZFar; 1.815 + 1.816 + mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; 1.817 + mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; 1.818 + mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); 1.819 + mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); 1.820 + 1.821 + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; 1.822 + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; 1.823 + 1.824 + mVertexConstants.depthRange[0] = actualZNear; 1.825 + mVertexConstants.depthRange[1] = actualZFar; 1.826 + mVertexConstants.depthRange[2] = actualZFar - actualZNear; 1.827 + 1.828 + mPixelConstants.depthRange[0] = actualZNear; 1.829 + mPixelConstants.depthRange[1] = actualZFar; 1.830 + mPixelConstants.depthRange[2] = actualZFar - actualZNear; 1.831 + } 1.832 + 1.833 + mForceSetViewport = false; 1.834 + return true; 1.835 +} 1.836 + 1.837 +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) 1.838 +{ 1.839 + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; 1.840 + 1.841 + GLsizei minCount = 0; 1.842 + 1.843 + switch (mode) 1.844 + { 1.845 + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; 1.846 + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; 1.847 + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; 1.848 + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; 1.849 + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; 1.850 + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; 1.851 + // emulate fans via rewriting index buffer 1.852 + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; 1.853 + default: 1.854 + return gl::error(GL_INVALID_ENUM, false); 1.855 + } 1.856 + 1.857 + if (primitiveTopology != mCurrentPrimitiveTopology) 1.858 + { 1.859 + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); 1.860 + mCurrentPrimitiveTopology = primitiveTopology; 1.861 + } 1.862 + 1.863 + return count >= minCount; 1.864 +} 1.865 + 1.866 +bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) 1.867 +{ 1.868 + // Get the color render buffer and serial 1.869 + // Also extract the render target dimensions and view 1.870 + unsigned int renderTargetWidth = 0; 1.871 + unsigned int renderTargetHeight = 0; 1.872 + GLenum renderTargetFormat = 0; 1.873 + unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; 1.874 + ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; 1.875 + bool missingColorRenderTarget = true; 1.876 + 1.877 + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 1.878 + { 1.879 + const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); 1.880 + 1.881 + if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) 1.882 + { 1.883 + // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) 1.884 + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); 1.885 + 1.886 + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); 1.887 + 1.888 + if (!colorbuffer) 1.889 + { 1.890 + ERR("render target pointer unexpectedly null."); 1.891 + return false; 1.892 + } 1.893 + 1.894 + // check for zero-sized default framebuffer, which is a special case. 1.895 + // in this case we do not wish to modify any state and just silently return false. 1.896 + // this will not report any gl error but will cause the calling method to return. 1.897 + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) 1.898 + { 1.899 + return false; 1.900 + } 1.901 + 1.902 + renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); 1.903 + 1.904 + // Extract the render target dimensions and view 1.905 + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 1.906 + if (!renderTarget) 1.907 + { 1.908 + ERR("render target pointer unexpectedly null."); 1.909 + return false; 1.910 + } 1.911 + 1.912 + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); 1.913 + if (!framebufferRTVs[colorAttachment]) 1.914 + { 1.915 + ERR("render target view pointer unexpectedly null."); 1.916 + return false; 1.917 + } 1.918 + 1.919 + if (missingColorRenderTarget) 1.920 + { 1.921 + renderTargetWidth = colorbuffer->getWidth(); 1.922 + renderTargetHeight = colorbuffer->getHeight(); 1.923 + renderTargetFormat = colorbuffer->getActualFormat(); 1.924 + missingColorRenderTarget = false; 1.925 + } 1.926 + } 1.927 + } 1.928 + 1.929 + // Get the depth stencil render buffer and serials 1.930 + gl::Renderbuffer *depthStencil = NULL; 1.931 + unsigned int depthbufferSerial = 0; 1.932 + unsigned int stencilbufferSerial = 0; 1.933 + if (framebuffer->getDepthbufferType() != GL_NONE) 1.934 + { 1.935 + depthStencil = framebuffer->getDepthbuffer(); 1.936 + if (!depthStencil) 1.937 + { 1.938 + ERR("Depth stencil pointer unexpectedly null."); 1.939 + SafeRelease(framebufferRTVs); 1.940 + return false; 1.941 + } 1.942 + 1.943 + depthbufferSerial = depthStencil->getSerial(); 1.944 + } 1.945 + else if (framebuffer->getStencilbufferType() != GL_NONE) 1.946 + { 1.947 + depthStencil = framebuffer->getStencilbuffer(); 1.948 + if (!depthStencil) 1.949 + { 1.950 + ERR("Depth stencil pointer unexpectedly null."); 1.951 + SafeRelease(framebufferRTVs); 1.952 + return false; 1.953 + } 1.954 + 1.955 + stencilbufferSerial = depthStencil->getSerial(); 1.956 + } 1.957 + 1.958 + // Extract the depth stencil sizes and view 1.959 + unsigned int depthSize = 0; 1.960 + unsigned int stencilSize = 0; 1.961 + ID3D11DepthStencilView* framebufferDSV = NULL; 1.962 + if (depthStencil) 1.963 + { 1.964 + RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); 1.965 + if (!depthStencilRenderTarget) 1.966 + { 1.967 + ERR("render target pointer unexpectedly null."); 1.968 + SafeRelease(framebufferRTVs); 1.969 + return false; 1.970 + } 1.971 + 1.972 + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); 1.973 + if (!framebufferDSV) 1.974 + { 1.975 + ERR("depth stencil view pointer unexpectedly null."); 1.976 + SafeRelease(framebufferRTVs); 1.977 + return false; 1.978 + } 1.979 + 1.980 + // If there is no render buffer, the width, height and format values come from 1.981 + // the depth stencil 1.982 + if (missingColorRenderTarget) 1.983 + { 1.984 + renderTargetWidth = depthStencil->getWidth(); 1.985 + renderTargetHeight = depthStencil->getHeight(); 1.986 + renderTargetFormat = depthStencil->getActualFormat(); 1.987 + } 1.988 + 1.989 + depthSize = depthStencil->getDepthSize(); 1.990 + stencilSize = depthStencil->getStencilSize(); 1.991 + } 1.992 + 1.993 + // Apply the render target and depth stencil 1.994 + if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || 1.995 + memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || 1.996 + depthbufferSerial != mAppliedDepthbufferSerial || 1.997 + stencilbufferSerial != mAppliedStencilbufferSerial) 1.998 + { 1.999 + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); 1.1000 + 1.1001 + mRenderTargetDesc.width = renderTargetWidth; 1.1002 + mRenderTargetDesc.height = renderTargetHeight; 1.1003 + mRenderTargetDesc.format = renderTargetFormat; 1.1004 + mForceSetViewport = true; 1.1005 + mForceSetScissor = true; 1.1006 + 1.1007 + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) 1.1008 + { 1.1009 + mCurDepthSize = depthSize; 1.1010 + mForceSetRasterState = true; 1.1011 + } 1.1012 + 1.1013 + mCurStencilSize = stencilSize; 1.1014 + 1.1015 + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 1.1016 + { 1.1017 + mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; 1.1018 + } 1.1019 + mAppliedDepthbufferSerial = depthbufferSerial; 1.1020 + mAppliedStencilbufferSerial = stencilbufferSerial; 1.1021 + mRenderTargetDescInitialized = true; 1.1022 + mDepthStencilInitialized = true; 1.1023 + } 1.1024 + 1.1025 + return true; 1.1026 +} 1.1027 + 1.1028 +GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) 1.1029 +{ 1.1030 + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; 1.1031 + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); 1.1032 + if (err != GL_NO_ERROR) 1.1033 + { 1.1034 + return err; 1.1035 + } 1.1036 + 1.1037 + return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); 1.1038 +} 1.1039 + 1.1040 +GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) 1.1041 +{ 1.1042 + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); 1.1043 + 1.1044 + if (err == GL_NO_ERROR) 1.1045 + { 1.1046 + if (indexInfo->storage) 1.1047 + { 1.1048 + if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) 1.1049 + { 1.1050 + BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); 1.1051 + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); 1.1052 + 1.1053 + mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); 1.1054 + 1.1055 + mAppliedIBSerial = 0; 1.1056 + mAppliedStorageIBSerial = storage->getSerial(); 1.1057 + mAppliedIBOffset = indexInfo->startOffset; 1.1058 + } 1.1059 + } 1.1060 + else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) 1.1061 + { 1.1062 + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); 1.1063 + 1.1064 + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); 1.1065 + 1.1066 + mAppliedIBSerial = indexInfo->serial; 1.1067 + mAppliedStorageIBSerial = 0; 1.1068 + mAppliedIBOffset = indexInfo->startOffset; 1.1069 + } 1.1070 + } 1.1071 + 1.1072 + return err; 1.1073 +} 1.1074 + 1.1075 +void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) 1.1076 +{ 1.1077 + if (mode == GL_LINE_LOOP) 1.1078 + { 1.1079 + drawLineLoop(count, GL_NONE, NULL, 0, NULL); 1.1080 + } 1.1081 + else if (mode == GL_TRIANGLE_FAN) 1.1082 + { 1.1083 + drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); 1.1084 + } 1.1085 + else if (instances > 0) 1.1086 + { 1.1087 + mDeviceContext->DrawInstanced(count, instances, 0, 0); 1.1088 + } 1.1089 + else 1.1090 + { 1.1091 + mDeviceContext->Draw(count, 0); 1.1092 + } 1.1093 +} 1.1094 + 1.1095 +void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) 1.1096 +{ 1.1097 + if (mode == GL_LINE_LOOP) 1.1098 + { 1.1099 + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); 1.1100 + } 1.1101 + else if (mode == GL_TRIANGLE_FAN) 1.1102 + { 1.1103 + drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); 1.1104 + } 1.1105 + else if (instances > 0) 1.1106 + { 1.1107 + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0); 1.1108 + } 1.1109 + else 1.1110 + { 1.1111 + mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex)); 1.1112 + } 1.1113 +} 1.1114 + 1.1115 +void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) 1.1116 +{ 1.1117 + // Get the raw indices for an indexed draw 1.1118 + if (type != GL_NONE && elementArrayBuffer) 1.1119 + { 1.1120 + gl::Buffer *indexBuffer = elementArrayBuffer; 1.1121 + BufferStorage *storage = indexBuffer->getStorage(); 1.1122 + intptr_t offset = reinterpret_cast<intptr_t>(indices); 1.1123 + indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1.1124 + } 1.1125 + 1.1126 + if (!mLineLoopIB) 1.1127 + { 1.1128 + mLineLoopIB = new StreamingIndexBufferInterface(this); 1.1129 + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) 1.1130 + { 1.1131 + delete mLineLoopIB; 1.1132 + mLineLoopIB = NULL; 1.1133 + 1.1134 + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); 1.1135 + return gl::error(GL_OUT_OF_MEMORY); 1.1136 + } 1.1137 + } 1.1138 + 1.1139 + // Checked by Renderer11::applyPrimitiveType 1.1140 + ASSERT(count >= 0); 1.1141 + 1.1142 + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) 1.1143 + { 1.1144 + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); 1.1145 + return gl::error(GL_OUT_OF_MEMORY); 1.1146 + } 1.1147 + 1.1148 + const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); 1.1149 + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) 1.1150 + { 1.1151 + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); 1.1152 + return gl::error(GL_OUT_OF_MEMORY); 1.1153 + } 1.1154 + 1.1155 + void* mappedMemory = NULL; 1.1156 + unsigned int offset; 1.1157 + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1.1158 + { 1.1159 + ERR("Could not map index buffer for GL_LINE_LOOP."); 1.1160 + return gl::error(GL_OUT_OF_MEMORY); 1.1161 + } 1.1162 + 1.1163 + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1.1164 + unsigned int indexBufferOffset = offset; 1.1165 + 1.1166 + switch (type) 1.1167 + { 1.1168 + case GL_NONE: // Non-indexed draw 1.1169 + for (int i = 0; i < count; i++) 1.1170 + { 1.1171 + data[i] = i; 1.1172 + } 1.1173 + data[count] = 0; 1.1174 + break; 1.1175 + case GL_UNSIGNED_BYTE: 1.1176 + for (int i = 0; i < count; i++) 1.1177 + { 1.1178 + data[i] = static_cast<const GLubyte*>(indices)[i]; 1.1179 + } 1.1180 + data[count] = static_cast<const GLubyte*>(indices)[0]; 1.1181 + break; 1.1182 + case GL_UNSIGNED_SHORT: 1.1183 + for (int i = 0; i < count; i++) 1.1184 + { 1.1185 + data[i] = static_cast<const GLushort*>(indices)[i]; 1.1186 + } 1.1187 + data[count] = static_cast<const GLushort*>(indices)[0]; 1.1188 + break; 1.1189 + case GL_UNSIGNED_INT: 1.1190 + for (int i = 0; i < count; i++) 1.1191 + { 1.1192 + data[i] = static_cast<const GLuint*>(indices)[i]; 1.1193 + } 1.1194 + data[count] = static_cast<const GLuint*>(indices)[0]; 1.1195 + break; 1.1196 + default: UNREACHABLE(); 1.1197 + } 1.1198 + 1.1199 + if (!mLineLoopIB->unmapBuffer()) 1.1200 + { 1.1201 + ERR("Could not unmap index buffer for GL_LINE_LOOP."); 1.1202 + return gl::error(GL_OUT_OF_MEMORY); 1.1203 + } 1.1204 + 1.1205 + if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) 1.1206 + { 1.1207 + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); 1.1208 + 1.1209 + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); 1.1210 + mAppliedIBSerial = mLineLoopIB->getSerial(); 1.1211 + mAppliedStorageIBSerial = 0; 1.1212 + mAppliedIBOffset = indexBufferOffset; 1.1213 + } 1.1214 + 1.1215 + mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); 1.1216 +} 1.1217 + 1.1218 +void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) 1.1219 +{ 1.1220 + // Get the raw indices for an indexed draw 1.1221 + if (type != GL_NONE && elementArrayBuffer) 1.1222 + { 1.1223 + gl::Buffer *indexBuffer = elementArrayBuffer; 1.1224 + BufferStorage *storage = indexBuffer->getStorage(); 1.1225 + intptr_t offset = reinterpret_cast<intptr_t>(indices); 1.1226 + indices = static_cast<const GLubyte*>(storage->getData()) + offset; 1.1227 + } 1.1228 + 1.1229 + if (!mTriangleFanIB) 1.1230 + { 1.1231 + mTriangleFanIB = new StreamingIndexBufferInterface(this); 1.1232 + if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) 1.1233 + { 1.1234 + delete mTriangleFanIB; 1.1235 + mTriangleFanIB = NULL; 1.1236 + 1.1237 + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); 1.1238 + return gl::error(GL_OUT_OF_MEMORY); 1.1239 + } 1.1240 + } 1.1241 + 1.1242 + // Checked by Renderer11::applyPrimitiveType 1.1243 + ASSERT(count >= 3); 1.1244 + 1.1245 + const unsigned int numTris = count - 2; 1.1246 + 1.1247 + if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) 1.1248 + { 1.1249 + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); 1.1250 + return gl::error(GL_OUT_OF_MEMORY); 1.1251 + } 1.1252 + 1.1253 + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); 1.1254 + if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) 1.1255 + { 1.1256 + ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); 1.1257 + return gl::error(GL_OUT_OF_MEMORY); 1.1258 + } 1.1259 + 1.1260 + void* mappedMemory = NULL; 1.1261 + unsigned int offset; 1.1262 + if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) 1.1263 + { 1.1264 + ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); 1.1265 + return gl::error(GL_OUT_OF_MEMORY); 1.1266 + } 1.1267 + 1.1268 + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); 1.1269 + unsigned int indexBufferOffset = offset; 1.1270 + 1.1271 + switch (type) 1.1272 + { 1.1273 + case GL_NONE: // Non-indexed draw 1.1274 + for (unsigned int i = 0; i < numTris; i++) 1.1275 + { 1.1276 + data[i*3 + 0] = 0; 1.1277 + data[i*3 + 1] = i + 1; 1.1278 + data[i*3 + 2] = i + 2; 1.1279 + } 1.1280 + break; 1.1281 + case GL_UNSIGNED_BYTE: 1.1282 + for (unsigned int i = 0; i < numTris; i++) 1.1283 + { 1.1284 + data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0]; 1.1285 + data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1]; 1.1286 + data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2]; 1.1287 + } 1.1288 + break; 1.1289 + case GL_UNSIGNED_SHORT: 1.1290 + for (unsigned int i = 0; i < numTris; i++) 1.1291 + { 1.1292 + data[i*3 + 0] = static_cast<const GLushort*>(indices)[0]; 1.1293 + data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1]; 1.1294 + data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2]; 1.1295 + } 1.1296 + break; 1.1297 + case GL_UNSIGNED_INT: 1.1298 + for (unsigned int i = 0; i < numTris; i++) 1.1299 + { 1.1300 + data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; 1.1301 + data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; 1.1302 + data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2]; 1.1303 + } 1.1304 + break; 1.1305 + default: UNREACHABLE(); 1.1306 + } 1.1307 + 1.1308 + if (!mTriangleFanIB->unmapBuffer()) 1.1309 + { 1.1310 + ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); 1.1311 + return gl::error(GL_OUT_OF_MEMORY); 1.1312 + } 1.1313 + 1.1314 + if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) 1.1315 + { 1.1316 + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); 1.1317 + 1.1318 + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); 1.1319 + mAppliedIBSerial = mTriangleFanIB->getSerial(); 1.1320 + mAppliedStorageIBSerial = 0; 1.1321 + mAppliedIBOffset = indexBufferOffset; 1.1322 + } 1.1323 + 1.1324 + if (instances > 0) 1.1325 + { 1.1326 + mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); 1.1327 + } 1.1328 + else 1.1329 + { 1.1330 + mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); 1.1331 + } 1.1332 +} 1.1333 + 1.1334 +void Renderer11::applyShaders(gl::ProgramBinary *programBinary) 1.1335 +{ 1.1336 + unsigned int programBinarySerial = programBinary->getSerial(); 1.1337 + const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); 1.1338 + 1.1339 + if (updateProgramState) 1.1340 + { 1.1341 + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); 1.1342 + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); 1.1343 + 1.1344 + ID3D11VertexShader *vertexShader = NULL; 1.1345 + if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); 1.1346 + 1.1347 + ID3D11PixelShader *pixelShader = NULL; 1.1348 + if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); 1.1349 + 1.1350 + mDeviceContext->PSSetShader(pixelShader, NULL, 0); 1.1351 + mDeviceContext->VSSetShader(vertexShader, NULL, 0); 1.1352 + 1.1353 + programBinary->dirtyAllUniforms(); 1.1354 + 1.1355 + mAppliedProgramBinarySerial = programBinarySerial; 1.1356 + } 1.1357 + 1.1358 + // Only use the geometry shader currently for point sprite drawing 1.1359 + const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); 1.1360 + 1.1361 + if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) 1.1362 + { 1.1363 + if (usesGeometryShader) 1.1364 + { 1.1365 + ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); 1.1366 + ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); 1.1367 + mDeviceContext->GSSetShader(geometryShader, NULL, 0); 1.1368 + } 1.1369 + else 1.1370 + { 1.1371 + mDeviceContext->GSSetShader(NULL, NULL, 0); 1.1372 + } 1.1373 + 1.1374 + mIsGeometryShaderActive = usesGeometryShader; 1.1375 + } 1.1376 +} 1.1377 + 1.1378 +void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) 1.1379 +{ 1.1380 + ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); 1.1381 + ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); 1.1382 + 1.1383 + unsigned int totalRegisterCountVS = 0; 1.1384 + unsigned int totalRegisterCountPS = 0; 1.1385 + 1.1386 + bool vertexUniformsDirty = false; 1.1387 + bool pixelUniformsDirty = false; 1.1388 + 1.1389 + for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) 1.1390 + { 1.1391 + const gl::Uniform *uniform = *uniform_iterator; 1.1392 + 1.1393 + if (uniform->vsRegisterIndex >= 0) 1.1394 + { 1.1395 + totalRegisterCountVS += uniform->registerCount; 1.1396 + vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; 1.1397 + } 1.1398 + 1.1399 + if (uniform->psRegisterIndex >= 0) 1.1400 + { 1.1401 + totalRegisterCountPS += uniform->registerCount; 1.1402 + pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; 1.1403 + } 1.1404 + } 1.1405 + 1.1406 + ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); 1.1407 + ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); 1.1408 + 1.1409 + float (*mapVS)[4] = NULL; 1.1410 + float (*mapPS)[4] = NULL; 1.1411 + 1.1412 + if (totalRegisterCountVS > 0 && vertexUniformsDirty) 1.1413 + { 1.1414 + D3D11_MAPPED_SUBRESOURCE map = {0}; 1.1415 + HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); 1.1416 + ASSERT(SUCCEEDED(result)); 1.1417 + mapVS = (float(*)[4])map.pData; 1.1418 + } 1.1419 + 1.1420 + if (totalRegisterCountPS > 0 && pixelUniformsDirty) 1.1421 + { 1.1422 + D3D11_MAPPED_SUBRESOURCE map = {0}; 1.1423 + HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); 1.1424 + ASSERT(SUCCEEDED(result)); 1.1425 + mapPS = (float(*)[4])map.pData; 1.1426 + } 1.1427 + 1.1428 + for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) 1.1429 + { 1.1430 + gl::Uniform *uniform = *uniform_iterator; 1.1431 + 1.1432 + if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) 1.1433 + { 1.1434 + if (uniform->vsRegisterIndex >= 0 && mapVS) 1.1435 + { 1.1436 + memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); 1.1437 + } 1.1438 + 1.1439 + if (uniform->psRegisterIndex >= 0 && mapPS) 1.1440 + { 1.1441 + memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); 1.1442 + } 1.1443 + } 1.1444 + 1.1445 + uniform->dirty = false; 1.1446 + } 1.1447 + 1.1448 + if (mapVS) 1.1449 + { 1.1450 + mDeviceContext->Unmap(vertexConstantBuffer, 0); 1.1451 + } 1.1452 + 1.1453 + if (mapPS) 1.1454 + { 1.1455 + mDeviceContext->Unmap(pixelConstantBuffer, 0); 1.1456 + } 1.1457 + 1.1458 + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) 1.1459 + { 1.1460 + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); 1.1461 + mCurrentVertexConstantBuffer = vertexConstantBuffer; 1.1462 + } 1.1463 + 1.1464 + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) 1.1465 + { 1.1466 + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); 1.1467 + mCurrentPixelConstantBuffer = pixelConstantBuffer; 1.1468 + } 1.1469 + 1.1470 + // Driver uniforms 1.1471 + if (!mDriverConstantBufferVS) 1.1472 + { 1.1473 + D3D11_BUFFER_DESC constantBufferDescription = {0}; 1.1474 + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); 1.1475 + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; 1.1476 + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 1.1477 + constantBufferDescription.CPUAccessFlags = 0; 1.1478 + constantBufferDescription.MiscFlags = 0; 1.1479 + constantBufferDescription.StructureByteStride = 0; 1.1480 + 1.1481 + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); 1.1482 + ASSERT(SUCCEEDED(result)); 1.1483 + 1.1484 + mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); 1.1485 + } 1.1486 + 1.1487 + if (!mDriverConstantBufferPS) 1.1488 + { 1.1489 + D3D11_BUFFER_DESC constantBufferDescription = {0}; 1.1490 + constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); 1.1491 + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; 1.1492 + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 1.1493 + constantBufferDescription.CPUAccessFlags = 0; 1.1494 + constantBufferDescription.MiscFlags = 0; 1.1495 + constantBufferDescription.StructureByteStride = 0; 1.1496 + 1.1497 + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); 1.1498 + ASSERT(SUCCEEDED(result)); 1.1499 + 1.1500 + mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); 1.1501 + } 1.1502 + 1.1503 + if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) 1.1504 + { 1.1505 + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); 1.1506 + memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); 1.1507 + } 1.1508 + 1.1509 + if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) 1.1510 + { 1.1511 + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); 1.1512 + memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); 1.1513 + } 1.1514 + 1.1515 + // needed for the point sprite geometry shader 1.1516 + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) 1.1517 + { 1.1518 + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); 1.1519 + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; 1.1520 + } 1.1521 +} 1.1522 + 1.1523 +void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) 1.1524 +{ 1.1525 + bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; 1.1526 + bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && 1.1527 + !(clearParams.colorMaskRed && clearParams.colorMaskGreen && 1.1528 + clearParams.colorMaskBlue && alphaUnmasked); 1.1529 + 1.1530 + unsigned int stencilUnmasked = 0x0; 1.1531 + if (frameBuffer->hasStencil()) 1.1532 + { 1.1533 + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); 1.1534 + stencilUnmasked = (0x1 << stencilSize) - 1; 1.1535 + } 1.1536 + bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && 1.1537 + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; 1.1538 + 1.1539 + bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || 1.1540 + mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || 1.1541 + mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); 1.1542 + 1.1543 + if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) 1.1544 + { 1.1545 + maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers()); 1.1546 + } 1.1547 + else 1.1548 + { 1.1549 + if (clearParams.mask & GL_COLOR_BUFFER_BIT) 1.1550 + { 1.1551 + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 1.1552 + { 1.1553 + if (frameBuffer->isEnabledColorAttachment(colorAttachment)) 1.1554 + { 1.1555 + gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); 1.1556 + if (renderbufferObject) 1.1557 + { 1.1558 + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); 1.1559 + if (!renderTarget) 1.1560 + { 1.1561 + ERR("render target pointer unexpectedly null."); 1.1562 + return; 1.1563 + } 1.1564 + 1.1565 + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); 1.1566 + if (!framebufferRTV) 1.1567 + { 1.1568 + ERR("render target view pointer unexpectedly null."); 1.1569 + return; 1.1570 + } 1.1571 + 1.1572 + const float clearValues[4] = { clearParams.colorClearValue.red, 1.1573 + clearParams.colorClearValue.green, 1.1574 + clearParams.colorClearValue.blue, 1.1575 + clearParams.colorClearValue.alpha }; 1.1576 + mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); 1.1577 + } 1.1578 + } 1.1579 + } 1.1580 + } 1.1581 + if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) 1.1582 + { 1.1583 + gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); 1.1584 + if (renderbufferObject) 1.1585 + { 1.1586 + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); 1.1587 + if (!renderTarget) 1.1588 + { 1.1589 + ERR("render target pointer unexpectedly null."); 1.1590 + return; 1.1591 + } 1.1592 + 1.1593 + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); 1.1594 + if (!framebufferDSV) 1.1595 + { 1.1596 + ERR("depth stencil view pointer unexpectedly null."); 1.1597 + return; 1.1598 + } 1.1599 + 1.1600 + UINT clearFlags = 0; 1.1601 + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) 1.1602 + { 1.1603 + clearFlags |= D3D11_CLEAR_DEPTH; 1.1604 + } 1.1605 + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) 1.1606 + { 1.1607 + clearFlags |= D3D11_CLEAR_STENCIL; 1.1608 + } 1.1609 + 1.1610 + float depthClear = gl::clamp01(clearParams.depthClearValue); 1.1611 + UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; 1.1612 + 1.1613 + mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); 1.1614 + } 1.1615 + } 1.1616 + } 1.1617 +} 1.1618 + 1.1619 +void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers) 1.1620 +{ 1.1621 + HRESULT result; 1.1622 + 1.1623 + if (!mClearResourcesInitialized) 1.1624 + { 1.1625 + ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); 1.1626 + 1.1627 + D3D11_BUFFER_DESC vbDesc; 1.1628 + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; 1.1629 + vbDesc.Usage = D3D11_USAGE_DYNAMIC; 1.1630 + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 1.1631 + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 1.1632 + vbDesc.MiscFlags = 0; 1.1633 + vbDesc.StructureByteStride = 0; 1.1634 + 1.1635 + result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); 1.1636 + ASSERT(SUCCEEDED(result)); 1.1637 + d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); 1.1638 + 1.1639 + D3D11_INPUT_ELEMENT_DESC quadLayout[] = 1.1640 + { 1.1641 + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.1642 + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.1643 + }; 1.1644 + 1.1645 + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); 1.1646 + ASSERT(SUCCEEDED(result)); 1.1647 + d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); 1.1648 + 1.1649 + result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); 1.1650 + ASSERT(SUCCEEDED(result)); 1.1651 + d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); 1.1652 + 1.1653 + result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); 1.1654 + ASSERT(SUCCEEDED(result)); 1.1655 + d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); 1.1656 + 1.1657 + result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); 1.1658 + ASSERT(SUCCEEDED(result)); 1.1659 + d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); 1.1660 + 1.1661 + D3D11_RASTERIZER_DESC rsScissorDesc; 1.1662 + rsScissorDesc.FillMode = D3D11_FILL_SOLID; 1.1663 + rsScissorDesc.CullMode = D3D11_CULL_NONE; 1.1664 + rsScissorDesc.FrontCounterClockwise = FALSE; 1.1665 + rsScissorDesc.DepthBias = 0; 1.1666 + rsScissorDesc.DepthBiasClamp = 0.0f; 1.1667 + rsScissorDesc.SlopeScaledDepthBias = 0.0f; 1.1668 + rsScissorDesc.DepthClipEnable = FALSE; 1.1669 + rsScissorDesc.ScissorEnable = TRUE; 1.1670 + rsScissorDesc.MultisampleEnable = FALSE; 1.1671 + rsScissorDesc.AntialiasedLineEnable = FALSE; 1.1672 + 1.1673 + result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); 1.1674 + ASSERT(SUCCEEDED(result)); 1.1675 + d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); 1.1676 + 1.1677 + D3D11_RASTERIZER_DESC rsNoScissorDesc; 1.1678 + rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; 1.1679 + rsNoScissorDesc.CullMode = D3D11_CULL_NONE; 1.1680 + rsNoScissorDesc.FrontCounterClockwise = FALSE; 1.1681 + rsNoScissorDesc.DepthBias = 0; 1.1682 + rsNoScissorDesc.DepthBiasClamp = 0.0f; 1.1683 + rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; 1.1684 + rsNoScissorDesc.DepthClipEnable = FALSE; 1.1685 + rsNoScissorDesc.ScissorEnable = FALSE; 1.1686 + rsNoScissorDesc.MultisampleEnable = FALSE; 1.1687 + rsNoScissorDesc.AntialiasedLineEnable = FALSE; 1.1688 + 1.1689 + result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); 1.1690 + ASSERT(SUCCEEDED(result)); 1.1691 + d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); 1.1692 + 1.1693 + mClearResourcesInitialized = true; 1.1694 + } 1.1695 + 1.1696 + // Prepare the depth stencil state to write depth values if the depth should be cleared 1.1697 + // and stencil values if the stencil should be cleared 1.1698 + gl::DepthStencilState glDSState; 1.1699 + glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; 1.1700 + glDSState.depthFunc = GL_ALWAYS; 1.1701 + glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; 1.1702 + glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; 1.1703 + glDSState.stencilFunc = GL_ALWAYS; 1.1704 + glDSState.stencilMask = 0; 1.1705 + glDSState.stencilFail = GL_REPLACE; 1.1706 + glDSState.stencilPassDepthFail = GL_REPLACE; 1.1707 + glDSState.stencilPassDepthPass = GL_REPLACE; 1.1708 + glDSState.stencilWritemask = clearParams.stencilWriteMask; 1.1709 + glDSState.stencilBackFunc = GL_ALWAYS; 1.1710 + glDSState.stencilBackMask = 0; 1.1711 + glDSState.stencilBackFail = GL_REPLACE; 1.1712 + glDSState.stencilBackPassDepthFail = GL_REPLACE; 1.1713 + glDSState.stencilBackPassDepthPass = GL_REPLACE; 1.1714 + glDSState.stencilBackWritemask = clearParams.stencilWriteMask; 1.1715 + 1.1716 + int stencilClear = clearParams.stencilClearValue & 0x000000FF; 1.1717 + 1.1718 + ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); 1.1719 + 1.1720 + // Prepare the blend state to use a write mask if the color buffer should be cleared 1.1721 + gl::BlendState glBlendState; 1.1722 + glBlendState.blend = false; 1.1723 + glBlendState.sourceBlendRGB = GL_ONE; 1.1724 + glBlendState.destBlendRGB = GL_ZERO; 1.1725 + glBlendState.sourceBlendAlpha = GL_ONE; 1.1726 + glBlendState.destBlendAlpha = GL_ZERO; 1.1727 + glBlendState.blendEquationRGB = GL_FUNC_ADD; 1.1728 + glBlendState.blendEquationAlpha = GL_FUNC_ADD; 1.1729 + glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; 1.1730 + glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; 1.1731 + glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; 1.1732 + glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; 1.1733 + glBlendState.sampleAlphaToCoverage = false; 1.1734 + glBlendState.dither = false; 1.1735 + 1.1736 + static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; 1.1737 + static const UINT sampleMask = 0xFFFFFFFF; 1.1738 + 1.1739 + ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState); 1.1740 + 1.1741 + // Set the vertices 1.1742 + D3D11_MAPPED_SUBRESOURCE mappedResource; 1.1743 + result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); 1.1744 + if (FAILED(result)) 1.1745 + { 1.1746 + ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); 1.1747 + return; 1.1748 + } 1.1749 + 1.1750 + d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData); 1.1751 + 1.1752 + float depthClear = gl::clamp01(clearParams.depthClearValue); 1.1753 + d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); 1.1754 + d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); 1.1755 + d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); 1.1756 + d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); 1.1757 + 1.1758 + mDeviceContext->Unmap(mClearVB, 0); 1.1759 + 1.1760 + // Apply state 1.1761 + mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); 1.1762 + mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); 1.1763 + mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); 1.1764 + 1.1765 + // Apply shaders 1.1766 + ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS; 1.1767 + 1.1768 + mDeviceContext->IASetInputLayout(mClearIL); 1.1769 + mDeviceContext->VSSetShader(mClearVS, NULL, 0); 1.1770 + mDeviceContext->PSSetShader(pixelShader, NULL, 0); 1.1771 + mDeviceContext->GSSetShader(NULL, NULL, 0); 1.1772 + 1.1773 + // Apply vertex buffer 1.1774 + static UINT stride = sizeof(d3d11::PositionDepthColorVertex); 1.1775 + static UINT startIdx = 0; 1.1776 + mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); 1.1777 + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 1.1778 + 1.1779 + // Draw the clear quad 1.1780 + mDeviceContext->Draw(4, 0); 1.1781 + 1.1782 + // Clean up 1.1783 + markAllStateDirty(); 1.1784 +} 1.1785 + 1.1786 +void Renderer11::markAllStateDirty() 1.1787 +{ 1.1788 + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 1.1789 + { 1.1790 + mAppliedRenderTargetSerials[rtIndex] = 0; 1.1791 + } 1.1792 + mAppliedDepthbufferSerial = 0; 1.1793 + mAppliedStencilbufferSerial = 0; 1.1794 + mDepthStencilInitialized = false; 1.1795 + mRenderTargetDescInitialized = false; 1.1796 + 1.1797 + for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) 1.1798 + { 1.1799 + mForceSetVertexSamplerStates[i] = true; 1.1800 + mCurVertexTextureSerials[i] = 0; 1.1801 + } 1.1802 + for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) 1.1803 + { 1.1804 + mForceSetPixelSamplerStates[i] = true; 1.1805 + mCurPixelTextureSerials[i] = 0; 1.1806 + } 1.1807 + 1.1808 + mForceSetBlendState = true; 1.1809 + mForceSetRasterState = true; 1.1810 + mForceSetDepthStencilState = true; 1.1811 + mForceSetScissor = true; 1.1812 + mForceSetViewport = true; 1.1813 + 1.1814 + mAppliedIBSerial = 0; 1.1815 + mAppliedStorageIBSerial = 0; 1.1816 + mAppliedIBOffset = 0; 1.1817 + 1.1818 + mAppliedProgramBinarySerial = 0; 1.1819 + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); 1.1820 + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); 1.1821 + 1.1822 + mInputLayoutCache.markDirty(); 1.1823 + 1.1824 + mCurrentVertexConstantBuffer = NULL; 1.1825 + mCurrentPixelConstantBuffer = NULL; 1.1826 + mCurrentGeometryConstantBuffer = NULL; 1.1827 + 1.1828 + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; 1.1829 +} 1.1830 + 1.1831 +void Renderer11::releaseDeviceResources() 1.1832 +{ 1.1833 + mStateCache.clear(); 1.1834 + mInputLayoutCache.clear(); 1.1835 + 1.1836 + delete mVertexDataManager; 1.1837 + mVertexDataManager = NULL; 1.1838 + 1.1839 + delete mIndexDataManager; 1.1840 + mIndexDataManager = NULL; 1.1841 + 1.1842 + delete mLineLoopIB; 1.1843 + mLineLoopIB = NULL; 1.1844 + 1.1845 + delete mTriangleFanIB; 1.1846 + mTriangleFanIB = NULL; 1.1847 + 1.1848 + SafeRelease(mCopyVB); 1.1849 + SafeRelease(mCopySampler); 1.1850 + SafeRelease(mCopyIL); 1.1851 + SafeRelease(mCopyIL); 1.1852 + SafeRelease(mCopyVS); 1.1853 + SafeRelease(mCopyRGBAPS); 1.1854 + SafeRelease(mCopyRGBPS); 1.1855 + SafeRelease(mCopyLumPS); 1.1856 + SafeRelease(mCopyLumAlphaPS); 1.1857 + 1.1858 + mCopyResourcesInitialized = false; 1.1859 + 1.1860 + SafeRelease(mClearVB); 1.1861 + SafeRelease(mClearIL); 1.1862 + SafeRelease(mClearVS); 1.1863 + SafeRelease(mClearSinglePS); 1.1864 + SafeRelease(mClearMultiplePS); 1.1865 + SafeRelease(mClearScissorRS); 1.1866 + SafeRelease(mClearNoScissorRS); 1.1867 + 1.1868 + mClearResourcesInitialized = false; 1.1869 + 1.1870 + SafeRelease(mDriverConstantBufferVS); 1.1871 + SafeRelease(mDriverConstantBufferPS); 1.1872 + SafeRelease(mSyncQuery); 1.1873 +} 1.1874 + 1.1875 +void Renderer11::notifyDeviceLost() 1.1876 +{ 1.1877 + mDeviceLost = true; 1.1878 + mDisplay->notifyDeviceLost(); 1.1879 +} 1.1880 + 1.1881 +bool Renderer11::isDeviceLost() 1.1882 +{ 1.1883 + return mDeviceLost; 1.1884 +} 1.1885 + 1.1886 +// set notify to true to broadcast a message to all contexts of the device loss 1.1887 +bool Renderer11::testDeviceLost(bool notify) 1.1888 +{ 1.1889 + bool isLost = false; 1.1890 + 1.1891 + // GetRemovedReason is used to test if the device is removed 1.1892 + HRESULT result = mDevice->GetDeviceRemovedReason(); 1.1893 + isLost = d3d11::isDeviceLostError(result); 1.1894 + 1.1895 + if (isLost) 1.1896 + { 1.1897 + // Log error if this is a new device lost event 1.1898 + if (mDeviceLost == false) 1.1899 + { 1.1900 + ERR("The D3D11 device was removed: 0x%08X", result); 1.1901 + } 1.1902 + 1.1903 + // ensure we note the device loss -- 1.1904 + // we'll probably get this done again by notifyDeviceLost 1.1905 + // but best to remember it! 1.1906 + // Note that we don't want to clear the device loss status here 1.1907 + // -- this needs to be done by resetDevice 1.1908 + mDeviceLost = true; 1.1909 + if (notify) 1.1910 + { 1.1911 + notifyDeviceLost(); 1.1912 + } 1.1913 + } 1.1914 + 1.1915 + return isLost; 1.1916 +} 1.1917 + 1.1918 +bool Renderer11::testDeviceResettable() 1.1919 +{ 1.1920 + // determine if the device is resettable by creating a dummy device 1.1921 + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); 1.1922 + 1.1923 + if (D3D11CreateDevice == NULL) 1.1924 + { 1.1925 + return false; 1.1926 + } 1.1927 + 1.1928 + D3D_FEATURE_LEVEL featureLevels[] = 1.1929 + { 1.1930 + D3D_FEATURE_LEVEL_11_0, 1.1931 + D3D_FEATURE_LEVEL_10_1, 1.1932 + D3D_FEATURE_LEVEL_10_0, 1.1933 + }; 1.1934 + 1.1935 + ID3D11Device* dummyDevice; 1.1936 + D3D_FEATURE_LEVEL dummyFeatureLevel; 1.1937 + ID3D11DeviceContext* dummyContext; 1.1938 + 1.1939 + HRESULT result = D3D11CreateDevice(NULL, 1.1940 + D3D_DRIVER_TYPE_HARDWARE, 1.1941 + NULL, 1.1942 + #if defined(_DEBUG) 1.1943 + D3D11_CREATE_DEVICE_DEBUG, 1.1944 + #else 1.1945 + 0, 1.1946 + #endif 1.1947 + featureLevels, 1.1948 + ArraySize(featureLevels), 1.1949 + D3D11_SDK_VERSION, 1.1950 + &dummyDevice, 1.1951 + &dummyFeatureLevel, 1.1952 + &dummyContext); 1.1953 + 1.1954 + if (!mDevice || FAILED(result)) 1.1955 + { 1.1956 + return false; 1.1957 + } 1.1958 + 1.1959 + dummyContext->Release(); 1.1960 + dummyDevice->Release(); 1.1961 + 1.1962 + return true; 1.1963 +} 1.1964 + 1.1965 +void Renderer11::release() 1.1966 +{ 1.1967 + releaseDeviceResources(); 1.1968 + 1.1969 + if (mDxgiFactory) 1.1970 + { 1.1971 + mDxgiFactory->Release(); 1.1972 + mDxgiFactory = NULL; 1.1973 + } 1.1974 + 1.1975 + if (mDxgiAdapter) 1.1976 + { 1.1977 + mDxgiAdapter->Release(); 1.1978 + mDxgiAdapter = NULL; 1.1979 + } 1.1980 + 1.1981 + if (mDeviceContext) 1.1982 + { 1.1983 + mDeviceContext->ClearState(); 1.1984 + mDeviceContext->Flush(); 1.1985 + mDeviceContext->Release(); 1.1986 + mDeviceContext = NULL; 1.1987 + } 1.1988 + 1.1989 + if (mDevice) 1.1990 + { 1.1991 + mDevice->Release(); 1.1992 + mDevice = NULL; 1.1993 + } 1.1994 + 1.1995 + if (mD3d11Module) 1.1996 + { 1.1997 + FreeLibrary(mD3d11Module); 1.1998 + mD3d11Module = NULL; 1.1999 + } 1.2000 + 1.2001 + if (mDxgiModule) 1.2002 + { 1.2003 + FreeLibrary(mDxgiModule); 1.2004 + mDxgiModule = NULL; 1.2005 + } 1.2006 +} 1.2007 + 1.2008 +bool Renderer11::resetDevice() 1.2009 +{ 1.2010 + // recreate everything 1.2011 + release(); 1.2012 + EGLint result = initialize(); 1.2013 + 1.2014 + if (result != EGL_SUCCESS) 1.2015 + { 1.2016 + ERR("Could not reinitialize D3D11 device: %08X", result); 1.2017 + return false; 1.2018 + } 1.2019 + 1.2020 + mDeviceLost = false; 1.2021 + 1.2022 + return true; 1.2023 +} 1.2024 + 1.2025 +DWORD Renderer11::getAdapterVendor() const 1.2026 +{ 1.2027 + return mAdapterDescription.VendorId; 1.2028 +} 1.2029 + 1.2030 +std::string Renderer11::getRendererDescription() const 1.2031 +{ 1.2032 + std::ostringstream rendererString; 1.2033 + 1.2034 + rendererString << mDescription; 1.2035 + rendererString << " Direct3D11"; 1.2036 + 1.2037 + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); 1.2038 + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); 1.2039 + 1.2040 + return rendererString.str(); 1.2041 +} 1.2042 + 1.2043 +GUID Renderer11::getAdapterIdentifier() const 1.2044 +{ 1.2045 + // Use the adapter LUID as our adapter ID 1.2046 + // This number is local to a machine is only guaranteed to be unique between restarts 1.2047 + META_ASSERT(sizeof(LUID) <= sizeof(GUID)); 1.2048 + GUID adapterId = {0}; 1.2049 + memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); 1.2050 + return adapterId; 1.2051 +} 1.2052 + 1.2053 +bool Renderer11::getBGRATextureSupport() const 1.2054 +{ 1.2055 + return mBGRATextureSupport; 1.2056 +} 1.2057 + 1.2058 +bool Renderer11::getDXT1TextureSupport() 1.2059 +{ 1.2060 + return mDXT1TextureSupport; 1.2061 +} 1.2062 + 1.2063 +bool Renderer11::getDXT3TextureSupport() 1.2064 +{ 1.2065 + return mDXT3TextureSupport; 1.2066 +} 1.2067 + 1.2068 +bool Renderer11::getDXT5TextureSupport() 1.2069 +{ 1.2070 + return mDXT5TextureSupport; 1.2071 +} 1.2072 + 1.2073 +bool Renderer11::getDepthTextureSupport() const 1.2074 +{ 1.2075 + return mDepthTextureSupport; 1.2076 +} 1.2077 + 1.2078 +bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) 1.2079 +{ 1.2080 + *renderable = mFloat32RenderSupport; 1.2081 + *filtering = mFloat32FilterSupport; 1.2082 + return mFloat32TextureSupport; 1.2083 +} 1.2084 + 1.2085 +bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) 1.2086 +{ 1.2087 + *renderable = mFloat16RenderSupport; 1.2088 + *filtering = mFloat16FilterSupport; 1.2089 + return mFloat16TextureSupport; 1.2090 +} 1.2091 + 1.2092 +bool Renderer11::getLuminanceTextureSupport() 1.2093 +{ 1.2094 + return false; 1.2095 +} 1.2096 + 1.2097 +bool Renderer11::getLuminanceAlphaTextureSupport() 1.2098 +{ 1.2099 + return false; 1.2100 +} 1.2101 + 1.2102 +bool Renderer11::getTextureFilterAnisotropySupport() const 1.2103 +{ 1.2104 + return true; 1.2105 +} 1.2106 + 1.2107 +float Renderer11::getTextureMaxAnisotropy() const 1.2108 +{ 1.2109 + switch (mFeatureLevel) 1.2110 + { 1.2111 + case D3D_FEATURE_LEVEL_11_0: 1.2112 + return D3D11_MAX_MAXANISOTROPY; 1.2113 + case D3D_FEATURE_LEVEL_10_1: 1.2114 + case D3D_FEATURE_LEVEL_10_0: 1.2115 + return D3D10_MAX_MAXANISOTROPY; 1.2116 + default: UNREACHABLE(); 1.2117 + return 0; 1.2118 + } 1.2119 +} 1.2120 + 1.2121 +bool Renderer11::getEventQuerySupport() 1.2122 +{ 1.2123 + return true; 1.2124 +} 1.2125 + 1.2126 +Range Renderer11::getViewportBounds() const 1.2127 +{ 1.2128 + switch (mFeatureLevel) 1.2129 + { 1.2130 + case D3D_FEATURE_LEVEL_11_0: 1.2131 + return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); 1.2132 + case D3D_FEATURE_LEVEL_10_1: 1.2133 + case D3D_FEATURE_LEVEL_10_0: 1.2134 + return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); 1.2135 + default: UNREACHABLE(); 1.2136 + return Range(0, 0); 1.2137 + } 1.2138 +} 1.2139 + 1.2140 +unsigned int Renderer11::getMaxVertexTextureImageUnits() const 1.2141 +{ 1.2142 + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1.2143 + switch (mFeatureLevel) 1.2144 + { 1.2145 + case D3D_FEATURE_LEVEL_11_0: 1.2146 + case D3D_FEATURE_LEVEL_10_1: 1.2147 + case D3D_FEATURE_LEVEL_10_0: 1.2148 + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; 1.2149 + default: UNREACHABLE(); 1.2150 + return 0; 1.2151 + } 1.2152 +} 1.2153 + 1.2154 +unsigned int Renderer11::getMaxCombinedTextureImageUnits() const 1.2155 +{ 1.2156 + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); 1.2157 +} 1.2158 + 1.2159 +unsigned int Renderer11::getReservedVertexUniformVectors() const 1.2160 +{ 1.2161 + return 0; // Driver uniforms are stored in a separate constant buffer 1.2162 +} 1.2163 + 1.2164 +unsigned int Renderer11::getReservedFragmentUniformVectors() const 1.2165 +{ 1.2166 + return 0; // Driver uniforms are stored in a separate constant buffer 1.2167 +} 1.2168 + 1.2169 +unsigned int Renderer11::getMaxVertexUniformVectors() const 1.2170 +{ 1.2171 + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); 1.2172 + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); 1.2173 + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; 1.2174 +} 1.2175 + 1.2176 +unsigned int Renderer11::getMaxFragmentUniformVectors() const 1.2177 +{ 1.2178 + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); 1.2179 + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); 1.2180 + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; 1.2181 +} 1.2182 + 1.2183 +unsigned int Renderer11::getMaxVaryingVectors() const 1.2184 +{ 1.2185 + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); 1.2186 + switch (mFeatureLevel) 1.2187 + { 1.2188 + case D3D_FEATURE_LEVEL_11_0: 1.2189 + return D3D11_VS_OUTPUT_REGISTER_COUNT; 1.2190 + case D3D_FEATURE_LEVEL_10_1: 1.2191 + case D3D_FEATURE_LEVEL_10_0: 1.2192 + return D3D10_VS_OUTPUT_REGISTER_COUNT; 1.2193 + default: UNREACHABLE(); 1.2194 + return 0; 1.2195 + } 1.2196 +} 1.2197 + 1.2198 +bool Renderer11::getNonPower2TextureSupport() const 1.2199 +{ 1.2200 + switch (mFeatureLevel) 1.2201 + { 1.2202 + case D3D_FEATURE_LEVEL_11_0: 1.2203 + case D3D_FEATURE_LEVEL_10_1: 1.2204 + case D3D_FEATURE_LEVEL_10_0: 1.2205 + return true; 1.2206 + default: UNREACHABLE(); 1.2207 + return false; 1.2208 + } 1.2209 +} 1.2210 + 1.2211 +bool Renderer11::getOcclusionQuerySupport() const 1.2212 +{ 1.2213 + switch (mFeatureLevel) 1.2214 + { 1.2215 + case D3D_FEATURE_LEVEL_11_0: 1.2216 + case D3D_FEATURE_LEVEL_10_1: 1.2217 + case D3D_FEATURE_LEVEL_10_0: 1.2218 + return true; 1.2219 + default: UNREACHABLE(); 1.2220 + return false; 1.2221 + } 1.2222 +} 1.2223 + 1.2224 +bool Renderer11::getInstancingSupport() const 1.2225 +{ 1.2226 + switch (mFeatureLevel) 1.2227 + { 1.2228 + case D3D_FEATURE_LEVEL_11_0: 1.2229 + case D3D_FEATURE_LEVEL_10_1: 1.2230 + case D3D_FEATURE_LEVEL_10_0: 1.2231 + return true; 1.2232 + default: UNREACHABLE(); 1.2233 + return false; 1.2234 + } 1.2235 +} 1.2236 + 1.2237 +bool Renderer11::getShareHandleSupport() const 1.2238 +{ 1.2239 + // We only currently support share handles with BGRA surfaces, because 1.2240 + // chrome needs BGRA. Once chrome fixes this, we should always support them. 1.2241 + // PIX doesn't seem to support using share handles, so disable them. 1.2242 + return getBGRATextureSupport() && !gl::perfActive(); 1.2243 +} 1.2244 + 1.2245 +bool Renderer11::getDerivativeInstructionSupport() const 1.2246 +{ 1.2247 + switch (mFeatureLevel) 1.2248 + { 1.2249 + case D3D_FEATURE_LEVEL_11_0: 1.2250 + case D3D_FEATURE_LEVEL_10_1: 1.2251 + case D3D_FEATURE_LEVEL_10_0: 1.2252 + return true; 1.2253 + default: UNREACHABLE(); 1.2254 + return false; 1.2255 + } 1.2256 +} 1.2257 + 1.2258 +bool Renderer11::getPostSubBufferSupport() const 1.2259 +{ 1.2260 + // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. 1.2261 + return false; 1.2262 +} 1.2263 + 1.2264 +int Renderer11::getMajorShaderModel() const 1.2265 +{ 1.2266 + switch (mFeatureLevel) 1.2267 + { 1.2268 + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 1.2269 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 1.2270 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 1.2271 + default: UNREACHABLE(); return 0; 1.2272 + } 1.2273 +} 1.2274 + 1.2275 +int Renderer11::getMinorShaderModel() const 1.2276 +{ 1.2277 + switch (mFeatureLevel) 1.2278 + { 1.2279 + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 1.2280 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 1.2281 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 1.2282 + default: UNREACHABLE(); return 0; 1.2283 + } 1.2284 +} 1.2285 + 1.2286 +float Renderer11::getMaxPointSize() const 1.2287 +{ 1.2288 + // choose a reasonable maximum. we enforce this in the shader. 1.2289 + // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) 1.2290 + return 1024.0f; 1.2291 +} 1.2292 + 1.2293 +int Renderer11::getMaxViewportDimension() const 1.2294 +{ 1.2295 + // Maximum viewport size must be at least as large as the largest render buffer (or larger). 1.2296 + // In our case return the maximum texture size, which is the maximum render buffer size. 1.2297 + META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); 1.2298 + META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); 1.2299 + 1.2300 + switch (mFeatureLevel) 1.2301 + { 1.2302 + case D3D_FEATURE_LEVEL_11_0: 1.2303 + return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 1.2304 + case D3D_FEATURE_LEVEL_10_1: 1.2305 + case D3D_FEATURE_LEVEL_10_0: 1.2306 + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 1.2307 + default: UNREACHABLE(); 1.2308 + return 0; 1.2309 + } 1.2310 +} 1.2311 + 1.2312 +int Renderer11::getMaxTextureWidth() const 1.2313 +{ 1.2314 + switch (mFeatureLevel) 1.2315 + { 1.2316 + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 1.2317 + case D3D_FEATURE_LEVEL_10_1: 1.2318 + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 1.2319 + default: UNREACHABLE(); return 0; 1.2320 + } 1.2321 +} 1.2322 + 1.2323 +int Renderer11::getMaxTextureHeight() const 1.2324 +{ 1.2325 + switch (mFeatureLevel) 1.2326 + { 1.2327 + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 1.2328 + case D3D_FEATURE_LEVEL_10_1: 1.2329 + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 1.2330 + default: UNREACHABLE(); return 0; 1.2331 + } 1.2332 +} 1.2333 + 1.2334 +bool Renderer11::get32BitIndexSupport() const 1.2335 +{ 1.2336 + switch (mFeatureLevel) 1.2337 + { 1.2338 + case D3D_FEATURE_LEVEL_11_0: 1.2339 + case D3D_FEATURE_LEVEL_10_1: 1.2340 + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true 1.2341 + default: UNREACHABLE(); return false; 1.2342 + } 1.2343 +} 1.2344 + 1.2345 +int Renderer11::getMinSwapInterval() const 1.2346 +{ 1.2347 + return 0; 1.2348 +} 1.2349 + 1.2350 +int Renderer11::getMaxSwapInterval() const 1.2351 +{ 1.2352 + return 4; 1.2353 +} 1.2354 + 1.2355 +int Renderer11::getMaxSupportedSamples() const 1.2356 +{ 1.2357 + return mMaxSupportedSamples; 1.2358 +} 1.2359 + 1.2360 +int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const 1.2361 +{ 1.2362 + if (requested == 0) 1.2363 + { 1.2364 + return 0; 1.2365 + } 1.2366 + 1.2367 + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); 1.2368 + if (iter != mMultisampleSupportMap.end()) 1.2369 + { 1.2370 + const MultisampleSupportInfo& info = iter->second; 1.2371 + for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) 1.2372 + { 1.2373 + if (info.qualityLevels[i] > 0) 1.2374 + { 1.2375 + return i + 1; 1.2376 + } 1.2377 + } 1.2378 + } 1.2379 + 1.2380 + return -1; 1.2381 +} 1.2382 + 1.2383 +unsigned int Renderer11::getMaxRenderTargets() const 1.2384 +{ 1.2385 + META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); 1.2386 + META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); 1.2387 + 1.2388 + switch (mFeatureLevel) 1.2389 + { 1.2390 + case D3D_FEATURE_LEVEL_11_0: 1.2391 + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 1.2392 + case D3D_FEATURE_LEVEL_10_1: 1.2393 + case D3D_FEATURE_LEVEL_10_0: 1.2394 + return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 1.2395 + default: 1.2396 + UNREACHABLE(); 1.2397 + return 1; 1.2398 + } 1.2399 +} 1.2400 + 1.2401 +bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) 1.2402 +{ 1.2403 + if (source && dest) 1.2404 + { 1.2405 + TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); 1.2406 + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); 1.2407 + 1.2408 + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); 1.2409 + return true; 1.2410 + } 1.2411 + 1.2412 + return false; 1.2413 +} 1.2414 + 1.2415 +bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) 1.2416 +{ 1.2417 + if (source && dest) 1.2418 + { 1.2419 + TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); 1.2420 + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); 1.2421 + 1.2422 + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); 1.2423 + return true; 1.2424 + } 1.2425 + 1.2426 + return false; 1.2427 +} 1.2428 + 1.2429 +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 1.2430 + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) 1.2431 +{ 1.2432 + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); 1.2433 + if (!colorbuffer) 1.2434 + { 1.2435 + ERR("Failed to retrieve the color buffer from the frame buffer."); 1.2436 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2437 + } 1.2438 + 1.2439 + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 1.2440 + if (!sourceRenderTarget) 1.2441 + { 1.2442 + ERR("Failed to retrieve the render target from the frame buffer."); 1.2443 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2444 + } 1.2445 + 1.2446 + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 1.2447 + if (!source) 1.2448 + { 1.2449 + ERR("Failed to retrieve the render target view from the render target."); 1.2450 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2451 + } 1.2452 + 1.2453 + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); 1.2454 + if (!storage11) 1.2455 + { 1.2456 + ERR("Failed to retrieve the texture storage from the destination."); 1.2457 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2458 + } 1.2459 + 1.2460 + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); 1.2461 + if (!destRenderTarget) 1.2462 + { 1.2463 + ERR("Failed to retrieve the render target from the destination storage."); 1.2464 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2465 + } 1.2466 + 1.2467 + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 1.2468 + if (!dest) 1.2469 + { 1.2470 + ERR("Failed to retrieve the render target view from the destination render target."); 1.2471 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2472 + } 1.2473 + 1.2474 + gl::Rectangle destRect; 1.2475 + destRect.x = xoffset; 1.2476 + destRect.y = yoffset; 1.2477 + destRect.width = sourceRect.width; 1.2478 + destRect.height = sourceRect.height; 1.2479 + 1.2480 + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1.2481 + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); 1.2482 + 1.2483 + return ret; 1.2484 +} 1.2485 + 1.2486 +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, 1.2487 + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) 1.2488 +{ 1.2489 + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); 1.2490 + if (!colorbuffer) 1.2491 + { 1.2492 + ERR("Failed to retrieve the color buffer from the frame buffer."); 1.2493 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2494 + } 1.2495 + 1.2496 + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 1.2497 + if (!sourceRenderTarget) 1.2498 + { 1.2499 + ERR("Failed to retrieve the render target from the frame buffer."); 1.2500 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2501 + } 1.2502 + 1.2503 + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); 1.2504 + if (!source) 1.2505 + { 1.2506 + ERR("Failed to retrieve the render target view from the render target."); 1.2507 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2508 + } 1.2509 + 1.2510 + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); 1.2511 + if (!storage11) 1.2512 + { 1.2513 + ERR("Failed to retrieve the texture storage from the destination."); 1.2514 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2515 + } 1.2516 + 1.2517 + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); 1.2518 + if (!destRenderTarget) 1.2519 + { 1.2520 + ERR("Failed to retrieve the render target from the destination storage."); 1.2521 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2522 + } 1.2523 + 1.2524 + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); 1.2525 + if (!dest) 1.2526 + { 1.2527 + ERR("Failed to retrieve the render target view from the destination render target."); 1.2528 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2529 + } 1.2530 + 1.2531 + gl::Rectangle destRect; 1.2532 + destRect.x = xoffset; 1.2533 + destRect.y = yoffset; 1.2534 + destRect.width = sourceRect.width; 1.2535 + destRect.height = sourceRect.height; 1.2536 + 1.2537 + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1.2538 + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); 1.2539 + 1.2540 + return ret; 1.2541 +} 1.2542 + 1.2543 +bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, 1.2544 + ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) 1.2545 +{ 1.2546 + HRESULT result; 1.2547 + 1.2548 + if (!mCopyResourcesInitialized) 1.2549 + { 1.2550 + ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); 1.2551 + 1.2552 + D3D11_BUFFER_DESC vbDesc; 1.2553 + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; 1.2554 + vbDesc.Usage = D3D11_USAGE_DYNAMIC; 1.2555 + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 1.2556 + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 1.2557 + vbDesc.MiscFlags = 0; 1.2558 + vbDesc.StructureByteStride = 0; 1.2559 + 1.2560 + result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); 1.2561 + ASSERT(SUCCEEDED(result)); 1.2562 + d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); 1.2563 + 1.2564 + D3D11_SAMPLER_DESC samplerDesc; 1.2565 + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 1.2566 + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; 1.2567 + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; 1.2568 + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; 1.2569 + samplerDesc.MipLODBias = 0.0f; 1.2570 + samplerDesc.MaxAnisotropy = 0; 1.2571 + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; 1.2572 + samplerDesc.BorderColor[0] = 0.0f; 1.2573 + samplerDesc.BorderColor[1] = 0.0f; 1.2574 + samplerDesc.BorderColor[2] = 0.0f; 1.2575 + samplerDesc.BorderColor[3] = 0.0f; 1.2576 + samplerDesc.MinLOD = 0.0f; 1.2577 + samplerDesc.MaxLOD = 0.0f; 1.2578 + 1.2579 + result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); 1.2580 + ASSERT(SUCCEEDED(result)); 1.2581 + d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); 1.2582 + 1.2583 + D3D11_INPUT_ELEMENT_DESC quadLayout[] = 1.2584 + { 1.2585 + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.2586 + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.2587 + }; 1.2588 + 1.2589 + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); 1.2590 + ASSERT(SUCCEEDED(result)); 1.2591 + d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); 1.2592 + 1.2593 + result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); 1.2594 + ASSERT(SUCCEEDED(result)); 1.2595 + d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); 1.2596 + 1.2597 + result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); 1.2598 + ASSERT(SUCCEEDED(result)); 1.2599 + d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); 1.2600 + 1.2601 + result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); 1.2602 + ASSERT(SUCCEEDED(result)); 1.2603 + d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); 1.2604 + 1.2605 + result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); 1.2606 + ASSERT(SUCCEEDED(result)); 1.2607 + d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); 1.2608 + 1.2609 + result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); 1.2610 + ASSERT(SUCCEEDED(result)); 1.2611 + d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); 1.2612 + 1.2613 + mCopyResourcesInitialized = true; 1.2614 + } 1.2615 + 1.2616 + // Verify the source and destination area sizes 1.2617 + if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) || 1.2618 + sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) || 1.2619 + destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) || 1.2620 + destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight)) 1.2621 + { 1.2622 + return gl::error(GL_INVALID_VALUE, false); 1.2623 + } 1.2624 + 1.2625 + // Set vertices 1.2626 + D3D11_MAPPED_SUBRESOURCE mappedResource; 1.2627 + result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); 1.2628 + if (FAILED(result)) 1.2629 + { 1.2630 + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); 1.2631 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2632 + } 1.2633 + 1.2634 + d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); 1.2635 + 1.2636 + // Create a quad in homogeneous coordinates 1.2637 + float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; 1.2638 + float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; 1.2639 + float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; 1.2640 + float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; 1.2641 + 1.2642 + float u1 = sourceArea.x / float(sourceWidth); 1.2643 + float v1 = sourceArea.y / float(sourceHeight); 1.2644 + float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); 1.2645 + float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); 1.2646 + 1.2647 + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); 1.2648 + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); 1.2649 + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); 1.2650 + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); 1.2651 + 1.2652 + mDeviceContext->Unmap(mCopyVB, 0); 1.2653 + 1.2654 + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); 1.2655 + static UINT startIdx = 0; 1.2656 + mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); 1.2657 + 1.2658 + // Apply state 1.2659 + mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); 1.2660 + mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); 1.2661 + mDeviceContext->RSSetState(NULL); 1.2662 + 1.2663 + // Apply shaders 1.2664 + mDeviceContext->IASetInputLayout(mCopyIL); 1.2665 + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 1.2666 + mDeviceContext->VSSetShader(mCopyVS, NULL, 0); 1.2667 + 1.2668 + ID3D11PixelShader *ps = NULL; 1.2669 + switch(destFormat) 1.2670 + { 1.2671 + case GL_RGBA: ps = mCopyRGBAPS; break; 1.2672 + case GL_RGB: ps = mCopyRGBPS; break; 1.2673 + case GL_ALPHA: ps = mCopyRGBAPS; break; 1.2674 + case GL_BGRA_EXT: ps = mCopyRGBAPS; break; 1.2675 + case GL_LUMINANCE: ps = mCopyLumPS; break; 1.2676 + case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; 1.2677 + default: UNREACHABLE(); ps = NULL; break; 1.2678 + } 1.2679 + 1.2680 + mDeviceContext->PSSetShader(ps, NULL, 0); 1.2681 + mDeviceContext->GSSetShader(NULL, NULL, 0); 1.2682 + 1.2683 + // Unset the currently bound shader resource to avoid conflicts 1.2684 + static ID3D11ShaderResourceView *const nullSRV = NULL; 1.2685 + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); 1.2686 + 1.2687 + // Apply render target 1.2688 + setOneTimeRenderTarget(dest); 1.2689 + 1.2690 + // Set the viewport 1.2691 + D3D11_VIEWPORT viewport; 1.2692 + viewport.TopLeftX = 0; 1.2693 + viewport.TopLeftY = 0; 1.2694 + viewport.Width = destWidth; 1.2695 + viewport.Height = destHeight; 1.2696 + viewport.MinDepth = 0.0f; 1.2697 + viewport.MaxDepth = 1.0f; 1.2698 + mDeviceContext->RSSetViewports(1, &viewport); 1.2699 + 1.2700 + // Apply textures 1.2701 + mDeviceContext->PSSetShaderResources(0, 1, &source); 1.2702 + mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); 1.2703 + 1.2704 + // Draw the quad 1.2705 + mDeviceContext->Draw(4, 0); 1.2706 + 1.2707 + // Unbind textures and render targets and vertex buffer 1.2708 + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); 1.2709 + 1.2710 + unapplyRenderTargets(); 1.2711 + 1.2712 + UINT zero = 0; 1.2713 + ID3D11Buffer *const nullBuffer = NULL; 1.2714 + mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); 1.2715 + 1.2716 + markAllStateDirty(); 1.2717 + 1.2718 + return true; 1.2719 +} 1.2720 + 1.2721 +void Renderer11::unapplyRenderTargets() 1.2722 +{ 1.2723 + setOneTimeRenderTarget(NULL); 1.2724 +} 1.2725 + 1.2726 +void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) 1.2727 +{ 1.2728 + ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; 1.2729 + 1.2730 + rtvArray[0] = renderTargetView; 1.2731 + 1.2732 + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); 1.2733 + 1.2734 + // Do not preserve the serial for this one-time-use render target 1.2735 + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) 1.2736 + { 1.2737 + mAppliedRenderTargetSerials[rtIndex] = 0; 1.2738 + } 1.2739 +} 1.2740 + 1.2741 +RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) 1.2742 +{ 1.2743 + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); 1.2744 + RenderTarget11 *renderTarget = NULL; 1.2745 + 1.2746 + if (depth) 1.2747 + { 1.2748 + // Note: depth stencil may be NULL for 0 sized surfaces 1.2749 + renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), 1.2750 + swapChain11->getDepthStencilTexture(), NULL, 1.2751 + swapChain11->getWidth(), swapChain11->getHeight()); 1.2752 + } 1.2753 + else 1.2754 + { 1.2755 + // Note: render target may be NULL for 0 sized surfaces 1.2756 + renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), 1.2757 + swapChain11->getOffscreenTexture(), 1.2758 + swapChain11->getRenderTargetShaderResource(), 1.2759 + swapChain11->getWidth(), swapChain11->getHeight()); 1.2760 + } 1.2761 + return renderTarget; 1.2762 +} 1.2763 + 1.2764 +RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) 1.2765 +{ 1.2766 + RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); 1.2767 + return renderTarget; 1.2768 +} 1.2769 + 1.2770 +ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) 1.2771 +{ 1.2772 + ShaderExecutable11 *executable = NULL; 1.2773 + 1.2774 + switch (type) 1.2775 + { 1.2776 + case rx::SHADER_VERTEX: 1.2777 + { 1.2778 + ID3D11VertexShader *vshader = NULL; 1.2779 + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); 1.2780 + ASSERT(SUCCEEDED(result)); 1.2781 + 1.2782 + if (vshader) 1.2783 + { 1.2784 + executable = new ShaderExecutable11(function, length, vshader); 1.2785 + } 1.2786 + } 1.2787 + break; 1.2788 + case rx::SHADER_PIXEL: 1.2789 + { 1.2790 + ID3D11PixelShader *pshader = NULL; 1.2791 + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); 1.2792 + ASSERT(SUCCEEDED(result)); 1.2793 + 1.2794 + if (pshader) 1.2795 + { 1.2796 + executable = new ShaderExecutable11(function, length, pshader); 1.2797 + } 1.2798 + } 1.2799 + break; 1.2800 + case rx::SHADER_GEOMETRY: 1.2801 + { 1.2802 + ID3D11GeometryShader *gshader = NULL; 1.2803 + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); 1.2804 + ASSERT(SUCCEEDED(result)); 1.2805 + 1.2806 + if (gshader) 1.2807 + { 1.2808 + executable = new ShaderExecutable11(function, length, gshader); 1.2809 + } 1.2810 + } 1.2811 + break; 1.2812 + default: 1.2813 + UNREACHABLE(); 1.2814 + break; 1.2815 + } 1.2816 + 1.2817 + return executable; 1.2818 +} 1.2819 + 1.2820 +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) 1.2821 +{ 1.2822 + const char *profile = NULL; 1.2823 + 1.2824 + switch (type) 1.2825 + { 1.2826 + case rx::SHADER_VERTEX: 1.2827 + profile = "vs_4_0"; 1.2828 + break; 1.2829 + case rx::SHADER_PIXEL: 1.2830 + profile = "ps_4_0"; 1.2831 + break; 1.2832 + case rx::SHADER_GEOMETRY: 1.2833 + profile = "gs_4_0"; 1.2834 + break; 1.2835 + default: 1.2836 + UNREACHABLE(); 1.2837 + return NULL; 1.2838 + } 1.2839 + 1.2840 + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false); 1.2841 + if (!binary) 1.2842 + return NULL; 1.2843 + 1.2844 + ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); 1.2845 + binary->Release(); 1.2846 + 1.2847 + return executable; 1.2848 +} 1.2849 + 1.2850 +VertexBuffer *Renderer11::createVertexBuffer() 1.2851 +{ 1.2852 + return new VertexBuffer11(this); 1.2853 +} 1.2854 + 1.2855 +IndexBuffer *Renderer11::createIndexBuffer() 1.2856 +{ 1.2857 + return new IndexBuffer11(this); 1.2858 +} 1.2859 + 1.2860 +BufferStorage *Renderer11::createBufferStorage() 1.2861 +{ 1.2862 + return new BufferStorage11(this); 1.2863 +} 1.2864 + 1.2865 +QueryImpl *Renderer11::createQuery(GLenum type) 1.2866 +{ 1.2867 + return new Query11(this, type); 1.2868 +} 1.2869 + 1.2870 +FenceImpl *Renderer11::createFence() 1.2871 +{ 1.2872 + return new Fence11(this); 1.2873 +} 1.2874 + 1.2875 +bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) 1.2876 +{ 1.2877 + ASSERT(colorbuffer != NULL); 1.2878 + 1.2879 + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); 1.2880 + if (renderTarget) 1.2881 + { 1.2882 + *subresourceIndex = renderTarget->getSubresourceIndex(); 1.2883 + 1.2884 + ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); 1.2885 + if (colorBufferRTV) 1.2886 + { 1.2887 + ID3D11Resource *textureResource = NULL; 1.2888 + colorBufferRTV->GetResource(&textureResource); 1.2889 + 1.2890 + if (textureResource) 1.2891 + { 1.2892 + HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); 1.2893 + textureResource->Release(); 1.2894 + 1.2895 + if (SUCCEEDED(result)) 1.2896 + { 1.2897 + return true; 1.2898 + } 1.2899 + else 1.2900 + { 1.2901 + ERR("Failed to extract the ID3D11Texture2D from the render target resource, " 1.2902 + "HRESULT: 0x%X.", result); 1.2903 + } 1.2904 + } 1.2905 + } 1.2906 + } 1.2907 + 1.2908 + return false; 1.2909 +} 1.2910 + 1.2911 +bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, 1.2912 + bool blitRenderTarget, bool blitDepthStencil) 1.2913 +{ 1.2914 + if (blitRenderTarget) 1.2915 + { 1.2916 + gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); 1.2917 + 1.2918 + if (!readBuffer) 1.2919 + { 1.2920 + ERR("Failed to retrieve the read buffer from the read framebuffer."); 1.2921 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2922 + } 1.2923 + 1.2924 + RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); 1.2925 + 1.2926 + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 1.2927 + { 1.2928 + if (drawTarget->isEnabledColorAttachment(colorAttachment)) 1.2929 + { 1.2930 + gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); 1.2931 + 1.2932 + if (!drawBuffer) 1.2933 + { 1.2934 + ERR("Failed to retrieve the draw buffer from the draw framebuffer."); 1.2935 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2936 + } 1.2937 + 1.2938 + RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); 1.2939 + 1.2940 + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) 1.2941 + { 1.2942 + return false; 1.2943 + } 1.2944 + } 1.2945 + } 1.2946 + } 1.2947 + 1.2948 + if (blitDepthStencil) 1.2949 + { 1.2950 + gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); 1.2951 + gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); 1.2952 + 1.2953 + if (!readBuffer) 1.2954 + { 1.2955 + ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); 1.2956 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2957 + } 1.2958 + 1.2959 + if (!drawBuffer) 1.2960 + { 1.2961 + ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); 1.2962 + return gl::error(GL_OUT_OF_MEMORY, false); 1.2963 + } 1.2964 + 1.2965 + RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); 1.2966 + RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); 1.2967 + 1.2968 + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) 1.2969 + { 1.2970 + return false; 1.2971 + } 1.2972 + } 1.2973 + 1.2974 + return true; 1.2975 +} 1.2976 + 1.2977 +void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 1.2978 + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) 1.2979 +{ 1.2980 + ID3D11Texture2D *colorBufferTexture = NULL; 1.2981 + unsigned int subresourceIndex = 0; 1.2982 + 1.2983 + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); 1.2984 + 1.2985 + if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) 1.2986 + { 1.2987 + gl::Rectangle area; 1.2988 + area.x = x; 1.2989 + area.y = y; 1.2990 + area.width = width; 1.2991 + area.height = height; 1.2992 + 1.2993 + readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, 1.2994 + packReverseRowOrder, packAlignment, pixels); 1.2995 + 1.2996 + colorBufferTexture->Release(); 1.2997 + colorBufferTexture = NULL; 1.2998 + } 1.2999 +} 1.3000 + 1.3001 +Image *Renderer11::createImage() 1.3002 +{ 1.3003 + return new Image11(); 1.3004 +} 1.3005 + 1.3006 +void Renderer11::generateMipmap(Image *dest, Image *src) 1.3007 +{ 1.3008 + Image11 *dest11 = Image11::makeImage11(dest); 1.3009 + Image11 *src11 = Image11::makeImage11(src); 1.3010 + Image11::generateMipmap(dest11, src11); 1.3011 +} 1.3012 + 1.3013 +TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) 1.3014 +{ 1.3015 + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); 1.3016 + return new TextureStorage11_2D(this, swapChain11); 1.3017 +} 1.3018 + 1.3019 +TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) 1.3020 +{ 1.3021 + return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); 1.3022 +} 1.3023 + 1.3024 +TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) 1.3025 +{ 1.3026 + return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); 1.3027 +} 1.3028 + 1.3029 +static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) 1.3030 +{ 1.3031 + if (sourceFormat == DXGI_FORMAT_A8_UNORM && 1.3032 + destFormat == GL_ALPHA && 1.3033 + destType == GL_UNSIGNED_BYTE) 1.3034 + { 1.3035 + return 1; 1.3036 + } 1.3037 + else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && 1.3038 + destFormat == GL_RGBA && 1.3039 + destType == GL_UNSIGNED_BYTE) 1.3040 + { 1.3041 + return 4; 1.3042 + } 1.3043 + else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && 1.3044 + destFormat == GL_BGRA_EXT && 1.3045 + destType == GL_UNSIGNED_BYTE) 1.3046 + { 1.3047 + return 4; 1.3048 + } 1.3049 + else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && 1.3050 + destFormat == GL_RGBA && 1.3051 + destType == GL_HALF_FLOAT_OES) 1.3052 + { 1.3053 + return 8; 1.3054 + } 1.3055 + else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && 1.3056 + destFormat == GL_RGB && 1.3057 + destType == GL_FLOAT) 1.3058 + { 1.3059 + return 12; 1.3060 + } 1.3061 + else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && 1.3062 + destFormat == GL_RGBA && 1.3063 + destType == GL_FLOAT) 1.3064 + { 1.3065 + return 16; 1.3066 + } 1.3067 + else 1.3068 + { 1.3069 + return 0; 1.3070 + } 1.3071 +} 1.3072 + 1.3073 +static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x, 1.3074 + unsigned int y, int inputPitch, gl::Color *outColor) 1.3075 +{ 1.3076 + switch (format) 1.3077 + { 1.3078 + case DXGI_FORMAT_R8G8B8A8_UNORM: 1.3079 + { 1.3080 + unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch); 1.3081 + outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); 1.3082 + outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); 1.3083 + outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); 1.3084 + outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); 1.3085 + } 1.3086 + break; 1.3087 + 1.3088 + case DXGI_FORMAT_A8_UNORM: 1.3089 + { 1.3090 + outColor->red = 0.0f; 1.3091 + outColor->green = 0.0f; 1.3092 + outColor->blue = 0.0f; 1.3093 + outColor->alpha = *(data + x + y * inputPitch) / 255.0f; 1.3094 + } 1.3095 + break; 1.3096 + 1.3097 + case DXGI_FORMAT_R32G32B32A32_FLOAT: 1.3098 + { 1.3099 + outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0); 1.3100 + outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1); 1.3101 + outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2); 1.3102 + outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3); 1.3103 + } 1.3104 + break; 1.3105 + 1.3106 + case DXGI_FORMAT_R32G32B32_FLOAT: 1.3107 + { 1.3108 + outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0); 1.3109 + outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1); 1.3110 + outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2); 1.3111 + outColor->alpha = 1.0f; 1.3112 + } 1.3113 + break; 1.3114 + 1.3115 + case DXGI_FORMAT_R16G16B16A16_FLOAT: 1.3116 + { 1.3117 + outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0)); 1.3118 + outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1)); 1.3119 + outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2)); 1.3120 + outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3)); 1.3121 + } 1.3122 + break; 1.3123 + 1.3124 + case DXGI_FORMAT_B8G8R8A8_UNORM: 1.3125 + { 1.3126 + unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch); 1.3127 + outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); 1.3128 + outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); 1.3129 + outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); 1.3130 + outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); 1.3131 + } 1.3132 + break; 1.3133 + 1.3134 + case DXGI_FORMAT_R8_UNORM: 1.3135 + { 1.3136 + outColor->red = *(data + x + y * inputPitch) / 255.0f; 1.3137 + outColor->green = 0.0f; 1.3138 + outColor->blue = 0.0f; 1.3139 + outColor->alpha = 1.0f; 1.3140 + } 1.3141 + break; 1.3142 + 1.3143 + case DXGI_FORMAT_R8G8_UNORM: 1.3144 + { 1.3145 + unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch); 1.3146 + 1.3147 + outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); 1.3148 + outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); 1.3149 + outColor->blue = 0.0f; 1.3150 + outColor->alpha = 1.0f; 1.3151 + } 1.3152 + break; 1.3153 + 1.3154 + case DXGI_FORMAT_R16_FLOAT: 1.3155 + { 1.3156 + outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch)); 1.3157 + outColor->green = 0.0f; 1.3158 + outColor->blue = 0.0f; 1.3159 + outColor->alpha = 1.0f; 1.3160 + } 1.3161 + break; 1.3162 + 1.3163 + case DXGI_FORMAT_R16G16_FLOAT: 1.3164 + { 1.3165 + outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0)); 1.3166 + outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1)); 1.3167 + outColor->blue = 0.0f; 1.3168 + outColor->alpha = 1.0f; 1.3169 + } 1.3170 + break; 1.3171 + 1.3172 + default: 1.3173 + ERR("ReadPixelColor not implemented for DXGI format %u.", format); 1.3174 + UNIMPLEMENTED(); 1.3175 + break; 1.3176 + } 1.3177 +} 1.3178 + 1.3179 +static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, 1.3180 + unsigned int y, int outputPitch, void *outData) 1.3181 +{ 1.3182 + unsigned char* byteData = reinterpret_cast<unsigned char*>(outData); 1.3183 + unsigned short* shortData = reinterpret_cast<unsigned short*>(outData); 1.3184 + 1.3185 + switch (format) 1.3186 + { 1.3187 + case GL_RGBA: 1.3188 + switch (type) 1.3189 + { 1.3190 + case GL_UNSIGNED_BYTE: 1.3191 + byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f); 1.3192 + byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); 1.3193 + byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f); 1.3194 + byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f); 1.3195 + break; 1.3196 + 1.3197 + default: 1.3198 + ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); 1.3199 + UNIMPLEMENTED(); 1.3200 + break; 1.3201 + } 1.3202 + break; 1.3203 + 1.3204 + case GL_BGRA_EXT: 1.3205 + switch (type) 1.3206 + { 1.3207 + case GL_UNSIGNED_BYTE: 1.3208 + byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f); 1.3209 + byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); 1.3210 + byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f); 1.3211 + byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f); 1.3212 + break; 1.3213 + 1.3214 + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: 1.3215 + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 1.3216 + // this type is packed as follows: 1.3217 + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.3218 + // -------------------------------------------------------------------------------- 1.3219 + // | 4th | 3rd | 2nd | 1st component | 1.3220 + // -------------------------------------------------------------------------------- 1.3221 + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 1.3222 + shortData[x + y * outputPitch / sizeof(unsigned short)] = 1.3223 + (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) | 1.3224 + (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) | 1.3225 + (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) | 1.3226 + (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0); 1.3227 + break; 1.3228 + 1.3229 + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: 1.3230 + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 1.3231 + // this type is packed as follows: 1.3232 + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.3233 + // -------------------------------------------------------------------------------- 1.3234 + // | 4th | 3rd | 2nd | 1st component | 1.3235 + // -------------------------------------------------------------------------------- 1.3236 + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 1.3237 + shortData[x + y * outputPitch / sizeof(unsigned short)] = 1.3238 + (static_cast<unsigned short>( color.alpha + 0.5f) << 15) | 1.3239 + (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) | 1.3240 + (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) | 1.3241 + (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0); 1.3242 + break; 1.3243 + 1.3244 + default: 1.3245 + ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); 1.3246 + UNIMPLEMENTED(); 1.3247 + break; 1.3248 + } 1.3249 + break; 1.3250 + 1.3251 + case GL_RGB: 1.3252 + switch (type) 1.3253 + { 1.3254 + case GL_UNSIGNED_SHORT_5_6_5: 1.3255 + shortData[x + y * outputPitch / sizeof(unsigned short)] = 1.3256 + (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) | 1.3257 + (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) | 1.3258 + (static_cast<unsigned short>(31 * color.red + 0.5f) << 11); 1.3259 + break; 1.3260 + 1.3261 + case GL_UNSIGNED_BYTE: 1.3262 + byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f); 1.3263 + byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); 1.3264 + byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f); 1.3265 + break; 1.3266 + 1.3267 + default: 1.3268 + ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); 1.3269 + UNIMPLEMENTED(); 1.3270 + break; 1.3271 + } 1.3272 + break; 1.3273 + 1.3274 + default: 1.3275 + ERR("WritePixelColor not implemented for format 0x%X.", format); 1.3276 + UNIMPLEMENTED(); 1.3277 + break; 1.3278 + } 1.3279 +} 1.3280 + 1.3281 +void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, 1.3282 + GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, 1.3283 + GLint packAlignment, void *pixels) 1.3284 +{ 1.3285 + D3D11_TEXTURE2D_DESC textureDesc; 1.3286 + texture->GetDesc(&textureDesc); 1.3287 + 1.3288 + D3D11_TEXTURE2D_DESC stagingDesc; 1.3289 + stagingDesc.Width = area.width; 1.3290 + stagingDesc.Height = area.height; 1.3291 + stagingDesc.MipLevels = 1; 1.3292 + stagingDesc.ArraySize = 1; 1.3293 + stagingDesc.Format = textureDesc.Format; 1.3294 + stagingDesc.SampleDesc.Count = 1; 1.3295 + stagingDesc.SampleDesc.Quality = 0; 1.3296 + stagingDesc.Usage = D3D11_USAGE_STAGING; 1.3297 + stagingDesc.BindFlags = 0; 1.3298 + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 1.3299 + stagingDesc.MiscFlags = 0; 1.3300 + 1.3301 + ID3D11Texture2D* stagingTex = NULL; 1.3302 + HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); 1.3303 + if (FAILED(result)) 1.3304 + { 1.3305 + ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); 1.3306 + return; 1.3307 + } 1.3308 + 1.3309 + ID3D11Texture2D* srcTex = NULL; 1.3310 + if (textureDesc.SampleDesc.Count > 1) 1.3311 + { 1.3312 + D3D11_TEXTURE2D_DESC resolveDesc; 1.3313 + resolveDesc.Width = textureDesc.Width; 1.3314 + resolveDesc.Height = textureDesc.Height; 1.3315 + resolveDesc.MipLevels = 1; 1.3316 + resolveDesc.ArraySize = 1; 1.3317 + resolveDesc.Format = textureDesc.Format; 1.3318 + resolveDesc.SampleDesc.Count = 1; 1.3319 + resolveDesc.SampleDesc.Quality = 0; 1.3320 + resolveDesc.Usage = D3D11_USAGE_DEFAULT; 1.3321 + resolveDesc.BindFlags = 0; 1.3322 + resolveDesc.CPUAccessFlags = 0; 1.3323 + resolveDesc.MiscFlags = 0; 1.3324 + 1.3325 + result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); 1.3326 + if (FAILED(result)) 1.3327 + { 1.3328 + ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); 1.3329 + stagingTex->Release(); 1.3330 + return; 1.3331 + } 1.3332 + 1.3333 + mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); 1.3334 + subResource = 0; 1.3335 + } 1.3336 + else 1.3337 + { 1.3338 + srcTex = texture; 1.3339 + srcTex->AddRef(); 1.3340 + } 1.3341 + 1.3342 + D3D11_BOX srcBox; 1.3343 + srcBox.left = area.x; 1.3344 + srcBox.right = area.x + area.width; 1.3345 + srcBox.top = area.y; 1.3346 + srcBox.bottom = area.y + area.height; 1.3347 + srcBox.front = 0; 1.3348 + srcBox.back = 1; 1.3349 + 1.3350 + mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); 1.3351 + 1.3352 + srcTex->Release(); 1.3353 + srcTex = NULL; 1.3354 + 1.3355 + D3D11_MAPPED_SUBRESOURCE mapping; 1.3356 + mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); 1.3357 + 1.3358 + unsigned char *source; 1.3359 + int inputPitch; 1.3360 + if (packReverseRowOrder) 1.3361 + { 1.3362 + source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1); 1.3363 + inputPitch = -static_cast<int>(mapping.RowPitch); 1.3364 + } 1.3365 + else 1.3366 + { 1.3367 + source = static_cast<unsigned char*>(mapping.pData); 1.3368 + inputPitch = static_cast<int>(mapping.RowPitch); 1.3369 + } 1.3370 + 1.3371 + unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type); 1.3372 + if (fastPixelSize != 0) 1.3373 + { 1.3374 + unsigned char *dest = static_cast<unsigned char*>(pixels); 1.3375 + for (int j = 0; j < area.height; j++) 1.3376 + { 1.3377 + memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); 1.3378 + } 1.3379 + } 1.3380 + else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && 1.3381 + format == GL_RGBA && 1.3382 + type == GL_UNSIGNED_BYTE) 1.3383 + { 1.3384 + // Fast path for swapping red with blue 1.3385 + unsigned char *dest = static_cast<unsigned char*>(pixels); 1.3386 + 1.3387 + for (int j = 0; j < area.height; j++) 1.3388 + { 1.3389 + for (int i = 0; i < area.width; i++) 1.3390 + { 1.3391 + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); 1.3392 + *(unsigned int*)(dest + 4 * i + j * outputPitch) = 1.3393 + (argb & 0xFF00FF00) | // Keep alpha and green 1.3394 + (argb & 0x00FF0000) >> 16 | // Move red to blue 1.3395 + (argb & 0x000000FF) << 16; // Move blue to red 1.3396 + } 1.3397 + } 1.3398 + } 1.3399 + else 1.3400 + { 1.3401 + gl::Color pixelColor; 1.3402 + for (int j = 0; j < area.height; j++) 1.3403 + { 1.3404 + for (int i = 0; i < area.width; i++) 1.3405 + { 1.3406 + readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor); 1.3407 + writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); 1.3408 + } 1.3409 + } 1.3410 + } 1.3411 + 1.3412 + mDeviceContext->Unmap(stagingTex, 0); 1.3413 + 1.3414 + stagingTex->Release(); 1.3415 + stagingTex = NULL; 1.3416 +} 1.3417 + 1.3418 +bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, 1.3419 + RenderTarget *drawRenderTarget, bool wholeBufferCopy) 1.3420 +{ 1.3421 + ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); 1.3422 + 1.3423 + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); 1.3424 + if (!drawRenderTarget) 1.3425 + { 1.3426 + ERR("Failed to retrieve the draw render target from the draw framebuffer."); 1.3427 + return gl::error(GL_OUT_OF_MEMORY, false); 1.3428 + } 1.3429 + 1.3430 + ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); 1.3431 + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); 1.3432 + 1.3433 + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); 1.3434 + if (!readRenderTarget) 1.3435 + { 1.3436 + ERR("Failed to retrieve the read render target from the read framebuffer."); 1.3437 + return gl::error(GL_OUT_OF_MEMORY, false); 1.3438 + } 1.3439 + 1.3440 + ID3D11Texture2D *readTexture = NULL; 1.3441 + unsigned int readSubresource = 0; 1.3442 + if (readRenderTarget->getSamples() > 0) 1.3443 + { 1.3444 + readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); 1.3445 + readSubresource = 0; 1.3446 + } 1.3447 + else 1.3448 + { 1.3449 + readTexture = readRenderTarget11->getTexture(); 1.3450 + readTexture->AddRef(); 1.3451 + readSubresource = readRenderTarget11->getSubresourceIndex(); 1.3452 + } 1.3453 + 1.3454 + if (!readTexture) 1.3455 + { 1.3456 + ERR("Failed to retrieve the read render target view from the read render target."); 1.3457 + return gl::error(GL_OUT_OF_MEMORY, false); 1.3458 + } 1.3459 + 1.3460 + D3D11_BOX readBox; 1.3461 + readBox.left = readRect.x; 1.3462 + readBox.right = readRect.x + readRect.width; 1.3463 + readBox.top = readRect.y; 1.3464 + readBox.bottom = readRect.y + readRect.height; 1.3465 + readBox.front = 0; 1.3466 + readBox.back = 1; 1.3467 + 1.3468 + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox 1.3469 + // We also require complete framebuffer copies for depth-stencil blit. 1.3470 + D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; 1.3471 + 1.3472 + mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, 1.3473 + readTexture, readSubresource, pSrcBox); 1.3474 + 1.3475 + SafeRelease(readTexture); 1.3476 + 1.3477 + return true; 1.3478 +} 1.3479 + 1.3480 +ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) 1.3481 +{ 1.3482 + D3D11_TEXTURE2D_DESC textureDesc; 1.3483 + source->GetDesc(&textureDesc); 1.3484 + 1.3485 + if (textureDesc.SampleDesc.Count > 1) 1.3486 + { 1.3487 + D3D11_TEXTURE2D_DESC resolveDesc; 1.3488 + resolveDesc.Width = textureDesc.Width; 1.3489 + resolveDesc.Height = textureDesc.Height; 1.3490 + resolveDesc.MipLevels = 1; 1.3491 + resolveDesc.ArraySize = 1; 1.3492 + resolveDesc.Format = textureDesc.Format; 1.3493 + resolveDesc.SampleDesc.Count = 1; 1.3494 + resolveDesc.SampleDesc.Quality = 0; 1.3495 + resolveDesc.Usage = textureDesc.Usage; 1.3496 + resolveDesc.BindFlags = textureDesc.BindFlags; 1.3497 + resolveDesc.CPUAccessFlags = 0; 1.3498 + resolveDesc.MiscFlags = 0; 1.3499 + 1.3500 + ID3D11Texture2D *resolveTexture = NULL; 1.3501 + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); 1.3502 + if (FAILED(result)) 1.3503 + { 1.3504 + ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); 1.3505 + return NULL; 1.3506 + } 1.3507 + 1.3508 + mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); 1.3509 + return resolveTexture; 1.3510 + } 1.3511 + else 1.3512 + { 1.3513 + source->AddRef(); 1.3514 + return source; 1.3515 + } 1.3516 +} 1.3517 + 1.3518 +bool Renderer11::getLUID(LUID *adapterLuid) const 1.3519 +{ 1.3520 + adapterLuid->HighPart = 0; 1.3521 + adapterLuid->LowPart = 0; 1.3522 + 1.3523 + if (!mDxgiAdapter) 1.3524 + { 1.3525 + return false; 1.3526 + } 1.3527 + 1.3528 + DXGI_ADAPTER_DESC adapterDesc; 1.3529 + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) 1.3530 + { 1.3531 + return false; 1.3532 + } 1.3533 + 1.3534 + *adapterLuid = adapterDesc.AdapterLuid; 1.3535 + return true; 1.3536 +} 1.3537 + 1.3538 +}