mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #11859 from iwubcode/backend-multi-output
VideoBackends: add support to allow rendering to multiple output targets
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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = {};
|
||||
};
|
||||
|
||||
@@ -28,7 +28,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;
|
||||
|
||||
@@ -93,7 +93,8 @@ Metal::Gfx::CreateStagingTexture(StagingTextureType type, const TextureConfig& c
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment)
|
||||
Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*>)
|
||||
{
|
||||
AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||
return std::make_unique<Framebuffer>(
|
||||
|
||||
@@ -191,7 +191,7 @@ void Metal::StagingTexture::Flush()
|
||||
|
||||
Metal::Framebuffer::Framebuffer(AbstractTexture* color, AbstractTexture* depth, //
|
||||
u32 width, u32 height, u32 layers, u32 samples)
|
||||
: AbstractFramebuffer(color, depth,
|
||||
: AbstractFramebuffer(color, depth, {},
|
||||
color ? color->GetFormat() : AbstractTextureFormat::Undefined, //
|
||||
depth ? depth->GetFormat() : AbstractTextureFormat::Undefined, //
|
||||
width, height, layers, samples)
|
||||
|
||||
@@ -77,11 +77,13 @@ std::unique_ptr<AbstractPipeline> NullGfx::CreatePipeline(const AbstractPipeline
|
||||
return std::make_unique<NullPipeline>();
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer> NullGfx::CreateFramebuffer(AbstractTexture* color_attachment,
|
||||
AbstractTexture* depth_attachment)
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
NullGfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments)
|
||||
{
|
||||
return NullFramebuffer::Create(static_cast<NullTexture*>(color_attachment),
|
||||
static_cast<NullTexture*>(depth_attachment));
|
||||
static_cast<NullTexture*>(depth_attachment),
|
||||
std::move(additional_color_attachments));
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeVertexFormat>
|
||||
|
||||
@@ -22,7 +22,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;
|
||||
|
||||
@@ -66,18 +66,21 @@ void NullStagingTexture::Flush()
|
||||
|
||||
NullFramebuffer::NullFramebuffer(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)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(NullTexture* color_attachment,
|
||||
NullTexture* depth_attachment)
|
||||
std::unique_ptr<NullFramebuffer>
|
||||
NullFramebuffer::Create(NullTexture* color_attachment, NullTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
if (!ValidateConfig(color_attachment, depth_attachment, additional_color_attachments))
|
||||
return nullptr;
|
||||
|
||||
const AbstractTextureFormat color_format =
|
||||
@@ -90,7 +93,8 @@ std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(NullTexture* color_atta
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
return std::make_unique<NullFramebuffer>(color_attachment, depth_attachment, color_format,
|
||||
return std::make_unique<NullFramebuffer>(color_attachment, depth_attachment,
|
||||
std::move(additional_color_attachments), color_format,
|
||||
depth_format, width, height, layers, samples);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +54,13 @@ class NullFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
explicit NullFramebuffer(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);
|
||||
|
||||
static std::unique_ptr<NullFramebuffer> Create(NullTexture* color_attachment,
|
||||
NullTexture* depth_attachment);
|
||||
static std::unique_ptr<NullFramebuffer>
|
||||
Create(NullTexture* color_attachment, NullTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments);
|
||||
};
|
||||
|
||||
} // namespace Null
|
||||
|
||||
@@ -480,6 +480,8 @@ bool PopulateConfig(GLContext* m_main_gl_context)
|
||||
else if (GLExtensions::Version() == 330)
|
||||
{
|
||||
g_ogl_config.eSupportedGLSLVersion = Glsl330;
|
||||
g_ogl_config.bSupportsExplicitLayoutInShader =
|
||||
GLExtensions::Supports("GL_ARB_explicit_attrib_location");
|
||||
}
|
||||
else if (GLExtensions::Version() >= 430)
|
||||
{
|
||||
@@ -495,6 +497,7 @@ bool PopulateConfig(GLContext* m_main_gl_context)
|
||||
g_ogl_config.bSupportsTextureStorage = true;
|
||||
g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore;
|
||||
g_ogl_config.bSupportsImageLoadStore = true;
|
||||
g_ogl_config.bSupportsExplicitLayoutInShader = true;
|
||||
g_Config.backend_info.bSupportsSSAA = true;
|
||||
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user