in TechniqueDemos/D3D12MemoryManagement/src/Framework.cpp [334:687]
HRESULT DX12Framework::CreateDeviceDependentStateInternal()
{
HRESULT hr;
{
//
// Have the user select the desired graphics adapter.
//
IDXGIAdapter* pTempAdapter;
UINT AdapterOrdinal = 0;
printf("Available Adapters:\n");
while (m_pDXGIFactory->EnumAdapters(AdapterOrdinal, &pTempAdapter) != DXGI_ERROR_NOT_FOUND)
{
DXGI_ADAPTER_DESC Desc;
pTempAdapter->GetDesc(&Desc);
printf(" [%d] %ls\n", AdapterOrdinal, Desc.Description);
pTempAdapter->Release();
++AdapterOrdinal;
}
for (;;)
{
printf("\nSelect Adapter: ");
AdapterOrdinal = m_NewAdapterIndex;
if (AdapterOrdinal == 0xFFFFFFFF)
{
if (scanf_s("%d", &AdapterOrdinal) == 0)
{
//
// If the user did not specify valid input, just use adapter 0.
//
AdapterOrdinal = 0;
}
}
hr = m_pDXGIFactory->EnumAdapters(AdapterOrdinal, &pTempAdapter);
if (hr == DXGI_ERROR_NOT_FOUND)
{
LOG_WARNING("Invalid adapter ordinal");
continue;
}
hr = pTempAdapter->QueryInterface(&m_pDXGIAdapter);
pTempAdapter->Release();
if (FAILED(hr))
{
LOG_ERROR("Failed to query IDXGIAdapter3 interface from selected adapter.");
return hr;
}
break;
}
}
//
// Obtain the default video memory information for the local and non-local segment groups.
//
hr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &m_LocalVideoMemoryInfo);
if (FAILED(hr))
{
LOG_ERROR("Failed to query initial video memory info for local segment group");
return hr;
}
hr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &m_NonLocalVideoMemoryInfo);
if (FAILED(hr))
{
LOG_ERROR("Failed to query initial video memory info for non-local segment group");
return hr;
}
hr = D3D12CreateDevice(m_pDXGIAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pDevice));
if (FAILED(hr))
{
LOG_ERROR("Failed to create D3D12 device, hr=0x%.8x", hr);
return hr;
}
#if _DEBUG
ID3D12InfoQueue* pInfoQueue = nullptr;
if (SUCCEEDED(m_pDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue))))
{
// Suppress whole categories of messages.
//D3D12_MESSAGE_CATEGORY Categories[] = {};
// Suppress messages based on their severity level.
D3D12_MESSAGE_SEVERITY Severities[] =
{
D3D12_MESSAGE_SEVERITY_INFO
};
// Suppress individual messages by their ID.
D3D12_MESSAGE_ID DenyIds[] =
{
// The 11On12 implementation does not use optimized clearing yet.
D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE
};
D3D12_INFO_QUEUE_FILTER NewFilter = {};
//NewFilter.DenyList.NumCategories = _countof(Categories);
//NewFilter.DenyList.pCategoryList = Categories;
NewFilter.DenyList.NumSeverities = _countof(Severities);
NewFilter.DenyList.pSeverityList = Severities;
NewFilter.DenyList.NumIDs = _countof(DenyIds);
NewFilter.DenyList.pIDList = DenyIds;
pInfoQueue->PushStorageFilter(&NewFilter);
pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
pInfoQueue->Release();
}
#endif
//
// Cache the descriptor sizes.
//
m_DescriptorInfo.RtvDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
m_DescriptorInfo.SamplerDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
m_DescriptorInfo.SrvUavCbvDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
hr = QueryCaps();
if (FAILED(hr))
{
LOG_WARNING("Failed to query device caps");
return hr;
}
hr = m_RenderContext.CreateDeviceDependentState(SWAPCHAIN_BUFFER_COUNT);
if (FAILED(hr))
{
LOG_WARNING("Failed to initialize render context");
return hr;
}
hr = m_PagingContext.CreateDeviceDependentState();
if (FAILED(hr))
{
LOG_WARNING("Failed to initialize paging context");
return hr;
}
hr = m_TextureShader.CreateDeviceDependentState(m_pDevice, L"Assets\\Shaders\\Texture.hlsl");
if (FAILED(hr))
{
LOG_WARNING("Failed to initialize texture shader");
return hr;
}
hr = m_ColorShader.CreateDeviceDependentState(m_pDevice, L"Assets\\Shaders\\Color.hlsl");
if (FAILED(hr))
{
LOG_WARNING("Failed to initialize color shader");
return hr;
}
//
// Create a basic Flip-Discard swapchain.
//
DXGI_SWAP_CHAIN_DESC1 SwapChainDesc = {};
SwapChainDesc.BufferCount = SWAPCHAIN_BUFFER_COUNT;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.Format = SWAPCHAIN_BACK_BUFFER_FORMAT;
SwapChainDesc.Height = m_WindowHeight;
SwapChainDesc.Scaling = DXGI_SCALING_NONE;
SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
SwapChainDesc.Width = m_WindowWidth;
SwapChainDesc.Flags = 0;
//
// The swap chain is created as an IDXGISwapChain1 interface, but we then query
// the IDXGISwapchain3 interface from it.
//
IDXGISwapChain1* pSwapChain;
hr = m_pDXGIFactory->CreateSwapChainForHwnd(m_RenderContext.GetCommandQueue(), m_Hwnd, &SwapChainDesc, nullptr, nullptr, &pSwapChain);
if (FAILED(hr))
{
LOG_ERROR("Failed to create swap chain for hwnd, hr=0x%.8x", hr);
return hr;
}
hr = pSwapChain->QueryInterface(&m_pDXGISwapChain);
pSwapChain->Release();
if (FAILED(hr))
{
LOG_ERROR("Failed to query IDXGISwapChain3 interface, hr=0x%.8x", hr);
return hr;
}
//
// Create RTV heap for render target.
//
{
D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};
HeapDesc.NumDescriptors = SWAPCHAIN_BUFFER_COUNT;
HeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
hr = m_pDevice->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&m_pRtvHeap));
if (FAILED(hr))
{
LOG_ERROR("Failed to create RTV descriptor heap, hr=0x%.8x", hr);
return hr;
}
}
//
// If enabled, create the shared staging resource used for transfers.
//
if (m_bUseSharedStagingSurface)
{
hr = m_pDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(MAX_TRANSFER_SIZE),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_pStagingSurface));
if (FAILED(hr))
{
LOG_ERROR("Failed to create staging upload buffer, hr=0x%.8x", hr);
return hr;
}
CD3DX12_RANGE readRange(0, 0);
hr = m_pStagingSurface->Map(0, &readRange, &m_pStagingSurfaceData);
if (FAILED(hr))
{
LOG_ERROR("Failed to map upload buffer data, hr=0x%.8x", hr);
return hr;
}
}
//
// Create 11On12 state to enable D2D rendering on D3D12.
//
IUnknown* pRenderCommandQueue = m_RenderContext.GetCommandQueue();
hr = D3D11On12CreateDevice(m_pDevice, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, &pRenderCommandQueue, 1, 0, &m_p11Device, &m_p11Context, nullptr);
if (FAILED(hr))
{
LOG_ERROR("Failed to create D3D11On12 device, hr=0x%.8x", hr);
return hr;
}
hr = m_p11Device->QueryInterface(&m_p11On12Device);
if (FAILED(hr))
{
LOG_ERROR("Failed to query 11On12 device interface, hr=0x%.8x", hr);
return hr;
}
//
// Create D2D/DWrite components.
//
{
D2D1_DEVICE_CONTEXT_OPTIONS DeviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;
IDXGIDevice* pDxgiDevice;
hr = m_p11On12Device->QueryInterface(&pDxgiDevice);
if (FAILED(hr))
{
LOG_ERROR("Failed to query IDXGIDevice interface, hr=0x%.8x", hr);
return hr;
}
hr = m_pD2DFactory->CreateDevice(pDxgiDevice, &m_pD2DDevice);
pDxgiDevice->Release();
if (FAILED(hr))
{
LOG_ERROR("Failed to create D2D device, hr=0x%.8x", hr);
return hr;
}
hr = m_pD2DDevice->CreateDeviceContext(DeviceOptions, &m_pD2DContext);
if (FAILED(hr))
{
LOG_ERROR("Failed to create D2D context, hr=0x%.8x", hr);
return hr;
}
}
//
// Create the resources to enable D2D to access the swap chain.
//
hr = CreateSwapChainResources();
if (FAILED(hr))
{
LOG_WARNING("Failed to create swap chain resources");
return hr;
}
//
// Initialize our paging worker thread. The worker thread will be used for streaming
// resource mipmaps asynchronously from the rendering thread.
//
try
{
m_pWorkerThread = new PagingWorkerThread(this);
}
catch (std::bad_alloc&)
{
LOG_ERROR("Failed to allocate paging worker thread instance");
return E_OUTOFMEMORY;
}
hr = m_pWorkerThread->Init();
if (FAILED(hr))
{
LOG_WARNING("Failed to initialize paging worker thread");
return hr;
}
//
// If we are reinitializing from a device removed state, the application may have
// resources already which need to be reinitialized. Do this now.
//
{
LIST_ENTRY* pResourceEntry = m_ResourceListHead.Flink;
while (pResourceEntry != &m_ResourceListHead)
{
Resource* pResource = CONTAINING_RECORD(pResourceEntry, Resource, ListEntry);
pResourceEntry = pResourceEntry->Flink;
UINT NumMips;
UINT Width;
UINT Height;
DXGI_FORMAT Format;
hr = GetResourceInformation(pResource->pDecoder, NumMips, Format, Width, Height);
if (FAILED(hr))
{
LOG_ERROR("Failed to get resource information, hr=0x%.8x", hr);
return hr;
}
hr = CreateResourceDeviceState(pResource, NumMips, Format, Width, Height);
if (FAILED(hr))
{
return hr;
}
}
}
hr = CreateDeviceDependentState();
if (FAILED(hr))
{
return hr;
}
return S_OK;
}