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
This commit is contained in:
SpecialX
2026-03-26 19:01:08 +08:00
parent b7eebc11b2
commit 3fdc774f3f
11 changed files with 425 additions and 15 deletions

View File

@@ -14,4 +14,41 @@
// 引入 Windows Runtime C++ 模板库WRL头文件提供智能指针如 Microsoft::WRL::ComPtr
// 用于简化 COM 对象的生命周期管理
#include <wrl.h>
#include <wrl.h>
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d12.lib")
// 定义 DirectX 调试宏 DXCall用于在调试模式下检查 DirectX API 调用返回值
// 如果调用失败FAILED则输出错误信息文件名、行号、调用语句并触发断点
// 在发布模式下DXCall 宏不执行任何额外操作,直接执行原始调用
#ifdef _DEBUG
#ifndef DXCall
#define DXCall(x) \
if(FAILED(x)){ \
char line_number[32]; \
sprintf_s(line_number, "%u", __LINE__); \
OutputDebugStringA("Error in: "); \
OutputDebugStringA(__FILE__); \
OutputDebugStringA("\nLine: "); \
OutputDebugStringA(line_number); \
OutputDebugStringA("\n"); \
OutputDebugStringA(#x); \
OutputDebugStringA("\n"); \
__debugbreak(); \
}
#endif // !DXCall
#else
#ifndef DXCall
#define DXCall(x) x
#endif // !DXCall
#endif // _DEBUG
// 定义 DirectX 对象命名宏,用于在调试模式下为 Direct3D 12 对象设置名称
#ifdef _DEBUG
#define NAME_D3D12_OBJECT(obj, name) obj->SetName(name); OutputDebugString(L"::D3D12 Object Created: ");OutputDebugString(name);OutputDebugString(L"\n");
#else
#define NAME_D3D12_OBJECT(obj, name)
#endif

View File

@@ -1,20 +1,169 @@
#include "D3D12Core.h"
#include "D3D12CommonHeader.h"
namespace XEngine::graphics::d3d12::core{
namespace{
using namespace Microsoft::WRL;
namespace XEngine::graphics::d3d12::core {
namespace {
ID3D12Device8* main_device;
/**
* @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
bool
initialize()
{
// determine which adapter
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
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

View File

@@ -1,6 +1,30 @@
#pragma once
/**
* @brief Direct3D 12 核心类
* @details 定义了 Direct3D 12 核心功能的初始化与关闭函数
*/
namespace XEngine::graphics::d3d12::core{
/**
* @brief 初始化 Direct3D 12 核心功能
* @details 调用 DXGI 接口,确定要使用的 GPU 并创建 Direct3D 12 设备
* @return true 如果初始化成功,否则返回 false
*/
bool initialize();
/**
* @brief 关闭 Direct3D 12 核心功能
* @details 调用 Direct3D 12 设备的关闭函数,释放所有资源
*/
void shutdown();
template<typename T>
constexpr void release(T*& resource)
{
if(resource)
{
resource->Release();
resource = nullptr;
}
}
}// namespace XEngine::graphics::d3d12

View File

@@ -1,3 +1,4 @@
#include "CommonHeader.h"
#include "D3D12Interface.h"
#include "D3D12Core.h"
#include "Graphics\GraphicsPlatformInterface.h"

View File

@@ -3,6 +3,10 @@
#include "Renderer.h"
namespace XEngine::graphics{
/**
* @brief 平台接口结构体
* @details 定义了图形渲染平台的初始化与关闭函数指针
*/
struct platform_interface{
bool(*initialize)(void);
void(*shutdown)(void);

View File

@@ -5,6 +5,13 @@
namespace XEngine::graphics {
namespace {
platform_interface gfx{};
/**
* @brief 设置图形渲染平台的接口
* @details 根据指定的平台类型,调用对应的初始化与关闭函数指针
* @param platform 图形渲染平台类型
* @return true 如果初始化成功,否则返回 false
*/
bool
set_platform_interface(graphics_platform platform)
{
@@ -22,13 +29,19 @@ set_platform_interface(graphics_platform platform)
default:
return false;
}
return gfx.initialize();
return true;
}
}// anonymous namespace
/**
* @brief 初始化图形渲染平台
* @details 调用设置平台接口函数,初始化指定的图形渲染平台
* @param platform 图形渲染平台类型
* @return true 如果初始化成功,否则返回 false
*/
bool initialize(graphics_platform platform)
{
return set_platform_interface(platform);
return set_platform_interface(platform) && gfx.initialize();
}
void shutdown()

View File

@@ -5,16 +5,28 @@
namespace XEngine::graphics {
/**
* @brief 表面类
* @details 定义了渲染表面的属性与操作
*/
class surface
{
};
/**
* @brief 渲染表面结构体
* @details 定义了渲染表面的窗口与表面对象
*/
struct render_surface
{
platform::window window{};
surface surface{};
};
/**
* @brief 图形渲染平台枚举
* @details 定义了支持的图形渲染平台类型
*/
enum class graphics_platform : u32
{
direct3d12 = 0,
@@ -22,7 +34,17 @@ enum class graphics_platform : u32
opengl = 2,
};
/**
* @brief 初始化图形渲染平台
* @details 调用设置平台接口函数,初始化指定的图形渲染平台
* @param platform 图形渲染平台类型
* @return true 如果初始化成功,否则返回 false
*/
bool initialize(graphics_platform platform);
/**
* @brief 关闭图形渲染平台
* @details 调用关闭函数指针,关闭指定的图形渲染平台
*/
void shutdown();
}