gl: Commit to bindless framebuffer object management

This commit is contained in:
kd-11 2022-05-27 00:39:56 +03:00 committed by kd-11
parent 7ec481d99b
commit 55e68441cb
4 changed files with 67 additions and 62 deletions

View file

@ -4,6 +4,7 @@
#include "GLCompute.h" #include "GLCompute.h"
#include "util/logs.hpp" #include "util/logs.hpp"
#include "../Common/simple_array.hpp"
#include <unordered_map> #include <unordered_map>
namespace gl namespace gl
@ -223,8 +224,7 @@ namespace gl
bool fbo::check() const bool fbo::check() const
{ {
save_binding_state save(*this); GLenum status = DSA_CALL2_RET(CheckNamedFramebufferStatus, m_id, GL_FRAMEBUFFER);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) if (status != GL_FRAMEBUFFER_COMPLETE)
{ {
@ -245,29 +245,24 @@ namespace gl
void fbo::draw_buffer(const attachment& buffer) const void fbo::draw_buffer(const attachment& buffer) const
{ {
save_binding_state save(*this);
GLenum buf = buffer.id(); GLenum buf = buffer.id();
glDrawBuffers(1, &buf); DSA_CALL3(NamedFramebufferDrawBuffers, FramebufferDrawBuffers, m_id, 1, &buf);
} }
void fbo::draw_buffers(const std::initializer_list<attachment>& indexes) const void fbo::draw_buffers(const std::initializer_list<attachment>& indexes) const
{ {
save_binding_state save(*this); rsx::simple_array<GLenum> ids;
std::vector<GLenum> ids;
ids.reserve(indexes.size()); ids.reserve(indexes.size());
for (auto &index : indexes) for (auto &index : indexes)
ids.push_back(index.id()); ids.push_back(index.id());
glDrawBuffers(::narrow<GLsizei>(ids.size()), ids.data()); DSA_CALL3(NamedFramebufferDrawBuffers, FramebufferDrawBuffers, m_id, static_cast<GLsizei>(ids.size()), ids.data());
} }
void fbo::read_buffer(const attachment& buffer) const void fbo::read_buffer(const attachment& buffer) const
{ {
save_binding_state save(*this); DSA_CALL3(NamedFramebufferReadBuffer, FramebufferReadBuffer, m_id, buffer.id());
GLenum buf = buffer.id();
glReadBuffer(buf);
} }
void fbo::draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first) const void fbo::draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first) const
@ -565,25 +560,25 @@ namespace gl
{ {
const bool is_depth_copy = (real_src->aspect() != image_aspect::color); const bool is_depth_copy = (real_src->aspect() != image_aspect::color);
const filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest; const filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest;
GLenum attachment; gl::fbo::attachment::type attachment;
gl::buffers target; gl::buffers target;
if (is_depth_copy) if (is_depth_copy)
{ {
if (real_dst->aspect() & gl::image_aspect::stencil) if (real_dst->aspect() & gl::image_aspect::stencil)
{ {
attachment = GL_DEPTH_STENCIL_ATTACHMENT; attachment = fbo::attachment::type::depth_stencil;
target = gl::buffers::depth_stencil; target = gl::buffers::depth_stencil;
} }
else else
{ {
attachment = GL_DEPTH_ATTACHMENT; attachment = fbo::attachment::type::depth;
target = gl::buffers::depth; target = gl::buffers::depth;
} }
} }
else else
{ {
attachment = GL_COLOR_ATTACHMENT0; attachment = fbo::attachment::type::color;
target = gl::buffers::color; target = gl::buffers::color;
} }
@ -591,11 +586,11 @@ namespace gl
save_binding_state saved; save_binding_state saved;
glBindFramebuffer(GL_READ_FRAMEBUFFER, blit_src.id()); gl::fbo::attachment src_att{blit_src, static_cast<fbo::attachment::type>(attachment)};
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_src->id(), 0); src_att = *real_src;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blit_dst.id()); gl::fbo::attachment dst_att{ blit_dst, static_cast<fbo::attachment::type>(attachment) };
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_dst->id(), 0); dst_att = *real_dst;
if (xfer_info.flip_horizontal) if (xfer_info.flip_horizontal)
{ {
@ -607,13 +602,11 @@ namespace gl
src_rect.flip_vertical(); src_rect.flip_vertical();
} }
glBlitFramebuffer(src_rect.x1, src_rect.y1, src_rect.x2, src_rect.y2, blit_src.blit(blit_dst, src_rect, dst_rect, target, interp);
dst_rect.x1, dst_rect.y1, dst_rect.x2, dst_rect.y2,
static_cast<GLbitfield>(target), static_cast<GLenum>(interp));
// Release the attachments explicitly (not doing so causes glitches, e.g Journey Menu) // Release the attachments explicitly (not doing so causes glitches, e.g Journey Menu)
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); src_att = GL_NONE;
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); dst_att = GL_NONE;
} }
if (xfer_info.dst_is_typeless) if (xfer_info.dst_is_typeless)
@ -628,19 +621,19 @@ namespace gl
save_binding_state saved; save_binding_state saved;
blit_dst.bind(); blit_dst.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->id(), 0); blit_dst.color[0] = *dst;
blit_dst.check(); blit_dst.check();
cmd->clear_color(color); cmd->clear_color(color);
cmd->color_maski(0, true, true, true, true); cmd->color_maski(0, true, true, true, true);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, GL_NONE, 0); blit_dst.color[0] = GL_NONE;
} }
void blitter::fast_clear_image(gl::command_context& cmd, const texture* dst, float /*depth*/, u8 /*stencil*/) void blitter::fast_clear_image(gl::command_context& cmd, const texture* dst, float /*depth*/, u8 /*stencil*/)
{ {
GLenum attachment; fbo::attachment::type attachment;
GLbitfield clear_mask; GLbitfield clear_mask;
switch (const auto fmt = dst->get_internal_format()) switch (const auto fmt = dst->get_internal_format())
@ -648,27 +641,28 @@ namespace gl
case texture::internal_format::depth16: case texture::internal_format::depth16:
case texture::internal_format::depth32f: case texture::internal_format::depth32f:
clear_mask = GL_DEPTH_BUFFER_BIT; clear_mask = GL_DEPTH_BUFFER_BIT;
attachment = GL_DEPTH_ATTACHMENT; attachment = fbo::attachment::type::depth;
break; break;
case texture::internal_format::depth24_stencil8: case texture::internal_format::depth24_stencil8:
case texture::internal_format::depth32f_stencil8: case texture::internal_format::depth32f_stencil8:
clear_mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; clear_mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
attachment = GL_DEPTH_STENCIL_ATTACHMENT; attachment = fbo::attachment::type::depth_stencil;
break; break;
default: default:
fmt::throw_exception("Invalid texture passed to clear depth function, format=0x%x", static_cast<u32>(fmt)); fmt::throw_exception("Invalid texture passed to clear depth function, format=0x%x", static_cast<u32>(fmt));
} }
save_binding_state saved; save_binding_state saved;
fbo::attachment attach_point{ blit_dst, attachment };
blit_dst.bind(); blit_dst.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst->id(), 0); attach_point = *dst;
blit_dst.check(); blit_dst.check();
cmd->depth_mask(GL_TRUE); cmd->depth_mask(GL_TRUE);
cmd->stencil_mask(0xFF); cmd->stencil_mask(0xFF);
glClear(clear_mask); glClear(clear_mask);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); attach_point = GL_NONE;
} }
} }

