rsx/gl/vk: Enable frame skipping

This commit is contained in:
kd-11 2017-06-30 01:20:23 +03:00
parent b95ffaf4dd
commit e9b8f94fb1
10 changed files with 102 additions and 26 deletions

View file

@ -186,6 +186,9 @@ void GLGSRender::begin()
{ {
rsx::thread::begin(); rsx::thread::begin();
if (skip_frame)
return;
init_buffers(); init_buffers();
if (!draw_fbo.check()) if (!draw_fbo.check())
@ -319,7 +322,7 @@ namespace
void GLGSRender::end() void GLGSRender::end()
{ {
if (!draw_fbo || !draw_fbo.check()) if (skip_frame || !draw_fbo || !draw_fbo.check())
{ {
rsx::thread::end(); rsx::thread::end();
return; return;
@ -688,13 +691,9 @@ void GLGSRender::on_exit()
void GLGSRender::clear_surface(u32 arg) void GLGSRender::clear_surface(u32 arg)
{ {
if (skip_frame) return;
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return; if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
if ((arg & 0xf3) == 0) return;
if ((arg & 0xf3) == 0)
{
//do nothing
return;
}
GLbitfield mask = 0; GLbitfield mask = 0;
@ -864,6 +863,23 @@ bool GLGSRender::load_program()
void GLGSRender::flip(int buffer) void GLGSRender::flip(int buffer)
{ {
if (skip_frame)
{
m_frame->flip(m_context, true);
rsx::thread::flip(buffer);
if (!skip_frame)
{
m_draw_calls = 0;
m_begin_time = 0;
m_draw_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
}
return;
}
u32 buffer_width = gcm_buffers[buffer].width; u32 buffer_width = gcm_buffers[buffer].width;
u32 buffer_height = gcm_buffers[buffer].height; u32 buffer_height = gcm_buffers[buffer].height;
u32 buffer_pitch = gcm_buffers[buffer].pitch; u32 buffer_pitch = gcm_buffers[buffer].pitch;
@ -963,24 +979,26 @@ void GLGSRender::flip(int buffer)
} }
m_frame->flip(m_context); m_frame->flip(m_context);
rsx::thread::flip(buffer);
m_gl_texture_cache.clear_temporary_surfaces();
for (auto &tex : m_rtts.invalidated_resources)
tex->remove();
m_rtts.invalidated_resources.clear();
if (g_cfg.video.invalidate_surface_cache_every_frame)
m_rtts.invalidate_surface_cache_data(nullptr);
//If we are skipping the next frame, fo not reset perf counters
if (skip_frame) return;
m_draw_calls = 0; m_draw_calls = 0;
m_begin_time = 0; m_begin_time = 0;
m_draw_time = 0; m_draw_time = 0;
m_vertex_upload_time = 0; m_vertex_upload_time = 0;
m_textures_upload_time = 0; m_textures_upload_time = 0;
m_gl_texture_cache.clear_temporary_surfaces();
for (auto &tex : m_rtts.invalidated_resources)
{
tex->remove();
}
m_rtts.invalidated_resources.clear();
if (g_cfg.video.invalidate_surface_cache_every_frame)
m_rtts.invalidate_surface_cache_data(nullptr);
} }

View file

@ -36,7 +36,7 @@ public:
draw_context_t new_context(); draw_context_t new_context();
virtual void set_current(draw_context_t ctx) = 0; virtual void set_current(draw_context_t ctx) = 0;
virtual void flip(draw_context_t ctx) = 0; virtual void flip(draw_context_t ctx, bool skip_frame=false) = 0;
virtual int client_width() = 0; virtual int client_width() = 0;
virtual int client_height() = 0; virtual int client_height() = 0;

View file

@ -1228,4 +1228,17 @@ namespace rsx
return (m_vertex_streaming_task.remaining_packets == 0 && m_vertex_streaming_task.ready_threads == 0); return (m_vertex_streaming_task.remaining_packets == 0 && m_vertex_streaming_task.ready_threads == 0);
} }
void thread::flip(int buffer)
{
if (g_cfg.video.frame_skip_enabled)
{
m_skip_frame_ctr++;
if (m_skip_frame_ctr == g_cfg.video.consequtive_frames_to_draw)
m_skip_frame_ctr = -g_cfg.video.consequtive_frames_to_skip;
skip_frame = (m_skip_frame_ctr < 0);
}
}
} }

View file

@ -151,6 +151,10 @@ namespace rsx
bool m_textures_dirty[16]; bool m_textures_dirty[16];
bool m_vertex_attribs_changed; bool m_vertex_attribs_changed;
bool m_index_buffer_changed; bool m_index_buffer_changed;
protected:
s32 m_skip_frame_ctr = 0;
bool skip_frame = false;
protected: protected:
std::array<u32, 4> get_color_surface_addresses() const; std::array<u32, 4> get_color_surface_addresses() const;
u32 get_zeta_surface_address() const; u32 get_zeta_surface_address() const;

View file

@ -795,6 +795,9 @@ void VKGSRender::begin()
{ {
rsx::thread::begin(); rsx::thread::begin();
if (skip_frame)
return;
//Ease resource pressure if the number of draw calls becomes too high or we are running low on memory resources //Ease resource pressure if the number of draw calls becomes too high or we are running low on memory resources
if (m_used_descriptors >= DESCRIPTOR_MAX_DRAW_CALLS || if (m_used_descriptors >= DESCRIPTOR_MAX_DRAW_CALLS ||
m_attrib_ring_info.is_critical() || m_attrib_ring_info.is_critical() ||
@ -895,6 +898,12 @@ void VKGSRender::close_render_pass()
void VKGSRender::end() void VKGSRender::end()
{ {
if (skip_frame)
{
rsx::thread::end();
return;
}
std::chrono::time_point<steady_clock> program_start = steady_clock::now(); std::chrono::time_point<steady_clock> program_start = steady_clock::now();
const bool is_instanced = is_probable_instanced_draw() && m_last_descriptor_set != VK_NULL_HANDLE && m_program != nullptr; const bool is_instanced = is_probable_instanced_draw() && m_last_descriptor_set != VK_NULL_HANDLE && m_program != nullptr;
@ -1159,6 +1168,8 @@ void VKGSRender::on_exit()
void VKGSRender::clear_surface(u32 mask) void VKGSRender::clear_surface(u32 mask)
{ {
if (skip_frame) return;
// Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE // Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return; if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
@ -1870,6 +1881,24 @@ void VKGSRender::prepare_rtts()
void VKGSRender::flip(int buffer) void VKGSRender::flip(int buffer)
{ {
if (skip_frame)
{
m_frame->flip(m_context);
rsx::thread::flip(buffer);
if (!skip_frame)
{
m_draw_calls = 0;
m_instanced_draws = 0;
m_draw_time = 0;
m_setup_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
}
return;
}
bool resize_screen = false; bool resize_screen = false;
if (m_client_height != m_frame->client_height() || if (m_client_height != m_frame->client_height() ||
@ -2062,7 +2091,13 @@ void VKGSRender::flip(int buffer)
m_attrib_ring_info.reset_allocation_stats(); m_attrib_ring_info.reset_allocation_stats();
m_texture_upload_buffer_ring_info.reset_allocation_stats(); m_texture_upload_buffer_ring_info.reset_allocation_stats();
//Resource destruction is handled within the real swap handler //NOTE:Resource destruction is handled within the real swap handler
m_frame->flip(m_context);
rsx::thread::flip(buffer);
//Do not reset perf counters if we are skipping the next frame
if (skip_frame) return;
m_draw_calls = 0; m_draw_calls = 0;
m_instanced_draws = 0; m_instanced_draws = 0;
@ -2070,5 +2105,4 @@ void VKGSRender::flip(int buffer)
m_setup_time = 0; m_setup_time = 0;
m_vertex_upload_time = 0; m_vertex_upload_time = 0;
m_textures_upload_time = 0; m_textures_upload_time = 0;
m_frame->flip(m_context);
} }

View file

@ -317,6 +317,10 @@ struct cfg_root : cfg::node
cfg::_bool batch_instanced_geometry{this, "Batch Instanced Geometry", false}; cfg::_bool batch_instanced_geometry{this, "Batch Instanced Geometry", false};
cfg::_int<1, 16> vertex_upload_threads{ this, "Vertex Upload Threads", 1 }; cfg::_int<1, 16> vertex_upload_threads{ this, "Vertex Upload Threads", 1 };
cfg::_bool frame_skip_enabled{this, "Enable Frame Skip"};
cfg::_int<1, 8> consequtive_frames_to_draw{this, "Consequtive Frames Drawn", 1};
cfg::_int<1, 8> consequtive_frames_to_skip{this, "Consequtive Frames Skept", 1};
struct node_d3d12 : cfg::node struct node_d3d12 : cfg::node
{ {
node_d3d12(cfg::node* _this) : cfg::node(_this, "D3D12") {} node_d3d12(cfg::node* _this) : cfg::node(_this, "D3D12") {}

View file

@ -45,10 +45,13 @@ void gl_gs_frame::delete_context(void* ctx)
delete (QOpenGLContext*)ctx; delete (QOpenGLContext*)ctx;
} }
void gl_gs_frame::flip(draw_context_t context) void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
{ {
gs_frame::flip(context); gs_frame::flip(context);
//Do not swap buffers if frame skip is active
if (skip_frame) return;
((QOpenGLContext*)context.get())->makeCurrent(this); ((QOpenGLContext*)context.get())->makeCurrent(this);
((QOpenGLContext*)context.get())->swapBuffers(this); ((QOpenGLContext*)context.get())->swapBuffers(this);
} }

View file

@ -14,5 +14,5 @@ public:
void* make_context() override; void* make_context() override;
void set_current(draw_context_t context) override; void set_current(draw_context_t context) override;
void delete_context(void* context) override; void delete_context(void* context) override;
void flip(draw_context_t context) override; void flip(draw_context_t context, bool skip_frame=false) override;
}; };

View file

@ -151,7 +151,7 @@ int gs_frame::client_height()
#endif #endif
} }
void gs_frame::flip(draw_context_t) void gs_frame::flip(draw_context_t, bool /*skip_frame*/)
{ {
QString title; QString title;

View file

@ -35,7 +35,7 @@ protected:
void* make_context() override; void* make_context() override;
void set_current(draw_context_t context) override; void set_current(draw_context_t context) override;
void delete_context(void* context) override; void delete_context(void* context) override;
void flip(draw_context_t context) override; void flip(draw_context_t context, bool skip_frame=false) override;
int client_width() override; int client_width() override;
int client_height() override; int client_height() override;