mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
VideoBackends: add support to allow rendering to multiple output textures
This commit is contained in:
@ -61,11 +61,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>
|
||||
@ -202,15 +204,7 @@ void Gfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
|
||||
|
||||
// We can't leave the framebuffer bound as a texture and a render target.
|
||||
DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
|
||||
if ((fb->GetColorAttachment() &&
|
||||
D3D::stateman->UnsetTexture(
|
||||
static_cast<DXTexture*>(fb->GetColorAttachment())->GetD3DSRV()) != 0) ||
|
||||
(fb->GetDepthAttachment() &&
|
||||
D3D::stateman->UnsetTexture(
|
||||
static_cast<DXTexture*>(fb->GetDepthAttachment())->GetD3DSRV()) != 0))
|
||||
{
|
||||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
fb->Unbind();
|
||||
|
||||
D3D::stateman->SetFramebuffer(fb);
|
||||
m_current_framebuffer = fb;
|
||||
@ -227,16 +221,8 @@ void Gfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearCo
|
||||
SetFramebuffer(framebuffer);
|
||||
D3D::stateman->Apply();
|
||||
|
||||
if (framebuffer->GetColorFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
D3D::context->ClearRenderTargetView(
|
||||
static_cast<const DXFramebuffer*>(framebuffer)->GetRTVArray()[0], color_value.data());
|
||||
}
|
||||
if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
D3D::context->ClearDepthStencilView(static_cast<const DXFramebuffer*>(framebuffer)->GetDSV(),
|
||||
D3D11_CLEAR_DEPTH, depth_value, 0);
|
||||
}
|
||||
DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
|
||||
fb->Clear(color_value, depth_value);
|
||||
}
|
||||
|
||||
void Gfx::SetTexture(u32 index, const AbstractTexture* texture)
|
||||
|
@ -41,7 +41,8 @@ public:
|
||||
const void* cache_data = nullptr,
|
||||
size_t cache_data_length = 0) 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;
|
||||
|
||||
void SetPipeline(const AbstractPipeline* pipeline) override;
|
||||
void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
|
||||
|
@ -41,7 +41,8 @@ void StateManager::Apply()
|
||||
m_pending.framebuffer->GetNumRTVs(),
|
||||
m_pending.use_integer_rtv ? m_pending.framebuffer->GetIntegerRTVArray() :
|
||||
m_pending.framebuffer->GetRTVArray(),
|
||||
m_pending.framebuffer->GetDSV(), 2, 1, &m_pending.uav, nullptr);
|
||||
m_pending.framebuffer->GetDSV(), m_pending.framebuffer->GetNumRTVs() + 1, 1,
|
||||
&m_pending.uav, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ bool SwapChain::CreateSwapChainBuffers()
|
||||
if (!m_texture)
|
||||
return false;
|
||||
|
||||
m_framebuffer = DXFramebuffer::Create(m_texture.get(), nullptr);
|
||||
m_framebuffer = DXFramebuffer::Create(m_texture.get(), nullptr, {});
|
||||
if (!m_framebuffer)
|
||||
return false;
|
||||
|
||||
|
@ -324,23 +324,79 @@ void DXStagingTexture::Flush()
|
||||
}
|
||||
|
||||
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,
|
||||
ComPtr<ID3D11RenderTargetView> rtv,
|
||||
ComPtr<ID3D11RenderTargetView> integer_rtv,
|
||||
ComPtr<ID3D11DepthStencilView> dsv)
|
||||
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
|
||||
height, layers, samples),
|
||||
m_rtv(std::move(rtv)), m_integer_rtv(std::move(integer_rtv)), m_dsv(std::move(dsv))
|
||||
ComPtr<ID3D11DepthStencilView> dsv,
|
||||
std::vector<ComPtr<ID3D11RenderTargetView>> additional_rtvs)
|
||||
: AbstractFramebuffer(color_attachment, depth_attachment,
|
||||
std::move(additional_color_attachments), color_format, depth_format,
|
||||
width, height, layers, samples),
|
||||
m_integer_rtv(std::move(integer_rtv)), m_dsv(std::move(dsv))
|
||||
{
|
||||
m_render_targets.push_back(std::move(rtv));
|
||||
for (auto additional_rtv : additional_rtvs)
|
||||
{
|
||||
m_render_targets.push_back(std::move(additional_rtv));
|
||||
}
|
||||
for (auto& render_target : m_render_targets)
|
||||
{
|
||||
m_render_targets_raw.push_back(render_target.Get());
|
||||
}
|
||||
}
|
||||
|
||||
DXFramebuffer::~DXFramebuffer() = default;
|
||||
|
||||
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment,
|
||||
DXTexture* depth_attachment)
|
||||
void DXFramebuffer::Unbind()
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
bool should_apply = false;
|
||||
if (GetColorAttachment() &&
|
||||
D3D::stateman->UnsetTexture(static_cast<DXTexture*>(GetColorAttachment())->GetD3DSRV()) != 0)
|
||||
{
|
||||
should_apply = true;
|
||||
}
|
||||
|
||||
if (GetDepthAttachment() &&
|
||||
D3D::stateman->UnsetTexture(static_cast<DXTexture*>(GetDepthAttachment())->GetD3DSRV()) != 0)
|
||||
{
|
||||
should_apply = true;
|
||||
}
|
||||
|
||||
for (auto additional_color_attachment : m_additional_color_attachments)
|
||||
{
|
||||
if (D3D::stateman->UnsetTexture(
|
||||
static_cast<DXTexture*>(additional_color_attachment)->GetD3DSRV()) != 0)
|
||||
{
|
||||
should_apply = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (should_apply)
|
||||
{
|
||||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
}
|
||||
|
||||
void DXFramebuffer::Clear(const ClearColor& color_value, float depth_value)
|
||||
{
|
||||
if (GetDepthFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
D3D::context->ClearDepthStencilView(GetDSV(), D3D11_CLEAR_DEPTH, depth_value, 0);
|
||||
}
|
||||
|
||||
for (auto render_target : m_render_targets_raw)
|
||||
{
|
||||
D3D::context->ClearRenderTargetView(render_target, color_value.data());
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
@ -382,6 +438,25 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ComPtr<ID3D11RenderTargetView>> additional_rtvs;
|
||||
for (auto additional_color_attachment : additional_color_attachments)
|
||||
{
|
||||
ComPtr<ID3D11RenderTargetView> additional_rtv;
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC desc(
|
||||
additional_color_attachment->IsMultisampled() ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
|
||||
D3DCommon::GetRTVFormatForAbstractFormat(additional_color_attachment->GetFormat(), false),
|
||||
0, 0, 1);
|
||||
HRESULT hr = D3D::device->CreateRenderTargetView(
|
||||
static_cast<DXTexture*>(additional_color_attachment)->GetD3DTexture(), &desc,
|
||||
additional_rtv.GetAddressOf());
|
||||
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Create render target view for framebuffer: {}",
|
||||
DX11HRWrap(hr));
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
additional_rtvs.push_back(std::move(additional_rtv));
|
||||
}
|
||||
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
if (depth_attachment)
|
||||
{
|
||||
@ -398,9 +473,10 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format,
|
||||
depth_format, width, height, layers, samples,
|
||||
std::move(rtv), std::move(integer_rtv), std::move(dsv));
|
||||
return std::make_unique<DXFramebuffer>(
|
||||
color_attachment, depth_attachment, std::move(additional_color_attachments), color_format,
|
||||
depth_format, width, height, layers, samples, std::move(rtv), std::move(integer_rtv),
|
||||
std::move(dsv), std::move(additional_rtvs));
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -7,13 +7,15 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <vector>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoCommon/AbstractFramebuffer.h"
|
||||
#include "VideoCommon/AbstractGfx.h"
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
@ -81,20 +83,28 @@ class DXFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
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, ComPtr<ID3D11RenderTargetView> rtv,
|
||||
ComPtr<ID3D11RenderTargetView> integer_rtv, ComPtr<ID3D11DepthStencilView> dsv);
|
||||
ComPtr<ID3D11RenderTargetView> integer_rtv, ComPtr<ID3D11DepthStencilView> dsv,
|
||||
std::vector<ComPtr<ID3D11RenderTargetView>> additional_rtvs);
|
||||
~DXFramebuffer() override;
|
||||
|
||||
ID3D11RenderTargetView* const* GetRTVArray() const { return m_rtv.GetAddressOf(); }
|
||||
ID3D11RenderTargetView* const* GetRTVArray() const { return m_render_targets_raw.data(); }
|
||||
ID3D11RenderTargetView* const* GetIntegerRTVArray() const { return m_integer_rtv.GetAddressOf(); }
|
||||
UINT GetNumRTVs() const { return m_rtv ? 1 : 0; }
|
||||
UINT GetNumRTVs() const { return static_cast<UINT>(m_render_targets_raw.size()); }
|
||||
ID3D11DepthStencilView* GetDSV() const { return m_dsv.Get(); }
|
||||
static std::unique_ptr<DXFramebuffer> Create(DXTexture* color_attachment,
|
||||
DXTexture* depth_attachment);
|
||||
|
||||
void Unbind();
|
||||
void Clear(const ClearColor& color_value, float depth_value);
|
||||
|
||||
static std::unique_ptr<DXFramebuffer>
|
||||
Create(DXTexture* color_attachment, DXTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments);
|
||||
|
||||
protected:
|
||||
ComPtr<ID3D11RenderTargetView> m_rtv;
|
||||
std::vector<ComPtr<ID3D11RenderTargetView>> m_render_targets;
|
||||
std::vector<ID3D11RenderTargetView*> m_render_targets_raw;
|
||||
ComPtr<ID3D11RenderTargetView> m_integer_rtv;
|
||||
ComPtr<ID3D11DepthStencilView> m_dsv;
|
||||
};
|
||||
|
Reference in New Issue
Block a user