void DeviceResources::CreateFactory() { #if defined(_DEBUG) && (_WIN32_WINNT >= 0x0603 /*_WIN32_WINNT_WINBLUE*/) bool debugDXGI = false; { ComPtr<IDXGIInfoQueue> dxgiInfoQueue; if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) { debugDXGI = true; ThrowIfFailed(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); DXGI_INFO_QUEUE_MESSAGE_ID hide[] = { 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; filter.DenyList.NumIDs = _countof(hide); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } } if (!debugDXGI) #endif ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); }
// Configures the Direct3D device, and stores handles to it and the device context. void DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) // Enable the debug layer (requires the Graphics Tools "optional feature"). // // NOTE: Enabling the debug layer after device creation will invalidate the active device. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) { debugController->EnableDebugLayer(); } else { OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); } ComPtr<IDXGIInfoQueue> dxgiInfoQueue; if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) { m_dxgiFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); DXGI_INFO_QUEUE_MESSAGE_ID hide[] = { 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; filter.DenyList.NumIDs = _countof(hide); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } } #endif ThrowIfFailed(CreateDXGIFactory2(m_dxgiFactoryFlags, IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); // Determines whether tearing support is available for fullscreen borderless windows. if (m_options & c_AllowTearing) { BOOL allowTearing = FALSE; ComPtr<IDXGIFactory5> factory5; HRESULT hr = m_dxgiFactory.As(&factory5); if (SUCCEEDED(hr)) { hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing)); } if (FAILED(hr) || !allowTearing) { m_options &= ~c_AllowTearing; #ifdef _DEBUG OutputDebugStringA("WARNING: Variable refresh rate displays not supported"); #endif } } ComPtr<IDXGIAdapter1> adapter; GetAdapter(adapter.GetAddressOf()); // Create the DX12 API device object. ThrowIfFailed(D3D12CreateDevice( adapter.Get(), m_d3dMinFeatureLevel, IID_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) )); m_d3dDevice->SetName(L"DeviceResources"); #ifndef NDEBUG // Configure debug device (if active). ComPtr<ID3D12InfoQueue> d3dInfoQueue; if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) { #ifdef _DEBUG d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); #endif D3D12_MESSAGE_ID hide[] = { D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE }; D3D12_INFO_QUEUE_FILTER filter = {}; filter.DenyList.NumIDs = _countof(hide); filter.DenyList.pIDList = hide; d3dInfoQueue->AddStorageFilterEntries(&filter); } #endif // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, }; D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = { _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 }; HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); if (SUCCEEDED(hr)) { m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel; } else { m_d3dFeatureLevel = m_d3dMinFeatureLevel; } // Create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); m_commandQueue->SetName(L"DeviceResources"); // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); m_rtvDescriptorHeap->SetName(L"DeviceResources"); m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) { D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; dsvDescriptorHeapDesc.NumDescriptors = 1; dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); m_dsvDescriptorHeap->SetName(L"DeviceResources"); } // Create a command allocator for each back buffer that will be rendered to. for (UINT n = 0; n < m_backBufferCount; n++) { ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); wchar_t name[25] = {}; swprintf_s(name, L"Render target %u", n); m_commandAllocators[n]->SetName(name); } // Create a command list for recording graphics commands. ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); ThrowIfFailed(m_commandList->Close()); m_commandList->SetName(L"DeviceResources"); // Create a fence for tracking GPU execution progress. ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); m_fenceValues[m_backBufferIndex]++; m_fence->SetName(L"DeviceResources"); m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { throw std::exception("CreateEvent"); } // Some additional caps information #ifdef _DEBUG const char* featLevel = "Unknown"; switch (m_d3dFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: featLevel = "11.0"; break; case D3D_FEATURE_LEVEL_11_1: featLevel = "11.1"; break; case D3D_FEATURE_LEVEL_12_0: featLevel = "12.0"; break; case D3D_FEATURE_LEVEL_12_1: featLevel = "12.1"; break; } // Determine maximum shader model / root signature D3D12_FEATURE_DATA_ROOT_SIGNATURE rootSig = {}; rootSig.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1; if (FAILED(m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &rootSig, sizeof(rootSig)))) { rootSig.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0; } const char* rootSigVer = "Unknown"; switch (rootSig.HighestVersion) { case D3D_ROOT_SIGNATURE_VERSION_1_0: rootSigVer = "1.0"; break; case D3D_ROOT_SIGNATURE_VERSION_1_1: rootSigVer = "1.1"; break; } D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = {}; #if defined(NTDDI_WIN10_19H1) && (NTDDI_VERSION >= NTDDI_WIN10_19H1) shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_5; #elif defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5) shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_4; #elif defined(NTDDI_WIN10_RS4) && (NTDDI_VERSION >= NTDDI_WIN10_RS4) shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_2; #else shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_0; #endif hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel)); while (hr == E_INVALIDARG && shaderModel.HighestShaderModel > D3D_SHADER_MODEL_6_0) { shaderModel.HighestShaderModel = static_cast<D3D_SHADER_MODEL>(static_cast<int>(shaderModel.HighestShaderModel) - 1); hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel)); } if (FAILED(hr)) { shaderModel.HighestShaderModel = D3D_SHADER_MODEL_5_1; } const char* shaderModelVer = "Unknown"; switch (shaderModel.HighestShaderModel) { case D3D_SHADER_MODEL_5_1: shaderModelVer = "5.1"; break; case D3D_SHADER_MODEL_6_0: shaderModelVer = "6.0"; break; #if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) case D3D_SHADER_MODEL_6_1: shaderModelVer = "6.1"; break; #endif #if defined(NTDDI_WIN10_RS4) && (NTDDI_VERSION >= NTDDI_WIN10_RS4) case D3D_SHADER_MODEL_6_2: shaderModelVer = "6.2"; break; #endif #if defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5) case D3D_SHADER_MODEL_6_3: shaderModelVer = "6.3"; break; case D3D_SHADER_MODEL_6_4: shaderModelVer = "6.4"; break; #endif #if defined(NTDDI_WIN10_19H1) && (NTDDI_VERSION >= NTDDI_WIN10_19H1) case D3D_SHADER_MODEL_6_5: shaderModelVer = "6.5"; break; #endif } char buff[128] = {}; sprintf_s(buff, "INFO: Direct3D hardware feature level %s (Shader Model %s / Root Signature %s)\n", featLevel, shaderModelVer, rootSigVer); OutputDebugStringA(buff); #endif }