Compare commits
2 Commits
80cb696a3c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
188a8aea2f | ||
|
|
4d13d8df89 |
14
Engine/Graphics/Direct3D12/D3D12Helpers.h
Normal file
14
Engine/Graphics/Direct3D12/D3D12Helpers.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "D3D12CommonHeader.h"
|
||||||
|
namespace XEngine::graphics::d3d12::d3dx
|
||||||
|
{
|
||||||
|
constexpr struct{
|
||||||
|
D3D12_HEAP_PROPERTIES default_heap{
|
||||||
|
D3D12_HEAP_TYPE_DEFAULT, // 堆类型:默认堆,GPU可读写,CPU不可直接访问。选项:D3D12_HEAP_TYPE_DEFAULT(默认堆)、D3D12_HEAP_TYPE_UPLOAD(上传堆,CPU写入GPU读取)、D3D12_HEAP_TYPE_READBACK(回读堆,GPU写入CPU读取)、D3D12_HEAP_TYPE_CUSTOM(自定义堆)
|
||||||
|
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, // CPU页属性:未知,使用默认设置。选项:D3D12_CPU_PAGE_PROPERTY_UNKNOWN(未知)、D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE(不可用)、D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE(写入合并)、D3D12_CPU_PAGE_PROPERTY_WRITE_BACK(写回)
|
||||||
|
D3D12_MEMORY_POOL_UNKNOWN, // 内存池:未知,由驱动自动选择。选项:D3D12_MEMORY_POOL_UNKNOWN(未知)、D3D12_MEMORY_POOL_L0(系统内存池)、D3D12_MEMORY_POOL_L1(显存池)
|
||||||
|
0, // 节点掩码:单GPU系统设为0,多GPU系统中指定使用哪个GPU节点
|
||||||
|
0, // 保留字段:必须为0,为将来扩展预留
|
||||||
|
};
|
||||||
|
}heap_properties;
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "D3D12Resources.h"
|
#include "D3D12Resources.h"
|
||||||
#include "D3D12Core.h"
|
#include "D3D12Core.h"
|
||||||
|
#include "D3D12Helpers.h"
|
||||||
|
|
||||||
namespace XEngine::graphics::d3d12{
|
namespace XEngine::graphics::d3d12{
|
||||||
//////////// DESCRIPTOR HEAP ////////////
|
//////////// DESCRIPTOR HEAP ////////////
|
||||||
|
|
||||||
|
|
||||||
// 该类将被多个线程并发访问:资源创建(如纹理)与资源销毁/释放可能发生在不同线程,
|
// 该类将被多个线程并发访问:资源创建(如纹理)与资源销毁/释放可能发生在不同线程,
|
||||||
// 因此需要同步机制保护内部数据结构
|
// 因此需要同步机制保护内部数据结构
|
||||||
bool
|
bool
|
||||||
@@ -134,4 +137,140 @@ descriptor_heap::free(descriptor_handle handle)
|
|||||||
handle = {};
|
handle = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////// D3D12 TEXTURE ////////////
|
||||||
|
|
||||||
|
d3d12_texture::d3d12_texture( d3d12_texture_init_info info)
|
||||||
|
{
|
||||||
|
auto *const device {core::device()};
|
||||||
|
assert(device);
|
||||||
|
|
||||||
|
D3D12_CLEAR_VALUE *const clear_value{
|
||||||
|
(info.desc &&
|
||||||
|
(info.desc->Flags &D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET ||
|
||||||
|
info.desc && info.desc->Flags &D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
|
||||||
|
? &info.clear_value : nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
if(info.resource)
|
||||||
|
{
|
||||||
|
_resource = info.resource;
|
||||||
|
}
|
||||||
|
else if(info.heap && info.desc)
|
||||||
|
{
|
||||||
|
assert(!info.resource);
|
||||||
|
DXCall(device->CreatePlacedResource(
|
||||||
|
info.heap,
|
||||||
|
info.allocation_info.Offset,
|
||||||
|
info.desc,
|
||||||
|
info.initial_state,
|
||||||
|
clear_value,
|
||||||
|
IID_PPV_ARGS(&_resource)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else if (info.desc)
|
||||||
|
{
|
||||||
|
assert(!info.srv_desc);
|
||||||
|
|
||||||
|
DXCall(device->CreateCommittedResource(
|
||||||
|
&d3dx::heap_properties.default_heap,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
info.desc,
|
||||||
|
info.initial_state,
|
||||||
|
clear_value,
|
||||||
|
IID_PPV_ARGS(&_resource)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_resource);
|
||||||
|
_srv = core::srv_heap().allocate();
|
||||||
|
device->CreateShaderResourceView(_resource, info.srv_desc, _srv.cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_texture::release()
|
||||||
|
{
|
||||||
|
core::srv_heap().free(_srv);
|
||||||
|
core::deferred_release(_resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// D3D12 RENDER TEXTURE ////////////
|
||||||
|
d3d12_render_texture::d3d12_render_texture(d3d12_texture_init_info info)
|
||||||
|
: _texture(info)
|
||||||
|
{
|
||||||
|
assert(info.desc);
|
||||||
|
_mip_count = resource()->GetDesc().MipLevels;
|
||||||
|
assert(_mip_count && _mip_count <= d3d12_texture::max_mips);
|
||||||
|
|
||||||
|
descriptor_heap& rtv_heap {core::rtv_heap()};
|
||||||
|
D3D12_RENDER_TARGET_VIEW_DESC desc{};
|
||||||
|
desc.Format = info.desc->Format;
|
||||||
|
desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
desc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
auto *const device {core::device()};
|
||||||
|
assert(device);
|
||||||
|
for(u32 i{0}; i<_mip_count;++i)
|
||||||
|
{
|
||||||
|
_rtv[i] = rtv_heap.allocate();
|
||||||
|
device->CreateRenderTargetView(resource(), &desc, _rtv[i].cpu);
|
||||||
|
++desc.Texture2D.MipSlice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_render_texture::release()
|
||||||
|
{
|
||||||
|
for(u32 i{0}; i<_mip_count;++i) core::srv_heap().free(_rtv[i]);
|
||||||
|
_texture.release();
|
||||||
|
_mip_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// D3D12 DEPTH TEXTURE ////////////
|
||||||
|
d3d12_depth_buffer::d3d12_depth_buffer(d3d12_texture_init_info info)
|
||||||
|
: _texture(info)
|
||||||
|
{
|
||||||
|
assert(info.desc);
|
||||||
|
const DXGI_FORMAT dsv_format {info.desc->Format};
|
||||||
|
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc{};
|
||||||
|
if(info.desc->Format == DXGI_FORMAT_D32_FLOAT)
|
||||||
|
{
|
||||||
|
info.desc->Format = DXGI_FORMAT_R32_TYPELESS;
|
||||||
|
srv_desc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
|
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srv_desc.Texture2D.MipLevels = 1;
|
||||||
|
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||||
|
srv_desc.Texture2D.PlaneSlice = 0;
|
||||||
|
srv_desc.Texture2D.ResourceMinLODClamp = 0.f;
|
||||||
|
|
||||||
|
assert(!info.srv_desc && !info.resource);
|
||||||
|
info.srv_desc = &srv_desc;
|
||||||
|
_texture = d3d12_texture(info);
|
||||||
|
|
||||||
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc{};
|
||||||
|
dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
dsv_desc.Flags = D3D12_DSV_FLAG_NONE;
|
||||||
|
dsv_desc.Format = dsv_format;
|
||||||
|
dsv_desc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
_dsv = core::dsv_heap().allocate();
|
||||||
|
auto *const device {core::device()};
|
||||||
|
assert(device);
|
||||||
|
device->CreateDepthStencilView(resource(), &dsv_desc, _dsv.cpu);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
void
|
||||||
|
d3d12_depth_buffer::release()
|
||||||
|
{
|
||||||
|
core::dsv_heap().free(_dsv);
|
||||||
|
_texture.release();
|
||||||
|
_dsv = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} //XEngine::graphics::d3d12
|
} //XEngine::graphics::d3d12
|
||||||
@@ -417,4 +417,145 @@ private:
|
|||||||
const D3D12_DESCRIPTOR_HEAP_TYPE _type;
|
const D3D12_DESCRIPTOR_HEAP_TYPE _type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct d3d12_texture_init_info
|
||||||
|
{
|
||||||
|
ID3D12Heap1* heap{nullptr};
|
||||||
|
ID3D12Resource* resource{nullptr};
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC* srv_desc{nullptr};
|
||||||
|
D3D12_RESOURCE_DESC* desc{nullptr};
|
||||||
|
D3D12_RESOURCE_ALLOCATION_INFO1 allocation_info{};
|
||||||
|
D3D12_RESOURCE_STATES initial_state{};
|
||||||
|
D3D12_CLEAR_VALUE clear_value{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class d3d12_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static u32 max_mips{ 14 };
|
||||||
|
d3d12_texture() = default;
|
||||||
|
explicit d3d12_texture(d3d12_texture_init_info info);
|
||||||
|
~d3d12_texture() { release(); }
|
||||||
|
DISABLE_COPY(d3d12_texture);
|
||||||
|
constexpr d3d12_texture(d3d12_texture&& o)
|
||||||
|
: _resource(o._resource), _srv(o._srv) //这些值只是指针和句柄,不需要move
|
||||||
|
{
|
||||||
|
o.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr d3d12_texture& operator=(d3d12_texture&& o)
|
||||||
|
{
|
||||||
|
assert(this != &o);
|
||||||
|
if(this != &o)
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
move(o);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release();
|
||||||
|
constexpr ID3D12Resource *const resource() const { return _resource; }
|
||||||
|
constexpr descriptor_handle srv() const { return _srv; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr void move(d3d12_texture& o)
|
||||||
|
{
|
||||||
|
_resource = o._resource;
|
||||||
|
_srv = o._srv;
|
||||||
|
o.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void reset()
|
||||||
|
{
|
||||||
|
_resource = nullptr;
|
||||||
|
_srv = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D12Resource* _resource{nullptr};
|
||||||
|
descriptor_handle _srv;
|
||||||
|
};
|
||||||
|
|
||||||
|
class d3d12_render_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
d3d12_render_texture() = default;
|
||||||
|
explicit d3d12_render_texture(d3d12_texture_init_info info);
|
||||||
|
DISABLE_COPY(d3d12_render_texture);
|
||||||
|
~d3d12_render_texture() { release(); }
|
||||||
|
constexpr d3d12_render_texture(d3d12_render_texture&& o)
|
||||||
|
: _texture{std::move(o._texture)}, _mip_count{o._mip_count}
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < o._mip_count; ++i) _rtv[i] = o._rtv[i];
|
||||||
|
o.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr d3d12_render_texture& operator=(d3d12_render_texture&& o)
|
||||||
|
{
|
||||||
|
assert(this != &o);
|
||||||
|
if(this != &o)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
move(o);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release();
|
||||||
|
constexpr u32 mip_count() const { return _mip_count; }
|
||||||
|
constexpr D3D12_CPU_DESCRIPTOR_HANDLE rtv(u32 mip) const { assert(mip < _mip_count); return _rtv[mip].cpu; }
|
||||||
|
constexpr descriptor_handle srv() const { return _texture.srv(); }
|
||||||
|
constexpr ID3D12Resource *const resource() const { return _texture.resource(); }
|
||||||
|
private:
|
||||||
|
constexpr void move(d3d12_render_texture& o)
|
||||||
|
{
|
||||||
|
_texture = std::move(o._texture);
|
||||||
|
for(u32 i = 0; i < o._mip_count; ++i) _rtv[i] = o._rtv[i];
|
||||||
|
o.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void reset()
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < _mip_count; ++i) _rtv[i] = {};
|
||||||
|
_mip_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _rtv[d3d12_texture::max_mips]{};
|
||||||
|
u32 _mip_count{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
class d3d12_depth_buffer
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
d3d12_depth_buffer() = default;
|
||||||
|
explicit d3d12_depth_buffer(d3d12_texture_init_info info);
|
||||||
|
DISABLE_COPY(d3d12_depth_buffer);
|
||||||
|
~d3d12_depth_buffer() { release(); }
|
||||||
|
constexpr d3d12_depth_buffer(d3d12_depth_buffer&& o)
|
||||||
|
: _texture{std::move(o._texture)}, _dsv(o._dsv)
|
||||||
|
{
|
||||||
|
o._dsv = {};
|
||||||
|
}
|
||||||
|
constexpr d3d12_depth_buffer& operator=(d3d12_depth_buffer&& o)
|
||||||
|
{
|
||||||
|
assert(this != &o);
|
||||||
|
if(this != &o)
|
||||||
|
{
|
||||||
|
_texture = std::move(o._texture);
|
||||||
|
_dsv = o._dsv;
|
||||||
|
o._dsv = {};
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release();
|
||||||
|
constexpr D3D12_CPU_DESCRIPTOR_HANDLE dsv() const { return _dsv.cpu; }
|
||||||
|
constexpr descriptor_handle srv() const { return _texture.srv(); }
|
||||||
|
constexpr ID3D12Resource *const resource() const { return _texture.resource(); }
|
||||||
|
private:
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _dsv{};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace XEngine::graphics::d3d12
|
} // namespace XEngine::graphics::d3d12
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ d3d12_surface::create_swap_chain(IDXGIFactory7* factory, ID3D12CommandQueue* cmd
|
|||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 desc{};
|
DXGI_SWAP_CHAIN_DESC1 desc{};
|
||||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Alpha通道模式(窗口透明度相关)
|
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Alpha通道模式(窗口透明度相关)
|
||||||
desc.BufferCount = frame_buffer_count; // 后台缓冲区数量(用于双缓冲/多缓冲)
|
desc.BufferCount = buffer_count; // 后台缓冲区数量(用于双缓冲/多缓冲)
|
||||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 缓冲区用途(作为渲染目标输出)
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 缓冲区用途(作为渲染目标输出)
|
||||||
desc.Flags = _allow_tearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; // 交换链标志位(无)
|
desc.Flags = _allow_tearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; // 交换链标志位(无)
|
||||||
desc.Format = to_non_srgb(format); // 像素格式(转换为非SRGB格式)
|
desc.Format = to_non_srgb(format); // 像素格式(转换为非SRGB格式)
|
||||||
@@ -53,7 +53,7 @@ d3d12_surface::create_swap_chain(IDXGIFactory7* factory, ID3D12CommandQueue* cmd
|
|||||||
|
|
||||||
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
||||||
|
|
||||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
for (u32 i = 0; i < buffer_count; ++i)
|
||||||
{
|
{
|
||||||
_render_target_data[i].rtv = core::rtv_heap().allocate();
|
_render_target_data[i].rtv = core::rtv_heap().allocate();
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ void
|
|||||||
d3d12_surface::finalize()
|
d3d12_surface::finalize()
|
||||||
{
|
{
|
||||||
// 为每个缓冲区创建渲染目标视图
|
// 为每个缓冲区创建渲染目标视图
|
||||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
for (u32 i = 0; i < buffer_count; ++i)
|
||||||
{
|
{
|
||||||
render_target_data& data{ _render_target_data[i] };
|
render_target_data& data{ _render_target_data[i] };
|
||||||
assert(!data.resource);
|
assert(!data.resource);
|
||||||
@@ -107,7 +107,7 @@ d3d12_surface::finalize()
|
|||||||
void
|
void
|
||||||
d3d12_surface::release()
|
d3d12_surface::release()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
for (u32 i = 0; i < buffer_count; ++i)
|
||||||
{
|
{
|
||||||
render_target_data& data{ _render_target_data[i] };
|
render_target_data& data{ _render_target_data[i] };
|
||||||
core::release(data.resource);
|
core::release(data.resource);
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
~d3d12_surface(){ release(); }
|
~d3d12_surface(){ release(); }
|
||||||
|
|
||||||
|
|
||||||
|
constexpr static u32 buffer_count{ 3 };
|
||||||
|
|
||||||
#if USE_STL_VECTOR
|
#if USE_STL_VECTOR
|
||||||
DISABLE_COPY(d3d12_surface)
|
DISABLE_COPY(d3d12_surface)
|
||||||
|
|
||||||
@@ -288,7 +291,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
IDXGISwapChain4* _swap_chain{nullptr}; ///< DXGI 交换链对象
|
IDXGISwapChain4* _swap_chain{nullptr}; ///< DXGI 交换链对象
|
||||||
render_target_data _render_target_data[frame_buffer_count];///< 后台缓冲区数据数组
|
render_target_data _render_target_data[buffer_count]; ///< 后台缓冲区数据数组
|
||||||
platform::window _window{}; ///< 关联的平台窗口
|
platform::window _window{}; ///< 关联的平台窗口
|
||||||
mutable u32 _current_bb_index{0}; ///< 当前后台缓冲区索引
|
mutable u32 _current_bb_index{0}; ///< 当前后台缓冲区索引
|
||||||
D3D12_VIEWPORT _viewport{}; ///< 视口描述
|
D3D12_VIEWPORT _viewport{}; ///< 视口描述
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
# 变更记录:Surface 管理重构与容器文档完善
|
# 变更记录:Surface 管理重构、纹理资源与文档完善
|
||||||
|
|
||||||
**提交日期**: 2026-03-31
|
**提交日期**: 2026-04-01
|
||||||
**提交哈希**: `b284d81`
|
**提交哈希**: `b72fcf4`
|
||||||
**变更类型**: Bug修复 + 文档完善
|
**变更类型**: Bug修复 + 功能新增 + 文档完善
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 变更概述
|
## 变更概述
|
||||||
|
|
||||||
本次提交修复了 surface 管理中的资源重复释放问题,重构为使用 `utl::free_list` 容器,并为 `FreeList.h` 和 `Vector.h` 添加了完整的国际标准中文注释。
|
本次提交修复了 surface 管理中的资源重复释放问题,新增纹理资源类,并为容器和 D3D12 资源添加了完整的文档。
|
||||||
|
|
||||||
## 修改文件
|
## 修改文件
|
||||||
|
|
||||||
@@ -20,6 +20,14 @@
|
|||||||
| `D3D12Surface.h` | 添加移动语义,禁用拷贝,支持撕裂检测 |
|
| `D3D12Surface.h` | 添加移动语义,禁用拷贝,支持撕裂检测 |
|
||||||
| `D3D12Surface.cpp` | 完善交换链创建和资源释放逻辑 |
|
| `D3D12Surface.cpp` | 完善交换链创建和资源释放逻辑 |
|
||||||
|
|
||||||
|
### 新增功能
|
||||||
|
|
||||||
|
| 文件 | 变更说明 |
|
||||||
|
|------|----------|
|
||||||
|
| `D3D12Helpers.h` | 新增堆属性辅助结构 `d3dx::heap_properties` |
|
||||||
|
| `D3D12Resources.h` | 新增 `d3d12_texture_init_info`、`d3d12_texture`、`d3d12_render_texture` 类 |
|
||||||
|
| `D3D12Resource.cpp` | 实现纹理资源创建和 SRV 绑定 |
|
||||||
|
|
||||||
### 文档完善
|
### 文档完善
|
||||||
|
|
||||||
| 文件 | 变更说明 |
|
| 文件 | 变更说明 |
|
||||||
@@ -208,6 +216,181 @@ vec.erase_unordered(index); // 适用于顺序不重要的场景
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 交换链详解
|
||||||
|
|
||||||
|
### 核心职责
|
||||||
|
|
||||||
|
交换链连接窗口与渲染管线,管理一组后台缓冲区,并通过 `Present()` 实现缓冲区翻转,将绘制内容显示到窗口。
|
||||||
|
|
||||||
|
**交换链只负责**:
|
||||||
|
- 缓冲区的分配与翻转
|
||||||
|
|
||||||
|
**开发者需显式完成**:
|
||||||
|
- 绑定渲染目标(`OMSetRenderTargets`)
|
||||||
|
- GPU 同步(Fence)
|
||||||
|
- 状态转换(资源屏障)
|
||||||
|
|
||||||
|
### 标准使用流程
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 获取当前后台缓冲区(GetBuffer)
|
||||||
|
↓
|
||||||
|
2. 将其绑定为渲染目标(OMSetRenderTargets)
|
||||||
|
↓
|
||||||
|
3. 执行绘制命令(写入该缓冲区)
|
||||||
|
↓
|
||||||
|
4. 提交命令并同步(Fence)
|
||||||
|
↓
|
||||||
|
5. 调用 Present(翻转缓冲区,显示图像)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 职责边界
|
||||||
|
|
||||||
|
| 操作 | 负责方 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| 缓冲区分配 | 交换链 | 创建指定数量的后台缓冲区 |
|
||||||
|
| 缓冲区翻转 | 交换链 | `Present()` 切换前后缓冲区 |
|
||||||
|
| 渲染目标绑定 | 开发者 | `OMSetRenderTargets()` 绑定 RTV |
|
||||||
|
| GPU 同步 | 开发者 | 使用 Fence 确保 GPU 完成渲染 |
|
||||||
|
| 状态转换 | 开发者 | 资源屏障管理缓冲区状态 |
|
||||||
|
| 窗口大小调整 | 开发者 | 调用 `ResizeBuffers()` 重新分配 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SRV 创建与资源创建方式
|
||||||
|
|
||||||
|
### CreateShaderResourceView 参数说明
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void CreateShaderResourceView(
|
||||||
|
ID3D12Resource *pResource,
|
||||||
|
const D3D12_SHADER_RESOURCE_VIEW_DESC *pDesc,
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
| 参数 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `pResource` | 要创建 SRV 的 GPU 资源指针(必须是有效资源,不能为 nullptr) |
|
||||||
|
| `pDesc` | 视图描述符,指定格式、维度、Mip 级别范围等。为 `nullptr` 时使用资源默认属性 |
|
||||||
|
| `DestDescriptor` | SRV 描述符堆中 CPU 描述符句柄的位置 |
|
||||||
|
|
||||||
|
**关键点**:
|
||||||
|
- `pDesc` 为 `nullptr` 时,视图描述符默认使用资源本身的格式和全部子资源(空描述符初始化)
|
||||||
|
- 同一个资源可以创建多个不同的 SRV(不同格式、不同 Mip 切片)
|
||||||
|
|
||||||
|
### D3D12 资源创建函数对比
|
||||||
|
|
||||||
|
| 函数 | 堆类型 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `CreateCommittedResource` | 隐式堆 | D3D12 自动分配堆,资源直接映射。适用于大多数常规资源 |
|
||||||
|
| `CreatePlacedResource` | 显式堆 | 资源放置在用户创建的堆的特定偏移位置。用于精确控制内存布局 |
|
||||||
|
| `CreateReservedResource` | 预留资源 | 仅预留虚拟地址,不提交物理内存。用于稀疏资源,支持流式加载 |
|
||||||
|
|
||||||
|
**选择建议**:
|
||||||
|
- **Committed**:最常用,堆由系统隐式管理
|
||||||
|
- **Placed**:需要显式堆,资源放置于堆的指定偏移
|
||||||
|
- **Reserved**:仅预留虚拟地址,用于稀疏资源,实现内存的按需提交
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 纹理资源类
|
||||||
|
|
||||||
|
### d3d12_texture_init_info 结构
|
||||||
|
|
||||||
|
纹理初始化信息结构,支持三种资源创建方式:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct d3d12_texture_init_info
|
||||||
|
{
|
||||||
|
ID3D12Heap1* heap{nullptr}; // 显式堆(Placed Resource)
|
||||||
|
ID3D12Resource* resource{nullptr}; // 已有资源(直接使用)
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC* srv_desc{nullptr}; // SRV 描述(nullptr 使用默认)
|
||||||
|
D3D12_RESOURCE_DESC* desc{nullptr}; // 资源描述
|
||||||
|
D3D12_RESOURCE_ALLOCATION_INFO1 allocation_info{}; // 分配信息(偏移量)
|
||||||
|
D3D12_RESOURCE_STATES initial_state{}; // 初始状态
|
||||||
|
D3D12_CLEAR_VALUE clear_value{}; // 清除值(RTV/DSV)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### d3d12_texture 类
|
||||||
|
|
||||||
|
基础纹理类,封装资源创建和 SRV 绑定:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static u32 max_mips{ 14 };
|
||||||
|
|
||||||
|
explicit d3d12_texture(d3d12_texture_init_info info);
|
||||||
|
|
||||||
|
// 移动语义
|
||||||
|
d3d12_texture(d3d12_texture&& o);
|
||||||
|
d3d12_texture& operator=(d3d12_texture&& o);
|
||||||
|
|
||||||
|
// 禁用拷贝
|
||||||
|
DISABLE_COPY(d3d12_texture);
|
||||||
|
|
||||||
|
void release();
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
descriptor_handle srv() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ID3D12Resource* _resource{nullptr};
|
||||||
|
descriptor_handle _srv;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 资源创建逻辑
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
d3d12_texture::d3d12_texture(d3d12_texture_init_info info)
|
||||||
|
{
|
||||||
|
// 优先级 1:使用已有资源
|
||||||
|
if (info.resource) {
|
||||||
|
_resource = info.resource;
|
||||||
|
}
|
||||||
|
// 优先级 2:Placed Resource(显式堆)
|
||||||
|
else if (info.heap && info.desc) {
|
||||||
|
device->CreatePlacedResource(
|
||||||
|
info.heap,
|
||||||
|
info.allocation_info.Offset,
|
||||||
|
info.desc, ...);
|
||||||
|
}
|
||||||
|
// 优先级 3:Committed Resource(隐式堆)
|
||||||
|
else if (info.desc) {
|
||||||
|
device->CreateCommittedResource(
|
||||||
|
&d3dx::heap_properties.default_heap,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
info.desc, ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 SRV
|
||||||
|
_srv = core::srv_heap().allocate();
|
||||||
|
device->CreateShaderResourceView(_resource, info.srv_desc, _srv.cpu);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### d3dx::heap_properties 辅助结构
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace XEngine::graphics::d3d12::d3dx
|
||||||
|
{
|
||||||
|
constexpr struct {
|
||||||
|
D3D12_HEAP_PROPERTIES default_heap{
|
||||||
|
D3D12_HEAP_TYPE_DEFAULT, // GPU 可读写,CPU 不可访问
|
||||||
|
D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||||
|
D3D12_MEMORY_POOL_UNKNOWN,
|
||||||
|
0, // 单 GPU 系统
|
||||||
|
0
|
||||||
|
};
|
||||||
|
} heap_properties;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 后续工作
|
## 后续工作
|
||||||
|
|
||||||
- [ ] 实现深度模板视图
|
- [ ] 实现深度模板视图
|
||||||
|
|||||||
212
docs/changelogs/2026-04/20260401-render-texture-depth-buffer.md
Normal file
212
docs/changelogs/2026-04/20260401-render-texture-depth-buffer.md
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
# 变更记录:渲染目标纹理与深度缓冲区实现
|
||||||
|
|
||||||
|
**提交日期**: 2026-04-01
|
||||||
|
**提交哈希**: `57afd12`
|
||||||
|
**变更类型**: 功能新增
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 变更概述
|
||||||
|
|
||||||
|
本次提交实现了 `d3d12_render_texture`(渲染目标纹理)和 `d3d12_depth_buffer`(深度缓冲区)类,为纹理资源类添加了析构函数。
|
||||||
|
|
||||||
|
## 修改文件
|
||||||
|
|
||||||
|
| 文件 | 变更说明 |
|
||||||
|
|------|----------|
|
||||||
|
| `D3D12Resources.h` | 为纹理类添加析构函数,完善 `d3d12_render_texture` 和 `d3d12_depth_buffer` 类定义 |
|
||||||
|
| `D3D12Resource.cpp` | 实现 `d3d12_render_texture` 和 `d3d12_depth_buffer` 构造与释放逻辑 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## d3d12_render_texture 类
|
||||||
|
|
||||||
|
### 功能说明
|
||||||
|
|
||||||
|
渲染目标纹理类,支持多 Mip 级别的渲染目标视图(RTV):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_render_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
d3d12_render_texture() = default;
|
||||||
|
explicit d3d12_render_texture(d3d12_texture_init_info info);
|
||||||
|
~d3d12_render_texture() { release(); }
|
||||||
|
|
||||||
|
// 移动语义
|
||||||
|
d3d12_render_texture(d3d12_render_texture&& o);
|
||||||
|
d3d12_render_texture& operator=(d3d12_render_texture&& o);
|
||||||
|
|
||||||
|
// 禁用拷贝
|
||||||
|
DISABLE_COPY(d3d12_render_texture);
|
||||||
|
|
||||||
|
void release();
|
||||||
|
u32 mip_count() const;
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtv(u32 mip) const;
|
||||||
|
descriptor_handle srv() const;
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _rtv[d3d12_texture::max_mips]{}; // 每个 Mip 一个 RTV
|
||||||
|
u32 _mip_count{0};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构造流程
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
d3d12_render_texture::d3d12_render_texture(d3d12_texture_init_info info)
|
||||||
|
: _texture(info) // 先创建基础纹理
|
||||||
|
{
|
||||||
|
// 获取 Mip 级别数
|
||||||
|
_mip_count = resource()->GetDesc().MipLevels;
|
||||||
|
|
||||||
|
// 为每个 Mip 级别创建 RTV
|
||||||
|
D3D12_RENDER_TARGET_VIEW_DESC desc{};
|
||||||
|
desc.Format = info.desc->Format;
|
||||||
|
desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < _mip_count; ++i)
|
||||||
|
{
|
||||||
|
_rtv[i] = rtv_heap.allocate();
|
||||||
|
device->CreateRenderTargetView(resource(), &desc, _rtv[i].cpu);
|
||||||
|
++desc.Texture2D.MipSlice; // 下一个 Mip 切片
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用场景
|
||||||
|
|
||||||
|
- 离屏渲染(Render-to-Texture)
|
||||||
|
- 多级渐远纹理生成
|
||||||
|
- 后处理效果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## d3d12_depth_buffer 类
|
||||||
|
|
||||||
|
### 功能说明
|
||||||
|
|
||||||
|
深度缓冲区类,封装深度模板视图(DSV)和着色器资源视图(SRV):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_depth_buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
d3d12_depth_buffer() = default;
|
||||||
|
explicit d3d12_depth_buffer(d3d12_texture_init_info info);
|
||||||
|
~d3d12_depth_buffer() { release(); }
|
||||||
|
|
||||||
|
// 移动语义
|
||||||
|
d3d12_depth_buffer(d3d12_depth_buffer&& o);
|
||||||
|
d3d12_depth_buffer& operator=(d3d12_depth_buffer&& o);
|
||||||
|
|
||||||
|
// 禁用拷贝
|
||||||
|
DISABLE_COPY(d3d12_depth_buffer);
|
||||||
|
|
||||||
|
void release();
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE dsv() const;
|
||||||
|
descriptor_handle srv() const;
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _dsv{};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构造流程
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
d3d12_depth_buffer::d3d12_depth_buffer(d3d12_texture_init_info info)
|
||||||
|
{
|
||||||
|
// 深度缓冲区需要特殊处理格式
|
||||||
|
// DSV 使用 D32_FLOAT,SRV 使用 R32_FLOAT
|
||||||
|
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc{};
|
||||||
|
if(info.desc->Format == DXGI_FORMAT_D32_FLOAT)
|
||||||
|
{
|
||||||
|
info.desc->Format = DXGI_FORMAT_R32_TYPELESS; // 资源使用无类型格式
|
||||||
|
srv_desc.Format = DXGI_FORMAT_R32_FLOAT; // SRV 使用浮点格式
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建纹理和 SRV
|
||||||
|
info.srv_desc = &srv_desc;
|
||||||
|
_texture = d3d12_texture(info);
|
||||||
|
|
||||||
|
// 创建 DSV
|
||||||
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc{};
|
||||||
|
dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; // DSV 使用深度格式
|
||||||
|
dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
|
_dsv = dsv_heap.allocate();
|
||||||
|
device->CreateDepthStencilView(resource(), &dsv_desc, _dsv.cpu);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 格式转换说明
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 深度缓冲区格式处理 │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 用户指定格式:DXGI_FORMAT_D32_FLOAT │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 资源格式:DXGI_FORMAT_R32_TYPELESS(无类型) │
|
||||||
|
│ │ │
|
||||||
|
│ ┌──────────┴──────────┐ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ DSV 格式:D32_FLOAT SRV 格式:R32_FLOAT │
|
||||||
|
│ (深度测试用) (着色器采样用) │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**为什么要这样处理?**
|
||||||
|
|
||||||
|
- 深度缓冲区需要作为着色器资源被采样(如阴影映射、SSAO)
|
||||||
|
- DSV 格式(D32_FLOAT)不能直接用于 SRV
|
||||||
|
- 使用 TYPELESS 格式允许同一资源创建不同格式的视图
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 析构函数添加
|
||||||
|
|
||||||
|
为所有纹理类添加了析构函数,确保资源自动释放:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_texture {
|
||||||
|
public:
|
||||||
|
~d3d12_texture() { release(); }
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
class d3d12_render_texture {
|
||||||
|
public:
|
||||||
|
~d3d12_render_texture() { release(); }
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
class d3d12_depth_buffer {
|
||||||
|
public:
|
||||||
|
~d3d12_depth_buffer() { release(); }
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 后续工作
|
||||||
|
|
||||||
|
- [ ] 实现根签名和管线状态对象
|
||||||
|
- [ ] 渲染第一个三角形
|
||||||
|
- [ ] 实现常量缓冲区
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [D3D12学习Wiki](../wiki/D3D12学习Wiki.md)
|
||||||
@@ -489,12 +489,444 @@ void allocate() {
|
|||||||
} // 自动解锁
|
} // 自动解锁
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 7.9 着色器资源视图(SRV)
|
||||||
|
|
||||||
|
#### CreateShaderResourceView 函数
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void CreateShaderResourceView(
|
||||||
|
ID3D12Resource *pResource,
|
||||||
|
const D3D12_SHADER_RESOURCE_VIEW_DESC *pDesc,
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
| 参数 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `pResource` | 要创建 SRV 的 GPU 资源指针(必须是有效资源,不能为 nullptr) |
|
||||||
|
| `pDesc` | 视图描述符,指定格式、维度、Mip 级别范围等。为 `nullptr` 时使用资源默认属性 |
|
||||||
|
| `DestDescriptor` | SRV 描述符堆中 CPU 描述符句柄的位置 |
|
||||||
|
|
||||||
|
#### 空描述符初始化
|
||||||
|
|
||||||
|
当 `pDesc` 为 `nullptr` 时,视图描述符默认使用资源本身的格式和全部子资源:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 使用默认视图属性
|
||||||
|
device->CreateShaderResourceView(texture, nullptr, rtv_handle);
|
||||||
|
|
||||||
|
// 等价于显式指定完整描述
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC desc{};
|
||||||
|
desc.Format = texture->GetDesc().Format;
|
||||||
|
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
|
desc.Texture2D.MostDetailedMip = 0;
|
||||||
|
desc.Texture2D.MipLevels = texture->GetDesc().MipLevels;
|
||||||
|
device->CreateShaderResourceView(texture, &desc, rtv_handle);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 多视图支持
|
||||||
|
|
||||||
|
同一个资源可以创建多个不同的 SRV:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 原始格式视图
|
||||||
|
device->CreateShaderResourceView(texture, nullptr, srv_handle0);
|
||||||
|
|
||||||
|
// 不同格式视图(如 R32_FLOAT 作为 RGBA 视图)
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC rgba_desc{};
|
||||||
|
rgba_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
// ...
|
||||||
|
device->CreateShaderResourceView(texture, &rgba_desc, srv_handle1);
|
||||||
|
|
||||||
|
// 特定 Mip 切片视图
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC mip_desc{};
|
||||||
|
mip_desc.Texture2D.MostDetailedMip = 2;
|
||||||
|
mip_desc.Texture2D.MipLevels = 1;
|
||||||
|
// ...
|
||||||
|
device->CreateShaderResourceView(texture, &mip_desc, srv_handle2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.10 资源创建方式
|
||||||
|
|
||||||
|
D3D12 提供三种资源创建函数,对应不同的堆管理策略:
|
||||||
|
|
||||||
|
#### 函数对比
|
||||||
|
|
||||||
|
| 函数 | 堆类型 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `CreateCommittedResource` | 隐式堆 | D3D12 自动分配堆,资源直接映射。适用于大多数常规资源 |
|
||||||
|
| `CreatePlacedResource` | 显式堆 | 资源放置在用户创建的堆的特定偏移位置。用于精确控制内存布局 |
|
||||||
|
| `CreateReservedResource` | 预留资源 | 仅预留虚拟地址,不提交物理内存。用于稀疏资源,支持流式加载 |
|
||||||
|
|
||||||
|
#### CreateCommittedResource(最常用)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 系统自动管理堆,最简单的方式
|
||||||
|
D3D12_HEAP_PROPERTIES heap_props{
|
||||||
|
.Type = D3D12_HEAP_TYPE_DEFAULT
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC resource_desc{
|
||||||
|
.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
.Width = width,
|
||||||
|
.Height = height,
|
||||||
|
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
ID3D12Resource* texture;
|
||||||
|
device->CreateCommittedResource(
|
||||||
|
&heap_props,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&resource_desc,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&texture)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### CreatePlacedResource(精确控制)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 先创建堆
|
||||||
|
ID3D12Heap* heap;
|
||||||
|
D3D12_HEAP_DESC heap_desc{
|
||||||
|
.SizeInBytes = heap_size,
|
||||||
|
.Properties = { .Type = D3D12_HEAP_TYPE_DEFAULT },
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
device->CreateHeap(&heap_desc, IID_PPV_ARGS(&heap));
|
||||||
|
|
||||||
|
// 在堆的特定偏移放置资源
|
||||||
|
ID3D12Resource* texture;
|
||||||
|
device->CreatePlacedResource(
|
||||||
|
heap,
|
||||||
|
0, // 偏移量(必须满足对齐要求)
|
||||||
|
&resource_desc,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&texture)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**适用场景**:
|
||||||
|
- 资源复用(同一堆位置放置不同资源)
|
||||||
|
- 精确内存对齐
|
||||||
|
- 自定义内存管理
|
||||||
|
|
||||||
|
#### CreateReservedResource(稀疏资源)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 仅预留虚拟地址,不分配物理内存
|
||||||
|
ID3D12Resource* sparse_texture;
|
||||||
|
device->CreateReservedResource(
|
||||||
|
&resource_desc,
|
||||||
|
D3D12_RESOURCE_STATE_COMMON,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&sparse_texture)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 后续按需提交物理内存页面
|
||||||
|
// 使用 UpdateTileMappings 和 MakeResident
|
||||||
|
```
|
||||||
|
|
||||||
|
**适用场景**:
|
||||||
|
- 超大纹理(如地形纹理)按需加载
|
||||||
|
- 流式资源管理
|
||||||
|
- 虚拟纹理系统
|
||||||
|
|
||||||
|
#### 选择建议
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 资源创建方式选择 │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 常规纹理/缓冲区? │
|
||||||
|
│ │ │
|
||||||
|
│ ├── 是 ──► CreateCommittedResource │
|
||||||
|
│ │ (简单、自动管理) │
|
||||||
|
│ │ │
|
||||||
|
│ └── 否 ──► 需要精确内存控制? │
|
||||||
|
│ │ │
|
||||||
|
│ ├── 是 ──► CreatePlacedResource │
|
||||||
|
│ │ (资源复用、对齐控制) │
|
||||||
|
│ │ │
|
||||||
|
│ └── 否 ──► 超大资源按需加载? │
|
||||||
|
│ │ │
|
||||||
|
│ ├── 是 ──► │
|
||||||
|
│ │ CreateReservedResource│
|
||||||
|
│ │ (稀疏资源) │
|
||||||
|
│ │ │
|
||||||
|
│ └── 否 ──► 重新评估需求 │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.11 纹理资源类
|
||||||
|
|
||||||
|
#### d3d12_texture_init_info 结构
|
||||||
|
|
||||||
|
纹理初始化信息结构,统一管理三种资源创建方式的参数:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct d3d12_texture_init_info
|
||||||
|
{
|
||||||
|
ID3D12Heap1* heap{nullptr}; // 显式堆(Placed Resource)
|
||||||
|
ID3D12Resource* resource{nullptr}; // 已有资源(直接使用)
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC* srv_desc{nullptr}; // SRV 描述(nullptr 使用默认)
|
||||||
|
D3D12_RESOURCE_DESC* desc{nullptr}; // 资源描述
|
||||||
|
D3D12_RESOURCE_ALLOCATION_INFO1 allocation_info{}; // 分配信息(偏移量)
|
||||||
|
D3D12_RESOURCE_STATES initial_state{}; // 初始状态
|
||||||
|
D3D12_CLEAR_VALUE clear_value{}; // 清除值(RTV/DSV)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### d3d12_texture 类
|
||||||
|
|
||||||
|
基础纹理类,封装资源创建和 SRV 绑定:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static u32 max_mips{ 14 };
|
||||||
|
|
||||||
|
explicit d3d12_texture(d3d12_texture_init_info info);
|
||||||
|
|
||||||
|
// 移动语义
|
||||||
|
d3d12_texture(d3d12_texture&& o);
|
||||||
|
d3d12_texture& operator=(d3d12_texture&& o);
|
||||||
|
|
||||||
|
// 禁用拷贝
|
||||||
|
DISABLE_COPY(d3d12_texture);
|
||||||
|
|
||||||
|
void release();
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
descriptor_handle srv() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ID3D12Resource* _resource{nullptr};
|
||||||
|
descriptor_handle _srv;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 资源创建优先级
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 纹理资源创建优先级 │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ info.resource != nullptr ? │
|
||||||
|
│ │ │
|
||||||
|
│ ├── 是 ──► 直接使用已有资源 │
|
||||||
|
│ │ (适用于外部管理的资源) │
|
||||||
|
│ │ │
|
||||||
|
│ └── 否 ──► info.heap != nullptr ? │
|
||||||
|
│ │ │
|
||||||
|
│ ├── 是 ──► CreatePlacedResource │
|
||||||
|
│ │ (显式堆,精确控制) │
|
||||||
|
│ │ │
|
||||||
|
│ └── 否 ──► CreateCommittedResource │
|
||||||
|
│ (隐式堆,最常用) │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### d3dx::heap_properties 辅助结构
|
||||||
|
|
||||||
|
提供常用的堆属性配置:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace XEngine::graphics::d3d12::d3dx
|
||||||
|
{
|
||||||
|
constexpr struct {
|
||||||
|
D3D12_HEAP_PROPERTIES default_heap{
|
||||||
|
D3D12_HEAP_TYPE_DEFAULT, // GPU 可读写,CPU 不可访问
|
||||||
|
D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||||
|
D3D12_MEMORY_POOL_UNKNOWN,
|
||||||
|
0, // 单 GPU 系统
|
||||||
|
0
|
||||||
|
};
|
||||||
|
} heap_properties;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 使用示例
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 创建默认纹理(Committed Resource)
|
||||||
|
D3D12_RESOURCE_DESC desc{
|
||||||
|
.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
.Width = 1024,
|
||||||
|
.Height = 1024,
|
||||||
|
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
d3d12_texture_init_info info{
|
||||||
|
.desc = &desc,
|
||||||
|
.initial_state = D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
};
|
||||||
|
|
||||||
|
d3d12_texture texture{info};
|
||||||
|
|
||||||
|
// 获取资源用于后续操作
|
||||||
|
ID3D12Resource* resource = texture.resource();
|
||||||
|
descriptor_handle srv = texture.srv();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.12 渲染目标纹理(d3d12_render_texture)
|
||||||
|
|
||||||
|
#### 功能说明
|
||||||
|
|
||||||
|
渲染目标纹理类,支持多 Mip 级别的渲染目标视图(RTV),用于离屏渲染:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_render_texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit d3d12_render_texture(d3d12_texture_init_info info);
|
||||||
|
~d3d12_render_texture() { release(); }
|
||||||
|
|
||||||
|
void release();
|
||||||
|
u32 mip_count() const;
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtv(u32 mip) const; // 获取指定 Mip 的 RTV
|
||||||
|
descriptor_handle srv() const; // 获取 SRV
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _rtv[d3d12_texture::max_mips]{}; // 每个 Mip 一个 RTV
|
||||||
|
u32 _mip_count{0};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 多 Mip RTV 创建
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
d3d12_render_texture::d3d12_render_texture(d3d12_texture_init_info info)
|
||||||
|
: _texture(info)
|
||||||
|
{
|
||||||
|
_mip_count = resource()->GetDesc().MipLevels;
|
||||||
|
|
||||||
|
D3D12_RENDER_TARGET_VIEW_DESC desc{};
|
||||||
|
desc.Format = info.desc->Format;
|
||||||
|
desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
desc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < _mip_count; ++i)
|
||||||
|
{
|
||||||
|
_rtv[i] = rtv_heap.allocate();
|
||||||
|
device->CreateRenderTargetView(resource(), &desc, _rtv[i].cpu);
|
||||||
|
++desc.Texture2D.MipSlice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
| 场景 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 离屏渲染 | 将场景渲染到纹理而非屏幕 |
|
||||||
|
| 多级渐远纹理 | 生成 Mip Chain |
|
||||||
|
| 后处理 | 渲染结果作为后处理输入 |
|
||||||
|
|
||||||
|
### 7.13 深度缓冲区(d3d12_depth_buffer)
|
||||||
|
|
||||||
|
#### 功能说明
|
||||||
|
|
||||||
|
深度缓冲区类,同时提供深度模板视图(DSV)和着色器资源视图(SRV):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class d3d12_depth_buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit d3d12_depth_buffer(d3d12_texture_init_info info);
|
||||||
|
~d3d12_depth_buffer() { release(); }
|
||||||
|
|
||||||
|
void release();
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE dsv() const; // 深度模板视图
|
||||||
|
descriptor_handle srv() const; // 着色器资源视图
|
||||||
|
ID3D12Resource* resource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
d3d12_texture _texture{};
|
||||||
|
descriptor_handle _dsv{};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 格式转换处理
|
||||||
|
|
||||||
|
深度缓冲区需要特殊处理格式,以支持同时作为 DSV 和 SRV 使用:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 深度缓冲区格式处理 │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 用户指定格式:DXGI_FORMAT_D32_FLOAT │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 资源格式:DXGI_FORMAT_R32_TYPELESS(无类型) │
|
||||||
|
│ │ │
|
||||||
|
│ ┌──────────┴──────────┐ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ DSV 格式:D32_FLOAT SRV 格式:R32_FLOAT │
|
||||||
|
│ (深度测试用) (着色器采样用) │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 构造实现
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
d3d12_depth_buffer::d3d12_depth_buffer(d3d12_texture_init_info info)
|
||||||
|
{
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc{};
|
||||||
|
if(info.desc->Format == DXGI_FORMAT_D32_FLOAT)
|
||||||
|
{
|
||||||
|
info.desc->Format = DXGI_FORMAT_R32_TYPELESS;
|
||||||
|
srv_desc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srv_desc.Texture2D.MipLevels = 1;
|
||||||
|
|
||||||
|
info.srv_desc = &srv_desc;
|
||||||
|
_texture = d3d12_texture(info);
|
||||||
|
|
||||||
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc{};
|
||||||
|
dsv_desc.Format = DXGI_FORMAT_D32_FLOAT;
|
||||||
|
dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
|
_dsv = dsv_heap.allocate();
|
||||||
|
device->CreateDepthStencilView(resource(), &dsv_desc, _dsv.cpu);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
| 场景 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 深度测试 | 作为 DSV 用于深度缓冲 |
|
||||||
|
| 阴影映射 | 作为 SRV 采样深度值 |
|
||||||
|
| SSAO | 采样深度重建位置 |
|
||||||
|
|
||||||
## 8. 交换链(Swap Chain)
|
## 8. 交换链(Swap Chain)
|
||||||
|
|
||||||
### 8.1 什么是交换链?
|
### 8.1 什么是交换链?
|
||||||
|
|
||||||
交换链是 DXGI 提供的机制,用于管理前后缓冲区的交换,实现流畅的画面显示。
|
交换链是 DXGI 提供的机制,用于管理前后缓冲区的交换,实现流畅的画面显示。
|
||||||
|
|
||||||
|
**核心职责**:
|
||||||
|
|
||||||
|
- **连接窗口与渲染管线**:将渲染输出与显示器关联
|
||||||
|
- **管理后台缓冲区**:分配和维护一组用于渲染的缓冲区
|
||||||
|
- **缓冲区翻转**:通过 `Present()` 实现前后缓冲区交换,将绘制内容显示到窗口
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
│ 交换链工作原理 │
|
│ 交换链工作原理 │
|
||||||
@@ -520,7 +952,65 @@ void allocate() {
|
|||||||
└─────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.2 三重缓冲
|
### 8.2 交换链的职责边界
|
||||||
|
|
||||||
|
交换链**只负责**缓冲区的分配与翻转,以下操作需开发者显式完成:
|
||||||
|
|
||||||
|
| 操作 | 负责方 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| 缓冲区分配 | 交换链 | 创建指定数量的后台缓冲区 |
|
||||||
|
| 缓冲区翻转 | 交换链 | `Present()` 切换前后缓冲区 |
|
||||||
|
| 渲染目标绑定 | 开发者 | `OMSetRenderTargets()` 绑定 RTV |
|
||||||
|
| GPU 同步 | 开发者 | 使用 Fence 确保 GPU 完成渲染 |
|
||||||
|
| 状态转换 | 开发者 | 资源屏障管理缓冲区状态 |
|
||||||
|
| 窗口大小调整 | 开发者 | 调用 `ResizeBuffers()` 重新分配 |
|
||||||
|
|
||||||
|
### 8.3 标准渲染流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 交换链标准使用流程 │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 1. 获取当前后台缓冲区 │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ ID3D12Resource* buffer = swap_chain-> │ │
|
||||||
|
│ │ GetBuffer(current_index); │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 2. 创建并绑定渲染目标视图 │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ device->CreateRenderTargetView( │ │
|
||||||
|
│ │ buffer, nullptr, rtv_handle); │ │
|
||||||
|
│ │ cmd_list->OMSetRenderTargets( │ │
|
||||||
|
│ │ 1, &rtv_handle, nullptr); │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 3. 执行绘制命令(写入后台缓冲区) │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ cmd_list->ClearRenderTargetView(...); │ │
|
||||||
|
│ │ cmd_list->DrawInstanced(...); │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 4. 提交命令并同步 │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ cmd_queue->ExecuteCommandLists(...); │ │
|
||||||
|
│ │ // 等待 GPU 完成(Fence 同步) │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ 5. 呈现(翻转缓冲区) │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ swap_chain->Present(sync_interval, 0); │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.5 三重缓冲
|
||||||
|
|
||||||
项目使用三重缓冲(`frame_buffer_count = 3`):
|
项目使用三重缓冲(`frame_buffer_count = 3`):
|
||||||
|
|
||||||
@@ -530,7 +1020,7 @@ void allocate() {
|
|||||||
| **提高并行性** | CPU 可提前录制多帧命令 |
|
| **提高并行性** | CPU 可提前录制多帧命令 |
|
||||||
| **平滑帧率** | 缓冲区平滑帧时间波动 |
|
| **平滑帧率** | 缓冲区平滑帧时间波动 |
|
||||||
|
|
||||||
### 8.3 d3d12_surface 类
|
### 8.6 d3d12_surface 类
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class d3d12_surface
|
class d3d12_surface
|
||||||
@@ -559,7 +1049,7 @@ private:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.4 交换链创建流程
|
### 8.7 交换链创建流程
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void create_swap_chain(...)
|
void create_swap_chain(...)
|
||||||
@@ -587,7 +1077,7 @@ void create_swap_chain(...)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.5 视口与裁剪矩形
|
### 8.8 视口与裁剪矩形
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// 视口:定义光栅化区域
|
// 视口:定义光栅化区域
|
||||||
@@ -604,7 +1094,7 @@ D3D12_VIEWPORT viewport{
|
|||||||
D3D12_RECT scissor_rect{0, 0, width, height};
|
D3D12_RECT scissor_rect{0, 0, width, height};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.6 Surface 管理与 free_list
|
### 8.9 Surface 管理与 free_list
|
||||||
|
|
||||||
#### 问题:Vector 扩容导致的资源重复释放
|
#### 问题:Vector 扩容导致的资源重复释放
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user