mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-23 04:55:22 +00:00
gl: Reuse framebuffer resources
- WIP optimizations for GL backend
This commit is contained in:
parent
cca488d0cf
commit
8c93db342f
5 changed files with 139 additions and 47 deletions
|
@ -269,7 +269,7 @@ void GLGSRender::end()
|
|||
GLfloat colors[] = { 0.f, 0.f, 0.f, 0.f };
|
||||
//It is impossible for the render target to be type A or B here (clear all would have been flagged)
|
||||
for (auto &i : buffers_to_clear)
|
||||
glClearBufferfv(draw_fbo.id(), i, colors);
|
||||
glClearBufferfv(m_draw_fbo->id(), i, colors);
|
||||
}
|
||||
|
||||
if (clear_depth)
|
||||
|
@ -924,11 +924,13 @@ void GLGSRender::on_exit()
|
|||
|
||||
m_prog_buffer.clear();
|
||||
|
||||
if (draw_fbo)
|
||||
for (auto &fbo : m_framebuffer_cache)
|
||||
{
|
||||
draw_fbo.remove();
|
||||
fbo.remove();
|
||||
}
|
||||
|
||||
m_framebuffer_cache.clear();
|
||||
|
||||
if (m_flip_fbo)
|
||||
{
|
||||
m_flip_fbo.remove();
|
||||
|
@ -1596,6 +1598,16 @@ void GLGSRender::flip(int buffer)
|
|||
m_rtts.free_invalidated();
|
||||
m_vertex_cache->purge();
|
||||
|
||||
if (m_framebuffer_cache.size() > 32)
|
||||
{
|
||||
for (auto &fbo : m_framebuffer_cache)
|
||||
{
|
||||
fbo.remove();
|
||||
}
|
||||
|
||||
m_framebuffer_cache.clear();
|
||||
}
|
||||
|
||||
//If we are skipping the next frame, do not reset perf counters
|
||||
if (skip_frame) return;
|
||||
|
||||
|
|
|
@ -331,7 +331,8 @@ private:
|
|||
draw_context_t m_decompiler_context;
|
||||
|
||||
//buffer
|
||||
gl::fbo draw_fbo;
|
||||
gl::fbo* m_draw_fbo = nullptr;
|
||||
std::list<gl::fbo> m_framebuffer_cache;
|
||||
gl::fbo m_flip_fbo;
|
||||
std::unique_ptr<gl::texture> m_flip_tex_color;
|
||||
|
||||
|
|
|
@ -306,6 +306,20 @@ namespace gl
|
|||
return m_size;
|
||||
}
|
||||
|
||||
bool fbo::matches(std::array<GLuint, 4> color_targets, GLuint depth_stencil_target)
|
||||
{
|
||||
for (u32 index = 0; index < 4; ++index)
|
||||
{
|
||||
if (color[index].resource_id() != color_targets[index])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto depth_resource = depth.resource_id() | depth_stencil.resource_id();
|
||||
return depth_resource == depth_stencil_target;
|
||||
}
|
||||
|
||||
bool is_primitive_native(rsx::primitive_type in)
|
||||
{
|
||||
switch (in)
|
||||
|
|
|
@ -2026,6 +2026,9 @@ public:
|
|||
GLuint m_id = GL_NONE;
|
||||
size2i m_size;
|
||||
|
||||
protected:
|
||||
std::unordered_map<GLenum, GLuint> m_resource_bindings;
|
||||
|
||||
public:
|
||||
fbo() = default;
|
||||
|
||||
|
@ -2095,9 +2098,21 @@ public:
|
|||
return m_id;
|
||||
}
|
||||
|
||||
GLuint resource_id() const
|
||||
{
|
||||
const auto found = m_parent.m_resource_bindings.find(m_id);
|
||||
if (found != m_parent.m_resource_bindings.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
return GL_NONE;
|
||||
}
|
||||
|
||||
void operator = (const rbo& rhs)
|
||||
{
|
||||
save_binding_state save(m_parent);
|
||||
m_parent.m_resource_bindings[m_id] = rhs.id();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_id, GL_RENDERBUFFER, rhs.id());
|
||||
}
|
||||
|
||||
|
@ -2106,12 +2121,14 @@ public:
|
|||
save_binding_state save(m_parent);
|
||||
|
||||
verify(HERE), rhs.get_target() == texture::target::texture2D;
|
||||
m_parent.m_resource_bindings[m_id] = rhs.id();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs.id(), 0);
|
||||
}
|
||||
|
||||
void operator = (const GLuint rhs)
|
||||
{
|
||||
save_binding_state save(m_parent);
|
||||
m_parent.m_resource_bindings[m_id] = rhs;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs, 0);
|
||||
}
|
||||
};
|
||||
|
@ -2200,6 +2217,8 @@ public:
|
|||
void set_extents(size2i extents);
|
||||
size2i get_extents() const;
|
||||
|
||||
bool matches(std::array<GLuint, 4> color_targets, GLuint depth_stencil_target);
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return created();
|
||||
|
|
|
@ -179,7 +179,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
m_rtts_dirty = true;
|
||||
}
|
||||
|
||||
if (draw_fbo && !m_rtts_dirty)
|
||||
if (m_draw_fbo && !m_rtts_dirty)
|
||||
{
|
||||
set_viewport();
|
||||
return;
|
||||
|
@ -195,7 +195,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
return;
|
||||
}
|
||||
|
||||
if (draw_fbo && layout.ignore_change)
|
||||
if (m_draw_fbo && layout.ignore_change)
|
||||
{
|
||||
// Nothing has changed, we're still using the same framebuffer
|
||||
// Update flags to match current
|
||||
|
@ -218,13 +218,12 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
m_rtts.prepare_render_target(nullptr, layout.color_format, layout.depth_format, layout.width, layout.height,
|
||||
layout.target, layout.color_addresses, layout.zeta_address);
|
||||
|
||||
draw_fbo.recreate();
|
||||
draw_fbo.bind();
|
||||
draw_fbo.set_extents({ (int)layout.width, (int)layout.height });
|
||||
|
||||
bool old_format_found = false;
|
||||
gl::texture::format old_format;
|
||||
|
||||
std::array<GLuint, 4> color_targets;
|
||||
GLuint depth_stencil_target;
|
||||
|
||||
const auto color_offsets = get_offsets();
|
||||
const auto color_locations = get_locations();
|
||||
|
||||
|
@ -245,7 +244,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
if (std::get<0>(m_rtts.m_bound_render_targets[i]))
|
||||
{
|
||||
auto rtt = std::get<1>(m_rtts.m_bound_render_targets[i]);
|
||||
draw_fbo.color[i] = *rtt;
|
||||
color_targets[i] = rtt->id();
|
||||
|
||||
rtt->set_rsx_pitch(layout.color_pitch[i]);
|
||||
m_surface_info[i] = { layout.color_addresses[i], layout.actual_color_pitch[i], false, layout.color_format, layout.depth_format, layout.width, layout.height };
|
||||
|
@ -256,7 +255,10 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
m_gl_texture_cache.tag_framebuffer(m_surface_info[i].address);
|
||||
}
|
||||
else
|
||||
{
|
||||
color_targets[i] = GL_NONE;
|
||||
m_surface_info[i] = {};
|
||||
}
|
||||
}
|
||||
|
||||
if (std::get<0>(m_rtts.m_bound_depth_stencil))
|
||||
|
@ -271,10 +273,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
}
|
||||
|
||||
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||
if (layout.depth_format == rsx::surface_depth_format::z24s8)
|
||||
draw_fbo.depth_stencil = *ds;
|
||||
else
|
||||
draw_fbo.depth = *ds;
|
||||
depth_stencil_target = ds->id();
|
||||
|
||||
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
|
||||
m_depth_surface_info = { layout.zeta_address, layout.actual_zeta_pitch, true, layout.color_format, layout.depth_format, layout.width, layout.height };
|
||||
|
@ -284,44 +283,91 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
m_gl_texture_cache.tag_framebuffer(layout.zeta_address);
|
||||
}
|
||||
else
|
||||
{
|
||||
depth_stencil_target = GL_NONE;
|
||||
m_depth_surface_info = {};
|
||||
}
|
||||
|
||||
framebuffer_status_valid = draw_fbo.check();
|
||||
framebuffer_status_valid = false;
|
||||
|
||||
for (auto &fbo : m_framebuffer_cache)
|
||||
{
|
||||
if (fbo.matches(color_targets, depth_stencil_target))
|
||||
{
|
||||
m_draw_fbo = &fbo;
|
||||
framebuffer_status_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!framebuffer_status_valid)
|
||||
{
|
||||
m_framebuffer_cache.emplace_back();
|
||||
m_draw_fbo = &m_framebuffer_cache.back();
|
||||
m_draw_fbo->create();
|
||||
m_draw_fbo->bind();
|
||||
m_draw_fbo->set_extents({ (int)layout.width, (int)layout.height });
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (color_targets[i])
|
||||
{
|
||||
m_draw_fbo->color[i] = color_targets[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_stencil_target)
|
||||
{
|
||||
if (layout.depth_format == rsx::surface_depth_format::z24s8)
|
||||
{
|
||||
m_draw_fbo->depth_stencil = depth_stencil_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_draw_fbo->depth = depth_stencil_target;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rsx::method_registers.surface_color_target())
|
||||
{
|
||||
case rsx::surface_target::none: break;
|
||||
|
||||
case rsx::surface_target::surface_a:
|
||||
m_draw_fbo->draw_buffer(m_draw_fbo->color[0]);
|
||||
m_draw_fbo->read_buffer(m_draw_fbo->color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surface_b:
|
||||
m_draw_fbo->draw_buffer(m_draw_fbo->color[1]);
|
||||
m_draw_fbo->read_buffer(m_draw_fbo->color[1]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b:
|
||||
m_draw_fbo->draw_buffers({ m_draw_fbo->color[0], m_draw_fbo->color[1] });
|
||||
m_draw_fbo->read_buffer(m_draw_fbo->color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b_c:
|
||||
m_draw_fbo->draw_buffers({ m_draw_fbo->color[0], m_draw_fbo->color[1], m_draw_fbo->color[2] });
|
||||
m_draw_fbo->read_buffer(m_draw_fbo->color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b_c_d:
|
||||
m_draw_fbo->draw_buffers({ m_draw_fbo->color[0], m_draw_fbo->color[1], m_draw_fbo->color[2], m_draw_fbo->color[3] });
|
||||
m_draw_fbo->read_buffer(m_draw_fbo->color[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
framebuffer_status_valid = m_draw_fbo->check();
|
||||
}
|
||||
|
||||
if (!framebuffer_status_valid) return;
|
||||
|
||||
m_draw_fbo->bind();
|
||||
|
||||
check_zcull_status(true);
|
||||
set_viewport();
|
||||
|
||||
switch (rsx::method_registers.surface_color_target())
|
||||
{
|
||||
case rsx::surface_target::none: break;
|
||||
|
||||
case rsx::surface_target::surface_a:
|
||||
draw_fbo.draw_buffer(draw_fbo.color[0]);
|
||||
draw_fbo.read_buffer(draw_fbo.color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surface_b:
|
||||
draw_fbo.draw_buffer(draw_fbo.color[1]);
|
||||
draw_fbo.read_buffer(draw_fbo.color[1]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b:
|
||||
draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1] });
|
||||
draw_fbo.read_buffer(draw_fbo.color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b_c:
|
||||
draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2] });
|
||||
draw_fbo.read_buffer(draw_fbo.color[0]);
|
||||
break;
|
||||
|
||||
case rsx::surface_target::surfaces_a_b_c_d:
|
||||
draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2], draw_fbo.color[3] });
|
||||
draw_fbo.read_buffer(draw_fbo.color[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
m_gl_texture_cache.clear_ro_tex_invalidate_intr();
|
||||
|
||||
//Mark buffer regions as NO_ACCESS on Cell visible side
|
||||
|
@ -373,7 +419,7 @@ std::array<std::vector<gsl::byte>, 2> GLGSRender::copy_depth_stencil_buffer_to_m
|
|||
|
||||
void GLGSRender::read_buffers()
|
||||
{
|
||||
if (!draw_fbo)
|
||||
if (!m_draw_fbo)
|
||||
return;
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
|
Loading…
Add table
Reference in a new issue