// 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 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(); }
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(); } }
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(); } }
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 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(); } }
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 D3DApp::InitializeD3D() { // describe our SwapChain Buffer DXGI_MODE_DESC mode_desc; ZeroMemory(&mode_desc, sizeof(DXGI_MODE_DESC)); mode_desc.Width = m_width; mode_desc.Height = m_height; mode_desc.RefreshRate.Numerator = 60; mode_desc.RefreshRate.Denominator = 1; mode_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; mode_desc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // describe our SwapChain DXGI_SWAP_CHAIN_DESC swapchain_desc; ZeroMemory(&swapchain_desc, sizeof(DXGI_SWAP_CHAIN_DESC)); swapchain_desc.BufferDesc = mode_desc; swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchain_desc.BufferCount = 1; swapchain_desc.OutputWindow = m_hwnd; swapchain_desc.Windowed = TRUE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // create DXGI factory to enumerate adapters IDXGIFactory1 *dxgi_factory; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&dxgi_factory); // use the first adapter IDXGIAdapter1 *adapter; hr = dxgi_factory->EnumAdapters1(0, &adapter); dxgi_factory->Release(); // create our Direct3D 11 Device and SwapChain hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, NULL, NULL, D3D11_SDK_VERSION, &swapchain_desc, &m_swap_chain, &m_d3d11_device, NULL, &m_d3d11_device_context); // initialize Direct2D, Direct3D 10.1, DirectWrite InitializeDWrite(adapter); // release the Adapter interface adapter->Release(); // create our BackBuffer and Render Target hr = m_swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&m_back_buffer); hr = m_d3d11_device->CreateRenderTargetView(m_back_buffer, NULL, &m_back_buffer_rtv); // describe our Depth/Stencil Buffer D3D11_TEXTURE2D_DESC depthstencil_desc; depthstencil_desc.Width = m_width; depthstencil_desc.Height = m_height; depthstencil_desc.MipLevels = 1; depthstencil_desc.ArraySize = 1; depthstencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthstencil_desc.SampleDesc.Count = 1; depthstencil_desc.SampleDesc.Quality = 0; depthstencil_desc.Usage = D3D11_USAGE_DEFAULT; depthstencil_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthstencil_desc.CPUAccessFlags = 0; depthstencil_desc.MiscFlags = 0; // create the Depth/Stencil View m_d3d11_device->CreateTexture2D(&depthstencil_desc, NULL, &m_depthstencil_buffer); m_d3d11_device->CreateDepthStencilView(m_depthstencil_buffer, NULL, &m_depthstencil_view); // set render target views and depth stencil view m_d3d11_device_context->OMSetRenderTargets(1, &m_back_buffer_rtv, m_depthstencil_view); // create a shader resource review from the texture D2D will render to hr = m_d3d11_device->CreateShaderResourceView(m_shared_texture, NULL, &m_d2d_texture); // create off-screen textures CD3D11_TEXTURE2D_DESC offscreen_tex_desc(DXGI_FORMAT_R16G16B16A16_FLOAT, m_width, m_height); offscreen_tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; offscreen_tex_desc.MipLevels = 1; for (int i = 0; i != ARRAYSIZE(m_offscreen_textures); ++i) { m_d3d11_device->CreateTexture2D(&offscreen_tex_desc, NULL, &m_offscreen_textures[i]); m_d3d11_device->CreateShaderResourceView(m_offscreen_textures[i], NULL, &m_offscreen_srvs[i]); m_d3d11_device->CreateRenderTargetView(m_offscreen_textures[i], NULL, &m_offscreen_rtvs[i]); } // create a constant buffer D3D11_BUFFER_DESC buffer_desc; ZeroMemory(&buffer_desc, sizeof(D3D11_BUFFER_DESC)); buffer_desc.Usage = D3D11_USAGE_DYNAMIC; buffer_desc.ByteWidth = sizeof(ShaderParameters); buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; buffer_desc.MiscFlags = 0; hr = m_d3d11_device->CreateBuffer(&buffer_desc, NULL, &m_parameter_buffer); buffer_desc.ByteWidth = sizeof(float4); hr = m_d3d11_device->CreateBuffer(&buffer_desc, NULL, &m_jitter_buffer); hr = m_d3d11_device->CreateBuffer(&buffer_desc, NULL, &m_interleave_buffer); // create a texture from file D3DX11CreateShaderResourceViewFromFile(m_d3d11_device, TEXT("media/tex.bmp"), NULL, NULL, &m_custom_texture, &hr); return true; }
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 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; }
bool D3D11App::initAPI(const API_Revision api_revision, const DXGI_FORMAT backBufferFmt, const DXGI_FORMAT depthBufferFmt, const int samples, const uint flags) { backBufferFormat = backBufferFmt; depthBufferFormat = depthBufferFmt; msaaSamples = samples; const bool sampleBackBuffer = (flags & SAMPLE_BACKBUFFER) != 0; // if (screen >= GetSystemMetrics(SM_CMONITORS)) screen = 0; IDXGIFactory1 *dxgiFactory; if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **) &dxgiFactory))) { ErrorMsg("Couldn't create DXGIFactory"); return false; } IDXGIAdapter1 *dxgiAdapter; if (dxgiFactory->EnumAdapters1(0, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) { ErrorMsg("No adapters found"); return false; } // DXGI_ADAPTER_DESC1 adapterDesc; // dxgiAdapter->GetDesc1(&adapterDesc); IDXGIOutput *dxgiOutput; if (dxgiAdapter->EnumOutputs(0, &dxgiOutput) == DXGI_ERROR_NOT_FOUND) { ErrorMsg("No outputs found"); return false; } DXGI_OUTPUT_DESC oDesc; dxgiOutput->GetDesc(&oDesc); // Find a suitable fullscreen format int targetHz = 85; DXGI_RATIONAL fullScreenRefresh; int fsRefresh = 60; fullScreenRefresh.Numerator = fsRefresh; fullScreenRefresh.Denominator = 1; char str[128]; uint nModes = 0; dxgiOutput->GetDisplayModeList(backBufferFormat, 0, &nModes, NULL); DXGI_MODE_DESC *modes = new DXGI_MODE_DESC[nModes]; dxgiOutput->GetDisplayModeList(backBufferFormat, 0, &nModes, modes); resolution->clear(); for (uint i = 0; i < nModes; i++) { if (modes[i].Width >= 640 && modes[i].Height >= 480) { sprintf(str, "%dx%d", modes[i].Width, modes[i].Height); int index = resolution->addItemUnique(str); if (int(modes[i].Width) == fullscreenWidth && int(modes[i].Height) == fullscreenHeight) { int refresh = modes[i].RefreshRate.Numerator / modes[i].RefreshRate.Denominator; if (abs(refresh - targetHz) < abs(fsRefresh - targetHz)) { fsRefresh = refresh; fullScreenRefresh = modes[i].RefreshRate; } resolution->selectItem(index); } } } delete [] modes; sprintf(str, "%s (%dx%d)", getTitle(), width, height); DWORD wndFlags = 0; int x, y, w, h; if (fullscreen) { wndFlags |= WS_POPUP; x = y = 0; w = width; h = height; } else { wndFlags |= WS_OVERLAPPEDWINDOW; RECT wRect; wRect.left = 0; wRect.right = width; wRect.top = 0; wRect.bottom = height; AdjustWindowRect(&wRect, wndFlags, FALSE); MONITORINFO monInfo; monInfo.cbSize = sizeof(monInfo); GetMonitorInfo(oDesc.Monitor, &monInfo); w = min(wRect.right - wRect.left, monInfo.rcWork.right - monInfo.rcWork.left); h = min(wRect.bottom - wRect.top, monInfo.rcWork.bottom - monInfo.rcWork.top); x = (monInfo.rcWork.left + monInfo.rcWork.right - w) / 2; y = (monInfo.rcWork.top + monInfo.rcWork.bottom - h) / 2; } hwnd = CreateWindow("Game", str, wndFlags, x, y, w, h, HWND_DESKTOP, NULL, hInstance, NULL); RECT rect; GetClientRect(hwnd, &rect); // Create device and swap chain DWORD deviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED; #ifdef _DEBUG deviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL requested_feature_level = (api_revision == D3D11)? D3D_FEATURE_LEVEL_11_0 : (api_revision == D3D11_1)? D3D_FEATURE_LEVEL_10_1 : D3D_FEATURE_LEVEL_10_0; D3D_FEATURE_LEVEL feature_level; if (FAILED(D3D11CreateDevice(dxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, deviceFlags, &requested_feature_level, 1, D3D11_SDK_VERSION, &device, &feature_level, &context))) { ErrorMsg("Couldn't create D3D11 device"); return false; } while (msaaSamples > 0) { UINT nQuality; if (SUCCEEDED(device->CheckMultisampleQualityLevels(backBufferFormat, msaaSamples, &nQuality)) && nQuality > 0) { if ((flags & NO_SETTING_CHANGE) == 0) antiAliasSamples = msaaSamples; break; } else { msaaSamples -= 2; } } DXGI_SWAP_CHAIN_DESC sd; memset(&sd, 0, sizeof(sd)); sd.BufferDesc.Width = rect.right; sd.BufferDesc.Height = rect.bottom; sd.BufferDesc.Format = backBufferFormat; sd.BufferDesc.RefreshRate = fullScreenRefresh; sd.BufferUsage = /*DXGI_USAGE_BACK_BUFFER | */DXGI_USAGE_RENDER_TARGET_OUTPUT | (sampleBackBuffer? DXGI_USAGE_SHADER_INPUT : 0); sd.BufferCount = 1; sd.OutputWindow = hwnd; sd.Windowed = (BOOL) (!fullscreen); sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; sd.SampleDesc.Count = msaaSamples; sd.SampleDesc.Quality = 0; if (FAILED(dxgiFactory->CreateSwapChain(device, &sd, &swapChain))) { ErrorMsg("Couldn't create swapchain"); return false; } // We'll handle Alt-Enter ourselves thank you very much ... dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER); dxgiOutput->Release(); dxgiAdapter->Release(); dxgiFactory->Release(); if (fullscreen) { captureMouse(!configDialog->isVisible()); } renderer = new Direct3D11Renderer(device, context); if (!createBuffers(sampleBackBuffer)) { delete renderer; return false; } antiAlias->selectItem(antiAliasSamples / 2); linearClamp = renderer->addSamplerState(LINEAR, CLAMP, CLAMP, CLAMP); defaultFont = renderer->addFont("../Textures/Fonts/Future.dds", "../Textures/Fonts/Future.font", linearClamp); blendSrcAlpha = renderer->addBlendState(SRC_ALPHA, ONE_MINUS_SRC_ALPHA); noDepthTest = renderer->addDepthState(false, false); noDepthWrite = renderer->addDepthState(true, false); cullNone = renderer->addRasterizerState(CULL_NONE); cullBack = renderer->addRasterizerState(CULL_BACK); cullFront = renderer->addRasterizerState(CULL_FRONT); return true; }
bool CRenderer::Initialize(int width, int height, HWND hwnd) { HRESULT result; DXGI_SWAP_CHAIN_DESC swapChainDesc; D3D_FEATURE_LEVEL featureLevel; //ID3D11Texture2D* backBufferPtr; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; D3D11_VIEWPORT viewport; IDXGIFactory1* factory = nullptr; IDXGIAdapter1* adapter = nullptr; if (!FindAdapter(&factory, &adapter)) { Log("Unable to find adapter!"); return false; } DXCall(result = adapter->EnumOutputs(0, &g_pVideoOutput)); // set up swapchain, device and context ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Width = width; swapChainDesc.BufferDesc.Height = height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = (BOOL)g_windowed;// (fullscreen ? FALSE : TRUE); swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.Flags = 0; // used in lieu of default full list // will force error/crash if d3d11 is not supported featureLevel = D3D_FEATURE_LEVEL_11_0; UINT flags = 0; #if _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif DXCall(result = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &m_pd3dSwapChain, &m_pd3dDevice, NULL, &m_pd3dDeviceContext)); if (SUCCEEDED(result)) { Log("Device and swap chain created."); } else { Log("Renderer did a bad. No device 4 U"); return false; } DXNameInit(m_pd3dDeviceContext); DXName(m_pd3dDevice, "The Device"); DXName(m_pd3dDeviceContext, "The Device Context"); DXName(m_pd3dSwapChain, "The Swap Chain"); // attach backbuffer to RTV DXCall(result = m_pd3dSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&m_pd3dBackBuffer)); DXCall(result = m_pd3dDevice->CreateRenderTargetView(m_pd3dBackBuffer, NULL, &m_pd3dRenderTargetView)); //SAFE_RELEASE(backBufferPtr); DXName(m_pd3dRenderTargetView, "Backbuffer RTV"); // setup depth buffer ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); depthBufferDesc.Width = width; depthBufferDesc.Height = height; 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; DXCall(result = m_pd3dDevice->CreateTexture2D(&depthBufferDesc, NULL, &m_pd3dDepthStencilBuffer)); DXName(m_pd3dDepthStencilBuffer, "Z Buffer"); // set up depth stencil state 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; DXCall(result = m_pd3dDevice->CreateDepthStencilState(&depthStencilDesc, &m_pd3dDepthStencilStateEnabled)); DXName(m_pd3dDepthStencilStateEnabled, "Depth Enabled State"); m_pd3dDeviceContext->OMSetDepthStencilState(m_pd3dDepthStencilStateEnabled, 1); depthStencilDesc.DepthEnable = false; 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; DXCall(result = m_pd3dDevice->CreateDepthStencilState(&depthStencilDesc, &m_pd3dDepthStencilStateDisabled)); DXName(m_pd3dDepthStencilStateDisabled, "Depth Disabled State"); // set up depth stencil view ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; DXCall(result = m_pd3dDevice->CreateDepthStencilView(m_pd3dDepthStencilBuffer, &depthStencilViewDesc, &m_pd3dDepthStencilView)); DXName(m_pd3dDepthStencilView, "Depth Stencil View"); m_pd3dDeviceContext->OMSetRenderTargets(1, &m_pd3dRenderTargetView, m_pd3dDepthStencilView); // set up rasterizer state ZeroMemory(&rasterDesc, sizeof(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 = TRUE; rasterDesc.MultisampleEnable = FALSE; rasterDesc.ScissorEnable = FALSE; rasterDesc.SlopeScaledDepthBias = 0.0f; DXCall(result = m_pd3dDevice->CreateRasterizerState(&rasterDesc, &m_pd3dRasterState)); DXName(m_pd3dRasterState, "Backface Culled Raster State"); m_pd3dDeviceContext->RSSetState(m_pd3dRasterState); // setup viewport viewport.Width = (FLOAT)width; viewport.Height = (FLOAT)height; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = viewport.TopLeftY = 0.0f; m_pd3dDeviceContext->RSSetViewports(1, &viewport); D3D11_BUFFER_DESC cb; ZeroMemory(&cb, sizeof(cb)); cb.ByteWidth = sizeof(TPerFrame); cb.Usage = D3D11_USAGE_DYNAMIC; cb.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; DXCall(result = m_pd3dDevice->CreateBuffer(&cb, NULL, &m_pd3dSceneBuffer)); DXName(m_pd3dSceneBuffer, "View Proj cBuffer"); D3D11_BLEND_DESC blendDesc; ZeroMemory(&blendDesc, sizeof(blendDesc)); // enabled blending blendDesc.RenderTarget[0].BlendEnable = TRUE; blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; DXCall(result = m_pd3dDevice->CreateBlendState(&blendDesc, &m_pd3dAlphaEnableBlendingState)); DXName(m_pd3dAlphaEnableBlendingState, "Alpha Blending Enabled"); // disabled blending blendDesc.RenderTarget[0].BlendEnable = FALSE; DXCall(result = m_pd3dDevice->CreateBlendState(&blendDesc, &m_pd3dAlphaDisableBlendingState)); DXName(m_pd3dAlphaDisableBlendingState, "Alpha Blending Disabled"); SetupSamplerStates(); //init render contexts m_pDebugRC = new CDebugRenderContext(); m_pDebugRC->Initialize(m_pd3dDevice, m_pd3dDeviceContext, m_pDefaultTexture); m_pParticleRC = new CParticleRenderContext(); m_pParticleRC->Initialize(m_pd3dDevice, m_pd3dDeviceContext, m_pDefaultTexture); g_ClearColor[0] = 0.1f; g_ClearColor[1] = 0.1f; g_ClearColor[2] = 0.1f; g_ClearColor[3] = 1.0f; return true; }
HRESULT D3D11Renderer::Create( HWND const &appWindow ) { HRESULT hr; D3D_FEATURE_LEVEL featureLevelsSupported; D3D_FEATURE_LEVEL featureLevelsRequested[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; UINT deviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) deviceFlags |= (D3D11_CREATE_DEVICE_DEBUG | D3D11_RLDO_DETAIL); #endif HR(hr, D3D11CreateDevice( GetPrimaryAdaptor(), // adapter D3D_DRIVER_TYPE_HARDWARE, // drive type 0, // hmodule deviceFlags, // device flags featureLevelsRequested, // array of feature levels requests 6, // number of feature levels D3D11_SDK_VERSION, // sdk version &m_device, // pointer to device &featureLevelsSupported, // number of feature levels supported &m_context)); // pointer to context /* #if defined(DEBUG) || defined(_DEBUG) HR(hr, m_device->QueryInterface(__uuidof(ID3D11Debug), (void **)&m_debug)); #endif */ DXGI_FORMAT formats[] = { g_settings.format, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R8G8B8A8_UNORM }; UINT formatSupport = 0; UINT supportedFormatIndex = 0; for (supportedFormatIndex; supportedFormatIndex < 3; supportedFormatIndex++) { m_device->CheckFormatSupport(formats[supportedFormatIndex], &formatSupport); if (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET && formatSupport & D3D11_FORMAT_SUPPORT_DISPLAY) { g_settings.format = formats[supportedFormatIndex]; break; } } ATOM_ASSERT(g_settings.xmsaa > 0, "XMSAA < 0, min value = 1"); UINT sampleCount = g_settings.xmsaa; UINT numQualityLevels = 0; this->m_device->CheckMultisampleQualityLevels( g_settings.format, sampleCount, &numQualityLevels); //this->m_appSettings->qmsaa = numQualityLevels - 1; if (sampleCount < g_settings.xmsaa) g_settings.xmsaa = sampleCount; if (numQualityLevels - 1 < g_settings.qmsaa) g_settings.qmsaa = numQualityLevels - 1; DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = SWAP_CHAIN_BUFFER_COUNT; sd.BufferDesc.Format = g_settings.format; sd.BufferDesc.Width = g_settings.width; sd.BufferDesc.Height = g_settings.height; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.OutputWindow = appWindow; sd.SampleDesc.Count = g_settings.xmsaa; sd.SampleDesc.Quality = g_settings.qmsaa; sd.Windowed = true; GetDefaultRefreshRate(); if (g_settings.frameRate <= 0) { DXGI_RATIONAL fr = GetDefaultRefreshRate(); sd.BufferDesc.RefreshRate.Numerator = fr.Numerator; sd.BufferDesc.RefreshRate.Denominator = fr.Denominator; g_settings.frameRate = fr.Numerator / fr.Denominator; } else { sd.BufferDesc.RefreshRate.Numerator = g_settings.frameRate; sd.BufferDesc.RefreshRate.Denominator = 1; } IDXGIDevice1 *dxgiDevice = 0; IDXGIAdapter1 *dxgiAdapter = 0; IDXGIFactory1 *dxgiFactory = 0; HR(hr, m_device->QueryInterface(__uuidof(IDXGIDevice1), (void **)&dxgiDevice)); HR(hr, dxgiDevice->GetParent(__uuidof(IDXGIAdapter1), (void **)&dxgiAdapter)); HR(hr, dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), (void **)&dxgiFactory)); HR(hr, dxgiFactory->CreateSwapChain((IUnknown *)m_device, &sd, &m_swapChain)); memory::SafeRelease(&dxgiDevice); memory::SafeRelease(&dxgiAdapter); memory::SafeRelease(&dxgiFactory); //LOG("num: %d, den: %d\n", sd.BufferDesc.RefreshRate.Numerator, sd.BufferDesc.RefreshRate.Denominator); //LOG("scaling: %d, scanline ordering: %d\n", sd.BufferDesc.Scaling, sd.BufferDesc.ScanlineOrdering); #if defined(DEBUG) || defined(_DEBUG) //EnumerateDisplayModes(); char *featureLevelNames[] = { "D3D11", "D3D10.1", "D3D10", "D3D9.3", "D3D9.2", "D3D9.1" }; for (int i = 0; i < 6; i++) { if (featureLevelsSupported == featureLevelsRequested[i]) ATOM_LOG("[info]: D3D_FEATURE_LEVEL: %s\n", featureLevelNames[i]); } ATOM_LOG("[info]: using format: %d, index: %d\n", formats[supportedFormatIndex], supportedFormatIndex); #endif InitRendererResources(); return Resize(g_settings.width, g_settings.height); }
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 }
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); }
bool RenderSystem::init(void* windowHandle, const InitParams& params) { IDXGIFactory1* factory = 0; IDXGIOutput* output = 0; DXGI_MODE_DESC modeDesc; ::ZeroMemory(&modeDesc, sizeof(DXGI_MODE_DESC)); modeDesc.Format = params.srgbTarget ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; modeDesc.Width = params.width; modeDesc.Height = params.height; if (SUCCEEDED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory))) { IDXGIAdapter1* adapter = 0; for (UINT i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i) { if (adapter->CheckInterfaceSupport(__uuidof(ID3D11Device), NULL)) break; adapter->Release(); } D3D_FEATURE_LEVEL supportedFeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, }; UINT flags = 0; #if defined (_DEBUG) flags |= D3D11_CREATE_DEVICE_DEBUG; #endif // _DEBUG if (adapter) { if (SUCCEEDED(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, supportedFeatureLevels, _countof(supportedFeatureLevels), D3D11_SDK_VERSION, &m_device, NULL, &m_renderContext))) { for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) { if (SUCCEEDED(output->FindClosestMatchingMode(&modeDesc, &modeDesc, m_device))) { // additional checks?? break; } output->Release(); output = 0; } /*if (output) output->Release();*/ } adapter->Release(); } if (m_device) { DXGI_SWAP_CHAIN_DESC sd; ::ZeroMemory(&sd, sizeof(DXGI_SWAP_CHAIN_DESC)); sd.BufferCount = 1; sd.BufferDesc = modeDesc; sd.BufferUsage = D3D11_BIND_RENDER_TARGET; sd.Flags = 0; sd.OutputWindow = (HWND)windowHandle; sd.SampleDesc.Quality = 0; sd.SampleDesc.Count = 1; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Windowed = TRUE; if (params.msaaSamples > 0) { UINT numLevels = 0; if (SUCCEEDED(m_device->CheckMultisampleQualityLevels(modeDesc.Format, params.msaaSamples, &numLevels)) && numLevels > 0) { sd.SampleDesc.Quality = numLevels-1; sd.SampleDesc.Count = params.msaaSamples; } else { printf("multisample quality not supported"); } } VALIDATE(factory->CreateSwapChain(m_device, &sd, &m_swapChain)); } if (params.fullscreen) { m_isFullScreen = SUCCEEDED(m_swapChain->SetFullscreenState(TRUE, output)); } // setup debug queue factory->MakeWindowAssociation((HWND)windowHandle, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); if (output) output->Release(); factory->Release(); } m_stateCache = new PipelineStateCache(m_renderContext); createFrameBuffer(); initDefaultResources(); return (m_device && m_swapChain); }
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; }
bool Direct3D::Initialize(int _screenWidth, int _screenHeight, bool _vsync, HWND _hwnd, bool _fullscreen, float _screenDepth, float _screenNear, TextClass* _timer) { HRESULT result; IDXGIFactory1* factory; IDXGIAdapter1* adapter; IDXGIOutput* adapterOutput; unsigned int numModes, i, numerator, denominator, stringLength; DXGI_MODE_DESC* displayModeList; DXGI_ADAPTER_DESC adapterDesc; int error; DXGI_SWAP_CHAIN_DESC swapChainDesc; D3D_FEATURE_LEVEL featureLevel; ID3D11Texture2D* backBufferPtr; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; float fieldOfView, screenAspect; D3D11_BLEND_DESC blendStateDescription; bool success; // Store the vsync setting. vsync_enabled = _vsync; // Create a DirectX graphics interface factory. result = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory); if (FAILED(result)) { return false; } // Use the factory to create an adapter for the primary graphics interface (video card). result = factory->EnumAdapters1(0, &adapter); if (FAILED(result)) { return false; } // Enumerate the primary adapter output (monitor). result = adapter->EnumOutputs(0, &adapterOutput); if (FAILED(result)) { return false; } // Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor). result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL); if (FAILED(result)) { return false; } // Create a list to hold all the possible display modes for this monitor/video card combination. displayModeList = new DXGI_MODE_DESC[numModes]; if (!displayModeList) { return false; } // Now fill the display mode list structures. result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList); if (FAILED(result)) { return false; } // Now go through all the display modes and find the one that matches the screen width and height. // When a match is found store the numerator and denominator of the refresh rate for that monitor. for (i = 0; i<numModes; i++) { if (displayModeList[i].Width == (unsigned int)_screenWidth) { if (displayModeList[i].Height == (unsigned int)_screenHeight) { numerator = displayModeList[i].RefreshRate.Numerator; denominator = displayModeList[i].RefreshRate.Denominator; } } } // Get the adapter (video card) description. result = adapter->GetDesc(&adapterDesc); if (FAILED(result)) { return false; } // Store the dedicated video card memory in megabytes. videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024); // Convert the name of the video card to a character array and store it. error = wcstombs_s(&stringLength, videoCardDescription, 128, adapterDesc.Description, 128); if (error != 0) { return false; } // Release the display mode list. delete[] displayModeList; displayModeList = 0; // Release the adapter output. adapterOutput->Release(); adapterOutput = 0; // Release the factory. factory->Release(); factory = 0; // Initialize the swap chain description. ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); // Set to a single back buffer. swapChainDesc.BufferCount = 1; // Set the width and height of the back buffer. swapChainDesc.BufferDesc.Width = _screenWidth; swapChainDesc.BufferDesc.Height = _screenHeight; // Set regular 32-bit surface for the back buffer. swapChainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // Set the refresh rate of the back buffer. if (vsync_enabled) { swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator; swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator; } else { swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } // Set the usage of the back buffer. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // Set the handle for the window to render to. swapChainDesc.OutputWindow = _hwnd; // Turn multisampling off. swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; // Set to full screen or windowed mode. if (_fullscreen) { swapChainDesc.Windowed = false; } else { swapChainDesc.Windowed = true; } //// Set the scan line ordering and scaling to unspecified. //swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; //swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //// Discard the back buffer contents after presenting. //swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // Don't set the advanced flags. swapChainDesc.Flags = 0; // Set the feature level to DirectX 11. featureLevel = D3D_FEATURE_LEVEL_11_0; // Create the swap chain, Direct3D device, and Direct3D device context. result = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, NULL, &deviceContext); if (FAILED(result)) { return false; } success = _timer->Initialize(device, adapter, _screenWidth, _screenHeight); if (!success) { return false; } // Release the adapter. adapter->Release(); adapter = 0; // Get the pointer to the back buffer. result = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr); if (FAILED(result)) { return false; } // Create the render target view with the back buffer pointer. result = device->CreateRenderTargetView(backBufferPtr, NULL, &backBuffer); if (FAILED(result)) { return false; } // Release pointer to the back buffer as we no longer need it. backBufferPtr->Release(); backBufferPtr = 0; // Initialize the description of the depth buffer. ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); // Set up the description of the depth buffer. 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; // Create the texture for the depth buffer using the filled out description. result = device->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer); if (FAILED(result)) { return false; } // Initialize the description of the stencil state. ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); // Set up the description of the stencil state. depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing. 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; // Stencil operations if pixel is back-facing. 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; // Create the depth stencil state. result = device->CreateDepthStencilState(&depthStencilDesc, &depthStencilStateON); if (FAILED(result)) { return false; } depthStencilDesc.DepthEnable = false; // Create the depth stencil state. result = device->CreateDepthStencilState(&depthStencilDesc, &depthStencilStateOFF); if (FAILED(result)) { return false; } // Set the depth stencil state. deviceContext->OMSetDepthStencilState(depthStencilStateON, 1); // Initailze the depth stencil view. ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); // Set up the depth stencil view description. depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; // Create the depth stencil view. result = device->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView); if (FAILED(result)) { return false; } // Bind the render target view and depth stencil buffer to the output render pipeline. deviceContext->OMSetRenderTargets(1, &backBuffer, depthStencilView); // Setup the raster description which will determine how and what polygons will be drawn. rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_NONE; 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; // Create the rasterizer state from the description we just filled out. result = device->CreateRasterizerState(&rasterDesc, &rasterState); if (FAILED(result)) { return false; } // Now set the rasterizer state. deviceContext->RSSetState(rasterState); // Setup the viewport for rendering. viewport.Width = (float)_screenWidth; viewport.Height = (float)_screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; // Create the viewport. deviceContext->RSSetViewports(1, &viewport); // Setup the projection matrix. fieldOfView = (float)XM_PI / 4.0f; screenAspect = (float)_screenWidth / (float)_screenHeight; // Create the projection matrix for 3D rendering. DirectX::XMStoreFloat4x4(&projectionMatrix, XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, _screenNear, _screenDepth)); // Create an orthographic projection matrix for 2D rendering. DirectX::XMStoreFloat4x4(&orthoMatrix, XMMatrixOrthographicLH((float)_screenWidth, (float)_screenHeight, _screenNear, _screenDepth)); // Clear the blend state description. ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); // Create an alpha enabled blend state description. blendStateDescription.RenderTarget[0].BlendEnable = TRUE; blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_COLOR; blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;; blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f; // Create the blend state using the description. result = device->CreateBlendState(&blendStateDescription, &alphaEnableBlendingState); if (FAILED(result)) { return false; } // Modify the description to create an alpha disabled blend state description. blendStateDescription.RenderTarget[0].BlendEnable = FALSE; // Create the blend state using the description. result = device->CreateBlendState(&blendStateDescription, &alphaDisableBlendingState); if (FAILED(result)) { return false; } renderer = new RenderManager(); if (!renderer) { return false; } result = renderer->Initialize(device,XMLoadFloat4x4(&projectionMatrix), _screenWidth, _screenHeight); return true; }
bool D3DApp::InitializeDirect3d11App(HINSTANCE hInstance) { //Describe our Buffer DXGI_MODE_DESC bufferDesc; ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC)); bufferDesc.Width = Width; bufferDesc.Height = Height; bufferDesc.RefreshRate.Numerator = 60; bufferDesc.RefreshRate.Denominator = 1; bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //Describe our SwapChain DXGI_SWAP_CHAIN_DESC swapChainDesc; ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC)); swapChainDesc.BufferDesc = bufferDesc; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount = 1; swapChainDesc.OutputWindow = hwnd; swapChainDesc.Windowed = TRUE; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // Create DXGI factory to enumerate adapters/////////////////////////////////////////////////////////////////////////// IDXGIFactory1 *DXGIFactory; HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&DXGIFactory); // Use the first adapter IDXGIAdapter1 *Adapter; hr = DXGIFactory->EnumAdapters1(0, &Adapter); DXGIFactory->Release(); //Create our Direct3D 11 Device and SwapChain////////////////////////////////////////////////////////////////////////// hr = D3D11CreateDeviceAndSwapChain(Adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT, NULL, NULL, D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon); //Initialize Direct2D, Direct3D 10.1, DirectWrite InitD2D_D3D101_DWrite(Adapter); //Release the Adapter interface Adapter->Release(); //Create our BackBuffer and Render Target hr = SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&BackBuffer11); hr = d3d11Device->CreateRenderTargetView(BackBuffer11, NULL, &renderTargetView); //Describe our Depth/Stencil Buffer D3D11_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.Width = Width; depthStencilDesc.Height = Height; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilDesc.SampleDesc.Count = 1; depthStencilDesc.SampleDesc.Quality = 0; depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; //Create the Depth/Stencil View d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer); d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView); return true; }
bool RenderCore::Init(int screenWidth, int screenHeight, HWND hWnd) { HRESULT hr; IDXGIAdapter1 *adapter; IDXGIOutput *adapterOutput; IDXGIOutput1 *adapterOutput1; DXGI_ADAPTER_DESC adapterDesc; DXGI_MODE_DESC *displayModeList; DXGI_SWAP_CHAIN_DESC swapChainDesc; ID3D11Texture2D *pBackBuffer; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; uint32_t numModes, fpsNumerator, fpsDenominator; size_t stringLength; int error; float fov, aspect; if (!EnumerateDisplayAdapters(&g_DXGIAdapters)) { return false; } adapter = g_DXGIAdapters.at(0); hr = adapter->EnumOutputs(0, &adapterOutput); if (FAILED(hr)) { return false; } // desktop duplication stuff hr = adapterOutput->QueryInterface(&adapterOutput1); hr = adapterOutput1->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, nullptr); if (FAILED(hr)) { return false; } displayModeList = new DXGI_MODE_DESC[numModes]; if (!displayModeList) { return false; } hr = adapterOutput1->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList); if (FAILED(hr)) { return false; } for (UINT i = 0; i < numModes; i++) { if (displayModeList[i].Width == (unsigned int)screenWidth) { if (displayModeList[i].Height == (unsigned int)screenHeight) { fpsNumerator = displayModeList[i].RefreshRate.Numerator; fpsDenominator = displayModeList[i].RefreshRate.Denominator; } } } hr = adapter->GetDesc(&adapterDesc); if (FAILED(hr)) { return false; } // retrieve video adapter memory and name m_VideoMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024); error = wcstombs_s(&stringLength, m_VideoCardDesc, 128, adapterDesc.Description, 128); if (error != 0) { return false; } DebugOut("Found graphics adapter: %s (%dMB VRAM)\n", m_VideoCardDesc, m_VideoMemory); delete[] displayModeList; displayModeList = nullptr; adapterOutput->Release(); adapter->Release(); // set single back buffer ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Width = screenWidth; swapChainDesc.BufferDesc.Height = screenHeight; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = hWnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = true; //swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; //swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //swapChainDesc.Flags = 0; // create swap chain, direct3d device, and d3d context uint32_t deviceFlags = 0; #define D3D_DEVICE_DEBUG #ifdef D3D_DEVICE_DEBUG deviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; uint32_t numFeatureLevels = ARRAYSIZE(featureLevels); hr = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, deviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapChainDesc, &m_SwapChain, &m_d3d11Device, nullptr, &m_d3d11DeviceContext); if (FAILED(hr)) { DebugOut("D3D11CreateDeviceAndSwapChain failed!\n"); return false; } // enable multithreaded device context protection ID3D10Multithread *contextMT = nullptr; m_d3d11DeviceContext->QueryInterface(&contextMT); if (contextMT) { contextMT->SetMultithreadProtected(true); contextMT->Release(); } else { DebugOut("Fatal error! ID3D10Multithread::SetMultithreadProtected for D3D11 device context failed!\n"); return false; } // get pointer to the back buffer hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)&pBackBuffer); if (FAILED(hr)) { DebugOut("IDXGISwapChain::GetBuffer failed!\n"); return false; } // create render target view from back buffer hr = m_d3d11Device->CreateRenderTargetView(pBackBuffer, nullptr, &m_d3d11RenderTargetView); if (FAILED(hr)) { DebugOut("ID3D11Device::CreateRenderTargetView failed!\n"); return false; } pBackBuffer->Release(); // set up depth buffer description 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; // create texture for depth buffer hr = m_d3d11Device->CreateTexture2D(&depthBufferDesc, nullptr, &m_d3d11DepthStencilBuffer); if (FAILED(hr)) { DebugOut("ID3D11Device::CreateTexture2D failed! Could not create texture for depth buffer.\n"); return false; } // set up description of stencil state ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); depthStencilDesc.DepthEnable = true; // z-buffer enabled depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing. 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; // Stencil operations if pixel is back-facing. 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; // create depth stencil state hr = m_d3d11Device->CreateDepthStencilState(&depthStencilDesc, &m_d3d11DepthStencilState); if (FAILED(hr)) { DebugOut("ID3D11Device::CreateDepthStencilState failed!\n"); return false; } // Now create a second depth stencil state which turns off the Z buffer for 2D rendering. The only difference is // that DepthEnable is set to false, all other parameters are the same as the other depth stencil state. 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; // Create the state using the device. hr = m_d3d11Device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_d3d11DepthStencilDisabledState); if (FAILED(hr)) { return false; } // disable the Z-Buffer ZBufferState(0); // set up depth stencil view description ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; // create depth stencil view hr = m_d3d11Device->CreateDepthStencilView(m_d3d11DepthStencilBuffer, &depthStencilViewDesc, &m_d3d11DepthStencilView); if (FAILED(hr)) { DebugOut("ID3D11Device::CreateDepthStencilView failed!\n"); return false; } // bind render target view and depth stencil buffer to the output render pipeline m_d3d11DeviceContext->OMSetRenderTargets(1, &m_d3d11RenderTargetView, m_d3d11DepthStencilView); // set up rasterizer description rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_NONE; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = false; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; // create the rasterizer hr = m_d3d11Device->CreateRasterizerState(&rasterDesc, &m_d3d11RasterState); if (FAILED(hr)) { DebugOut("ID3D11Device::CreateRasterizerState failed!"); return false; } m_d3d11DeviceContext->RSSetState(m_d3d11RasterState); // set up viewport for rendering 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; // create the viewport m_d3d11DeviceContext->RSSetViewports(1, &viewport); fov = (float)PI / 4.0f; aspect = (float)screenWidth / (float)screenHeight; m_ProjectionMatrix = DirectX::XMMatrixPerspectiveFovLH(fov, aspect, SCREEN_NEAR, SCREEN_DEPTH); m_WorldMatrix = DirectX::XMMatrixIdentity(); m_OrthoMatrix = DirectX::XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, SCREEN_NEAR, SCREEN_DEPTH); // Scene is a textured quad to draw on g_Scene = new Scene(GetDevice(), GetDeviceContext(), screenWidth, screenHeight); //g_Scene2 = new Scene(GetDevice(), GetDeviceContext(), screenWidth, screenHeight); // new DXGI Desktop Duplication object g_DesktopDuplication = new DXGIDuplication(); if (!g_DesktopDuplication->Init(0, 0, &g_DXGIAdapters, GetDevice())) { DebugOut("Failed to init DXGI Desktop Duplication API!\n"); return false; } //g_DesktopDuplication2 = new DXGIDuplication(); //if (!g_DesktopDuplication2->Init(0, 1, &g_DXGIAdapters, GetDevice())) { DebugOut("Failed to init DXGI Desktop Duplication API for Adapter 1/Output 2!\n"); return false; } // initialize Media Foundation g_MFEncoder = new MF_H264_Encoder(m_d3d11Device, m_d3d11DeviceContext); if (!g_MFEncoder->Init()) { DebugOut("Failed to init Media Foundation H.264 Encoder!\n"); return false; } return true; };
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; }
EErrorCode::Type GraphicsDevice::Initialize( RendererDesc *pDesc ) { // Only create this for immediate render context if ( pDesc->deviceContextType != EDeviceContext::IMMEDIATE ) return EErrorCode::GRAPHICS; GraphicsInfrastructure *pGI = GraphicsInfrastructure::GetInstance(); DXGIFactoryPtr pFactory = pGI->GetFactory(); IDXGIAdapter1 *pAdapter; UINT createFlags = 0; HRESULT hr; // Get adapter pFactory->EnumAdapters1( pDesc->adapter, &pAdapter ); if ( pDesc->bDebug ) createFlags |= D3D11_CREATE_DEVICE_DEBUG; D3D_FEATURE_LEVEL featureLevel[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 }; D3D_FEATURE_LEVEL retFet; hr = D3D11CreateDevice( pAdapter, DX11Mapping::ToDXProcessingType(ERendererProcessingType::UNKNOWN), //DX11Mapping::ToDXProcessingType(pDesc->processingType), PSX_NULL, createFlags, featureLevel, 1, D3D11_SDK_VERSION, &m_pDevice, &retFet, &m_pDeviceContext ); if ( FAILED(hr) ) { PSX_PushError( "Failed to create GraphicsDevice object." ); if ( pDesc->processingType == ERendererProcessingType::HARDWARE && pDesc->bSoftwareRendererFallback ) { PSX_PushLog1( "Attempting to create software device renderer." ); // TODO: This fallback create device doesn't work. Fix this. hr = D3D11CreateDevice( pAdapter, D3D_DRIVER_TYPE_REFERENCE, PSX_NULL, createFlags, featureLevel, 1, D3D11_SDK_VERSION, &m_pDevice, &retFet, &m_pDeviceContext ); if ( FAILED(hr ) ) PSX_PushError( "Failed to create software renderer device. Something went terribly wrong!" ); } } pAdapter->Release(); // It's now safe to initialize graphics resource manager if ( GraphicsResourceManager::GetInstance()->Initialize() != EErrorCode::OKAY ) { PSX_PushError( "Failed to initialize Graphics Resource Manager." ); return EErrorCode::GRAPHICS; } return m_pDevice ? EErrorCode::OKAY : EErrorCode::GRAPHICS; }