VideoBackends: add support to allow rendering to multiple output textures

This commit is contained in:
iwubcode
2023-05-28 20:59:02 -05:00
parent 252d3f353a
commit 834f8f7b5c
43 changed files with 713 additions and 327 deletions

View File

@ -59,11 +59,13 @@ std::unique_ptr<AbstractStagingTexture> Gfx::CreateStagingTexture(StagingTexture
return DXStagingTexture::Create(type, config);
}
std::unique_ptr<AbstractFramebuffer> Gfx::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment)
std::unique_ptr<AbstractFramebuffer>
Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments)
{
return DXFramebuffer::Create(static_cast<DXTexture*>(color_attachment),
static_cast<DXTexture*>(depth_attachment));
static_cast<DXTexture*>(depth_attachment),
std::move(additional_color_attachments));
}
std::unique_ptr<AbstractShader>
@ -109,20 +111,18 @@ void Gfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_enab
if (fast_color_clear || z_enable)
{
const D3D12_RECT d3d_clear_rc{target_rc.left, target_rc.top, target_rc.right, target_rc.bottom};
auto* d3d_frame_buffer = static_cast<const DXFramebuffer*>(m_current_framebuffer);
if (fast_color_clear)
{
static_cast<DXTexture*>(m_current_framebuffer->GetColorAttachment())
->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
d3d_frame_buffer->TransitionRenderTargets();
const std::array<float, 4> clear_color = {
{static_cast<float>((color >> 16) & 0xFF) / 255.0f,
static_cast<float>((color >> 8) & 0xFF) / 255.0f,
static_cast<float>((color >> 0) & 0xFF) / 255.0f,
static_cast<float>((color >> 24) & 0xFF) / 255.0f}};
g_dx_context->GetCommandList()->ClearRenderTargetView(
static_cast<const DXFramebuffer*>(m_current_framebuffer)->GetRTVDescriptor().cpu_handle,
clear_color.data(), 1, &d3d_clear_rc);
d3d_frame_buffer->ClearRenderTargets(clear_color, &d3d_clear_rc);
color_enable = false;
alpha_enable = false;
}
@ -134,9 +134,7 @@ void Gfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_enab
// D3D does not support reversed depth ranges.
const float clear_depth = 1.0f - static_cast<float>(z & 0xFFFFFF) / 16777216.0f;
g_dx_context->GetCommandList()->ClearDepthStencilView(
static_cast<const DXFramebuffer*>(m_current_framebuffer)->GetDSVDescriptor().cpu_handle,
D3D12_CLEAR_FLAG_DEPTH, clear_depth, 0, 1, &d3d_clear_rc);
d3d_frame_buffer->ClearDepth(clear_depth, &d3d_clear_rc);
z_enable = false;
}
}
@ -180,11 +178,7 @@ void Gfx::SetPipeline(const AbstractPipeline* pipeline)
void Gfx::BindFramebuffer(DXFramebuffer* fb)
{
if (fb->HasColorBuffer())
{
static_cast<DXTexture*>(fb->GetColorAttachment())
->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
}
fb->TransitionRenderTargets();
if (fb->HasDepthBuffer())
{
static_cast<DXTexture*>(fb->GetDepthAttachment())
@ -212,19 +206,14 @@ void Gfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
{
SetFramebuffer(framebuffer);
static const D3D12_DISCARD_REGION dr = {0, nullptr, 0, 1};
if (framebuffer->HasColorBuffer())
DXFramebuffer* d3d_frame_buffer = static_cast<DXFramebuffer*>(framebuffer);
d3d_frame_buffer->TransitionRenderTargets();
if (d3d_frame_buffer->HasDepthBuffer())
{
DXTexture* color_attachment = static_cast<DXTexture*>(framebuffer->GetColorAttachment());
color_attachment->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
g_dx_context->GetCommandList()->DiscardResource(color_attachment->GetResource(), &dr);
}
if (framebuffer->HasDepthBuffer())
{
DXTexture* depth_attachment = static_cast<DXTexture*>(framebuffer->GetDepthAttachment());
depth_attachment->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE);
g_dx_context->GetCommandList()->DiscardResource(depth_attachment->GetResource(), &dr);
static_cast<DXTexture*>(d3d_frame_buffer->GetDepthAttachment())
->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE);
}
d3d_frame_buffer->Unbind();
}
void Gfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value,
@ -233,17 +222,8 @@ void Gfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearCo
DXFramebuffer* dxfb = static_cast<DXFramebuffer*>(framebuffer);
BindFramebuffer(dxfb);
static const D3D12_DISCARD_REGION dr = {0, nullptr, 0, 1};
if (framebuffer->HasColorBuffer())
{
g_dx_context->GetCommandList()->ClearRenderTargetView(dxfb->GetRTVDescriptor().cpu_handle,
color_value.data(), 0, nullptr);
}
if (framebuffer->HasDepthBuffer())
{
g_dx_context->GetCommandList()->ClearDepthStencilView(
dxfb->GetDSVDescriptor().cpu_handle, D3D12_CLEAR_FLAG_DEPTH, depth_value, 0, 0, nullptr);
}
dxfb->ClearRenderTargets(color_value, nullptr);
dxfb->ClearDepth(depth_value, nullptr);
}
void Gfx::SetScissorRect(const MathUtil::Rectangle<int>& rc)

