Files
DX12/Engine/Graphics/Direct3D12/D3D12Core.cpp
SpecialX 3fdc774f3f feat: implement D3D12 device initialization with debug layer
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
2026-03-26 19:01:51 +08:00

170 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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