VideoBackends: add support to allow rendering to multiple output textures

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

View File

@ -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;

View File

@ -77,6 +77,7 @@ struct VideoConfig
bool bSupportsTextureSubImage;
EsFbFetchType SupportedFramebufferFetch;
bool bSupportsKHRShaderSubgroup; // basic + arithmetic + ballot
bool bSupportsExplicitLayoutInShader;
const char* gl_vendor;
const char* gl_renderer;

View File

@ -128,8 +128,8 @@ OGLGfx::OGLGfx(std::unique_ptr<GLContext> main_gl_context, float backbuffer_scal
if (!m_main_gl_context->IsHeadless())
{
m_system_framebuffer = std::make_unique<OGLFramebuffer>(
nullptr, nullptr, AbstractTextureFormat::RGBA8, AbstractTextureFormat::Undefined,
std::max(m_main_gl_context->GetBackBufferWidth(), 1u),
nullptr, nullptr, std::vector<AbstractTexture*>{}, AbstractTextureFormat::RGBA8,
AbstractTextureFormat::Undefined, std::max(m_main_gl_context->GetBackBufferWidth(), 1u),
std::max(m_main_gl_context->GetBackBufferHeight(), 1u), 1, 1, 0);
m_current_framebuffer = m_system_framebuffer.get();
}
@ -226,11 +226,13 @@ std::unique_ptr<AbstractStagingTexture> OGLGfx::CreateStagingTexture(StagingText
return OGLStagingTexture::Create(type, config);
}
std::unique_ptr<AbstractFramebuffer> OGLGfx::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment)
std::unique_ptr<AbstractFramebuffer>
OGLGfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments)
{
return OGLFramebuffer::Create(static_cast<OGLTexture*>(color_attachment),
static_cast<OGLTexture*>(depth_attachment));
static_cast<OGLTexture*>(depth_attachment),
std::move(additional_color_attachments));
}
std::unique_ptr<AbstractShader>

View File

@ -36,7 +36,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;

View File

@ -543,11 +543,13 @@ void OGLStagingTexture::Unmap()
}
OGLFramebuffer::OGLFramebuffer(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, GLuint fbo)
: 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),
m_fbo(fbo)
{
}
@ -557,10 +559,11 @@ OGLFramebuffer::~OGLFramebuffer()
glDeleteFramebuffers(1, &m_fbo);
}
std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(OGLTexture* color_attachment,
OGLTexture* depth_attachment)
std::unique_ptr<OGLFramebuffer>
OGLFramebuffer::Create(OGLTexture* color_attachment, OGLTexture* 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 =
@ -577,6 +580,7 @@ std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(OGLTexture* color_attachm
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
std::vector<GLenum> buffers;
if (color_attachment)
{
if (color_attachment->GetConfig().layers > 1)
@ -589,6 +593,7 @@ std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(OGLTexture* color_attachm
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
color_attachment->GetGLTextureId(), 0, 0);
}
buffers.push_back(GL_COLOR_ATTACHMENT0);
}
if (depth_attachment)
@ -607,10 +612,29 @@ std::unique_ptr<OGLFramebuffer> OGLFramebuffer::Create(OGLTexture* color_attachm
}
}
for (std::size_t i = 0; i < additional_color_attachments.size(); i++)
{
const auto attachment_enum = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i + 1);
OGLTexture* attachment = static_cast<OGLTexture*>(additional_color_attachments[i]);
if (attachment->GetConfig().layers > 1)
{
glFramebufferTexture(GL_FRAMEBUFFER, attachment_enum, attachment->GetGLTextureId(), 0);
}
else
{
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment_enum, attachment->GetGLTextureId(), 0,
0);
}
buffers.push_back(attachment_enum);
}
glDrawBuffers(static_cast<GLsizei>(buffers.size()), buffers.data());
DEBUG_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
GetOGLGfx()->RestoreFramebufferBinding();
return std::make_unique<OGLFramebuffer>(color_attachment, depth_attachment, color_format,
return std::make_unique<OGLFramebuffer>(color_attachment, depth_attachment,
std::move(additional_color_attachments), color_format,
depth_format, width, height, layers, samples, fbo);
}

