GPUDevice: Get rid of framebuffer abstraction

This commit is contained in:
Stenzek
2023-12-04 15:47:18 +10:00
parent a9ee2a34d8
commit 3b2c70cda5
47 changed files with 1404 additions and 1165 deletions

View File

@ -570,12 +570,9 @@ void D3D12Device::SubmitCommandListAndRestartRenderPass(const char* reason)
if (InRenderPass())
EndRenderPass();
D3D12Framebuffer* fb = m_current_framebuffer;
D3D12Pipeline* pl = m_current_pipeline;
SubmitCommandList(false, "%s", reason);
if (fb)
SetFramebuffer(fb);
SetPipeline(pl);
BeginRenderPass();
}
@ -1091,7 +1088,7 @@ bool D3D12Device::BeginPresent(bool frame_skip)
void D3D12Device::EndPresent()
{
DebugAssert(InRenderPass() && !m_current_framebuffer);
DebugAssert(InRenderPass() && m_num_current_render_targets == 0 && !m_current_depth_target);
EndRenderPass();
const auto& swap_chain_buf = m_swap_chain_buffers[m_current_swap_chain_buffer];
@ -1316,25 +1313,22 @@ void D3D12Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
void D3D12Device::ClearRenderTarget(GPUTexture* t, u32 c)
{
GPUDevice::ClearRenderTarget(t, c);
if (InRenderPass() && m_current_framebuffer && m_current_framebuffer->GetRT() == t)
if (InRenderPass() && IsRenderTargetBound(t))
EndRenderPass();
}
void D3D12Device::ClearDepth(GPUTexture* t, float d)
{
GPUDevice::ClearDepth(t, d);
if (InRenderPass() && m_current_framebuffer && m_current_framebuffer->GetDS() == t)
if (InRenderPass() && m_current_depth_target == t)
EndRenderPass();
}
void D3D12Device::InvalidateRenderTarget(GPUTexture* t)
{
GPUDevice::InvalidateRenderTarget(t);
if (InRenderPass() && m_current_framebuffer &&
(m_current_framebuffer->GetRT() == t || m_current_framebuffer->GetDS() == t))
{
if (InRenderPass() && (t->IsRenderTarget() ? IsRenderTargetBound(t) : (m_current_depth_target == t)))
EndRenderPass();
}
}
bool D3D12Device::CreateBuffers()
@ -1530,60 +1524,71 @@ void D3D12Device::DestroyRootSignatures()
it->Reset();
}
void D3D12Device::SetFramebuffer(GPUFramebuffer* fb)
void D3D12Device::SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds)
{
if (m_current_framebuffer == fb)
return;
if (InRenderPass())
EndRenderPass();
m_current_framebuffer = static_cast<D3D12Framebuffer*>(fb);
ID3D12GraphicsCommandList4* cmdlist = GetCommandList();
m_current_depth_target = static_cast<D3D12Texture*>(ds);
for (u32 i = 0; i < num_rts; i++)
{
D3D12Texture* const dt = static_cast<D3D12Texture*>(rts[i]);
m_current_render_targets[i] = dt;
dt->CommitClear(cmdlist);
}
for (u32 i = num_rts; i < m_num_current_render_targets; i++)
m_current_render_targets[i] = nullptr;
m_num_current_render_targets = num_rts;
}
void D3D12Device::BeginRenderPass()
{
DebugAssert(!InRenderPass());
D3D12_RENDER_PASS_RENDER_TARGET_DESC rt_desc;
std::array<D3D12_RENDER_PASS_RENDER_TARGET_DESC, MAX_RENDER_TARGETS> rt_desc;
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds_desc;
const D3D12_RENDER_PASS_RENDER_TARGET_DESC* rt_desc_p = nullptr;
const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC* ds_desc_p = nullptr;
D3D12_RENDER_PASS_RENDER_TARGET_DESC* rt_desc_p = nullptr;
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC* ds_desc_p = nullptr;
u32 num_rt_descs = 0;
ID3D12GraphicsCommandList4* cmdlist = GetCommandList();
if (m_current_framebuffer) [[likely]]
if (m_num_current_render_targets > 0 || m_current_depth_target) [[likely]]
{
D3D12Texture* rt = static_cast<D3D12Texture*>(m_current_framebuffer->GetRT());
if (rt)
for (u32 i = 0; i < m_num_current_render_targets; i++)
{
D3D12Texture* const rt = m_current_render_targets[i];
rt->TransitionToState(cmdlist, D3D12_RESOURCE_STATE_RENDER_TARGET);
rt->SetUseFenceValue(GetCurrentFenceValue());
rt_desc_p = &rt_desc;
rt_desc.cpuDescriptor = rt->GetWriteDescriptor();
rt_desc.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
D3D12_RENDER_PASS_RENDER_TARGET_DESC& desc = rt_desc[i];
desc.cpuDescriptor = rt->GetWriteDescriptor();
desc.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
switch (rt->GetState())
{
case GPUTexture::State::Cleared:
{
rt_desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
std::memcpy(rt_desc.BeginningAccess.Clear.ClearValue.Color, rt->GetUNormClearColor().data(),
sizeof(rt_desc.BeginningAccess.Clear.ClearValue.Color));
desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
std::memcpy(desc.BeginningAccess.Clear.ClearValue.Color, rt->GetUNormClearColor().data(),
sizeof(desc.BeginningAccess.Clear.ClearValue.Color));
rt->SetState(GPUTexture::State::Dirty);
}
break;
case GPUTexture::State::Invalidated:
{
rt_desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
rt->SetState(GPUTexture::State::Dirty);
}
break;
case GPUTexture::State::Dirty:
{
rt_desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
desc.BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
}
break;
@ -1593,9 +1598,11 @@ void D3D12Device::BeginRenderPass()
}
}
D3D12Texture* ds = static_cast<D3D12Texture*>(m_current_framebuffer->GetDS());
if (ds)
rt_desc_p = (m_num_current_render_targets > 0) ? rt_desc.data() : nullptr;
num_rt_descs = m_num_current_render_targets;
if (m_current_depth_target)
{
D3D12Texture* const ds = m_current_depth_target;
ds->TransitionToState(cmdlist, D3D12_RESOURCE_STATE_DEPTH_WRITE);
ds->SetUseFenceValue(GetCurrentFenceValue());
ds_desc_p = &ds_desc;
@ -1631,16 +1638,19 @@ void D3D12Device::BeginRenderPass()
UnreachableCode();
break;
}
ds_desc_p = &ds_desc;
}
}
else
{
// Re-rendering to swap chain.
const auto& swap_chain_buf = m_swap_chain_buffers[m_current_swap_chain_buffer];
rt_desc = {swap_chain_buf.second,
{D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE, {}},
{D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {}}};
rt_desc_p = &rt_desc;
rt_desc[0] = {swap_chain_buf.second,
{D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE, {}},
{D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {}}};
rt_desc_p = &rt_desc[0];
num_rt_descs = 1;
}
// All textures should be in shader read only optimal already, but just in case..
@ -1652,7 +1662,7 @@ void D3D12Device::BeginRenderPass()
}
DebugAssert(rt_desc_p || ds_desc_p);
cmdlist->BeginRenderPass(rt_desc_p ? 1 : 0, rt_desc_p, ds_desc_p, D3D12_RENDER_PASS_FLAG_NONE);
cmdlist->BeginRenderPass(num_rt_descs, rt_desc_p, ds_desc_p, D3D12_RENDER_PASS_FLAG_NONE);
// TODO: Stats
m_in_render_pass = true;
@ -1686,7 +1696,9 @@ void D3D12Device::BeginSwapChainRenderPass()
{D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {}}};
cmdlist->BeginRenderPass(1, &rt_desc, nullptr, D3D12_RENDER_PASS_FLAG_NONE);
m_current_framebuffer = nullptr;
std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets));
m_num_current_render_targets = 0;
m_current_depth_target = nullptr;
m_in_render_pass = true;
// Clear pipeline, it's likely incompatible.
@ -1708,29 +1720,6 @@ void D3D12Device::EndRenderPass()
GetCommandList()->EndRenderPass();
}
void D3D12Device::UnbindFramebuffer(D3D12Framebuffer* fb)
{
if (m_current_framebuffer != fb)
return;
if (InRenderPass())
EndRenderPass();
m_current_framebuffer = nullptr;
}
void D3D12Device::UnbindFramebuffer(D3D12Texture* tex)
{
if (!m_current_framebuffer)
return;
if (m_current_framebuffer->GetRT() != tex && m_current_framebuffer->GetDS() != tex)
return;
if (InRenderPass())
EndRenderPass();
m_current_framebuffer = nullptr;
}
void D3D12Device::SetPipeline(GPUPipeline* pipeline)
{
// First draw? Bind everything.
@ -1789,11 +1778,21 @@ void D3D12Device::UnbindPipeline(D3D12Pipeline* pl)
m_current_pipeline = nullptr;
}
bool D3D12Device::IsRenderTargetBound(const GPUTexture* tex) const
{
for (u32 i = 0; i < m_num_current_render_targets; i++)
{
if (m_current_render_targets[i] == tex)
return true;
}
return false;
}
void D3D12Device::InvalidateCachedState()
{
m_dirty_flags = ALL_DIRTY_STATE;
m_in_render_pass = false;
m_current_framebuffer = nullptr;
m_current_pipeline = nullptr;
m_current_vertex_stride = 0;
m_current_blend_constant = 0;
@ -1901,6 +1900,28 @@ void D3D12Device::UnbindTexture(D3D12Texture* tex)
m_dirty_flags |= DIRTY_FLAG_TEXTURES;
}
}
if (tex->IsRenderTarget())
{
for (u32 i = 0; i < m_num_current_render_targets; i++)
{
if (m_current_render_targets[i] == tex)
{
if (InRenderPass())
EndRenderPass();
m_current_render_targets[i] = nullptr;
}
}
}
else if (tex->IsDepthStencil())
{
if (m_current_depth_target == tex)
{
if (InRenderPass())
EndRenderPass();
m_current_depth_target = nullptr;
}
}
}
void D3D12Device::UnbindTextureBuffer(D3D12TextureBuffer* buf)