feat(d3d12): 完善描述符堆延迟释放机制与FreeList栈式索引管理
- 添加完整的中文Doxygen注释文档 - 实现process_deferred_release()延迟释放处理 - 添加deferred_release模板函数和current_frame_index() - 实现延迟释放队列和帧索引管理 - 详细说明FreeList栈式索引分配/释放算法 - 更新D3D12学习Wiki,添加延迟释放机制章节
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "D3D12Resources.h"
|
||||
#include "D3D12Core.h"
|
||||
|
||||
namespace XEngine::graphics::d3d12{
|
||||
namespace XEngine::graphics::d3d12::core{
|
||||
//////////// DESCRIPTOR HEAP ////////////
|
||||
// 该类将被多个线程并发访问:资源创建(如纹理)与资源销毁/释放可能发生在不同线程,
|
||||
// 因此需要同步机制保护内部数据结构
|
||||
@@ -45,7 +45,8 @@ descriptor_heap::initialize(u32 capacity, bool is_shader_visible)
|
||||
_size = 0;
|
||||
|
||||
for(u32 i = 0; i < capacity; ++i) _free_handles[i] = i;
|
||||
|
||||
DEBUG_OP(for(u32 i{0}; i<frame_buffer_count;++i) assert(_deferred_free_indices[i].empty()));
|
||||
|
||||
_descriptor_size = device->GetDescriptorHandleIncrementSize(_type);
|
||||
_cpu_start = _heap->GetCPUDescriptorHandleForHeapStart();
|
||||
_gpu_start = is_shader_visible
|
||||
@@ -59,7 +60,39 @@ descriptor_heap::initialize(u32 capacity, bool is_shader_visible)
|
||||
void
|
||||
descriptor_heap::release()
|
||||
{
|
||||
assert(!_size);
|
||||
core::deferred_release(_heap);
|
||||
}
|
||||
|
||||
// 处理延迟释放
|
||||
// 注意这里的free_handles对应的是一整块连续的内存,而不是对应的描述符句柄的索引index
|
||||
// 描述符自生是记录了自己的地址(通过简单的计算可以得出偏移和索引)
|
||||
// 所以释放后,只需要指向释放出来的索引index即可,这样下次新增时即可以
|
||||
// 放在对应的空闲区域.
|
||||
// 这一切都是应为freelist和内存是一对一对应的关系
|
||||
// 延迟释放机制确保GPU完成使用后才回收描述符,避免GPU仍在访问时重用
|
||||
// 使用双缓冲/多帧缓冲机制,当前帧释放的描述符会在若干帧后安全回收
|
||||
// _free_handles作为空闲索引栈,_size指向栈顶,回收的索引压入栈中供后续分配使用
|
||||
void
|
||||
descriptor_heap::process_deferred_release(u32 frame_index)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
assert(frame_index < frame_buffer_count);
|
||||
|
||||
utl::vector<u32>& indices { _deferred_free_indices[frame_index] };
|
||||
if(!indices.empty())
|
||||
{
|
||||
for(auto index : indices)
|
||||
{
|
||||
--_size;
|
||||
_free_handles[_size] = index;
|
||||
}
|
||||
indices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
descriptor_handle
|
||||
descriptor_heap::allocate()
|
||||
{
|
||||
@@ -95,6 +128,9 @@ descriptor_heap::free(descriptor_handle handle)
|
||||
const u32 index{ (u32)(handle.cpu.ptr - _cpu_start.ptr) / _descriptor_size };
|
||||
assert(handle.index == index);
|
||||
|
||||
const u32 frame_index{ core::current_frame_index() };
|
||||
_deferred_free_indices[frame_index].push_back(index);
|
||||
core::set_deferred_release_flag();
|
||||
handle = {};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user