feat(d3d12): 新增纹理资源类,修复 Surface 重复释放问题
核心变更: - 新增 d3d12_texture 和 d3d12_render_texture 类 - 新增 d3d12_texture_init_info 结构,支持三种资源创建方式 - 新增 D3D12Helpers.h,提供堆属性辅助结构 - 改用 utl::free_list 管理 surface,解决重复释放问题 - 为 d3d12_surface 添加移动语义,支持撕裂检测 文档完善: - 为 FreeList.h 和 Vector.h 添加完整 Doxygen 中文注释 - 更新 D3D12 学习 Wiki,添加 SRV、资源创建方式、纹理资源类章节 - 新增变更记录文档
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
#include "D3D12Core.h"
|
||||
#include "D3D12CommonHeader.h"
|
||||
#include "D3D12Resources.h"
|
||||
#include "D3D12Surface.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
namespace XEngine::graphics::d3d12::core {
|
||||
namespace {
|
||||
using suface_collection = utl::free_list<d3d12_surface>;
|
||||
|
||||
/**
|
||||
* @brief D3D12命令管理类设计说明
|
||||
* @details 本类采用RAII设计模式封装Direct3D 12的命令队列和命令列表,提供类型安全的GPU命令提交机制
|
||||
@@ -249,6 +251,9 @@ IDXGIFactory7* dxgi_factory{ nullptr };
|
||||
*/
|
||||
d3d12_command gfx_command;
|
||||
|
||||
suface_collection surfaces;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -531,25 +536,6 @@ shutdown()
|
||||
release(main_device);
|
||||
}
|
||||
|
||||
void
|
||||
render()
|
||||
{
|
||||
// 等待GPU完成命令列表,并重置命令分配器和命令列表
|
||||
gfx_command.begin_frame();
|
||||
ID3D12GraphicsCommandList6* cmd_list{ gfx_command.command_list() };
|
||||
|
||||
const u32 frame_index{ current_frame_index() };
|
||||
if(deferred_release_flag[frame_index])
|
||||
{
|
||||
process_deferred_release(frame_index);
|
||||
}
|
||||
// 记录命令
|
||||
//
|
||||
// 完成命令记录,立即提交命令列表到命令队列执行
|
||||
// 为下一帧标记并增加围栏值
|
||||
gfx_command.end_frame();
|
||||
}
|
||||
|
||||
ID3D12Device *const
|
||||
device()
|
||||
{
|
||||
@@ -583,5 +569,65 @@ set_deferred_release_flag()
|
||||
deferred_release_flag[current_frame_index()] = 1;
|
||||
}
|
||||
|
||||
#pragma region surface
|
||||
|
||||
surface
|
||||
create_surface(platform::window window)
|
||||
{
|
||||
surface_id id{ surfaces.add(window) };
|
||||
surfaces[id].create_swap_chain(dxgi_factory,gfx_command.command_queue(),render_target_format);
|
||||
return surface{id};
|
||||
}
|
||||
void
|
||||
remove_surface(surface_id id)
|
||||
{
|
||||
gfx_command.flush();
|
||||
surfaces.remove(id);
|
||||
}
|
||||
void
|
||||
resize_surface(surface_id id, u32 width, u32 height)
|
||||
{
|
||||
gfx_command.flush();
|
||||
surfaces[id].resize();
|
||||
}
|
||||
u32
|
||||
surface_width(surface_id id)
|
||||
{
|
||||
return surfaces[id].width();
|
||||
}
|
||||
u32
|
||||
surface_height(surface_id id)
|
||||
{
|
||||
return surfaces[id].height();
|
||||
}
|
||||
void
|
||||
render_surface(surface_id id)
|
||||
{
|
||||
// 等待GPU完成命令列表,并重置命令分配器和命令列表
|
||||
gfx_command.begin_frame();
|
||||
ID3D12GraphicsCommandList6* cmd_list{ gfx_command.command_list() };
|
||||
|
||||
const u32 frame_index{ current_frame_index() };
|
||||
if(deferred_release_flag[frame_index])
|
||||
{
|
||||
process_deferred_release(frame_index);
|
||||
}
|
||||
|
||||
// 呈现交换链
|
||||
surfaces[id].present();
|
||||
|
||||
|
||||
// 记录命令
|
||||
//
|
||||
// 完成命令记录,立即提交命令列表到命令队列执行
|
||||
// 为下一帧标记并增加围栏值
|
||||
gfx_command.end_frame();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
}// namespace XEngine::graphics::d3d12::core
|
||||
|
||||
@@ -22,12 +22,6 @@ bool initialize();
|
||||
* @details 调用 Direct3D 12 设备的关闭函数,释放所有资源
|
||||
*/
|
||||
void shutdown();
|
||||
/**
|
||||
* @brief 渲染 Direct3D 12 核心功能
|
||||
* @details 调用 Direct3D 12 设备的渲染函数,渲染当前渲染表面
|
||||
*/
|
||||
void render();
|
||||
|
||||
|
||||
/**
|
||||
* @brief 立即释放 DirectX COM 对象并将指针置空
|
||||
@@ -104,6 +98,12 @@ DXGI_FORMAT default_render_target_format();
|
||||
*/
|
||||
void set_deferred_release_flag();
|
||||
|
||||
surface create_surface(platform::window window);
|
||||
void remove_surface(surface_id id);
|
||||
void resize_surface(surface_id id, u32 width, u32 height);
|
||||
u32 surface_width(surface_id id);
|
||||
u32 surface_height(surface_id id);
|
||||
void render_surface(surface_id id);
|
||||
|
||||
|
||||
}// namespace XEngine::graphics::d3d12::core
|
||||
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;
|
||||
}
|
||||
@@ -7,7 +7,14 @@ void get_platform_interface(platform_interface& pi)
|
||||
{
|
||||
pi.initialize = core::initialize;
|
||||
pi.shutdown = core::shutdown;
|
||||
pi.render = core::render;
|
||||
|
||||
|
||||
pi.surface.create = core::create_surface;
|
||||
pi.surface.remove = core::remove_surface;
|
||||
pi.surface.resize = core::resize_surface;
|
||||
pi.surface.width = core::surface_width;
|
||||
pi.surface.height = core::surface_height;
|
||||
pi.surface.render = core::render_surface;
|
||||
}
|
||||
}// namespace XEngine::graphics::d3d12
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "D3D12Resources.h"
|
||||
#include "D3D12Core.h"
|
||||
#include "D3D12Helpers.h"
|
||||
|
||||
namespace XEngine::graphics::d3d12{
|
||||
//////////// DESCRIPTOR HEAP ////////////
|
||||
|
||||
|
||||
// 该类将被多个线程并发访问:资源创建(如纹理)与资源销毁/释放可能发生在不同线程,
|
||||
// 因此需要同步机制保护内部数据结构
|
||||
bool
|
||||
@@ -134,4 +137,63 @@ descriptor_heap::free(descriptor_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 ////////////
|
||||
|
||||
|
||||
} //XEngine::graphics::d3d12
|
||||
@@ -417,4 +417,64 @@ private:
|
||||
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);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace XEngine::graphics::d3d12
|
||||
|
||||
@@ -2,113 +2,137 @@
|
||||
#include "D3D12Core.h"
|
||||
|
||||
|
||||
namespace XEngine::graphics::d3d12 {
|
||||
namespace{
|
||||
namespace XEngine::graphics::d3d12 {
|
||||
namespace {
|
||||
constexpr DXGI_FORMAT
|
||||
to_non_srgb(DXGI_FORMAT format)
|
||||
{
|
||||
if(format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
return format;
|
||||
if (format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
return format;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
d3d12_surface::create_swap_chain(IDXGIFactory7* factory, ID3D12CommandQueue* cmd_queue, DXGI_FORMAT format)
|
||||
{
|
||||
assert(!factory && cmd_queue);
|
||||
assert(factory && cmd_queue);
|
||||
|
||||
// 应为可以多次调用,所以需要先释放旧的 swap chain
|
||||
release();
|
||||
// 应为可以多次调用,所以需要先释放旧的 swap chain
|
||||
release();
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 desc{};
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Alpha通道模式(窗口透明度相关)
|
||||
desc.BufferCount = frame_buffer_count; // 后台缓冲区数量(用于双缓冲/多缓冲)
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 缓冲区用途(作为渲染目标输出)
|
||||
desc.Flags = 0; // 交换链标志位(无)
|
||||
desc.Format = to_non_srgb(format); // 像素格式(转换为非SRGB格式)
|
||||
desc.Height = _window.height(); // 交换链高度(与窗口高度一致)
|
||||
desc.Width = _window.width(); // 交换链宽度(与窗口宽度一致)
|
||||
desc.SampleDesc.Count = 1; // 多重采样数量(1表示禁用MSAA)
|
||||
desc.SampleDesc.Quality = 0; // 多重采样质量等级(0表示禁用)
|
||||
desc.Scaling = DXGI_SCALING_STRETCH; // 缓冲区缩放模式(窗口大小变化时的处理方式)
|
||||
desc.Stereo = false; // 立体显示模式(3D显示)
|
||||
if (SUCCEEDED(factory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &_allow_tearing, sizeof(u32))) && _allow_tearing)
|
||||
{
|
||||
_present_flags = DXGI_PRESENT_ALLOW_TEARING;
|
||||
}
|
||||
|
||||
IDXGISwapChain1* swap_chain;
|
||||
HWND hwnd {(HWND)_window.handle()};
|
||||
// 为窗口创建交换链,指定交换链描述结构体
|
||||
DXCall(factory->CreateSwapChainForHwnd(cmd_queue, hwnd, &desc, nullptr, nullptr, &swap_chain));
|
||||
// 控制 DXGI 如何响应特定的系统按键,阻止 DXGI 响应 Alt+Enter 按键序列,由应用程序手动处理全屏切换逻辑。
|
||||
DXCall(factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER));
|
||||
// 将局部变量 swap_chain 创建的交换链对象“转移”给类成员 _swap_chain 来长期持有。
|
||||
// 免了直接赋值(_swap_chain = swap_chain)可能导致的引用计数问题:直接赋值不增加
|
||||
// 计数,后续释放 swap_chain 会使对象计数归零而被销毁,_swap_chain 就会变成悬空指针。
|
||||
DXCall(swap_chain->QueryInterface(IID_PPV_ARGS(&_swap_chain)));
|
||||
core::release(swap_chain);
|
||||
DXGI_SWAP_CHAIN_DESC1 desc{};
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Alpha通道模式(窗口透明度相关)
|
||||
desc.BufferCount = buffer_count; // 后台缓冲区数量(用于双缓冲/多缓冲)
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 缓冲区用途(作为渲染目标输出)
|
||||
desc.Flags = _allow_tearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; // 交换链标志位(无)
|
||||
desc.Format = to_non_srgb(format); // 像素格式(转换为非SRGB格式)
|
||||
desc.Height = _window.height(); // 交换链高度(与窗口高度一致)
|
||||
desc.Width = _window.width(); // 交换链宽度(与窗口宽度一致)
|
||||
desc.SampleDesc.Count = 1; // 多重采样数量(1表示禁用MSAA)
|
||||
desc.SampleDesc.Quality = 0; // 多重采样质量等级(0表示禁用)
|
||||
desc.Scaling = DXGI_SCALING_STRETCH; // 缓冲区缩放模式(窗口大小变化时的处理方式)
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // 交换链效果(翻转并丢弃旧缓冲区)
|
||||
desc.Stereo = false; // 立体显示模式(3D显示)
|
||||
|
||||
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
||||
IDXGISwapChain1* swap_chain;
|
||||
HWND hwnd{ (HWND)_window.handle() };
|
||||
// 为窗口创建交换链,指定交换链描述结构体
|
||||
DXCall(factory->CreateSwapChainForHwnd(cmd_queue, hwnd, &desc, nullptr, nullptr, &swap_chain));
|
||||
// 控制 DXGI 如何响应特定的系统按键,阻止 DXGI 响应 Alt+Enter 按键序列,由应用程序手动处理全屏切换逻辑。
|
||||
DXCall(factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER));
|
||||
// 将局部变量 swap_chain 创建的交换链对象“转移”给类成员 _swap_chain 来长期持有。
|
||||
// 免了直接赋值(_swap_chain = swap_chain)可能导致的引用计数问题:直接赋值不增加
|
||||
// 计数,后续释放 swap_chain 会使对象计数归零而被销毁,_swap_chain 就会变成悬空指针。
|
||||
DXCall(swap_chain->QueryInterface(IID_PPV_ARGS(&_swap_chain)));
|
||||
core::release(swap_chain);
|
||||
|
||||
for(u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
_render_target_data[i].rtv = core::rtv_heap().allocate();
|
||||
}
|
||||
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
||||
|
||||
finalize();
|
||||
for (u32 i = 0; i < buffer_count; ++i)
|
||||
{
|
||||
_render_target_data[i].rtv = core::rtv_heap().allocate();
|
||||
}
|
||||
|
||||
finalize();
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_surface::present() const
|
||||
{
|
||||
assert(_swap_chain);
|
||||
// 设置是否使用垂直同步
|
||||
// 0 表示不使用垂直同步,1 表示使用垂直同步
|
||||
// 第二个参数设置有无特殊行为,0 表示无特殊行为
|
||||
DXCall(_swap_chain->Present(0, 0));
|
||||
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
||||
assert(_swap_chain);
|
||||
// 设置是否使用垂直同步
|
||||
// 0 表示不使用垂直同步,1 表示使用垂直同步
|
||||
// 第二个参数设置有无特殊行为,0 表示无特殊行为
|
||||
DXCall(_swap_chain->Present(0, _present_flags));
|
||||
_current_bb_index = _swap_chain->GetCurrentBackBufferIndex();
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_surface::finalize()
|
||||
{
|
||||
// 为每个缓冲区创建渲染目标视图
|
||||
for(u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
render_target_data& data{ _render_target_data[i] };
|
||||
assert(!data.resource);
|
||||
DXCall(_swap_chain->GetBuffer(i, IID_PPV_ARGS(&data.resource)));
|
||||
D3D12_RENDER_TARGET_VIEW_DESC desc{};
|
||||
desc.Format = core::default_render_target_format();
|
||||
desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
core::device()->CreateRenderTargetView(data.resource, &desc, data.rtv.cpu);
|
||||
}
|
||||
// 为每个缓冲区创建渲染目标视图
|
||||
for (u32 i = 0; i < buffer_count; ++i)
|
||||
{
|
||||
render_target_data& data{ _render_target_data[i] };
|
||||
assert(!data.resource);
|
||||
DXCall(_swap_chain->GetBuffer(i, IID_PPV_ARGS(&data.resource)));
|
||||
D3D12_RENDER_TARGET_VIEW_DESC desc{};
|
||||
desc.Format = core::default_render_target_format();
|
||||
desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
core::device()->CreateRenderTargetView(data.resource, &desc, data.rtv.cpu);
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC desc{};
|
||||
DXCall(_swap_chain->GetDesc(&desc));
|
||||
const u32 width{ desc.BufferDesc.Width };
|
||||
const u32 height{ desc.BufferDesc.Height };
|
||||
assert(_window.width() == width && _window.height() == height);
|
||||
DXGI_SWAP_CHAIN_DESC desc{};
|
||||
DXCall(_swap_chain->GetDesc(&desc));
|
||||
const u32 width{ desc.BufferDesc.Width };
|
||||
const u32 height{ desc.BufferDesc.Height };
|
||||
assert(_window.width() == width && _window.height() == height);
|
||||
|
||||
|
||||
_viewport.TopLeftX = 0.0f;
|
||||
_viewport.TopLeftY = 0.0f;
|
||||
_viewport.Width = (float)width;
|
||||
_viewport.Height = (float)height;
|
||||
_viewport.MaxDepth = 1.0f;
|
||||
_viewport.MinDepth = 0.0f;
|
||||
_viewport.TopLeftX = 0.0f;
|
||||
_viewport.TopLeftY = 0.0f;
|
||||
_viewport.Width = (float)width;
|
||||
_viewport.Height = (float)height;
|
||||
_viewport.MaxDepth = 1.0f;
|
||||
_viewport.MinDepth = 0.0f;
|
||||
|
||||
_scissor_rect = {0, 0, (s32)width, (s32)height};
|
||||
_scissor_rect = { 0, 0, (s32)width, (s32)height };
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_surface::release()
|
||||
{
|
||||
for(u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
render_target_data& data{ _render_target_data[i] };
|
||||
core::release(data.resource);
|
||||
core::rtv_heap().free(data.rtv);
|
||||
}
|
||||
for (u32 i = 0; i < buffer_count; ++i)
|
||||
{
|
||||
render_target_data& data{ _render_target_data[i] };
|
||||
core::release(data.resource);
|
||||
core::rtv_heap().free(data.rtv);
|
||||
|
||||
core::release(_swap_chain);
|
||||
}
|
||||
core::release(_swap_chain);
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_surface::resize()
|
||||
{
|
||||
}
|
||||
|
||||
u32
|
||||
d3d12_surface::width()
|
||||
{
|
||||
return _window.width();
|
||||
}
|
||||
|
||||
u32
|
||||
d3d12_surface::height()
|
||||
{
|
||||
return _window.height();
|
||||
}
|
||||
|
||||
|
||||
} // namespace XEngine::graphics::d3d12
|
||||
@@ -69,7 +69,61 @@ public:
|
||||
* @details
|
||||
* 调用 release() 清理交换链和渲染目标资源。
|
||||
*/
|
||||
~d3d12_surface(){release();}
|
||||
~d3d12_surface(){ release(); }
|
||||
|
||||
|
||||
constexpr static u32 buffer_count{ 3 };
|
||||
|
||||
#if USE_STL_VECTOR
|
||||
DISABLE_COPY(d3d12_surface)
|
||||
|
||||
/**
|
||||
* @brief 移动构造函数
|
||||
*
|
||||
* @param o 要移动的源对象
|
||||
*
|
||||
* @details
|
||||
* 转移所有资源所有权,将源对象置为空状态。
|
||||
* 用于 vector 扩容时安全转移资源。
|
||||
*/
|
||||
constexpr d3d12_surface(d3d12_surface&& o) noexcept
|
||||
: _swap_chain{o._swap_chain}, _window{o._window}, _current_bb_index{o._current_bb_index}
|
||||
, _viewport{o._viewport}, _scissor_rect{o._scissor_rect}
|
||||
, _allow_tearing{o._allow_tearing}, _present_flags{o._present_flags}
|
||||
{
|
||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
_render_target_data[i].resource = o._render_target_data[i].resource;
|
||||
_render_target_data[i].rtv = o._render_target_data[i].rtv;
|
||||
}
|
||||
|
||||
o.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移动赋值运算符
|
||||
*
|
||||
* @param o 要移动的源对象
|
||||
* @return 当前对象引用
|
||||
*
|
||||
* @details
|
||||
* 先释放当前资源,再转移所有权。
|
||||
*/
|
||||
constexpr d3d12_surface& operator=(d3d12_surface&& o) noexcept
|
||||
{
|
||||
assert(this != &o);
|
||||
if (this != &o)
|
||||
{
|
||||
release();
|
||||
move(o);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
DISABLE_COPY_AND_MOVE(d3d12_surface);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief 创建交换链和渲染目标视图
|
||||
@@ -167,6 +221,43 @@ public:
|
||||
constexpr const D3D12_RECT& scissor_rect() const {return _scissor_rect;}
|
||||
|
||||
private:
|
||||
|
||||
#if USE_STL_VECTOR
|
||||
constexpr void move(d3d12_surface& o)
|
||||
{
|
||||
_swap_chain = o._swap_chain;
|
||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
_render_target_data[i] = o._render_target_data[i];
|
||||
}
|
||||
_window = o._window;
|
||||
_current_bb_index = o._current_bb_index;
|
||||
_viewport = o._viewport;
|
||||
_scissor_rect = o._scissor_rect;
|
||||
_allow_tearing = o._allow_tearing;
|
||||
_present_flags = o._present_flags;
|
||||
|
||||
o.reset();
|
||||
}
|
||||
|
||||
|
||||
constexpr void reset()
|
||||
{
|
||||
_swap_chain = nullptr;
|
||||
for (u32 i = 0; i < frame_buffer_count; ++i)
|
||||
{
|
||||
_render_target_data[i] = {};
|
||||
}
|
||||
_window = {};
|
||||
_current_bb_index = 0;
|
||||
_viewport = {};
|
||||
_scissor_rect = {};
|
||||
_allow_tearing = 0;
|
||||
_present_flags = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 释放所有资源
|
||||
*
|
||||
@@ -200,11 +291,13 @@ private:
|
||||
};
|
||||
|
||||
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{}; ///< 关联的平台窗口
|
||||
mutable u32 _current_bb_index{0}; ///< 当前后台缓冲区索引
|
||||
D3D12_VIEWPORT _viewport{}; ///< 视口描述
|
||||
D3D12_RECT _scissor_rect{}; ///< 裁剪矩形
|
||||
u32 _allow_tearing{ 0 }; ///< 是否允许撕裂
|
||||
u32 _present_flags{ 0 }; ///< 呈现标志位
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user