View File

@ -32,7 +32,8 @@ public:
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, std::string_view source,
std::string_view name) override;

View File

@ -42,7 +42,7 @@ bool SwapChain::CreateSwapChainBuffers()
if (!buffer.texture)
return false;
buffer.framebuffer = DXFramebuffer::Create(buffer.texture.get(), nullptr);
buffer.framebuffer = DXFramebuffer::Create(buffer.texture.get(), nullptr, {});
ASSERT_MSG(VIDEO, buffer.framebuffer != nullptr,
"Failed to create swap chain buffer framebuffer");
if (!buffer.framebuffer)

View File

@ -85,7 +85,8 @@ static void GetD3DDepthDesc(D3D12_DEPTH_STENCIL_DESC* desc, const DepthState& st
state.updateenable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
}
static void GetD3DBlendDesc(D3D12_BLEND_DESC* desc, const BlendingState& state)
static void GetD3DBlendDesc(D3D12_BLEND_DESC* desc, const BlendingState& state,
u8 render_target_count)
{
static constexpr std::array<D3D12_BLEND, 8> src_dual_src_factors = {
{D3D12_BLEND_ZERO, D3D12_BLEND_ONE, D3D12_BLEND_DEST_COLOR, D3D12_BLEND_INV_DEST_COLOR,
@ -115,45 +116,49 @@ static void GetD3DBlendDesc(D3D12_BLEND_DESC* desc, const BlendingState& state)
desc->AlphaToCoverageEnable = FALSE;
desc->IndependentBlendEnable = FALSE;
D3D12_RENDER_TARGET_BLEND_DESC* rtblend = &desc->RenderTarget[0];
if (state.colorupdate)
for (u8 i = 0; i < render_target_count; i++)
{
rtblend->RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_RED |
D3D12_COLOR_WRITE_ENABLE_GREEN |
D3D12_COLOR_WRITE_ENABLE_BLUE;
}
if (state.alphaupdate)
{
rtblend->RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_ALPHA;
}
// blend takes precedence over logic op
rtblend->BlendEnable = state.blendenable;
if (state.blendenable)
{
rtblend->BlendOp = state.subtract ? D3D12_BLEND_OP_REV_SUBTRACT : D3D12_BLEND_OP_ADD;
rtblend->BlendOpAlpha = state.subtractAlpha ? D3D12_BLEND_OP_REV_SUBTRACT : D3D12_BLEND_OP_ADD;
if (state.usedualsrc)
D3D12_RENDER_TARGET_BLEND_DESC* rtblend = &desc->RenderTarget[i];
if (state.colorupdate)
{
rtblend->SrcBlend = src_dual_src_factors[u32(state.srcfactor.Value())];
rtblend->SrcBlendAlpha = src_dual_src_factors[u32(state.srcfactoralpha.Value())];
rtblend->DestBlend = dst_dual_src_factors[u32(state.dstfactor.Value())];
rtblend->DestBlendAlpha = dst_dual_src_factors[u32(state.dstfactoralpha.Value())];
rtblend->RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_RED |
D3D12_COLOR_WRITE_ENABLE_GREEN |
D3D12_COLOR_WRITE_ENABLE_BLUE;
}
if (state.alphaupdate)
{
rtblend->RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_ALPHA;
}
// blend takes precedence over logic op
rtblend->BlendEnable = state.blendenable;
if (state.blendenable)
{
rtblend->BlendOp = state.subtract ? D3D12_BLEND_OP_REV_SUBTRACT : D3D12_BLEND_OP_ADD;
rtblend->BlendOpAlpha =
state.subtractAlpha ? D3D12_BLEND_OP_REV_SUBTRACT : D3D12_BLEND_OP_ADD;
if (state.usedualsrc)
{
rtblend->SrcBlend = src_dual_src_factors[u32(state.srcfactor.Value())];
rtblend->SrcBlendAlpha = src_dual_src_factors[u32(state.srcfactoralpha.Value())];
rtblend->DestBlend = dst_dual_src_factors[u32(state.dstfactor.Value())];
rtblend->DestBlendAlpha = dst_dual_src_factors[u32(state.dstfactoralpha.Value())];
}
else
{
rtblend->SrcBlend = src_factors[u32(state.srcfactor.Value())];
rtblend->SrcBlendAlpha = src_factors[u32(state.srcfactoralpha.Value())];
rtblend->DestBlend = dst_factors[u32(state.dstfactor.Value())];
rtblend->DestBlendAlpha = dst_factors[u32(state.dstfactoralpha.Value())];
}
}
else
{
rtblend->SrcBlend = src_factors[u32(state.srcfactor.Value())];
rtblend->SrcBlendAlpha = src_factors[u32(state.srcfactoralpha.Value())];
rtblend->DestBlend = dst_factors[u32(state.dstfactor.Value())];
rtblend->DestBlendAlpha = dst_factors[u32(state.dstfactoralpha.Value())];
rtblend->LogicOpEnable = state.logicopenable;
if (state.logicopenable)
rtblend->LogicOp = logic_ops[u32(state.logicmode.Value())];
}
}
else
{
rtblend->LogicOpEnable = state.logicopenable;
if (state.logicopenable)
rtblend->LogicOp = logic_ops[u32(state.logicmode.Value())];
}
}
std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& config,
@ -183,7 +188,8 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
if (config.pixel_shader)
desc.PS = static_cast<const DXShader*>(config.pixel_shader)->GetD3DByteCode();
GetD3DBlendDesc(&desc.BlendState, config.blending_state);
GetD3DBlendDesc(&desc.BlendState, config.blending_state,
config.framebuffer_state.additional_color_attachment_count + 1);
desc.SampleMask = 0xFFFFFFFF;
GetD3DRasterizerDesc(&desc.RasterizerState, config.rasterization_state, config.framebuffer_state);
GetD3DDepthDesc(&desc.DepthStencilState, config.depth_state);
@ -195,9 +201,25 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
desc.PrimitiveTopologyType = GetD3DTopologyType(config.rasterization_state);
if (config.framebuffer_state.color_texture_format != AbstractTextureFormat::Undefined)
{
desc.NumRenderTargets = 1;
desc.NumRenderTargets =
static_cast<u8>(config.framebuffer_state.additional_color_attachment_count) + 1;
desc.RTVFormats[0] = D3DCommon::GetRTVFormatForAbstractFormat(
config.framebuffer_state.color_texture_format, config.blending_state.logicopenable);
config.framebuffer_state.color_texture_format, false);
for (u8 i = 0; i < static_cast<u8>(config.framebuffer_state.additional_color_attachment_count);
i++)
{
// For now set all formats to be the same
desc.RTVFormats[i + 1] = D3DCommon::GetRTVFormatForAbstractFormat(
config.framebuffer_state.color_texture_format, false);
}
if (config.blending_state.logicopenable)
{
desc.NumRenderTargets++;
desc.RTVFormats[static_cast<u8>(config.framebuffer_state.additional_color_attachment_count) +
1] =
D3DCommon::GetRTVFormatForAbstractFormat(config.framebuffer_state.color_texture_format,
true);
}
}
if (config.framebuffer_state.depth_texture_format != AbstractTextureFormat::Undefined)
desc.DSVFormat =

View File

@ -393,10 +393,12 @@ void DXTexture::DestroyResource()
}
DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples)
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
height, layers, samples)
: AbstractFramebuffer(color_attachment, depth_attachment,
std::move(additional_color_attachments), color_format, depth_format,
width, height, layers, samples)
{
}
@ -412,15 +414,73 @@ DXFramebuffer::~DXFramebuffer()
g_dx_context->DeferDescriptorDestruction(g_dx_context->GetRTVHeapManager(),
m_int_rtv_descriptor.index);
}
}
for (auto render_target : m_render_targets)
{
g_dx_context->DeferDescriptorDestruction(g_dx_context->GetRTVHeapManager(),
m_rtv_descriptor.index);
render_target.index);
}
}
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment,
DXTexture* depth_attachment)
void DXFramebuffer::Unbind()
{
if (!ValidateConfig(color_attachment, depth_attachment))
static const D3D12_DISCARD_REGION dr = {0, nullptr, 0, 1};
if (HasColorBuffer())
{
g_dx_context->GetCommandList()->DiscardResource(
static_cast<DXTexture*>(GetColorAttachment())->GetResource(), &dr);
}
for (auto additional_color_attachment : m_additional_color_attachments)
{
g_dx_context->GetCommandList()->DiscardResource(
static_cast<DXTexture*>(additional_color_attachment)->GetResource(), &dr);
}
if (HasDepthBuffer())
{
g_dx_context->GetCommandList()->DiscardResource(
static_cast<DXTexture*>(GetDepthAttachment())->GetResource(), &dr);
}
}
void DXFramebuffer::ClearRenderTargets(const ClearColor& color_value,
const D3D12_RECT* rectangle) const
{
for (auto render_target : m_render_targets_raw)
{
g_dx_context->GetCommandList()->ClearRenderTargetView(render_target, color_value.data(),
rectangle ? 1 : 0, rectangle);
}
}
void DXFramebuffer::ClearDepth(float depth_value, const D3D12_RECT* rectangle) const
{
if (HasDepthBuffer())
{
g_dx_context->GetCommandList()->ClearDepthStencilView(GetDSVDescriptor().cpu_handle,
D3D12_CLEAR_FLAG_DEPTH, depth_value, 0,
rectangle ? 1 : 0, rectangle);
}
}
void DXFramebuffer::TransitionRenderTargets() const
{
if (HasColorBuffer())
{
static_cast<DXTexture*>(GetColorAttachment())
->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
}
for (auto additional_color_attachment : m_additional_color_attachments)
{
static_cast<DXTexture*>(additional_color_attachment)
->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
}
}
std::unique_ptr<DXFramebuffer>
DXFramebuffer::Create(DXTexture* color_attachment, DXTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments)
{
if (!ValidateConfig(color_attachment, depth_attachment, additional_color_attachments))
return nullptr;
const AbstractTextureFormat color_format =
@ -433,10 +493,10 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
std::unique_ptr<DXFramebuffer> fb(new DXFramebuffer(color_attachment, depth_attachment,
color_format, depth_format, width, height,
layers, samples));
if ((color_attachment && !fb->CreateRTVDescriptor()) ||
std::unique_ptr<DXFramebuffer> fb(
new DXFramebuffer(color_attachment, depth_attachment, std::move(additional_color_attachments),
color_format, depth_format, width, height, layers, samples));
if (!fb->CreateRTVDescriptors() || (color_attachment && !fb->CreateIRTVDescriptor()) ||
(depth_attachment && !fb->CreateDSVDescriptor()))
{
return nullptr;
@ -445,38 +505,73 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
return fb;
}
bool DXFramebuffer::CreateRTVDescriptor()
bool DXFramebuffer::CreateRTVDescriptors()
{
if (!g_dx_context->GetRTVHeapManager().Allocate(&m_rtv_descriptor))
if (m_color_attachment)
{
if (!CreateRTVDescriptor(m_layers, m_color_attachment))
{
return false;
}
}
for (auto* attachment : m_additional_color_attachments)
{
if (!CreateRTVDescriptor(1, attachment))
{
return false;
}
}
return true;
}
bool DXFramebuffer::CreateRTVDescriptor(u32 layers, AbstractTexture* attachment)
{
DescriptorHandle rtv;
if (!g_dx_context->GetRTVHeapManager().Allocate(&rtv))
{
PanicAlertFmt("Failed to allocate RTV descriptor");
return false;
}
m_render_targets.push_back(std::move(rtv));
m_render_targets_raw.push_back(m_render_targets.back().cpu_handle);
const bool multisampled = m_samples > 1;
D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {
D3DCommon::GetRTVFormatForAbstractFormat(m_color_format, false),
multisampled ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DARRAY};
if (multisampled)
rtv_desc.Texture2DMSArray.ArraySize = m_layers;
rtv_desc.Texture2DMSArray.ArraySize = layers;
else
rtv_desc.Texture2DArray.ArraySize = m_layers;
rtv_desc.Texture2DArray.ArraySize = layers;
g_dx_context->GetDevice()->CreateRenderTargetView(
static_cast<DXTexture*>(m_color_attachment)->GetResource(), &rtv_desc,
m_rtv_descriptor.cpu_handle);
static_cast<DXTexture*>(attachment)->GetResource(), &rtv_desc, m_render_targets_raw.back());
return true;
}
bool DXFramebuffer::CreateIRTVDescriptor()
{
const bool multisampled = m_samples > 1;
DXGI_FORMAT non_int_format = D3DCommon::GetRTVFormatForAbstractFormat(m_color_format, false);
DXGI_FORMAT int_format = D3DCommon::GetRTVFormatForAbstractFormat(m_color_format, true);
if (int_format != rtv_desc.Format)
if (int_format != non_int_format)
{
if (!g_dx_context->GetRTVHeapManager().Allocate(&m_int_rtv_descriptor))
return false;
rtv_desc.Format = int_format;
D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {int_format, multisampled ?
D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY :
D3D12_RTV_DIMENSION_TEXTURE2DARRAY};
if (multisampled)
rtv_desc.Texture2DMSArray.ArraySize = m_layers;
else
rtv_desc.Texture2DArray.ArraySize = m_layers;
g_dx_context->GetDevice()->CreateRenderTargetView(
static_cast<DXTexture*>(m_color_attachment)->GetResource(), &rtv_desc,
m_int_rtv_descriptor.cpu_handle);
}
return true;
}

View File

@ -10,8 +10,10 @@
#include "VideoBackends/D3D12/Common.h"
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/RenderBase.h"
namespace DX12
{
@ -65,14 +67,13 @@ class DXFramebuffer final : public AbstractFramebuffer
public:
~DXFramebuffer() override;
const DescriptorHandle& GetRTVDescriptor() const { return m_rtv_descriptor; }
const DescriptorHandle& GetIntRTVDescriptor() const { return m_int_rtv_descriptor; }
const DescriptorHandle& GetDSVDescriptor() const { return m_dsv_descriptor; }
UINT GetRTVDescriptorCount() const { return m_color_attachment ? 1 : 0; }
UINT GetRTVDescriptorCount() const { return static_cast<UINT>(m_render_targets.size()); }
const D3D12_CPU_DESCRIPTOR_HANDLE* GetRTVDescriptorArray() const
{
return m_color_attachment ? &m_rtv_descriptor.cpu_handle : nullptr;
return m_render_targets_raw.data();
}
const D3D12_CPU_DESCRIPTOR_HANDLE* GetIntRTVDescriptorArray() const
{
@ -83,18 +84,28 @@ public:
return m_depth_attachment ? &m_dsv_descriptor.cpu_handle : nullptr;
}
static std::unique_ptr<DXFramebuffer> Create(DXTexture* color_attachment,
DXTexture* depth_attachment);
void Unbind();
void ClearRenderTargets(const ClearColor& color_value, const D3D12_RECT* rectangle) const;
void ClearDepth(float depth_value, const D3D12_RECT* rectangle) const;
void TransitionRenderTargets() const;
static std::unique_ptr<DXFramebuffer>
Create(DXTexture* color_attachment, DXTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments);
private:
DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples);
bool CreateRTVDescriptor();
bool CreateRTVDescriptors();
bool CreateRTVDescriptor(u32 layers, AbstractTexture* attachment);
bool CreateIRTVDescriptor();
bool CreateDSVDescriptor();
DescriptorHandle m_rtv_descriptor = {};
std::vector<DescriptorHandle> m_render_targets;
std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> m_render_targets_raw;
DescriptorHandle m_int_rtv_descriptor = {};
DescriptorHandle m_dsv_descriptor = {};
};