int main(int argc, char** argv) { IDXGIFactory1* factory = 0; CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory); IDXGIAdapter* adapter = NULL; for (unsigned int index = 0; SUCCEEDED(factory->EnumAdapters(index, &adapter)); ++index) { DXGI_ADAPTER_DESC ad = {}; adapter->GetDesc(&ad); if (ad.VendorId == 0x1414 && ad.DeviceId == 0x8c) continue; // Skip Microsoft Basic Render Driver printf("// GPU %d: %S (Vendor %04x Device %04x)\n", index, ad.Description, ad.VendorId, ad.DeviceId); if (argc == 1) { testCache(adapter); } else if (argc > 1 && strcmp(argv[1], "--") == 0) { testCacheSequence(adapter, argc, argv); } else { testCacheMeshes(adapter, argc, argv); } } }
STDMETHODIMP CDecD3D11::GetHWAccelDeviceInfo(DWORD dwIndex, BSTR *pstrDeviceName, DWORD *dwDeviceIdentifier) { IDXGIAdapter *pDXGIAdapter = nullptr; IDXGIFactory1 *pDXGIFactory = nullptr; HRESULT hr = dx.mCreateDXGIFactory1(IID_IDXGIFactory1, (void **)&pDXGIFactory); if (FAILED(hr)) goto fail; hr = pDXGIFactory->EnumAdapters(dwIndex, &pDXGIAdapter); if (FAILED(hr)) goto fail; DXGI_ADAPTER_DESC desc; pDXGIAdapter->GetDesc(&desc); // stop when we hit the MS software device if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c) { hr = E_INVALIDARG; goto fail; } if (pstrDeviceName) *pstrDeviceName = SysAllocString(desc.Description); if (dwDeviceIdentifier) *dwDeviceIdentifier = desc.DeviceId; fail: SafeRelease(&pDXGIFactory); SafeRelease(&pDXGIAdapter); return hr; }
void DesktopDuplication::init() { IDXGIFactory1* dxgiFactory = nullptr; CHECKED(hr, CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory))); IDXGIAdapter1* dxgiAdapter = nullptr; CHECKED(hr, dxgiFactory->EnumAdapters1(adapter, &dxgiAdapter)); dxgiFactory->Release(); CHECKED(hr, D3D11CreateDevice(dxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &d3dDevice, NULL, &d3dContext)); IDXGIOutput* dxgiOutput = nullptr; CHECKED(hr, dxgiAdapter->EnumOutputs(output, &dxgiOutput)); dxgiAdapter->Release(); IDXGIOutput1* dxgiOutput1 = nullptr; CHECKED(hr, dxgiOutput->QueryInterface(__uuidof(dxgiOutput1), reinterpret_cast<void**>(&dxgiOutput1))); dxgiOutput->Release(); IDXGIDevice* dxgiDevice = nullptr; CHECKED(hr, d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice))); CHECKED(hr, dxgiOutput1->DuplicateOutput(dxgiDevice, &outputDuplication)); dxgiOutput1->Release(); dxgiDevice->Release(); }
STDMETHODIMP_(DWORD) CDecD3D11::GetHWAccelNumDevices() { DWORD nDevices = 0; UINT i = 0; IDXGIAdapter *pDXGIAdapter = nullptr; IDXGIFactory1 *pDXGIFactory = nullptr; HRESULT hr = dx.mCreateDXGIFactory1(IID_IDXGIFactory1, (void **)&pDXGIFactory); if (FAILED(hr)) goto fail; DXGI_ADAPTER_DESC desc; while (SUCCEEDED(pDXGIFactory->EnumAdapters(i, &pDXGIAdapter))) { pDXGIAdapter->GetDesc(&desc); SafeRelease(&pDXGIAdapter); // stop when we hit the MS software device if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c) break; i++; } nDevices = i; fail: SafeRelease(&pDXGIFactory); return nDevices; }
D3D11CanvasWindowGraphicsPtr D3D11CanvasWindowGraphics::Create( HWND hWnd, D3D11DriverPtr driver, CameraPtr camera) { D3D11CanvasWindowGraphicsPtr p(new D3D11CanvasWindowGraphics); p->m_hWnd = hWnd; p->m_driver = driver; p->m_camera = camera; ID3D11Device* pDevice = p->m_driver->GetD3D11Device(); IDXGIFactory1* pDXGIFactory = p->m_driver->GetDXGIFactory(); IDWriteFactory* pDWriteFactory = p->m_driver->GetDWriteFactory(); // Create text format CHECK_HR(pDWriteFactory->CreateTextFormat( L"Calibri", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 24.0f, L"en-US", p->m_textFormat.Receive())); // Create swap chain DXGI_SWAP_CHAIN_DESC scd = { 0 }; scd.BufferDesc.Format = BACKBUFFER_FORMAT; scd.SampleDesc.Count = 1; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 1; scd.OutputWindow = hWnd; scd.Windowed = TRUE; CHECK_HR(pDXGIFactory->CreateSwapChain(pDevice, &scd, p->m_swapChain.Receive())); p->CreateSwapChainResources(); return p; }
//---------------------------------------------------------------------------- void DXGIAdapter::Enumerate(std::vector<DXGIAdapter>& adapters) { adapters.clear(); IDXGIFactory1* factory = nullptr; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory); CHECK_HR_RETURN_NONE("Unexpected error"); if (factory) { for (UINT i = 0; /**/; ++i) { IDXGIAdapter1* adapter = nullptr; hr = factory->EnumAdapters1(i, &adapter); if (hr != DXGI_ERROR_NOT_FOUND) { adapters.push_back(DXGIAdapter(adapter)); } else { break; } } SafeRelease(factory); } }
bool CDuplicateOutputDx11::GetSpecificAdapter(int idAdapter, IDXGIAdapter** pAdapter) { HRESULT err = S_OK; if (!pAdapter) { return false; } REFIID iidVal = __uuidof(IDXGIFactory1); UINT adapterID = 0; // adapter index IDXGIFactory1* pFactory = NULL; if (FAILED(err = CreateDXGIFactory1(iidVal, (void**)&pFactory))) { return false; } UINT i = 0; UINT adapterDeviceID = idAdapter; // if device id equal zero, use the first device DXGI_ADAPTER_DESC dxgiDesc; IDXGIAdapter1 *giAdapter = NULL; if (pFactory->EnumAdapters1(i, &giAdapter) != S_OK) { return false; } if (pFactory)pFactory->Release(); *pAdapter = giAdapter; return true; }
void GetDisplayDevices(DeviceOutputs &deviceList) { HRESULT err; deviceList.ClearData(); #ifdef USE_DXGI1_2 REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1); #else REFIIF iidVal = __uuidof(IDXGIFactory1); #endif IDXGIFactory1 *factory; if(SUCCEEDED(err = CreateDXGIFactory1(iidVal, (void**)&factory))) { UINT i=0; IDXGIAdapter1 *giAdapter; while(factory->EnumAdapters1(i++, &giAdapter) == S_OK) { Log(TEXT("------------------------------------------")); DXGI_ADAPTER_DESC adapterDesc; if(SUCCEEDED(err = giAdapter->GetDesc(&adapterDesc))) { if (adapterDesc.DedicatedVideoMemory != 0) { DeviceOutputData &deviceData = *deviceList.devices.CreateNew(); deviceData.strDevice = adapterDesc.Description; UINT j=0; IDXGIOutput *giOutput; while(giAdapter->EnumOutputs(j++, &giOutput) == S_OK) { DXGI_OUTPUT_DESC outputDesc; if(SUCCEEDED(giOutput->GetDesc(&outputDesc))) { if(outputDesc.AttachedToDesktop) { deviceData.monitorNameList << outputDesc.DeviceName; MonitorInfo &monitorInfo = *deviceData.monitors.CreateNew(); monitorInfo.hMonitor = outputDesc.Monitor; mcpy(&monitorInfo.rect, &outputDesc.DesktopCoordinates, sizeof(RECT)); } } giOutput->Release(); } } } else AppWarning(TEXT("Could not query adapter %u"), i); giAdapter->Release(); } factory->Release(); } }
HRESULT WINAPI HookDXGIFactory(REFIID riid, void **ppFactory) { // We need shared texture support for OpenVR, so force DXGI 1.0 games to use DXGI 1.1 IDXGIFactory1* pDXGIFactory; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&pDXGIFactory); if (FAILED(hr)) return hr; return pDXGIFactory->QueryInterface(riid, ppFactory); }
/// This function is called by the Mumble client in Mumble's scope /// mainly to extract the offsets of various functions in the IDXGISwapChain /// and IDXGIObject interfaces that need to be hooked in target /// applications. The data is stored in the dxgi shared memory structure. extern "C" __declspec(dllexport) void __cdecl PrepareDXGI() { if (! dxgi) return; ods("DXGI: Preparing static data for DXGI Injection"); dxgi->wcFileName[0] = 0; dxgi->offsetPresent = 0; dxgi->offsetResize = 0; // Make sure this is Vista or greater as quite a number of <=WinXP users have fake DX10 libs installed OSVERSIONINFOEXW ovi; memset(&ovi, 0, sizeof(ovi)); ovi.dwOSVersionInfoSize = sizeof(ovi); GetVersionExW(reinterpret_cast<OSVERSIONINFOW *>(&ovi)); if (ovi.dwMajorVersion < 6 || (ovi.dwMajorVersion == 6 && ovi.dwBuildNumber < 6001)) { ods("DXGI: No DXGI pre-Vista - skipping prepare"); return; } HMODULE hDXGI = LoadLibrary("DXGI.DLL"); if (hDXGI != NULL) { GetModuleFileNameW(hDXGI, dxgi->wcFileName, ARRAY_NUM_ELEMENTS(dxgi->wcFileName)); CreateDXGIFactory1Type pCreateDXGIFactory1 = reinterpret_cast<CreateDXGIFactory1Type>(GetProcAddress(hDXGI, "CreateDXGIFactory1")); ods("DXGI: Got CreateDXGIFactory1 at %p", pCreateDXGIFactory1); if (pCreateDXGIFactory1) { IDXGIFactory1 * pFactory; HRESULT hr = pCreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory)); if (FAILED(hr)) ods("DXGI: Call to pCreateDXGIFactory1 failed!"); if (pFactory) { IDXGIAdapter1 *pAdapter = NULL; pFactory->EnumAdapters1(0, &pAdapter); /// Offsets have to be identified and initialized only once. bool initializeDXGIData = !dxgi->offsetPresent && !dxgi->offsetResize; PrepareDXGI10(pAdapter, initializeDXGIData); initializeDXGIData = !dxgi->offsetPresent && !dxgi->offsetResize; PrepareDXGI11(pAdapter, initializeDXGIData); pFactory->Release(); } else { FreeLibrary(hDXGI); } } else { FreeLibrary(hDXGI); } } else { FreeLibrary(hDXGI); } }
void LogVideoCardStats() { HRESULT err; #ifdef USE_DXGI1_2 REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1); #else REFIIF iidVal = __uuidof(IDXGIFactory1); #endif IDXGIFactory1 *factory; if(SUCCEEDED(err = CreateDXGIFactory1(iidVal, (void**)&factory))) { UINT i=0; IDXGIAdapter1 *giAdapter; while(factory->EnumAdapters1(i++, &giAdapter) == S_OK) { DXGI_ADAPTER_DESC adapterDesc; if(SUCCEEDED(err = giAdapter->GetDesc(&adapterDesc))) { if (!(adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x8c)) { // Ignore Microsoft Basic Render Driver Log(TEXT("------------------------------------------")); Log(TEXT("Adapter %u"), i); Log(TEXT(" Video Adapter: %s"), adapterDesc.Description); Log(TEXT(" Video Adapter Dedicated Video Memory: %u"), adapterDesc.DedicatedVideoMemory); Log(TEXT(" Video Adapter Shared System Memory: %u"), adapterDesc.SharedSystemMemory); UINT j = 0; IDXGIOutput *output; while(SUCCEEDED(giAdapter->EnumOutputs(j++, &output))) { DXGI_OUTPUT_DESC desc; if(SUCCEEDED(output->GetDesc(&desc))) Log(TEXT(" Video Adapter Output %u: pos={%d, %d}, size={%d, %d}, attached=%s"), j, desc.DesktopCoordinates.left, desc.DesktopCoordinates.top, desc.DesktopCoordinates.right-desc.DesktopCoordinates.left, desc.DesktopCoordinates.bottom-desc.DesktopCoordinates.top, desc.AttachedToDesktop ? L"true" : L"false"); output->Release(); } } } else AppWarning(TEXT("Could not query adapter %u"), i); giAdapter->Release(); } factory->Release(); } }
IDXGIAdapter1 *D3D11Renderer::GetPrimaryAdaptor() { IDXGIFactory1 *factory = 0; if (CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&factory) == S_OK) { IDXGIAdapter1 *adapter = 0; factory->EnumAdapters1(0, &adapter); memory::SafeRelease(&factory); memory::SafeRelease(&adapter); return adapter; } memory::SafeRelease(&factory); return 0; }
void D3D11Renderer::EnumerateDisplayModes() { IDXGIFactory1 *factory = 0; if (CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&factory) == S_OK) { IDXGIAdapter1 *adapter = 0; for (UINT i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) { DXGI_ADAPTER_DESC1 ad; adapter->GetDesc1(&ad); char description[128]; size_t n; wcstombs_s(&n, description, ad.Description, 128); ATOM_LOG("-------------------------------------------------------------------------------\n"); ATOM_LOG("[info]: adapter[%d]: %s\n", i, description); ATOM_LOG("[info]: - revision: %d\n", i, ad.Revision); ATOM_LOG("[info]: - video memory: %d\n", i, ad.DedicatedVideoMemory / 1024 / 1024); ATOM_LOG("[info]: - system memory: %d\n", i, ad.DedicatedSystemMemory / 1024 / 1024); ATOM_LOG("[info]: - shared system memory: %d\n", i, ad.SharedSystemMemory / 1024 / 1024); IDXGIOutput *output = 0; for (UINT j = 0; adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND; j++) { UINT modesCount; DXGI_FORMAT format = g_settings.format; output->GetDisplayModeList(format, 0, &modesCount, 0); DXGI_MODE_DESC *modeDescs = new DXGI_MODE_DESC[modesCount]; output->GetDisplayModeList(format, 0, &modesCount, modeDescs); ATOM_LOG("[info]: - output %d display modes(%d)\n", j, modesCount); for (UINT k = 0; k < modesCount; k++) { ATOM_LOG("[info]: -- mode[%d]: %d * %d", k, modeDescs[k].Width, modeDescs[k].Height); ATOM_LOG(", refresh rate: %d/%d\n", modeDescs[i].RefreshRate.Numerator, modeDescs[i].RefreshRate.Denominator); } delete[] modeDescs; memory::SafeRelease(&output); } memory::SafeRelease(&adapter); } } memory::SafeRelease(&factory); }
std::vector<IDXGIAdapter*> EnumerateDXGIAdapters() { IDXGIAdapter * adaptor; std::vector <IDXGIAdapter*> adaptors; IDXGIFactory1* factory = NULL; // Create a DXGIFactory object. if(FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1) ,(void**)&factory))) { return adaptors; } for (auto i = 0; factory->EnumAdapters(i, &adaptor) != DXGI_ERROR_NOT_FOUND; ++i) { adaptors.push_back(adaptor); } SafeRelease(&factory); return adaptors; }
DXGI_RATIONAL D3D11Renderer::GetDefaultRefreshRate() { DXGI_RATIONAL refreshRate = {59, 1}; IDXGIFactory1 *factory = 0; if (CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&factory) == S_OK) { IDXGIAdapter1 *adapter = 0; for (UINT i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) { DXGI_ADAPTER_DESC1 ad; IDXGIOutput *output = 0; adapter->GetDesc1(&ad); for (UINT j = 0; adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND; j++) { UINT modesCount; DXGI_FORMAT format = g_settings.format; output->GetDisplayModeList(format, 0, &modesCount, 0); DXGI_MODE_DESC *modeDescs = new DXGI_MODE_DESC[modesCount]; output->GetDisplayModeList(format, 0, &modesCount, modeDescs); for (UINT k = 0; k < modesCount; k++) { if (modeDescs[k].Width == (UINT)g_settings.width && modeDescs[k].Height == (UINT)g_settings.height) { refreshRate = modeDescs[i].RefreshRate; delete[] modeDescs; memory::SafeRelease(&output); memory::SafeRelease(&adapter); memory::SafeRelease(&factory); return refreshRate; } } delete[] modeDescs; memory::SafeRelease(&output); } memory::SafeRelease(&adapter); } } memory::SafeRelease(&factory); return refreshRate; }
void RenderContext::init(s32 width, s32 height, s32 refresh_rate, PlatformWindow *window) { pp = (PlatformPacket *)malloc(sizeof(PlatformPacket)); memset(pp, 0, sizeof(PlatformPacket)); DXGI_MODE_DESC buffer_desc = {0}; buffer_desc.Width = width; buffer_desc.Height = height; buffer_desc.RefreshRate.Numerator = refresh_rate; buffer_desc.RefreshRate.Denominator = 1; buffer_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; buffer_desc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; buffer_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED ; SDL_SysWMinfo win32_info = {0}; SDL_GetWindowWMInfo((SDL_Window *)window->handle, &win32_info); DXGI_SWAP_CHAIN_DESC swap_chain_desc = {0}; swap_chain_desc.BufferDesc = buffer_desc; swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Quality = 0; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.BufferCount = 1; // NOTE(nathan): double buffering swap_chain_desc.OutputWindow = win32_info.info.win.window; swap_chain_desc.Windowed = true; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swap_chain_desc.Flags = D3D11_CREATE_DEVICE_DEBUG; // NOTE(nathan): possible DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH HRESULT error = D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, 0, 0, D3D11_SDK_VERSION, &swap_chain_desc, &pp->swap_chain, &pp->device, 0, &pp->device_context); // NOTE(nathan): disable alt-enter fullscreen IDXGIFactory1 *factory = 0; if(SUCCEEDED(pp->swap_chain->GetParent(__uuidof(IDXGIFactory1), (void **)&factory))) { factory->MakeWindowAssociation(win32_info.info.win.window, DXGI_MWA_NO_ALT_ENTER|DXGI_MWA_NO_PRINT_SCREEN ); factory->Release(); } resizeBuffer(width, height); error = pp->device->QueryInterface(IID_PPV_ARGS(&pp->debug_interface)); }
bool RenderCore::EnumerateDisplayAdapters(std::vector<IDXGIAdapter1 *> *dxgiAdapters) { IDXGIAdapter1 *pAdapter; IDXGIFactory1 *pFactory = nullptr; HRESULT hr; hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory); if (FAILED(hr)) { return false; } for (UINT i = 0; pFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) { dxgiAdapters->push_back(pAdapter); //m_VideoAdapterList.push_back(pAdapter); } if (pFactory) { pFactory->Release(); } return true; };
bool DeviceDirect3D::getAdapterHandle(std::vector<IDXGIAdapter1*>* adapters) { HRESULT hr; //Create DXGI factory IDXGIFactory1* dxgiFactory; hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&dxgiFactory)); if(FAILED(hr)) { LOGERROR(hr, "CreateDXGIFactory1"); return false; } //Get all the adapters UINT i = 0; IDXGIAdapter1* pAdapter = nullptr; while(dxgiFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) { adapters->push_back(pAdapter); DXGI_ADAPTER_DESC1 desc; pAdapter->GetDesc1(&desc); std::wstring descriptionw(desc.Description); std::string description(descriptionw.begin(), descriptionw.end()); Logger() << "Adapter found: (" << i << ") " << description; ++i; } dxgiFactory->Release(); if(adapters->empty()) { LOGFUNCERROR("Your graphics card does not appear to support DirectX 10 or later"); return false; } return true; }
void LogVideoCardStats() { HRESULT err; #ifdef USE_DXGI1_2 REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1); #else REFIIF iidVal = __uuidof(IDXGIFactory1); #endif IDXGIFactory1 *factory; if(SUCCEEDED(err = CreateDXGIFactory1(iidVal, (void**)&factory))) { UINT i=0; IDXGIAdapter1 *giAdapter; while(factory->EnumAdapters1(i++, &giAdapter) == S_OK) { DXGI_ADAPTER_DESC adapterDesc; if(SUCCEEDED(err = giAdapter->GetDesc(&adapterDesc))) { if (adapterDesc.DedicatedVideoMemory > 0) { Log(TEXT("------------------------------------------")); Log(TEXT("Adapter %u"), i); Log(TEXT(" Video Adapter: %s"), adapterDesc.Description); Log(TEXT(" Video Adapter Dedicated Video Memory: %u"), adapterDesc.DedicatedVideoMemory); Log(TEXT(" Video Adapter Shared System Memory: %u"), adapterDesc.SharedSystemMemory); } } else AppWarning(TEXT("Could not query adapter %u"), i); giAdapter->Release(); } factory->Release(); } }
bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear){ HRESULT hr; float fov, screenAspect; m_vsync_enabled = vsync; m_featureLevel = D3D_FEATURE_LEVEL_11_0; D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = ARRAYSIZE(driverTypes); D3D_FEATURE_LEVEL featureLevels[] = { //D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE(featureLevels); for (int driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++){ m_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice(NULL, m_driverType, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &m_device, &m_featureLevel, &m_deviceContext); if (hr == E_INVALIDARG){ hr = D3D11CreateDevice(NULL, m_driverType, NULL, 0, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &m_device, &m_featureLevel, &m_deviceContext); } if (SUCCEEDED(hr)){ break; } } if (FAILED(hr)){ return false; } IDXGIFactory1* factory = 0; IDXGIDevice* device = 0; hr = m_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&device)); if (SUCCEEDED(hr)){ IDXGIAdapter* adapter = 0; hr = device->GetAdapter(&adapter); if (SUCCEEDED(hr)){ hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory)); adapter->Release(); } device->Release(); } if (FAILED(hr)){ return false; } IDXGIFactory2* factory2 = 0; hr = factory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&factory2)); if (factory2){ hr = m_device->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&m_device1)); if (SUCCEEDED(hr)){ (void)m_deviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&m_deviceContext1)); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = screenWidth; sd.Height = screenHeight; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = factory2->CreateSwapChainForHwnd(m_device, hwnd, &sd, NULL, NULL, &m_swapChain1); if (SUCCEEDED(hr)){ m_swapChain = NULL; hr = m_swapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&m_swapChain)); } factory2->Release(); } else{ DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = screenWidth; sd.BufferDesc.Height = screenHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hwnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = factory->CreateSwapChain(m_device, &sd, &m_swapChain); } factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); factory->Release(); if (FAILED(hr)){ return false; } ID3D11Texture2D* backBuffer = 0; hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); if (FAILED(hr)){ return false; } hr = m_device->CreateRenderTargetView(backBuffer, NULL, &m_renderTargetView); backBuffer->Release(); if (FAILED(hr)){ return false; } m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, NULL); D3D11_TEXTURE2D_DESC depthBufferDesc; ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); depthBufferDesc.Width = screenWidth; depthBufferDesc.Height = screenHeight; depthBufferDesc.MipLevels = 1; depthBufferDesc.ArraySize = 1; depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.SampleDesc.Quality = 0; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthBufferDesc.CPUAccessFlags = 0; depthBufferDesc.MiscFlags = 0; hr = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); if (FAILED(hr)){ return false; } D3D11_DEPTH_STENCIL_DESC depthStencilDesc; ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); if (FAILED(hr)){ return false; } m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; hr = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); if (FAILED(hr)){ return false; } m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; hr = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState); if (FAILED(hr)){ return false; } m_deviceContext->RSSetState(m_rasterState); D3D11_VIEWPORT viewport; viewport.Width = (float)screenWidth; viewport.Height = (float)screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; m_deviceContext->RSSetViewports(1, &viewport); fov = XM_PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; m_projectionMatrix = XMMatrixPerspectiveFovLH(fov, screenAspect, screenNear, screenDepth); m_worldMatrix = XMMatrixIdentity(); m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc)); depthDisabledStencilDesc.DepthEnable = false; depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthDisabledStencilDesc.StencilEnable = true; depthDisabledStencilDesc.StencilReadMask = 0xFF; depthDisabledStencilDesc.StencilWriteMask = 0xFF; depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = m_device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState); if (FAILED(hr)){ return false; } D3D11_BLEND_DESC blendStateDescription; ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); blendStateDescription.RenderTarget[0].BlendEnable = TRUE; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; //blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; // blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f; hr = m_device->CreateBlendState(&blendStateDescription, &m_alphaEnableBlendingState); if (FAILED(hr)){ return false; } blendStateDescription.RenderTarget[0].BlendEnable = FALSE; hr = m_device->CreateBlendState(&blendStateDescription, &m_alphaDisableBlendingState); if (FAILED(hr)){ return false; } return true; }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = ARRAYSIZE( driverTypes ); D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, nullptr ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); // Compile the vertex shader ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial02.fx", "VS", "vs_4_0", &pVSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, "The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", "Error", MB_OK ); return hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader ); if( FAILED( hr ) ) { pVSBlob->Release(); return hr; } // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout ); pVSBlob->Release(); if( FAILED( hr ) ) return hr; // Set the input layout g_pImmediateContext->IASetInputLayout( g_pVertexLayout ); // Compile the pixel shader ID3DBlob* pPSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, "The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", "Error", MB_OK ); return hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader ); pPSBlob->Release(); if( FAILED( hr ) ) return hr; // Create vertex buffer SimpleVertex vertices[] = { XMFLOAT3( 0.0f, 0.5f, 0.5f ), XMFLOAT3( 0.5f, -0.5f, 0.5f ), XMFLOAT3( -0.5f, -0.5f, 0.5f ), }; D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 3; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); // Set primitive topology g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); return S_OK; }
bool InitDirect3D(RENDERER_SETTINGS * pSetup) { DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM; DXGI_SWAP_CHAIN_DESC desc; ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC)); desc.BufferCount = 1; desc.BufferDesc.Width = pSetup->nWidth; desc.BufferDesc.Height = pSetup->nHeight; desc.BufferDesc.Format = format; if (pSetup->bVsync) { bVsync = true; IDXGIFactory1 * pFactory = NULL; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory); if (pFactory) { IDXGIAdapter1 * pAdapter = NULL; pFactory->EnumAdapters1( 0, &pAdapter ); if (pAdapter) { IDXGIOutput * pOutput = NULL; pAdapter->EnumOutputs( 0, &pOutput ); if (pOutput) { unsigned int nModeCount = 0; pOutput->GetDisplayModeList( format, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &nModeCount, NULL); DXGI_MODE_DESC * pModes = new DXGI_MODE_DESC[ nModeCount ]; pOutput->GetDisplayModeList( format, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &nModeCount, pModes); for (int i=0; i<nModeCount; i++) { if (pModes[i].Width == pSetup->nWidth && pModes[i].Height == pSetup->nHeight) { desc.BufferDesc = pModes[i]; break; } } delete[] pModes; pOutput->Release(); } pAdapter->Release(); } pFactory->Release(); } } desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.OutputWindow = hWnd; desc.SampleDesc.Count = 1; desc.Windowed = pSetup->windowMode != RENDERER_WINDOWMODE_FULLSCREEN; DWORD deviceCreationFlags = 0; #ifdef _DEBUG //deviceCreationFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif if (D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, deviceCreationFlags, NULL, NULL, D3D11_SDK_VERSION, &desc, &pSwapChain, &pDevice, NULL, &pContext) != S_OK) { printf("[Renderer] D3D11CreateDeviceAndSwapChain failed\n"); return false; } pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer); pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTarget); pBackBuffer->Release(); pContext->OMSetRenderTargets(1, &pRenderTarget, NULL); // create staging texture for frame grabbing D3D11_TEXTURE2D_DESC description; pBackBuffer->GetDesc( &description ); description.BindFlags = 0; description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; description.Usage = D3D11_USAGE_STAGING; HRESULT hr = pDevice->CreateTexture2D( &description, NULL, &pFrameGrabTexture ); return true; }
HRESULT InitDevice() { // Create swap chain { // Create DXGI factory to enumerate adapters IDXGIFactory1 *pDXGIFactory; HRESULT hResult = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pDXGIFactory); assert(SUCCEEDED(hResult)); // Use the first adapter IDXGIAdapter1 *pAdapter; hResult = pDXGIFactory->EnumAdapters1(0, &pAdapter); assert(SUCCEEDED(hResult)); pDXGIFactory->Release(); // Create D3D11 device and swapchain DXGI_SWAP_CHAIN_DESC scd = {0}; ZeroMemory(&scd, sizeof(scd)); scd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; scd.SampleDesc.Count = 1; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 1; scd.OutputWindow = hWnd; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Windowed = TRUE; hResult = D3D11CreateDeviceAndSwapChain( pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_SINGLETHREADED, NULL, 0, D3D11_SDK_VERSION, &scd, &g_swapChain, &g_device11, NULL, &g_immediateContext ); assert(SUCCEEDED(hResult)); } // Create vertex buffer { const size_t vertexCount = 4; Vertex vertices[vertexCount] = { { D3DXVECTOR3( -1.0f, -1.0f, 0.5f ),D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 0.5f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ),D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 0.5f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ),D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 0.5f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ),D3DXVECTOR2( 0.0f, 0.0f ) }, }; D3D11_BUFFER_DESC bd = {0}; bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( Vertex ) * vertexCount; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D11_SUBRESOURCE_DATA InitData = {0}; InitData.pSysMem = vertices; HRESULT hr = g_device11->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( Vertex ); UINT offset = 0; g_immediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); } // Create index buffer { DWORD indices[] = { 3,1,0, 2,1,3, }; g_indexCount = sizeof(indices)/sizeof(DWORD); D3D11_BUFFER_DESC bd = {0}; bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * g_indexCount; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D11_SUBRESOURCE_DATA InitData = {0}; InitData.pSysMem = indices; HRESULT hr = g_device11->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Set index buffer g_immediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Set primitive topology g_immediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); } ID3DBlob* vs = NULL; ID3DBlob* ps = NULL; // create shaders { HRESULT hr = S_OK; hr = CompileShaderFromFile(L"Data\\GUI_dx11.hlsl", "RenderSceneVS", "vs_4_0", &vs); assert(SUCCEEDED(hr)); hr = CompileShaderFromFile(L"Data\\GUI_dx11.hlsl", "RenderScenePS", "ps_4_0", &ps); assert(SUCCEEDED(hr)); hr = g_device11->CreateVertexShader( vs->GetBufferPointer(), vs->GetBufferSize(), NULL, &g_pVertexShader ); assert(SUCCEEDED(hr)); hr = g_device11->CreatePixelShader( ps->GetBufferPointer(), ps->GetBufferSize(), NULL, &g_pPixelShader ); assert(SUCCEEDED(hr)); } // create input layout { // Create our vertex input layout const D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); HRESULT hr = g_device11->CreateInputLayout( layout, numElements, vs->GetBufferPointer(), vs->GetBufferSize(), &g_pVertexLayout ); assert(SUCCEEDED(hr)); } SAFE_RELEASE(vs); SAFE_RELEASE(ps); RecreateTargets(window_width, window_height); return S_OK; }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = ARRAYSIZE( driverTypes ); D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd = {}; sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd = {}; sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, nullptr ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); return S_OK; }
//-------------------------------------------------------------------------------------- // Enumerate for each adapter all of the supported display modes, // device types, adapter formats, back buffer formats, window/full screen support, // depth stencil formats, multisampling types/qualities, and presentations intervals. // // For each combination of device type (HAL/REF), adapter format, back buffer format, and // IsWindowed it will call the app's ConfirmDevice callback. This allows the app // to reject or allow that combination based on its caps/etc. It also allows the // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP // if supported otherwise it will default to SWVP, however the app can change this // through the ConfirmDevice callback. //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc, void* pIsD3D11DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" ); HRESULT hr; IDXGIFactory1* pFactory = DXUTGetDXGIFactory(); if( !pFactory ) return E_FAIL; m_bHasEnumerated = true; m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc; m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext; ClearAdapterInfoList(); for( int index = 0; ; ++index ) { IDXGIAdapter* pAdapter = nullptr; hr = pFactory->EnumAdapters( index, &pAdapter ); if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit break; IDXGIAdapter2* pAdapter2 = nullptr; if ( SUCCEEDED( pAdapter->QueryInterface( __uuidof(IDXGIAdapter2), ( LPVOID* )&pAdapter2 ) ) ) { // Succeeds on DirectX 11.1 Runtime systems DXGI_ADAPTER_DESC2 desc; hr = pAdapter2->GetDesc2( &desc ); pAdapter2->Release(); if ( SUCCEEDED(hr) && ( desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE ) ) { // Skip "always there" Microsoft Basics Display Driver pAdapter->Release(); continue; } } CD3D11EnumAdapterInfo* pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { SAFE_RELEASE( pAdapter ); return E_OUTOFMEMORY; } pAdapterInfo->AdapterOrdinal = index; pAdapter->GetDesc( &pAdapterInfo->AdapterDesc ); pAdapterInfo->m_pAdapter = pAdapter; // Enumerate the device driver types on the adapter. hr = EnumerateDevices( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; continue; } hr = EnumerateOutputs( pAdapterInfo ); if( FAILED( hr ) || pAdapterInfo->outputInfoList.empty() ) { delete pAdapterInfo; continue; } // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo ) ) ) { delete pAdapterInfo; continue; } m_AdapterInfoList.push_back( pAdapterInfo ); } // If we did not get an adapter then we should still enumerate WARP and Ref. if (m_AdapterInfoList.size() == 0) { CD3D11EnumAdapterInfo* pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { return E_OUTOFMEMORY; } pAdapterInfo->bAdapterUnavailable = true; hr = EnumerateDevices( pAdapterInfo ); // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) ) { delete pAdapterInfo; } if (SUCCEEDED(hr)) m_AdapterInfoList.push_back( pAdapterInfo ); } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; for( size_t i = 0; i < m_AdapterInfoList.size(); i++ ) { auto pAdapterInfo1 = m_AdapterInfoList[ i ]; for( size_t j = i + 1; j < m_AdapterInfoList.size(); j++ ) { auto pAdapterInfo2 = m_AdapterInfoList[ j ]; if( wcsncmp( pAdapterInfo1->AdapterDesc.Description, pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( auto it = m_AdapterInfoList.begin(); it != m_AdapterInfoList.end(); ++it ) { wcscpy_s( (*it)->szUniqueDescription, 100, (*it)->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; swprintf_s( sz, 100, L" (#%u)", (*it)->AdapterOrdinal ); wcscat_s( (*it)->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); } } D3D_FEATURE_LEVEL fLvl[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 }; // Check WARP max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, fLvl, _countof(fLvl), D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 runtime will not recognize FL 11.1, so try without it hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_warpFL = D3D_FEATURE_LEVEL_10_1; } // Check REF max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, fLvl, _countof(fLvl), D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 runtime will not recognize FL 11.1, so try without it hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_refFL = D3D_FEATURE_LEVEL_11_0; } return S_OK; }
bool DoD3D11Hook(ID3D11Device *device) { HRESULT hErr; bD3D101Hooked = true; HMODULE hD3D10_1 = LoadLibrary(TEXT("d3d10_1.dll")); if(!hD3D10_1) { RUNONCE logOutput << "DoD3D11Hook: could not load d3d10.1" << endl; return false; } HMODULE hDXGI = GetModuleHandle(TEXT("dxgi.dll")); if(!hDXGI) { RUNONCE logOutput << "DoD3D11Hook: could not load dxgi" << endl; return false; } CREATEDXGIFACTORY1PROC createDXGIFactory1 = (CREATEDXGIFACTORY1PROC)GetProcAddress(hDXGI, "CreateDXGIFactory1"); if(!createDXGIFactory1) { RUNONCE logOutput << "DoD3D11Hook: could not get address of CreateDXGIFactory1" << endl; return false; } PFN_D3D10_CREATE_DEVICE1 d3d10CreateDevice1 = (PFN_D3D10_CREATE_DEVICE1)GetProcAddress(hD3D10_1, "D3D10CreateDevice1"); if(!d3d10CreateDevice1) { RUNONCE logOutput << "DoD3D11Hook: could not get address of D3D10CreateDevice1" << endl; return false; } IDXGIFactory1 *factory; if(FAILED(hErr = (*createDXGIFactory1)(__uuidof(IDXGIFactory1), (void**)&factory))) { RUNONCE logOutput << "DoD3D11Hook: CreateDXGIFactory1 failed, result = " << UINT(hErr) << endl; return false; } IDXGIAdapter1 *adapter; if(FAILED(hErr = factory->EnumAdapters1(0, &adapter))) { RUNONCE logOutput << "DoD3D11Hook: factory->EnumAdapters1 failed, result = " << UINT(hErr) << endl; factory->Release(); return false; } if(FAILED(hErr = (*d3d10CreateDevice1)(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &shareDevice))) { if(FAILED(hErr = (*d3d10CreateDevice1)(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_FEATURE_LEVEL_9_3, D3D10_1_SDK_VERSION, &shareDevice))) { RUNONCE logOutput << "DoD3D11Hook: device creation failed, result = " << UINT(hErr) << endl; adapter->Release(); factory->Release(); return false; } } adapter->Release(); factory->Release(); //------------------------------------------------ D3D11_TEXTURE2D_DESC texGameDesc; ZeroMemory(&texGameDesc, sizeof(texGameDesc)); texGameDesc.Width = d3d11CaptureInfo.cx; texGameDesc.Height = d3d11CaptureInfo.cy; texGameDesc.MipLevels = 1; texGameDesc.ArraySize = 1; texGameDesc.Format = dxgiFormat; texGameDesc.SampleDesc.Count = 1; texGameDesc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE; texGameDesc.Usage = D3D11_USAGE_DEFAULT; texGameDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Texture2D *d3d11Tex; if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d11Tex))) { RUNONCE logOutput << "DoD3D11Hook: creation of intermediary texture failed, result = " << UINT(hErr) << endl; return false; } if(FAILED(hErr = d3d11Tex->QueryInterface(__uuidof(ID3D11Resource), (void**)©TextureGame))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(ID3D11Resource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } IDXGIResource *res; if(FAILED(hErr = d3d11Tex->QueryInterface(IID_IDXGIResource, (void**)&res))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(IID_IDXGIResource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } HANDLE handle; if(FAILED(hErr = res->GetSharedHandle(&handle))) { RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); res->Release(); return false; } d3d11Tex->Release(); res->Release(); //------------------------------------------------ if(FAILED(hErr = shareDevice->OpenSharedResource(handle, __uuidof(ID3D10Resource), (void**)©TextureIntermediary))) { RUNONCE logOutput << "DoD3D11Hook: shareDevice->OpenSharedResource failed, result = " << UINT(hErr) << endl; return false; } //------------------------------------------------ D3D10_TEXTURE2D_DESC texDesc; ZeroMemory(&texDesc, sizeof(texDesc)); texDesc.Width = d3d11CaptureInfo.cx; texDesc.Height = d3d11CaptureInfo.cy; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = dxgiFormat; texDesc.SampleDesc.Count = 1; texDesc.BindFlags = D3D10_BIND_RENDER_TARGET|D3D10_BIND_SHADER_RESOURCE; texDesc.Usage = D3D10_USAGE_DEFAULT; texDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; for(UINT i=0; i<2; i++) { ID3D10Texture2D *d3d10tex; if(FAILED(hErr = shareDevice->CreateTexture2D(&texDesc, NULL, &d3d10tex))) { RUNONCE logOutput << "DoD3D11Hook: shareDevice->CreateTexture2D " << i << " failed, result = " << UINT(hErr) << endl; return false; } if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&sharedTextures[i]))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(ID3D10Resource) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&keyedMutexes[i]))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(IDXGIKeyedMutex) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } IDXGIResource *res; if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(IDXGIResource), (void**)&res))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(IDXGIResource) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } if(FAILED(hErr = res->GetSharedHandle(&sharedHandles[i]))) { RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle " << i << " failed, result = " << UINT(hErr) << endl; res->Release(); d3d10tex->Release(); return false; } res->Release(); d3d10tex->Release(); } return true; }
D3D10System::D3D10System() { HRESULT err; #ifdef USE_DXGI1_2 REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1); #else REFIID iidVal = __uuidof(IDXGIFactory1); #endif UINT adapterID = GlobalConfig->GetInt(TEXT("Video"), TEXT("Adapter"), 0); IDXGIFactory1 *factory; if(FAILED(err = CreateDXGIFactory1(iidVal, (void**)&factory))) CrashError(TEXT("Could not create DXGI factory")); IDXGIAdapter1 *adapter; if(FAILED(err = factory->EnumAdapters1(adapterID, &adapter))) CrashError(TEXT("Could not get DXGI adapter")); //------------------------------------------------------------------ DXGI_SWAP_CHAIN_DESC swapDesc; zero(&swapDesc, sizeof(swapDesc)); swapDesc.BufferCount = 2; swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swapDesc.BufferDesc.Width = App->renderFrameWidth; swapDesc.BufferDesc.Height = App->renderFrameHeight; swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapDesc.Flags = 0; swapDesc.OutputWindow = hwndRenderFrame; swapDesc.SampleDesc.Count = 1; swapDesc.Windowed = TRUE; bDisableCompatibilityMode = 1;//AppConfig->GetInt(TEXT("Video"), TEXT("DisableD3DCompatibilityMode"), 1) != 0; UINT createFlags = D3D10_CREATE_DEVICE_BGRA_SUPPORT; if(GlobalConfig->GetInt(TEXT("General"), TEXT("UseDebugD3D"))) createFlags |= D3D10_CREATE_DEVICE_DEBUG; D3D10_FEATURE_LEVEL1 level = bDisableCompatibilityMode ? D3D10_FEATURE_LEVEL_10_1 : D3D10_FEATURE_LEVEL_9_3; //D3D10_CREATE_DEVICE_DEBUG //D3D11_DRIVER_TYPE_REFERENCE, D3D11_DRIVER_TYPE_HARDWARE err = D3D10CreateDeviceAndSwapChain1(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, createFlags, level, D3D10_1_SDK_VERSION, &swapDesc, &swap, &d3d); if(FAILED(err)) { bDisableCompatibilityMode = !bDisableCompatibilityMode; level = bDisableCompatibilityMode ? D3D10_FEATURE_LEVEL_10_1 : D3D10_FEATURE_LEVEL_9_3; err = D3D10CreateDeviceAndSwapChain1(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, createFlags, level, D3D10_1_SDK_VERSION, &swapDesc, &swap, &d3d); } if(FAILED(err)) CrashError(TEXT("Could not create D3D10 device and swap chain. This error can happen for one of the following reasons:\r\n\r\n1.) Your GPU is not supported (DirectX 10 support is required - many integrated laptop GPUs do not support DX10)\r\n2.) You're running Windows Vista without the \"Platform Update\"\r\n3.) Your video card drivers are out of date")); adapter->Release(); factory->Release(); //------------------------------------------------------------------ Log(TEXT("Loading up D3D10...")); D3D10_DEPTH_STENCIL_DESC depthDesc; zero(&depthDesc, sizeof(depthDesc)); depthDesc.DepthEnable = FALSE; err = d3d->CreateDepthStencilState(&depthDesc, &depthState); if(FAILED(err)) CrashError(TEXT("Unable to create depth state")); d3d->OMSetDepthStencilState(depthState, 0); //------------------------------------------------------------------ D3D10_RASTERIZER_DESC rasterizerDesc; zero(&rasterizerDesc, sizeof(rasterizerDesc)); rasterizerDesc.FillMode = D3D10_FILL_SOLID; rasterizerDesc.CullMode = D3D10_CULL_NONE; rasterizerDesc.FrontCounterClockwise = FALSE; rasterizerDesc.DepthClipEnable = TRUE; err = d3d->CreateRasterizerState(&rasterizerDesc, &rasterizerState); if(FAILED(err)) CrashError(TEXT("Unable to create rasterizer state")); d3d->RSSetState(rasterizerState); //------------------------------------------------------------------ rasterizerDesc.ScissorEnable = TRUE; err = d3d->CreateRasterizerState(&rasterizerDesc, &scissorState); if(FAILED(err)) CrashError(TEXT("Unable to create scissor state")); //------------------------------------------------------------------ ID3D10Texture2D *backBuffer = NULL; err = swap->GetBuffer(0, IID_ID3D10Texture2D, (void**)&backBuffer); if(FAILED(err)) CrashError(TEXT("Unable to get back buffer from swap chain")); err = d3d->CreateRenderTargetView(backBuffer, NULL, &swapRenderView); if(FAILED(err)) CrashError(TEXT("Unable to get render view from back buffer")); backBuffer->Release(); //------------------------------------------------------------------ D3D10_BLEND_DESC disabledBlendDesc; zero(&disabledBlendDesc, sizeof(disabledBlendDesc)); for(int i=0; i<8; i++) { disabledBlendDesc.BlendEnable[i] = TRUE; disabledBlendDesc.RenderTargetWriteMask[i] = D3D10_COLOR_WRITE_ENABLE_ALL; } disabledBlendDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; disabledBlendDesc.BlendOp = D3D10_BLEND_OP_ADD; disabledBlendDesc.SrcBlendAlpha = D3D10_BLEND_ONE; disabledBlendDesc.DestBlendAlpha = D3D10_BLEND_ZERO; disabledBlendDesc.SrcBlend = D3D10_BLEND_ONE; disabledBlendDesc.DestBlend = D3D10_BLEND_ZERO; err = d3d->CreateBlendState(&disabledBlendDesc, &disabledBlend); if(FAILED(err)) CrashError(TEXT("Unable to create disabled blend state")); this->BlendFunction(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, 1.0f); bBlendingEnabled = true; }
int main() { printf("\n\ntest_win_api_directx_research\n\n"); /* Retrieve a IDXGIFactory that can enumerate the adapters. */ IDXGIFactory1* factory = NULL; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&factory)); if (S_OK != hr) { printf("Error: failed to retrieve the IDXGIFactory.\n"); exit(EXIT_FAILURE); } /* Enumerate the adapters.*/ UINT i = 0; IDXGIAdapter1* adapter = NULL; std::vector<IDXGIAdapter1*> adapters; /* Needs to be Released(). */ while (DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(i, &adapter)) { adapters.push_back(adapter); ++i; } /* Get some info about the adapters (GPUs). */ for (size_t i = 0; i < adapters.size(); ++i) { DXGI_ADAPTER_DESC1 desc; adapter = adapters[i]; hr = adapter->GetDesc1(&desc); if (S_OK != hr) { printf("Error: failed to get a description for the adapter: %lu\n", i); continue; } wprintf(L"Adapter: %lu, description: %s\n", i, desc.Description); } /* Check what devices/monitors are attached to the adapters. */ UINT dx = 0; IDXGIOutput* output = NULL; std::vector<IDXGIOutput*> outputs; /* Needs to be Released(). */ for (size_t i = 0; i < adapters.size(); ++i) { dx = 0; adapter = adapters[i]; while (DXGI_ERROR_NOT_FOUND != adapter->EnumOutputs(dx, &output)) { printf("Found monitor %d on adapter: %lu\n", dx, i); outputs.push_back(output); ++dx; } } if (0 >= outputs.size()) { printf("Error: no outputs found (%lu).\n", outputs.size()); exit(EXIT_FAILURE); } /* Print some info about the monitors. */ for (size_t i = 0; i < outputs.size(); ++i) { DXGI_OUTPUT_DESC desc; output = outputs[i]; hr = output->GetDesc(&desc); if (S_OK != hr) { printf("Error: failed to retrieve a DXGI_OUTPUT_DESC for output %lu.\n", i); continue; } wprintf(L"Monitor: %s, attached to desktop: %c\n", desc.DeviceName, (desc.AttachedToDesktop) ? 'y' : 'n'); } /* To get access to a OutputDuplication interface we need to have a Direct3D device which handles the actuall rendering and "gpu" stuff. According to a gamedev stackexchange it seems we can create one w/o a HWND. */ ID3D11Device* d3d_device = NULL; /* Needs to be released. */ ID3D11DeviceContext* d3d_context = NULL; /* Needs to be released. */ IDXGIAdapter1* d3d_adapter = NULL; D3D_FEATURE_LEVEL d3d_feature_level; /* The selected feature level (D3D version), selected from the Feature Levels array, which is NULL here; when it's NULL the default list is used see: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082%28v=vs.85%29.aspx ) */ { /* Start creating a D3D11 device */ #if 1 /* NOTE: Apparently the D3D11CreateDevice function returns E_INVALIDARG, when you pass a pointer to an adapter for the first parameter and use the D3D_DRIVER_TYPE_HARDWARE. When you want to pass a valid pointer for the adapter, you need to set the DriverType parameter (2nd) to D3D_DRIVER_TYPE_UNKNOWN. @todo figure out what would be the best solution; easiest to use is probably using NULL here. */ int use_adapter = 0; if (use_adapter >= adapters.size()) { printf("Invalid adapter index: %d, we only have: %lu - 1\n", use_adapter, adapters.size()); exit(EXIT_FAILURE); } d3d_adapter = adapters[use_adapter]; if (NULL == d3d_adapter) { printf("Error: the stored adapter is NULL.\n"); exit(EXIT_FAILURE); } #endif hr = D3D11CreateDevice(d3d_adapter, /* Adapter: The adapter (video card) we want to use. We may use NULL to pick the default adapter. */ D3D_DRIVER_TYPE_UNKNOWN, /* DriverType: We use the GPU as backing device. */ NULL, /* Software: we're using a D3D_DRIVER_TYPE_HARDWARE so it's not applicaple. */ NULL, /* Flags: maybe we need to use D3D11_CREATE_DEVICE_BGRA_SUPPORT because desktop duplication is using this. */ NULL, /* Feature Levels (ptr to array): what version to use. */ 0, /* Number of feature levels. */ D3D11_SDK_VERSION, /* The SDK version, use D3D11_SDK_VERSION */ &d3d_device, /* OUT: the ID3D11Device object. */ &d3d_feature_level, /* OUT: the selected feature level. */ &d3d_context); /* OUT: the ID3D11DeviceContext that represents the above features. */ if (S_OK != hr) { printf("Error: failed to create the D3D11 Device.\n"); if (E_INVALIDARG == hr) { printf("Got INVALID arg passed into D3D11CreateDevice. Did you pass a adapter + a driver which is not the UNKNOWN driver?.\n"); } exit(EXIT_FAILURE); } } /* End creating a D3D11 device. */ /* Create a IDXGIOutputDuplication for the first monitor. - From a IDXGIOutput which represents an monitor, we query a IDXGIOutput1 because the IDXGIOutput1 has the DuplicateOutput feature. */ IDXGIOutput1* output1 = NULL; IDXGIOutputDuplication* duplication = NULL; { /* Start IDGIOutputDuplication init. */ int use_monitor = 0; if (use_monitor >= outputs.size()) { printf("Invalid monitor index: %d, we only have: %lu - 1\n", use_monitor, outputs.size()); exit(EXIT_FAILURE); } output = outputs[use_monitor]; if (NULL == output) { printf("No valid output found. The output is NULL.\n"); exit(EXIT_FAILURE); } hr = output->QueryInterface(__uuidof(IDXGIOutput1), (void**)&output1); if (S_OK != hr) { printf("Error: failed to query the IDXGIOutput1 interface.\n"); exit(EXIT_FAILURE); } hr = output1->DuplicateOutput(d3d_device, &duplication); if (S_OK != hr) { printf("Error: failed to create the duplication output.\n"); exit(EXIT_FAILURE); } printf("Queried the IDXGIOutput1.\n"); } /* End IDGIOutputDuplication init. */ if (NULL == duplication) { printf("Error: okay, we shouldn't arrive here but the duplication var is NULL.\n"); exit(EXIT_FAILURE); } /* To download the pixel data from the GPU we need a staging texture. Therefore we need to determine the width and height of the buffers that we receive. @TODO - We could also retrieve the width/height from the texture we got from through the acquired frame (see the 'tex' variable below). That may be a safer solution. */ DXGI_OUTPUT_DESC output_desc; { hr = output->GetDesc(&output_desc); if (S_OK != hr) { printf("Error: failed to get the DXGI_OUTPUT_DESC from the output (monitor). We need this to create a staging texture when downloading the pixels from the gpu.\n"); exit(EXIT_FAILURE); } printf("The monitor has the following dimensions: left: %d, right: %d, top: %d, bottom: %d.\n" ,(int)output_desc.DesktopCoordinates.left ,(int)output_desc.DesktopCoordinates.right ,(int)output_desc.DesktopCoordinates.top ,(int)output_desc.DesktopCoordinates.bottom ); } if (0 == output_desc.DesktopCoordinates.right || 0 == output_desc.DesktopCoordinates.bottom) { printf("The output desktop coordinates are invalid.\n"); exit(EXIT_FAILURE); } /* Create the staging texture that we need to download the pixels from gpu. */ D3D11_TEXTURE2D_DESC tex_desc; tex_desc.Width = output_desc.DesktopCoordinates.right; tex_desc.Height = output_desc.DesktopCoordinates.bottom; tex_desc.MipLevels = 1; tex_desc.ArraySize = 1; /* When using a texture array. */ tex_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the default data when using desktop duplication, see https://msdn.microsoft.com/en-us/library/windows/desktop/hh404611(v=vs.85).aspx */ tex_desc.SampleDesc.Count = 1; /* MultiSampling, we can use 1 as we're just downloading an existing one. */ tex_desc.SampleDesc.Quality = 0; /* "" */ tex_desc.Usage = D3D11_USAGE_STAGING; tex_desc.BindFlags = 0; tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; tex_desc.MiscFlags = 0; ID3D11Texture2D* staging_tex = NULL; hr = d3d_device->CreateTexture2D(&tex_desc, NULL, &staging_tex); if (E_INVALIDARG == hr) { printf("Error: received E_INVALIDARG when trying to create the texture.\n"); exit(EXIT_FAILURE); } else if (S_OK != hr) { printf("Error: failed to create the 2D texture, error: %d.\n", hr); exit(EXIT_FAILURE); } /* Get some info about the output duplication. When the DesktopImageInSystemMemory is TRUE you can use the MapDesktopSurface/UnMapDesktopSurface directly to retrieve the pixel data. If not, then you need to use a surface. */ DXGI_OUTDUPL_DESC duplication_desc; duplication->GetDesc(&duplication_desc); printf("duplication desc.DesktopImageInSystemMemory: %c\n", (duplication_desc.DesktopImageInSystemMemory) ? 'y' : 'n'); /* Access a couple of frames. */ DXGI_OUTDUPL_FRAME_INFO frame_info; IDXGIResource* desktop_resource = NULL; ID3D11Texture2D* tex = NULL; DXGI_MAPPED_RECT mapped_rect; for (int i = 0; i < 500; ++i) { // printf("%02d - ", i); hr = duplication->AcquireNextFrame(1000, &frame_info, &desktop_resource); if (DXGI_ERROR_ACCESS_LOST == hr) { printf("Received a DXGI_ERROR_ACCESS_LOST.\n"); } else if (DXGI_ERROR_WAIT_TIMEOUT == hr) { printf("Received a DXGI_ERROR_WAIT_TIMEOUT.\n"); } else if (DXGI_ERROR_INVALID_CALL == hr) { printf("Received a DXGI_ERROR_INVALID_CALL.\n"); } else if (S_OK == hr) { //printf("Yay we got a frame.\n"); /* Print some info. */ //printf("frame_info.TotalMetadataBufferSize: %u\n", frame_info.TotalMetadataBufferSize); //printf("frame_info.AccumulatedFrames: %u\n", frame_info.AccumulatedFrames); /* Get the texture interface .. */ #if 1 hr = desktop_resource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&tex); if (S_OK != hr) { printf("Error: failed to query the ID3D11Texture2D interface on the IDXGIResource we got.\n"); exit(EXIT_FAILURE); } #endif /* Map the desktop surface */ hr = duplication->MapDesktopSurface(&mapped_rect); if (S_OK == hr) { printf("We got acess to the desktop surface\n"); hr = duplication->UnMapDesktopSurface(); if (S_OK != hr) { printf("Error: failed to unmap the desktop surface after successfully mapping it.\n"); } } else if (DXGI_ERROR_UNSUPPORTED == hr) { //printf("MapDesktopSurface returned DXGI_ERROR_UNSUPPORTED.\n"); /* According to the docs, when we receive this error we need to transfer the image to a staging surface and then lock the image by calling IDXGISurface::Map(). To get the data from GPU to the CPU, we do: - copy the frame into our staging texture - map the texture - ... do something - unmap. @TODO figure out what solution is faster: There are multiple solutions to copy a texture. I have to look into what solution is better. - d3d_context->CopySubresourceRegion(); - d3d_context->CopyResource(dest, src) @TODO we need to make sure that the width/height are valid. */ d3d_context->CopyResource(staging_tex, tex); D3D11_MAPPED_SUBRESOURCE map; HRESULT map_result = d3d_context->Map(staging_tex, /* Resource */ 0, /* Subresource */ D3D11_MAP_READ, /* Map type. */ 0, /* Map flags. */ &map); if (S_OK == map_result) { unsigned char* data = (unsigned char*)map.pData; //printf("Mapped the staging tex; we can access the data now.\n"); printf("RowPitch: %u, DepthPitch: %u, %02X, %02X, %02X\n", map.RowPitch, map.DepthPitch, data[0], data[1], data[2]); #if 0 if (i < 25) { char fname[512]; /* We have to make the image opaque. */ for (int k = 0; k < tex_desc.Width; ++k) { for (int l = 0; l < tex_desc.Height; ++l) { int dx = l * tex_desc.Width * 4 + k * 4; data[dx + 3] = 0xFF; } } sprintf(fname, "capture_%03d.png", i); save_png(fname, tex_desc.Width, tex_desc.Height, 8, PNG_COLOR_TYPE_RGBA, (unsigned char*)map.pData, map.RowPitch, PNG_TRANSFORM_BGR); } #endif } else { printf("Error: failed to map the staging tex. Cannot access the pixels.\n"); } d3d_context->Unmap(staging_tex, 0); } else if (DXGI_ERROR_INVALID_CALL == hr) { printf("MapDesktopSurface returned DXGI_ERROR_INVALID_CALL.\n"); } else if (DXGI_ERROR_ACCESS_LOST == hr) { printf("MapDesktopSurface returned DXGI_ERROR_ACCESS_LOST.\n"); } else if (E_INVALIDARG == hr) { printf("MapDesktopSurface returned E_INVALIDARG.\n"); } else { printf("MapDesktopSurface returned an unknown error.\n"); } } /* Clean up */ { if (NULL != tex) { tex->Release(); tex = NULL; } if (NULL != desktop_resource) { desktop_resource->Release(); desktop_resource = NULL; } /* We must release the frame. */ hr = duplication->ReleaseFrame(); if (S_OK != hr) { printf("Failed to release the duplication frame.\n"); } } } //printf("Monitors connected to adapter: %lu\n", i); /* Cleanup */ { if (NULL != staging_tex) { staging_tex->Release(); staging_tex = NULL; } if (NULL != d3d_device) { d3d_device->Release(); d3d_device = NULL; } if (NULL != d3d_context) { d3d_context->Release(); d3d_context = NULL; } if (NULL != duplication) { duplication->Release(); duplication = NULL; } for (size_t i = 0; i < adapters.size(); ++i) { if (NULL != adapters[i]) { adapters[i]->Release(); adapters[i] = NULL; } } for (size_t i = 0; i < outputs.size(); ++i) { if (NULL != outputs[i]) { outputs[i]->Release(); outputs[i] = NULL; } } if (NULL != output1) { output1->Release(); output1 = NULL; } if (NULL != factory) { factory->Release(); factory = NULL; } } return 0; }
bool DXGI1Device::Init(const mfxU32 adapterNum) { // release the object before initialization Close(); // load up the library if it is not loaded if (NULL == m_hModule) { LoadDLLModule(L"dxgi.dll"); } if (m_hModule) { DXGICreateFactoryFunc pFunc; IDXGIFactory1 *pFactory; IDXGIAdapter1 *pAdapter; DXGI_ADAPTER_DESC1 desc; mfxU32 curAdapter, maxAdapters; HRESULT hRes; // load address of procedure to create DXGI 1.1 factory pFunc = (DXGICreateFactoryFunc) GetProcAddress(m_hModule, "CreateDXGIFactory1"); if (NULL == pFunc) { return false; } // create the factory #if _MSC_VER >= 1400 hRes = pFunc(__uuidof(IDXGIFactory1), (void**) (&pFactory)); #else hRes = pFunc(IID_IDXGIFactory1, (void**) (&pFactory)); #endif if (FAILED(hRes)) { return false; } m_pDXGIFactory1 = pFactory; // get the number of adapters curAdapter = 0; maxAdapters = 0; mfxU32 outputs = 0; do { // get the required adapted hRes = pFactory->EnumAdapters1(curAdapter, &pAdapter); if (FAILED(hRes)) { break; } mfxU32 curOutput = 0; HRESULT h; do { IDXGIOutput *out; h = pAdapter->EnumOutputs(curOutput, &out); if(FAILED(h)) break; // if it is the required adapter, save the interface if (outputs == adapterNum) m_pDXGIAdapter1 = pAdapter; out->Release(); outputs += 1; curOutput += 1; } while(!m_pDXGIAdapter1 && SUCCEEDED(h)); if(!m_pDXGIAdapter1) pAdapter->Release(); curAdapter += 1; } while (!m_pDXGIAdapter1 && SUCCEEDED(hRes)); maxAdapters = curAdapter; // there is no required adapter if (adapterNum >= outputs) { return false; } pAdapter = (IDXGIAdapter1 *) m_pDXGIAdapter1; // get the adapter's parameters hRes = pAdapter->GetDesc1(&desc); if (FAILED(hRes)) { return false; } // save the parameters m_vendorID = desc.VendorId; m_deviceID = desc.DeviceId; *((LUID *) &m_luid) = desc.AdapterLuid; } return true; } // bool DXGI1Device::Init(const mfxU32 adapterNum)
bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { hWnd_ = wnd; LoadD3D11Error result = LoadD3D11(); HRESULT hr = E_FAIL; std::vector<std::string> adapterNames; std::string chosenAdapterName; if (result == LoadD3D11Error::SUCCESS) { std::vector<IDXGIAdapter *> adapters; int chosenAdapter = 0; IDXGIFactory * pFactory = nullptr; ptr_CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory); IDXGIAdapter *pAdapter; for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) { adapters.push_back(pAdapter); DXGI_ADAPTER_DESC desc; pAdapter->GetDesc(&desc); std::string str = ConvertWStringToUTF8(desc.Description); adapterNames.push_back(str); if (str == g_Config.sD3D11Device) { chosenAdapter = i; } } chosenAdapterName = adapterNames[chosenAdapter]; hr = CreateTheDevice(adapters[chosenAdapter]); for (int i = 0; i < (int)adapters.size(); i++) { adapters[i]->Release(); } } if (FAILED(hr)) { const char *defaultError = "Your GPU does not appear to support Direct3D 11.\n\nWould you like to try again using Direct3D 9 instead?"; I18NCategory *err = GetI18NCategory("Error"); std::wstring error; if (result == LoadD3D11Error::FAIL_NO_COMPILER) { error = ConvertUTF8ToWString(err->T("D3D11CompilerMissing", "D3DCompiler_47.dll not found. Please install. Or press Yes to try again using Direct3D9 instead.")); } else if (result == LoadD3D11Error::FAIL_NO_D3D11) { error = ConvertUTF8ToWString(err->T("D3D11Missing", "Your operating system version does not include D3D11. Please run Windows Update.\n\nPress Yes to try again using Direct3D9 instead.")); } error = ConvertUTF8ToWString(err->T("D3D11NotSupported", defaultError)); std::wstring title = ConvertUTF8ToWString(err->T("D3D11InitializationError", "Direct3D 11 initialization error")); bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); if (yes) { // Change the config to D3D9 and restart. g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; g_Config.sFailedGPUBackends.clear(); g_Config.Save("save_d3d9_fallback"); W32Util::ExitAndRestart(); } return false; } if (FAILED(device_->QueryInterface(__uuidof (ID3D11Device1), (void **)&device1_))) { device1_ = nullptr; } if (FAILED(context_->QueryInterface(__uuidof (ID3D11DeviceContext1), (void **)&context1_))) { context1_ = nullptr; } #ifdef _DEBUG if (SUCCEEDED(device_->QueryInterface(__uuidof(ID3D11Debug), (void**)&d3dDebug_))) { if (SUCCEEDED(d3dDebug_->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&d3dInfoQueue_))) { d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, true); } } #endif draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames); SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. _assert_msg_(G3D, success, "Failed to compile preset shaders"); int width; int height; GetRes(hWnd_, width, height); // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; IDXGIDevice* dxgiDevice = nullptr; IDXGIAdapter* adapter = nullptr; hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)); if (SUCCEEDED(hr)) { hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory)); DXGI_ADAPTER_DESC desc; adapter->GetDesc(&desc); adapter->Release(); } dxgiDevice->Release(); } // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd_; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain(device_, &sd, &swapChain_); dxgiFactory->MakeWindowAssociation(hWnd_, DXGI_MWA_NO_ALT_ENTER); dxgiFactory->Release(); GotBackbuffer(); return true; }