View file

@ -66,6 +66,12 @@ namespace gl
gl##func(object_name, __VA_ARGS__) :\ gl##func(object_name, __VA_ARGS__) :\
gl##func##EXT(object_name, __VA_ARGS__) gl##func##EXT(object_name, __VA_ARGS__)
#define DSA_CALL3(funcARB, funcDSA, ...)\
if (::gl::get_driver_caps().ARB_dsa_supported)\
gl##funcARB(__VA_ARGS__);\
else\
gl##funcDSA##EXT(__VA_ARGS__);
class fence; class fence;
void enable_debugging(); void enable_debugging();
@ -2090,6 +2096,10 @@ public:
GLuint m_id = GL_NONE; GLuint m_id = GL_NONE;
fbo &m_parent; fbo &m_parent;
attachment(fbo& parent)
: m_parent(parent)
{}
public: public:
attachment(fbo& parent, type type) attachment(fbo& parent, type type)
: m_id(static_cast<int>(type)) : m_id(static_cast<int>(type))
@ -2120,25 +2130,21 @@ public:
void operator = (const rbo& rhs) void operator = (const rbo& rhs)
{ {
save_binding_state save(m_parent);
m_parent.m_resource_bindings[m_id] = rhs.id(); m_parent.m_resource_bindings[m_id] = rhs.id();
glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_id, GL_RENDERBUFFER, rhs.id()); DSA_CALL2(NamedFramebufferRenderbuffer, m_parent.id(), m_id, GL_RENDERBUFFER, rhs.id());
} }
void operator = (const texture& rhs) void operator = (const texture& rhs)
{ {
save_binding_state save(m_parent);
ensure(rhs.get_target() == texture::target::texture2D); ensure(rhs.get_target() == texture::target::texture2D);
m_parent.m_resource_bindings[m_id] = rhs.id(); m_parent.m_resource_bindings[m_id] = rhs.id();
glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs.id(), 0); DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs.id(), 0);
} }
void operator = (const GLuint rhs) void operator = (const GLuint rhs)
{ {
save_binding_state save(m_parent);
m_parent.m_resource_bindings[m_id] = rhs; m_parent.m_resource_bindings[m_id] = rhs;
glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs, 0); DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs, 0);
} }
}; };
@ -2167,10 +2173,18 @@ public:
using attachment::operator =; using attachment::operator =;
}; };
struct null_attachment : public attachment
{
null_attachment(fbo& parent)
: attachment(parent)
{}
};
indexed_attachment color{ *this, attachment::type::color }; indexed_attachment color{ *this, attachment::type::color };
attachment depth{ *this, attachment::type::depth }; attachment depth{ *this, attachment::type::depth };
attachment stencil{ *this, attachment::type::stencil }; attachment stencil{ *this, attachment::type::stencil };
attachment depth_stencil{ *this, attachment::type::depth_stencil }; attachment depth_stencil{ *this, attachment::type::depth_stencil };
null_attachment no_color{ *this };
enum class target enum class target
{ {

View file

@ -77,28 +77,26 @@ namespace gl
return; return;
} }
GLint old_fbo;
GLint viewport[4]; GLint viewport[4];
std::unique_ptr<fbo::save_binding_state> save_fbo;
if (target_texture) if (target_texture)
{ {
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); save_fbo = std::make_unique<fbo::save_binding_state>(fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo.id());
if (depth_target) if (depth_target)
{ {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target_texture, 0); fbo.draw_buffer(fbo.no_color);
glDrawBuffer(GL_NONE); fbo.depth_stencil = target_texture;
} }
else else
{ {
GLenum buffer = GL_COLOR_ATTACHMENT0; fbo.color[0] = target_texture;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target_texture, 0); fbo.draw_buffer(fbo.color[0]);
glDrawBuffers(1, &buffer);
} }
} }
if (!target_texture || glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) if (!target_texture || fbo.check())
{ {
// Set initial state // Set initial state
glViewport(region.x1, region.y1, region.width(), region.height()); glViewport(region.x1, region.y1, region.width(), region.height());
@ -130,18 +128,13 @@ namespace gl
bind_resources(); bind_resources();
emit_geometry(); emit_geometry();
// Clean up glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
if (target_texture) if (target_texture)
{ {
if (depth_target) fbo.color[0] = GL_NONE;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); fbo.depth_stencil = GL_NONE;
else
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
} }
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
} }
else else
{ {

View file

@ -147,12 +147,15 @@ OPENGL_PROC(PFNGLRENDERBUFFERSTORAGEPROC, RenderbufferStorage);
OPENGL_PROC(PFNGLBINDFRAMEBUFFERPROC, BindFramebuffer); OPENGL_PROC(PFNGLBINDFRAMEBUFFERPROC, BindFramebuffer);
OPENGL_PROC(PFNGLDELETEFRAMEBUFFERSPROC, DeleteFramebuffers); OPENGL_PROC(PFNGLDELETEFRAMEBUFFERSPROC, DeleteFramebuffers);
OPENGL_PROC(PFNGLGENFRAMEBUFFERSPROC, GenFramebuffers); OPENGL_PROC(PFNGLGENFRAMEBUFFERSPROC, GenFramebuffers);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE1DPROC, FramebufferTexture1D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE3DPROC, FramebufferTexture3D);
OPENGL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer); OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer);
OPENGL_PROC(PFNGLDRAWBUFFERSPROC, DrawBuffers); OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC, NamedFramebufferRenderbuffer);
OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC, NamedFramebufferRenderbufferEXT);
OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERTEXTUREPROC, NamedFramebufferTexture);
OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC, NamedFramebufferTextureEXT);
OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC, NamedFramebufferDrawBuffers);
OPENGL_PROC(PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC, FramebufferDrawBuffersEXT);
OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC, NamedFramebufferReadBuffer);
OPENGL_PROC(PFNGLFRAMEBUFFERREADBUFFEREXTPROC, FramebufferReadBufferEXT);
OPENGL_PROC(PFNGLENABLEIPROC, Enablei); OPENGL_PROC(PFNGLENABLEIPROC, Enablei);
OPENGL_PROC(PFNGLDISABLEIPROC, Disablei); OPENGL_PROC(PFNGLDISABLEIPROC, Disablei);
@ -166,7 +169,8 @@ OPENGL_PROC(PFNGLGETINTEGER64VPROC, GetInteger64v);
OPENGL_PROC(PFNGLGETSTRINGIPROC, GetStringi); OPENGL_PROC(PFNGLGETSTRINGIPROC, GetStringi);
OPENGL_PROC(PFNGLGETINTEGERI_VPROC, GetIntegeri_v); OPENGL_PROC(PFNGLGETINTEGERI_VPROC, GetIntegeri_v);
OPENGL_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, CheckFramebufferStatus); OPENGL_PROC(PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC, CheckNamedFramebufferStatus);
OPENGL_PROC(PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC, CheckNamedFramebufferStatusEXT);
OPENGL_PROC(PFNGLBINDBUFFERRANGEPROC, BindBufferRange); OPENGL_PROC(PFNGLBINDBUFFERRANGEPROC, BindBufferRange);
OPENGL_PROC(PFNGLBINDBUFFERBASEPROC, BindBufferBase); OPENGL_PROC(PFNGLBINDBUFFERBASEPROC, BindBufferBase);