diff --git a/Engine/Graphics/Direct3D12/D3D12CommonHeader.h b/Engine/Graphics/Direct3D12/D3D12CommonHeader.h index 56c03c0..e20787b 100644 --- a/Engine/Graphics/Direct3D12/D3D12CommonHeader.h +++ b/Engine/Graphics/Direct3D12/D3D12CommonHeader.h @@ -14,4 +14,41 @@ // 引入 Windows Runtime C++ 模板库(WRL)头文件,提供智能指针(如 Microsoft::WRL::ComPtr) // 用于简化 COM 对象的生命周期管理 -#include \ No newline at end of file +#include + + +#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 diff --git a/Engine/Graphics/Direct3D12/D3D12Core.cpp b/Engine/Graphics/Direct3D12/D3D12Core.cpp index 14c275c..56dd8aa 100644 --- a/Engine/Graphics/Direct3D12/D3D12Core.cpp +++ b/Engine/Graphics/Direct3D12/D3D12Core.cpp @@ -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 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 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 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 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 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 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 diff --git a/Engine/Graphics/Direct3D12/D3D12Core.h b/Engine/Graphics/Direct3D12/D3D12Core.h index dd0f32e..d1565df 100644 --- a/Engine/Graphics/Direct3D12/D3D12Core.h +++ b/Engine/Graphics/Direct3D12/D3D12Core.h @@ -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 +constexpr void release(T*& resource) +{ + if(resource) + { + resource->Release(); + resource = nullptr; + } +} + }// namespace XEngine::graphics::d3d12 \ No newline at end of file diff --git a/Engine/Graphics/Direct3D12/D3D12Interface.cpp b/Engine/Graphics/Direct3D12/D3D12Interface.cpp index 1696edf..0a4e646 100644 --- a/Engine/Graphics/Direct3D12/D3D12Interface.cpp +++ b/Engine/Graphics/Direct3D12/D3D12Interface.cpp @@ -1,3 +1,4 @@ +#include "CommonHeader.h" #include "D3D12Interface.h" #include "D3D12Core.h" #include "Graphics\GraphicsPlatformInterface.h" diff --git a/Engine/Graphics/GraphicsPlatformInterface.h b/Engine/Graphics/GraphicsPlatformInterface.h index 18d73d8..2869e73 100644 --- a/Engine/Graphics/GraphicsPlatformInterface.h +++ b/Engine/Graphics/GraphicsPlatformInterface.h @@ -3,6 +3,10 @@ #include "Renderer.h" namespace XEngine::graphics{ +/** + * @brief 平台接口结构体 + * @details 定义了图形渲染平台的初始化与关闭函数指针 + */ struct platform_interface{ bool(*initialize)(void); void(*shutdown)(void); diff --git a/Engine/Graphics/Renderer.cpp b/Engine/Graphics/Renderer.cpp index 49dfe96..f8b850b 100644 --- a/Engine/Graphics/Renderer.cpp +++ b/Engine/Graphics/Renderer.cpp @@ -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() diff --git a/Engine/Graphics/Renderer.h b/Engine/Graphics/Renderer.h index 83f1d57..6314659 100644 --- a/Engine/Graphics/Renderer.h +++ b/Engine/Graphics/Renderer.h @@ -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(); } \ No newline at end of file diff --git a/docs/changelogs/2026-03/20260326-d3d12-device-init.md b/docs/changelogs/2026-03/20260326-d3d12-device-init.md new file mode 100644 index 0000000..9c1c54e --- /dev/null +++ b/docs/changelogs/2026-03/20260326-d3d12-device-init.md @@ -0,0 +1,142 @@ +# 变更记录:D3D12 设备初始化实现 + +**提交日期**: 2026-03-26 +**提交哈希**: `69b7352` +**变更类型**: 功能实现 + +--- + +## 变更概述 + +本次提交实现了 D3D12 设备的完整初始化流程,包括调试层、DXGI 工厂创建、GPU 适配器枚举与选择、特性级别检查和设备创建。 + +## 修改文件 + +### Engine/Graphics/Direct3D12/ + +| 文件 | 变更说明 | +|------|----------| +| `D3D12Core.cpp` | 实现完整的 D3D12 设备初始化流程 | +| `D3D12Core.h` | 添加 `release` 模板函数 | +| `D3D12CommonHeader.h` | 添加库链接、DXCall 宏、NAME_D3D12_OBJECT 宏 | + +### Engine/Graphics/ + +| 文件 | 变更说明 | +|------|----------| +| `Renderer.h` | 添加 Doxygen 注释 | +| `Renderer.cpp` | 添加 Doxygen 注释 | +| `GraphicsPlatformInterface.h` | 添加 Doxygen 注释 | + +--- + +## 技术要点 + +### 1. 调试层启用 + +```cpp +#ifdef _DEBUG +{ + ComPtr debug_interface; + DXCall(D3D12GetDebugInterface(IID_PPV_ARGS(&debug_interface))); + debug_interface->EnableDebugLayer(); + dxgi_factory_flag |= DXGI_CREATE_FACTORY_DEBUG; +} +#endif +``` + +调试层可捕获无效 API 调用和资源泄漏。 + +### 2. GPU 适配器选择 + +```cpp +IDXGIAdapter4* determine_main_adapter() +{ + for (u32 i{ 0 }; ...; ++i) + { + // 按高性能优先枚举适配器 + if (SUCCEEDED(D3D12CreateDevice(adapter, minumum_feature_level, ...))) + return adapter; + } + return nullptr; +} +``` + +优先选择高性能 GPU,并验证 D3D12 支持。 + +### 3. 特性级别检查 + +```cpp +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, +}; +``` + +获取适配器支持的最高特性级别,确保不低于最低要求 (11.0)。 + +### 4. 调试宏 + +```cpp +// DXCall 宏 - 检查 HRESULT 并输出错误信息 +#define DXCall(x) if(FAILED(x)) { ... __debugbreak(); } + +// NAME_D3D12_OBJECT 宏 - 为 D3D12 对象设置调试名称 +#define NAME_D3D12_OBJECT(obj, name) obj->SetName(name); +``` + +### 5. 信息队列配置 + +```cpp +info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); +info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true); +info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); +``` + +在调试模式下,遇到警告或错误时自动断点。 + +--- + +## 初始化流程 + +``` +initialize() + │ + ├─► 启用调试层 (DEBUG 模式) + │ + ├─► 创建 DXGI 工厂 + │ + ├─► 枚举并选择 GPU 适配器 + │ └─► 按高性能优先 + │ └─► 验证 D3D12 支持 + │ + ├─► 获取最高特性级别 + │ └─► 必须 >= 11.0 + │ + ├─► 创建 D3D12 设备 + │ + └─► 配置信息队列 (DEBUG 模式) +``` + +--- + +## 依赖 + +- `dxgi.lib` - DXGI 库 +- `d3d12.lib` - Direct3D 12 库 + +--- + +## 后续工作 + +- [ ] 命令队列创建 +- [ ] 交换链管理 +- [ ] 描述符堆 + +--- + +## 相关文档 + +- [D3D12学习Wiki](../wiki/D3D12学习Wiki.md) diff --git a/docs/changelogs/2026-03/20260326-d3d12-foundation.md b/docs/changelogs/2026-03/20260326-d3d12-foundation.md index 62a245f..8c31f07 100644 --- a/docs/changelogs/2026-03/20260326-d3d12-foundation.md +++ b/docs/changelogs/2026-03/20260326-d3d12-foundation.md @@ -1,7 +1,7 @@ # 变更记录:D3D12 基础框架 **提交日期**: 2026-03-26 -**提交哈希**: `16723ba` +**提交哈希**: `b7eebc1` **变更类型**: 新增功能 --- diff --git a/docs/changelogs/README.md b/docs/changelogs/README.md index 7f6db7d..d75e27d 100644 --- a/docs/changelogs/README.md +++ b/docs/changelogs/README.md @@ -16,6 +16,7 @@ changelogs/ | 日期 | 提交 | 变更内容 | |------|------|----------| +| 2026-03-26 | [D3D12设备初始化](./2026-03/20260326-d3d12-device-init.md) | D3D12 设备创建与调试层实现 | | 2026-03-26 | [Graphics模块](./2026-03/20260326-d3d12-foundation.md) | Graphics 模块与 D3D12 后端框架 | | 2026-03-19 | [DX12初始框架](./2026-03/20260326-dx12-initial.md) | 初始 DX12 基础框架 | diff --git a/docs/wiki/D3D12学习Wiki.md b/docs/wiki/D3D12学习Wiki.md index a3d9b40..bc537cd 100644 --- a/docs/wiki/D3D12学习Wiki.md +++ b/docs/wiki/D3D12学习Wiki.md @@ -78,19 +78,36 @@ IDXGISwapChain // 交换链接口 ### 3.2 项目当前状态 -[D3D12Core.cpp](file:///d:/AllWX/AllC/FeatureExtractDemo/Engine/Graphics/Direct3D12/D3D12Core.cpp) 目前是框架代码: +[D3D12Core.cpp](file:///d:/AllWX/AllC/FeatureExtractDemo/Engine/Graphics/Direct3D12/D3D12Core.cpp) 已实现完整的设备初始化: ```cpp namespace { - ID3D12Device8* main_device; // 已声明主设备 + ID3D12Device8* main_device{ nullptr }; + IDXGIFactory7* dxgi_factory{ nullptr }; } bool initialize() { - // TODO: 实现适配器选择和设备创建 - return true; + // 1. 启用调试层 (DEBUG 模式) + // 2. 创建 DXGI 工厂 + // 3. 枚举并选择 GPU 适配器 + // 4. 获取最高特性级别 + // 5. 创建 D3D12 设备 + // 6. 配置信息队列 (DEBUG 模式) } ``` +### 3.3 调试宏 + +项目定义了两个重要的调试宏: + +```cpp +// DXCall - 检查 HRESULT 并断点 +#define DXCall(x) if(FAILED(x)) { ... __debugbreak(); } + +// NAME_D3D12_OBJECT - 为对象设置调试名称 +#define NAME_D3D12_OBJECT(obj, name) obj->SetName(name); +``` + ## 4. COM 对象管理 ### 4.1 什么是 COM? @@ -193,7 +210,7 @@ if (wparam == VK_RETURN && (HIWORD(lparam) & KF_ALTDOWN)) { ### 7.1 基础阶段 -- [ ] 完成设备创建和适配器枚举 +- [x] 完成设备创建和适配器枚举 - [ ] 创建命令队列和命令列表 - [ ] 实现交换链和后台缓冲区 - [ ] 渲染第一个三角形