mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
VideoCommon: Add support for Abstract Framebuffers
This commit is contained in:
@@ -344,4 +344,88 @@ void DXStagingTexture::Flush()
|
||||
m_needs_flush = false;
|
||||
}
|
||||
|
||||
DXFramebuffer::DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
u32 width, u32 height, u32 layers, u32 samples,
|
||||
ID3D11RenderTargetView* rtv, ID3D11DepthStencilView* dsv)
|
||||
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples), m_rtv(rtv),
|
||||
m_dsv(dsv)
|
||||
{
|
||||
}
|
||||
|
||||
DXFramebuffer::~DXFramebuffer()
|
||||
{
|
||||
if (m_rtv)
|
||||
m_rtv->Release();
|
||||
if (m_dsv)
|
||||
m_dsv->Release();
|
||||
}
|
||||
|
||||
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(const DXTexture* color_attachment,
|
||||
const DXTexture* depth_attachment)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
return nullptr;
|
||||
|
||||
const AbstractTextureFormat color_format =
|
||||
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const AbstractTextureFormat depth_format =
|
||||
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const DXTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||
const u32 width = either_attachment->GetWidth();
|
||||
const u32 height = either_attachment->GetHeight();
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
if (color_attachment)
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
desc.Format = GetDXGIFormatForHostFormat(color_attachment->GetConfig().format);
|
||||
if (color_attachment->GetConfig().IsMultisampled())
|
||||
{
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
desc.Texture2DMSArray.ArraySize = color_attachment->GetConfig().layers;
|
||||
desc.Texture2DMSArray.FirstArraySlice = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.ArraySize = color_attachment->GetConfig().layers;
|
||||
desc.Texture2DArray.FirstArraySlice = 0;
|
||||
desc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateRenderTargetView(
|
||||
color_attachment->GetRawTexIdentifier()->GetTex(), &desc, &rtv);
|
||||
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
|
||||
}
|
||||
|
||||
ID3D11DepthStencilView* dsv = nullptr;
|
||||
if (depth_attachment)
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
|
||||
desc.Format = GetDXGIFormatForHostFormat(depth_attachment->GetConfig().format);
|
||||
if (depth_attachment->GetConfig().IsMultisampled())
|
||||
{
|
||||
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
desc.Texture2DMSArray.ArraySize = depth_attachment->GetConfig().layers;
|
||||
desc.Texture2DMSArray.FirstArraySlice = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.ArraySize = depth_attachment->GetConfig().layers;
|
||||
desc.Texture2DArray.FirstArraySlice = 0;
|
||||
desc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateDepthStencilView(
|
||||
depth_attachment->GetRawTexIdentifier()->GetTex(), &desc, &dsv);
|
||||
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
|
||||
}
|
||||
|
||||
return std::make_unique<DXFramebuffer>(color_format, depth_format, width, height, layers, samples,
|
||||
rtv, dsv);
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoCommon/AbstractFramebuffer.h"
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
|
||||
@@ -63,4 +65,23 @@ private:
|
||||
ID3D11Texture2D* m_tex = nullptr;
|
||||
};
|
||||
|
||||
class DXFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
|
||||
u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv,
|
||||
ID3D11DepthStencilView* dsv);
|
||||
~DXFramebuffer() override;
|
||||
|
||||
ID3D11RenderTargetView* const* GetRTVArray() const { return &m_rtv; }
|
||||
UINT GetNumRTVs() const { return m_rtv ? 1 : 0; }
|
||||
ID3D11DepthStencilView* GetDSV() const { return m_dsv; }
|
||||
static std::unique_ptr<DXFramebuffer> Create(const DXTexture* color_attachment,
|
||||
const DXTexture* depth_attachment);
|
||||
|
||||
protected:
|
||||
ID3D11RenderTargetView* m_rtv;
|
||||
ID3D11DepthStencilView* m_dsv;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
||||
@@ -90,6 +90,8 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
FramebufferManager::BindEFBRenderTarget();
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
@@ -243,6 +245,14 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
|
||||
return DXStagingTexture::Create(type, config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
{
|
||||
return DXFramebuffer::Create(static_cast<const DXTexture*>(color_attachment),
|
||||
static_cast<const DXTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
|
||||
{
|
||||
D3D::DrawTextScaled(static_cast<float>(left + 1), static_cast<float>(top + 1), 20.f, 0.0f,
|
||||
@@ -648,6 +658,9 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
static constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
|
||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
|
||||
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color.data());
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_backbuffer_width;
|
||||
m_current_framebuffer_height = m_backbuffer_height;
|
||||
|
||||
// activate linear filtering for the buffer copies
|
||||
D3D::SetLinearCopySampler();
|
||||
@@ -763,6 +776,9 @@ void Renderer::ResetAPIState()
|
||||
void Renderer::RestoreAPIState()
|
||||
{
|
||||
// Gets us back into a more game-like state.
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
FramebufferManager::BindEFBRenderTarget();
|
||||
BPFunctions::SetViewport();
|
||||
BPFunctions::SetScissor();
|
||||
@@ -792,6 +808,36 @@ void Renderer::RestoreState()
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
const DXFramebuffer* fb = static_cast<const DXFramebuffer*>(framebuffer);
|
||||
D3D::context->OMSetRenderTargets(fb->GetNumRTVs(), fb->GetRTVArray(), fb->GetDSV());
|
||||
m_current_framebuffer = fb;
|
||||
m_current_framebuffer_width = fb->GetWidth();
|
||||
m_current_framebuffer_height = fb->GetHeight();
|
||||
}
|
||||
|
||||
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
SetFramebuffer(framebuffer);
|
||||
}
|
||||
|
||||
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value, float depth_value)
|
||||
{
|
||||
SetFramebuffer(framebuffer);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetRasterizationState(const RasterizationState& state)
|
||||
{
|
||||
m_gx_state.raster.hex = state.hex;
|
||||
|
||||
@@ -31,8 +31,16 @@ public:
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length) override;
|
||||
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
|
||||
void SetPipeline(const AbstractPipeline* pipeline) override;
|
||||
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value = {},
|
||||
float depth_value = 0.0f) override;
|
||||
void SetBlendingState(const BlendingState& state) override;
|
||||
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
|
||||
void SetRasterizationState(const RasterizationState& state) override;
|
||||
|
||||
@@ -70,4 +70,31 @@ void NullStagingTexture::Flush()
|
||||
m_needs_flush = false;
|
||||
}
|
||||
|
||||
NullFramebuffer::NullFramebuffer(AbstractTextureFormat color_format,
|
||||
AbstractTextureFormat depth_format, u32 width, u32 height,
|
||||
u32 layers, u32 samples)
|
||||
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(const NullTexture* color_attachment,
|
||||
const NullTexture* depth_attachment)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
return nullptr;
|
||||
|
||||
const AbstractTextureFormat color_format =
|
||||
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const AbstractTextureFormat depth_format =
|
||||
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const NullTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||
const u32 width = either_attachment->GetWidth();
|
||||
const u32 height = either_attachment->GetHeight();
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
return std::make_unique<NullFramebuffer>(color_format, depth_format, width, height, layers,
|
||||
samples);
|
||||
}
|
||||
|
||||
} // namespace Null
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoCommon/AbstractFramebuffer.h"
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
|
||||
@@ -53,4 +55,15 @@ private:
|
||||
std::vector<u8> m_texture_buf;
|
||||
};
|
||||
|
||||
class NullFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
explicit NullFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
u32 width, u32 height, u32 layers, u32 samples);
|
||||
~NullFramebuffer() override = default;
|
||||
|
||||
static std::unique_ptr<NullFramebuffer> Create(const NullTexture* color_attachment,
|
||||
const NullTexture* depth_attachment);
|
||||
};
|
||||
|
||||
} // namespace Null
|
||||
|
||||
@@ -69,6 +69,14 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
|
||||
return std::make_unique<NullPipeline>();
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
{
|
||||
return NullFramebuffer::Create(static_cast<const NullTexture*>(color_attachment),
|
||||
static_cast<const NullTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "RenderText: %s", text.c_str());
|
||||
|
||||
@@ -17,6 +17,9 @@ public:
|
||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractStagingTexture>
|
||||
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
|
||||
size_t length) override;
|
||||
|
||||
@@ -593,4 +593,72 @@ void OGLStagingTexture::Unmap()
|
||||
m_map_pointer = nullptr;
|
||||
}
|
||||
|
||||
OGLFramebuffer::OGLFramebuffer(AbstractTextureFormat color_format,
|
||||
AbstractTextureFormat depth_format, u32 width, u32 height,
|
||||
u32 layers, u32 samples, GLuint fbo)
|
||||
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples), m_fbo(fbo)
|
||||
{
|
||||
}
|
||||
|
||||
OGLFramebuffer::~OGLFramebuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
}
|
||||
|
||||
std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(const OGLTexture* color_attachment,
|
||||
const OGLTexture* depth_attachment)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
return nullptr;
|
||||
|
||||
const AbstractTextureFormat color_format =
|
||||
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const AbstractTextureFormat depth_format =
|
||||
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const OGLTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||
const u32 width = either_attachment->GetWidth();
|
||||
const u32 height = either_attachment->GetHeight();
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
if (color_attachment)
|
||||
{
|
||||
if (color_attachment->GetConfig().layers > 1)
|
||||
{
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
color_attachment->GetRawTexIdentifier(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
color_attachment->GetRawTexIdentifier(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_attachment)
|
||||
{
|
||||
GLenum attachment = AbstractTexture::IsStencilFormat(depth_format) ?
|
||||
GL_DEPTH_STENCIL_ATTACHMENT :
|
||||
GL_DEPTH_ATTACHMENT;
|
||||
if (depth_attachment->GetConfig().layers > 1)
|
||||
{
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, depth_attachment->GetRawTexIdentifier(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, depth_attachment->GetRawTexIdentifier(),
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
_dbg_assert_(VIDEO, glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
return std::make_unique<OGLFramebuffer>(color_format, depth_format, width, height, layers,
|
||||
samples, fbo);
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/GL/GLUtil.h"
|
||||
|
||||
#include "VideoCommon/AbstractFramebuffer.h"
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
|
||||
@@ -74,4 +76,19 @@ private:
|
||||
GLsync m_fence = 0;
|
||||
};
|
||||
|
||||
class OGLFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
OGLFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
|
||||
u32 height, u32 layers, u32 samples, GLuint fbo);
|
||||
~OGLFramebuffer() override;
|
||||
|
||||
GLuint GetFBO() const { return m_fbo; }
|
||||
static std::unique_ptr<OGLFramebuffer> Create(const OGLTexture* color_attachment,
|
||||
const OGLTexture* depth_attachment);
|
||||
|
||||
protected:
|
||||
GLuint m_fbo;
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
@@ -827,6 +827,8 @@ void Renderer::Init()
|
||||
// Initialize the FramebufferManager
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(
|
||||
m_target_width, m_target_height, s_MSAASamples, BoundingBox::NeedsStencilBuffer());
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
|
||||
m_post_processor = std::make_unique<OpenGLPostProcessing>();
|
||||
s_raster_font = std::make_unique<RasterFont>();
|
||||
@@ -843,6 +845,14 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
|
||||
return OGLStagingTexture::Create(type, config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
{
|
||||
return OGLFramebuffer::Create(static_cast<const OGLTexture*>(color_attachment),
|
||||
static_cast<const OGLTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
|
||||
{
|
||||
s_raster_font->printMultilineText(text,
|
||||
@@ -1145,7 +1155,7 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
|
||||
{
|
||||
// The x/y parameters here assume a upper-left origin. glViewport takes an offset from the
|
||||
// lower-left of the framebuffer, so we must set y to the distance from the lower-left.
|
||||
y = static_cast<float>(m_target_height) - y - height;
|
||||
y = static_cast<float>(m_current_framebuffer_height) - y - height;
|
||||
if (g_ogl_config.bSupportViewportFloat)
|
||||
{
|
||||
glViewportIndexedf(0, x, y, width, height);
|
||||
@@ -1238,6 +1248,44 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<const OGLFramebuffer*>(framebuffer)->GetFBO());
|
||||
m_current_framebuffer = framebuffer;
|
||||
m_current_framebuffer_width = framebuffer->GetWidth();
|
||||
m_current_framebuffer_height = framebuffer->GetHeight();
|
||||
}
|
||||
|
||||
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
// EXT_discard_framebuffer could be used here to save bandwidth on tilers.
|
||||
SetFramebuffer(framebuffer);
|
||||
}
|
||||
|
||||
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value, float depth_value)
|
||||
{
|
||||
SetFramebuffer(framebuffer);
|
||||
|
||||
// NOTE: This disturbs the current scissor/mask setting.
|
||||
// This won't be an issue when we implement proper state tracking.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
GLbitfield clear_mask = 0;
|
||||
if (framebuffer->HasColorBuffer())
|
||||
{
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glClearColor(color_value[0], color_value[1], color_value[2], color_value[3]);
|
||||
clear_mask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (framebuffer->HasDepthBuffer())
|
||||
{
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearDepth(depth_value);
|
||||
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
glClear(clear_mask);
|
||||
}
|
||||
|
||||
void Renderer::ApplyBlendingState(const BlendingState& state)
|
||||
{
|
||||
bool useDualSource =
|
||||
@@ -1351,6 +1399,9 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_backbuffer_width;
|
||||
m_current_framebuffer_height = m_backbuffer_height;
|
||||
|
||||
// Copy the framebuffer to screen.
|
||||
BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(),
|
||||
@@ -1496,6 +1547,9 @@ void Renderer::ResetAPIState()
|
||||
|
||||
void Renderer::RestoreAPIState()
|
||||
{
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
||||
// Gets us back into a more game-like state.
|
||||
|
||||
@@ -95,8 +95,16 @@ public:
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length) override;
|
||||
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
|
||||
void SetPipeline(const AbstractPipeline* pipeline) override;
|
||||
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value = {},
|
||||
float depth_value = 0.0f) override;
|
||||
void SetBlendingState(const BlendingState& state) override;
|
||||
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
|
||||
void SetRasterizationState(const RasterizationState& state) override;
|
||||
|
||||
@@ -39,6 +39,14 @@ SWRenderer::CreateStagingTexture(StagingTextureType type, const TextureConfig& c
|
||||
return std::make_unique<SW::SWStagingTexture>(type, config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
SWRenderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
{
|
||||
return SW::SWFramebuffer::Create(static_cast<const SW::SWTexture*>(color_attachment),
|
||||
static_cast<const SW::SWTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 color)
|
||||
{
|
||||
SWOGLWindow::s_instance->PrintText(pstr, left, top, color);
|
||||
|
||||
@@ -16,6 +16,9 @@ public:
|
||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractStagingTexture>
|
||||
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
|
||||
size_t length) override;
|
||||
|
||||
@@ -152,4 +152,31 @@ void SWStagingTexture::Flush()
|
||||
{
|
||||
m_needs_flush = false;
|
||||
}
|
||||
|
||||
SWFramebuffer::SWFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
u32 width, u32 height, u32 layers, u32 samples)
|
||||
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<SWFramebuffer> SWFramebuffer::Create(const SWTexture* color_attachment,
|
||||
const SWTexture* depth_attachment)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
return nullptr;
|
||||
|
||||
const AbstractTextureFormat color_format =
|
||||
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const AbstractTextureFormat depth_format =
|
||||
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined;
|
||||
const SWTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||
const u32 width = either_attachment->GetWidth();
|
||||
const u32 height = either_attachment->GetHeight();
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
return std::make_unique<SWFramebuffer>(color_format, depth_format, width, height, layers,
|
||||
samples);
|
||||
}
|
||||
|
||||
} // namespace SW
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoCommon/AbstractFramebuffer.h"
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
|
||||
@@ -59,4 +61,15 @@ private:
|
||||
std::vector<u8> m_data;
|
||||
};
|
||||
|
||||
class SWFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
explicit SWFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
u32 width, u32 height, u32 layers, u32 samples);
|
||||
~SWFramebuffer() override = default;
|
||||
|
||||
static std::unique_ptr<SWFramebuffer> Create(const SWTexture* color_attachment,
|
||||
const SWTexture* depth_attachment);
|
||||
};
|
||||
|
||||
} // namespace SW
|
||||
|
||||
@@ -192,6 +192,14 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
|
||||
return VKPipeline::Create(config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
{
|
||||
return VKFramebuffer::Create(static_cast<const VKTexture*>(color_attachment),
|
||||
static_cast<const VKTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
std::tuple<VkBuffer, u32> Renderer::UpdateUtilityUniformBuffer(const void* uniforms,
|
||||
u32 uniforms_size)
|
||||
{
|
||||
@@ -593,8 +601,9 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
|
||||
// Fastest path: Use a render pass to clear the buffers.
|
||||
if (use_clear_render_pass)
|
||||
{
|
||||
VkClearValue clear_values[2] = {clear_color_value, clear_depth_value};
|
||||
StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values);
|
||||
const std::array<VkClearValue, 2> clear_values = {{clear_color_value, clear_depth_value}};
|
||||
StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values.data(),
|
||||
static_cast<u32>(clear_values.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -743,6 +752,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
// Restore the EFB color texture to color attachment ready for rendering the next frame.
|
||||
FramebufferManager::GetInstance()->GetEFBColorTexture()->TransitionToLayout(
|
||||
g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
RestoreAPIState();
|
||||
|
||||
// Determine what (if anything) has changed in the config.
|
||||
CheckForConfigChanges();
|
||||
@@ -792,6 +802,9 @@ void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region
|
||||
backbuffer->OverrideImageLayout(VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
backbuffer->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = backbuffer->GetWidth();
|
||||
m_current_framebuffer_height = backbuffer->GetHeight();
|
||||
|
||||
// Begin render pass for rendering to the swap chain.
|
||||
VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||
@@ -1010,6 +1023,9 @@ void Renderer::BindEFBToStateTracker()
|
||||
FramebufferManager::GetInstance()->GetEFBFramebuffer(), framebuffer_size);
|
||||
StateTracker::GetInstance()->SetMultisamplingstate(
|
||||
FramebufferManager::GetInstance()->GetEFBMultisamplingState());
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = FramebufferManager::GetInstance()->GetEFBWidth();
|
||||
m_current_framebuffer_height = FramebufferManager::GetInstance()->GetEFBHeight();
|
||||
}
|
||||
|
||||
void Renderer::RecreateEFBFramebuffer()
|
||||
@@ -1037,12 +1053,78 @@ void Renderer::ResetAPIState()
|
||||
void Renderer::RestoreAPIState()
|
||||
{
|
||||
StateTracker::GetInstance()->EndRenderPass();
|
||||
if (m_current_framebuffer)
|
||||
static_cast<const VKFramebuffer*>(m_current_framebuffer)->TransitionForSample();
|
||||
|
||||
BindEFBToStateTracker();
|
||||
|
||||
// Instruct the state tracker to re-bind everything before the next draw
|
||||
StateTracker::GetInstance()->SetPendingRebind();
|
||||
}
|
||||
|
||||
void Renderer::BindFramebuffer(const VKFramebuffer* fb)
|
||||
{
|
||||
const VkRect2D render_area = {static_cast<int>(fb->GetWidth()),
|
||||
static_cast<int>(fb->GetHeight())};
|
||||
|
||||
StateTracker::GetInstance()->EndRenderPass();
|
||||
if (m_current_framebuffer)
|
||||
static_cast<const VKFramebuffer*>(m_current_framebuffer)->TransitionForSample();
|
||||
|
||||
fb->TransitionForRender();
|
||||
StateTracker::GetInstance()->SetFramebuffer(fb->GetFB(), render_area);
|
||||
StateTracker::GetInstance()->SetRenderPass(fb->GetLoadRenderPass(), fb->GetClearRenderPass());
|
||||
m_current_framebuffer = fb;
|
||||
m_current_framebuffer_width = fb->GetWidth();
|
||||
m_current_framebuffer_height = fb->GetHeight();
|
||||
}
|
||||
|
||||
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
const VKFramebuffer* vkfb = static_cast<const VKFramebuffer*>(framebuffer);
|
||||
BindFramebuffer(vkfb);
|
||||
StateTracker::GetInstance()->BeginRenderPass();
|
||||
}
|
||||
|
||||
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
const VKFramebuffer* vkfb = static_cast<const VKFramebuffer*>(framebuffer);
|
||||
BindFramebuffer(vkfb);
|
||||
|
||||
// If we're discarding, begin the discard pass, then switch to a load pass.
|
||||
// This way if the command buffer is flushed, we don't start another discard pass.
|
||||
StateTracker::GetInstance()->SetRenderPass(vkfb->GetDiscardRenderPass(),
|
||||
vkfb->GetClearRenderPass());
|
||||
StateTracker::GetInstance()->BeginRenderPass();
|
||||
StateTracker::GetInstance()->SetRenderPass(vkfb->GetLoadRenderPass(), vkfb->GetClearRenderPass());
|
||||
}
|
||||
|
||||
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value, float depth_value)
|
||||
{
|
||||
const VKFramebuffer* vkfb = static_cast<const VKFramebuffer*>(framebuffer);
|
||||
BindFramebuffer(vkfb);
|
||||
|
||||
const VkRect2D render_area = {static_cast<int>(vkfb->GetWidth()),
|
||||
static_cast<int>(vkfb->GetHeight())};
|
||||
std::array<VkClearValue, 2> clear_values;
|
||||
u32 num_clear_values = 0;
|
||||
if (vkfb->GetColorFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
std::memcpy(clear_values[num_clear_values].color.float32, color_value.data(),
|
||||
sizeof(clear_values[num_clear_values].color.float32));
|
||||
num_clear_values++;
|
||||
}
|
||||
if (vkfb->GetDepthFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
clear_values[num_clear_values].depthStencil.depth = depth_value;
|
||||
clear_values[num_clear_values].depthStencil.stencil = 0;
|
||||
num_clear_values++;
|
||||
}
|
||||
StateTracker::GetInstance()->BeginClearRenderPass(render_area, clear_values.data(),
|
||||
num_clear_values);
|
||||
}
|
||||
|
||||
void Renderer::SetRasterizationState(const RasterizationState& state)
|
||||
{
|
||||
StateTracker::GetInstance()->SetRasterizationState(state);
|
||||
|
||||
@@ -23,6 +23,7 @@ class SwapChain;
|
||||
class StagingTexture2D;
|
||||
class Texture2D;
|
||||
class RasterFont;
|
||||
class VKFramebuffer;
|
||||
class VKPipeline;
|
||||
class VKTexture;
|
||||
|
||||
@@ -37,6 +38,9 @@ public:
|
||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractStagingTexture>
|
||||
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
|
||||
size_t length) override;
|
||||
@@ -68,6 +72,11 @@ public:
|
||||
void RestoreAPIState() override;
|
||||
|
||||
void SetPipeline(const AbstractPipeline* pipeline) override;
|
||||
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value = {},
|
||||
float depth_value = 0.0f) override;
|
||||
void SetBlendingState(const BlendingState& state) override;
|
||||
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
|
||||
void SetRasterizationState(const RasterizationState& state) override;
|
||||
@@ -99,6 +108,7 @@ private:
|
||||
void OnSwapChainResized();
|
||||
void BindEFBToStateTracker();
|
||||
void RecreateEFBFramebuffer();
|
||||
void BindFramebuffer(const VKFramebuffer* fb);
|
||||
|
||||
void RecompileShaders();
|
||||
bool CompileShaders();
|
||||
|
||||
@@ -703,7 +703,8 @@ void StateTracker::EndRenderPass()
|
||||
m_current_render_pass = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue clear_values[2])
|
||||
void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue* clear_values,
|
||||
u32 num_clear_values)
|
||||
{
|
||||
_assert_(!InRenderPass());
|
||||
|
||||
@@ -715,7 +716,7 @@ void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue
|
||||
m_current_render_pass,
|
||||
m_framebuffer,
|
||||
m_framebuffer_render_area,
|
||||
2,
|
||||
num_clear_values,
|
||||
clear_values};
|
||||
|
||||
vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info,
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
{
|
||||
return m_bindings.ps_samplers;
|
||||
}
|
||||
VkFramebuffer GetFramebuffer() const { return m_framebuffer; }
|
||||
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset);
|
||||
void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type);
|
||||
|
||||
@@ -90,7 +91,8 @@ public:
|
||||
void EndRenderPass();
|
||||
|
||||
// Ends the current render pass if it was a clear render pass.
|
||||
void BeginClearRenderPass(const VkRect2D& area, const VkClearValue clear_values[2]);
|
||||
void BeginClearRenderPass(const VkRect2D& area, const VkClearValue* clear_values,
|
||||
u32 num_clear_values);
|
||||
void EndClearRenderPass();
|
||||
|
||||
void SetViewport(const VkViewport& viewport);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user