View File

@ -82,12 +82,14 @@ class OGLFramebuffer final : public AbstractFramebuffer
{
public:
OGLFramebuffer(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, GLuint fbo);
~OGLFramebuffer() override;
static std::unique_ptr<OGLFramebuffer> Create(OGLTexture* color_attachment,
OGLTexture* depth_attachment);
static std::unique_ptr<OGLFramebuffer>
Create(OGLTexture* color_attachment, OGLTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments);
GLuint GetFBO() const { return m_fbo; }

View File

@ -126,6 +126,10 @@ void SHADER::SetProgramVariables()
void SHADER::SetProgramBindings(bool is_compute)
{
if (g_ogl_config.bSupportsExplicitLayoutInShader)
{
return;
}
if (!is_compute)
{
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
@ -729,6 +733,49 @@ void ProgramShaderCache::CreateHeader()
v >= GlslEs320 ||
g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone;
std::string binding_layout;
if (g_ActiveConfig.backend_info.bSupportsBindingLayout)
{
if (g_ogl_config.bSupportsExplicitLayoutInShader)
{
binding_layout =
"#extension GL_ARB_explicit_attrib_location : enable\n"
"#define ATTRIBUTE_LOCATION(x) layout(location = x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x) layout(location = x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y) layout(location = x, index = y)\n"
"#define UBO_BINDING(packing, x) layout(packing, binding = x)\n"
"#define SAMPLER_BINDING(x) layout(binding = x)\n"
"#define TEXEL_BUFFER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(std430, binding = x)\n"
"#define IMAGE_BINDING(format, x) layout(format, binding = x)\n";
}
else
{
binding_layout = "#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing, binding = x)\n"
"#define SAMPLER_BINDING(x) layout(binding = x)\n"
"#define TEXEL_BUFFER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(std430, binding = x)\n"
"#define IMAGE_BINDING(format, x) layout(format, binding = x)\n";
}
}
else
{
binding_layout = "#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing)\n"
"#define SAMPLER_BINDING(x)\n"
"#define TEXEL_BUFFER_BINDING(x)\n"
"#define SSBO_BINDING(x) layout(std430)\n"
"#define IMAGE_BINDING(format, x) layout(format)\n";
}
// TODO: actually define this if using 'bSupportsExplicitLayoutInShader'
const std::string varying_location = "#define VARYING_LOCATION(x)\n";
std::string shader_shuffle_string;
if (g_ogl_config.bSupportsKHRShaderSubgroup)
{
@ -799,28 +846,7 @@ void ProgramShaderCache::CreateHeader()
(g_ogl_config.bSupportsMSAA && v < Glsl150) ?
"#extension GL_ARB_texture_multisample : enable" :
"",
// Attribute and fragment output bindings are still done via glBindAttribLocation and
// glBindFragDataLocation. In the future this could be moved to the layout qualifier
// in GLSL, but requires verification of GL_ARB_explicit_attrib_location.
g_ActiveConfig.backend_info.bSupportsBindingLayout ?
"#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing, binding = x)\n"
"#define SAMPLER_BINDING(x) layout(binding = x)\n"
"#define TEXEL_BUFFER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(std430, binding = x)\n"
"#define IMAGE_BINDING(format, x) layout(format, binding = x)\n" :
"#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing)\n"
"#define SAMPLER_BINDING(x)\n"
"#define TEXEL_BUFFER_BINDING(x)\n"
"#define SSBO_BINDING(x) layout(std430)\n"
"#define IMAGE_BINDING(format, x) layout(format)\n",
// Input/output blocks are matched by name during program linking
"#define VARYING_LOCATION(x)\n",
binding_layout.c_str(), varying_location.c_str(),
!is_glsles && g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics ?
"#extension GL_ARB_shader_storage_buffer_object : enable" :
"",