D3D12 Core: - Implement complete device initialization flow - Add debug layer enablement in DEBUG mode - Add GPU adapter enumeration and selection - Add feature level checking (min 11.0) - Add DXCall and NAME_D3D12_OBJECT macros - Add release template function - Configure info queue for error/warning breakpoints Documentation: - Add changelog for D3D12 device initialization - Update D3D12 Wiki with current implementation status - Add Doxygen comments to Renderer and platform interface
170 lines
5.0 KiB
C++
170 lines
5.0 KiB
C++
#include "D3D12Core.h"
|
||
#include "D3D12CommonHeader.h"
|
||
|
||
using namespace Microsoft::WRL;
|
||
namespace XEngine::graphics::d3d12::core {
|
||
namespace {
|
||
|
||
/**
|
||
* @brief 主 Direct3D 12 设备指针
|
||
* @details 指向 Direct3D 12 设备的智能指针,用于创建渲染管线、管理资源与 GPU 命令
|
||
*/
|
||
ID3D12Device8* main_device{ nullptr };
|
||
|
||
/**
|
||
* @brief DXGI 工厂指针
|
||
* @details 指向 DXGI 工厂的智能指针,用于创建 Direct3D 12 设备
|
||
*/
|
||
IDXGIFactory7* dxgi_factory{ nullptr };
|
||
|
||
// 最小支持的 Direct3D 特本级别
|
||
constexpr D3D_FEATURE_LEVEL minumum_feature_level{ D3D_FEATURE_LEVEL_11_0 };
|
||
|
||
bool
|
||
failed_init()
|
||
{
|
||
shutdown();
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @brief 确定要使用的 GPU
|
||
* @details 枚举所有可用的 GPU,选择支持最小特征级别的 Direct3D 12 设备
|
||
* 注意:该功能可通过以下方式扩展:例如,检查是否有任何
|
||
* 输出设备(即显示器)已连接,枚举支持的分辨率,提供
|
||
* 一种机制供用户在多适配器环境中选择要使用的适配器等
|
||
* @return IDXGIAdapter4* 指向确定的 GPU 的智能指针
|
||
*/
|
||
IDXGIAdapter4*
|
||
determine_main_adapter()
|
||
{
|
||
IDXGIAdapter4* adapter;
|
||
for (u32 i{ 0 };
|
||
dxgi_factory->EnumAdapterByGpuPreference(i, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) != DXGI_ERROR_NOT_FOUND;
|
||
++i)
|
||
{
|
||
//获取支持最小特征级别的 Direct3D 12 设备
|
||
if (SUCCEEDED(D3D12CreateDevice(adapter, minumum_feature_level, __uuidof(ID3D12Device8), nullptr)))
|
||
{
|
||
return adapter;
|
||
}
|
||
release(adapter);
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取指定适配器支持的最高 Direct3D 特性级别
|
||
* @details 检查指定适配器是否支持 Direct3D 12 特性级别
|
||
* @param adapter 指向要检查的适配器的智能指针
|
||
* @return D3D_FEATURE_LEVEL 支持的最高 Direct3D 特性级别
|
||
*/
|
||
D3D_FEATURE_LEVEL
|
||
get_max_feature_level(IDXGIAdapter4* adapter)
|
||
{
|
||
constexpr D3D_FEATURE_LEVEL feature_levels[4]{
|
||
D3D_FEATURE_LEVEL_11_0,
|
||
D3D_FEATURE_LEVEL_11_1,
|
||
D3D_FEATURE_LEVEL_12_0,
|
||
D3D_FEATURE_LEVEL_12_1,
|
||
};
|
||
|
||
D3D12_FEATURE_DATA_FEATURE_LEVELS feature_level_info{};
|
||
feature_level_info.NumFeatureLevels = (_countof(feature_levels));
|
||
feature_level_info.pFeatureLevelsRequested = feature_levels;
|
||
|
||
ComPtr<ID3D12Device> device;
|
||
DXCall(D3D12CreateDevice(adapter, minumum_feature_level, IID_PPV_ARGS(&device)));
|
||
DXCall(device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &feature_level_info, sizeof(feature_level_info)));
|
||
|
||
return feature_level_info.MaxSupportedFeatureLevel;
|
||
}
|
||
|
||
}// anonymous namespace
|
||
|
||
|
||
bool
|
||
initialize()
|
||
{
|
||
if (main_device) shutdown();
|
||
|
||
|
||
// 在DEBUG模式下,捕获 DXGI 可能抛出的异常
|
||
u32 dxgi_factory_flag{ 0 };
|
||
// 开启调试层, 需要graphics tools支持
|
||
#ifdef _DEBUG
|
||
{
|
||
ComPtr<ID3D12Debug3> debug_interface;
|
||
DXCall(D3D12GetDebugInterface(IID_PPV_ARGS(&debug_interface)));
|
||
debug_interface->EnableDebugLayer();
|
||
dxgi_factory_flag |= DXGI_CREATE_FACTORY_DEBUG;
|
||
}
|
||
#endif
|
||
|
||
// 创建 DXGI 工厂实例,用于枚举显卡适配器和创建交换链等操作
|
||
HRESULT hr{ S_OK };
|
||
DXCall(hr = CreateDXGIFactory2(dxgi_factory_flag, IID_PPV_ARGS(&dxgi_factory)));
|
||
if (FAILED(hr)) return failed_init();
|
||
|
||
// 确定要使用的 GPU
|
||
ComPtr<IDXGIAdapter4> main_adapter;
|
||
main_adapter.Attach(determine_main_adapter());
|
||
if (!main_adapter) return failed_init();
|
||
|
||
// 获取主适配器支持的最高 Direct3D 特性级别,并且不得低于最小要求
|
||
D3D_FEATURE_LEVEL max_feature_level{ get_max_feature_level(main_adapter.Get()) };
|
||
assert(max_feature_level >= minumum_feature_level);
|
||
if (max_feature_level < minumum_feature_level) return failed_init();
|
||
|
||
// 使用最高适配特性级别创建Direct3D 12 设备
|
||
DXCall(hr = D3D12CreateDevice(main_adapter.Get(), max_feature_level, IID_PPV_ARGS(&main_device)));
|
||
if (FAILED(hr)) return failed_init();
|
||
|
||
// 为 Direct3D 12 设备设置名称
|
||
NAME_D3D12_OBJECT(main_device, L"Main Device");
|
||
|
||
#ifdef _DEBUG
|
||
{
|
||
ComPtr<ID3D12InfoQueue> info_queue;
|
||
DXCall(main_device->QueryInterface(IID_PPV_ARGS(&info_queue)));
|
||
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true);
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
|
||
}
|
||
#endif // _DEBUG
|
||
|
||
return true;
|
||
}
|
||
void
|
||
shutdown()
|
||
{
|
||
release(dxgi_factory);
|
||
|
||
// 关闭调试层,确保最后只有一个活动的主设备
|
||
#ifdef _DEBUG
|
||
{
|
||
{
|
||
ComPtr<ID3D12InfoQueue> info_queue;
|
||
DXCall(main_device->QueryInterface(IID_PPV_ARGS(&info_queue)));
|
||
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, false);
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, false);
|
||
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, false);
|
||
}
|
||
|
||
ComPtr<ID3D12DebugDevice2> debug_device;
|
||
DXCall(main_device->QueryInterface(IID_PPV_ARGS(&debug_device)));
|
||
release(main_device);
|
||
DXCall(debug_device->ReportLiveDeviceObjects(
|
||
D3D12_RLDO_SUMMARY | D3D12_RLDO_DETAIL | D3D12_RLDO_IGNORE_INTERNAL
|
||
));
|
||
}
|
||
#endif // _DEBUG
|
||
|
||
|
||
release(main_device);
|
||
}
|
||
}// namespace XEngine::graphics::d3d12::core
|