// Helper function for acquiring the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, *ppAdapter will be set to nullptr. void Renderer::GetHardwareAdapter(_In_ IDXGIFactory4* pFactory, _Outptr_result_maybenull_ IDXGIAdapter1** ppAdapter) { IDXGIAdapter1* pAdapter = nullptr; *ppAdapter = nullptr; for(UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &pAdapter); ++adapterIndex) { DXGI_ADAPTER_DESC1 desc; pAdapter->GetDesc1(&desc); if(desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { // Don't select the Basic Render Driver adapter. // If you want a software adapter, pass in "/warp" on the command line. continue; } // Check to see if the adapter supports Direct3D 12, but don't create the // actual device yet. if(SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_12_1, _uuidof(ID3D12Device), nullptr))) { break; } } *ppAdapter = pAdapter; }
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); }
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; }
bool CRenderer::FindAdapter(IDXGIFactory1** factory, IDXGIAdapter1** adapter) { HRESULT hr = S_OK; IDXGIAdapter1 * pCurrentAdapter = nullptr; DXGI_ADAPTER_DESC1 Bestdesc; if (!factory) { Log("Cannot send in a NULL factory"); return false; } if (!adapter) { Log("Cannot send in a NULL adapter"); return false; } // Create a factory to enumerate all of the hardware in the system. DXCall(hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast<void**>(factory))); #pragma warning(suppress: 6102) if (!*factory) { Log("Could not create the factory"); return false; } unsigned int index = 0; while (DXGI_ERROR_NOT_FOUND != (*factory)->EnumAdapters1(index++, &pCurrentAdapter)) { DXGI_ADAPTER_DESC1 desc; ZeroMemory(&desc, sizeof(desc)); DXCall(pCurrentAdapter->GetDesc1(&desc)); if (nullptr == *adapter) { *adapter = pCurrentAdapter; Bestdesc = desc; } else if (Bestdesc.DedicatedSystemMemory < desc.DedicatedSystemMemory) { (*adapter)->Release(); *adapter = pCurrentAdapter; Bestdesc = desc; } else { pCurrentAdapter->Release(); } } return true; }
//----------------------------------------------------------------------- BOOL D3D11DriverList::enumerate(IDXGIFactory1* pDXGIFactory) { LogManager::getSingleton().logMessage( "D3D11: Driver Detection Starts" ); // Create the DXGI Factory for( UINT iAdapter=0; ; iAdapter++ ) { IDXGIAdapter1* pDXGIAdapter; HRESULT hr = pDXGIFactory->EnumAdapters1( iAdapter, &pDXGIAdapter ); if( DXGI_ERROR_NOT_FOUND == hr ) { hr = S_OK; break; } if( FAILED(hr) ) { delete pDXGIAdapter; return false; } // we don't want NVIDIA PerfHUD in the list - so - here we filter it out DXGI_ADAPTER_DESC1 adaptDesc; if ( SUCCEEDED( pDXGIAdapter->GetDesc1( &adaptDesc ) ) ) { const bool isPerfHUD = wcscmp( adaptDesc.Description, L"NVIDIA PerfHUD" ) == 0; if (isPerfHUD) { continue; } } D3D11Device dev; mDriverList.push_back(new D3D11Driver( dev, iAdapter,pDXGIAdapter) ); } LogManager::getSingleton().logMessage( "D3D11: Driver Detection Ends" ); 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 EnumAllDeviceAdapter(rhi::IDeviceAdapter ** & adapterList, uint32 * num) { PtrGIFactory factory; HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())); K3D_ASSERT(hr == S_OK, "create dx factory failed."); vector<IDXGIAdapter1*> adapters; IDXGIAdapter1* pAdapter = nullptr; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(adapterIndex, &pAdapter); ++adapterIndex) { DXGI_ADAPTER_DESC1 desc; pAdapter->GetDesc1(&desc); if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { continue; } if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr))) { adapters.push_back(pAdapter); } } *num = (uint32)adapters.size(); if (adapters.empty()) { return; } adapterList = new rhi::IDeviceAdapter*[adapters.size()]; for (uint32 index = 0; index < adapters.size(); index++) { DXGI_ADAPTER_DESC1 desc; adapters[index]->GetDesc1(&desc); GpuVendor vendor = MapIdToVendor(desc.VendorId); char VendorName[256] = { 0 }; StringUtil::WCharToChar(desc.Description, VendorName, 256); DX12LOG(Info, "Device", "Vendor is %s, Id is %d.", VendorName, desc.VendorId); adapterList[index] = new DeviceAdapter(adapters[index], vendor); } };
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)
DeviceManager::DeviceManager(void) : m_pd3dDevice(NULL), m_pImmediateContext(NULL), m_pDXGIFactory1(NULL) { // create DXGIFactory, d3d device HRESULT hr = S_OK; // create dxgi factory and keep it for future use. hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&m_pDXGIFactory1) ); if (Logger::IsFailureLog(hr)) { return; } IDXGIAdapter1* pAdapter; // hardware vendor ID uint32_t nvidia = 0x10DE; // NVIDIA Corporation uint32_t ati = 0x1002; // ATI Technologies Inc. / Advanced Micro Devices, Inc. int i = 0; int adapterIndex = 0; printf("Available DXGIAdapters:\n"); while(m_pDXGIFactory1->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) { DXGI_ADAPTER_DESC1 descr; pAdapter->GetDesc1(&descr); wprintf(L"\t%s\n",descr.Description); // choose discrete graphics over integrated. if(adapterIndex == 0 && (descr.VendorId == nvidia || descr.VendorId == ati)) { adapterIndex = i; } i++; pAdapter->Release(); pAdapter = NULL; } hr = m_pDXGIFactory1->EnumAdapters1(adapterIndex, &pAdapter); if (Logger::IsFailureLog(hr)) { return; } 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_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); DXGI_ADAPTER_DESC1 pdescr; pAdapter->GetDesc1(&pdescr); Logger::Log(OutputMessageType::Info, L"%s\n",pdescr.Description); // Note: If you set the pAdapter parameter to a non-NULL value, // you must also set the DriverType parameter // to the D3D_DRIVER_TYPE_UNKNOWN // create d3d11 device on the first graphics adapter. hr = D3D11CreateDevice( pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &m_pd3dDevice, NULL, &m_pImmediateContext); pAdapter->Release(); // no longer needed. if (Logger::IsFailureLog(hr)) { return; } D3D_FEATURE_LEVEL featureLevel = m_pd3dDevice->GetFeatureLevel(); wchar_t* strFeatureLevel = NULL; if( featureLevel == D3D_FEATURE_LEVEL_9_1) { strFeatureLevel = L"D3D_FEATURE_LEVEL_9_1"; } else if( featureLevel == D3D_FEATURE_LEVEL_9_2) { strFeatureLevel = L"D3D_FEATURE_LEVEL_9_2"; } else if( featureLevel == D3D_FEATURE_LEVEL_9_3) { strFeatureLevel = L"D3D_FEATURE_LEVEL_9_3"; } else if( featureLevel ==D3D_FEATURE_LEVEL_10_0) { strFeatureLevel = L"D3D_FEATURE_LEVEL_10_0"; } else if( featureLevel ==D3D_FEATURE_LEVEL_10_1) { strFeatureLevel = L"D3D_FEATURE_LEVEL_10_1"; } else if( featureLevel ==D3D_FEATURE_LEVEL_11_0) { strFeatureLevel = L"D3D_FEATURE_LEVEL_11_0"; } else { strFeatureLevel = L"Newer than D3D_FEATURE_LEVEL_11_0"; } Logger::Log(OutputMessageType::Info,L"Feature Level: %s\n", strFeatureLevel); }
void DetectGpuInfo(std::ostream& os) { #if defined KLAYGE_PLATFORM_WINDOWS typedef HRESULT (WINAPI *CreateDXGIFactory1Func)(REFIID riid, void** ppFactory); #if defined KLAYGE_PLATFORM_WINDOWS_DESKTOP HMODULE dxgi = ::LoadLibraryEx(L"dxgi.dll", nullptr, 0); if (!dxgi) { os << "Unknown GPU"; return; } CreateDXGIFactory1Func DynamicCreateDXGIFactory1 = (CreateDXGIFactory1Func)::GetProcAddress(dxgi, "CreateDXGIFactory1"); if (!DynamicCreateDXGIFactory1) { os << "Unknown GPU"; return; } #else CreateDXGIFactory1Func DynamicCreateDXGIFactory1 = CreateDXGIFactory1; #endif IDXGIFactory1* factory; if (SUCCEEDED((*DynamicCreateDXGIFactory1)(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory)))) { UINT adapter_no = 0; IDXGIAdapter1* adapter = nullptr; while (factory->EnumAdapters1(adapter_no, &adapter) != DXGI_ERROR_NOT_FOUND) { if (adapter != nullptr) { DXGI_ADAPTER_DESC1 adapter_desc; adapter->GetDesc1(&adapter_desc); IDXGIAdapter2* adapter2; adapter->QueryInterface(IID_IDXGIAdapter2, reinterpret_cast<void**>(&adapter2)); if (adapter2 != nullptr) { DXGI_ADAPTER_DESC2 desc2; adapter2->GetDesc2(&desc2); memcpy(adapter_desc.Description, desc2.Description, sizeof(desc2.Description)); adapter_desc.VendorId = desc2.VendorId; adapter_desc.DeviceId = desc2.DeviceId; adapter_desc.SubSysId = desc2.SubSysId; adapter_desc.Revision = desc2.Revision; adapter_desc.DedicatedVideoMemory = desc2.DedicatedVideoMemory; adapter_desc.DedicatedSystemMemory = desc2.DedicatedSystemMemory; adapter_desc.SharedSystemMemory = desc2.SharedSystemMemory; adapter_desc.AdapterLuid = desc2.AdapterLuid; adapter_desc.Flags = desc2.Flags; adapter2->Release(); } adapter->Release(); if (adapter_desc.Flags != DXGI_ADAPTER_FLAG_SOFTWARE) { os << "Adapter " << adapter_no << endl << endl; std::string description; Convert(description, adapter_desc.Description); os << "Brand: " << description << endl; os << "Vendor ID: " << std::hex << std::uppercase << adapter_desc.VendorId << endl; os << "Device ID: " << std::hex << std::uppercase << adapter_desc.DeviceId << endl; os << "Revision: " << std::hex << std::uppercase << adapter_desc.Revision << endl; os << "Dedicated video memory: " << std::dec << adapter_desc.DedicatedVideoMemory / 1024 / 1024 << " MB" << endl; os << "Dedicated system memory: " << std::dec << adapter_desc.DedicatedSystemMemory / 1024 / 1024 << " MB" << endl; os << "Shared system memory: " << std::dec << adapter_desc.SharedSystemMemory / 1024 / 1024 << " MB" << endl; } } ++ adapter_no; } } #if defined KLAYGE_PLATFORM_WINDOWS_DESKTOP ::FreeLibrary(dxgi); #endif #else os << "Unknown GPU" << endl; #endif }