rsx: Refactoring and improvement

- Separate displayed statistics from actual backend statistics.
  Allows asynchronous flipping to work correctly as it just uses display stats.
  The real stats are used by the frame scope marker to determine behavior like engaging the FIFO optimizer or skipping draw calls correctly.
This commit is contained in:
kd-11 2019-09-19 20:08:06 +03:00 committed by kd-11
parent 2c76f47eec
commit e0005ec347
11 changed files with 119 additions and 136 deletions

View file

@ -518,7 +518,7 @@ bool is_flip_surface_in_global_memory(rsx::surface_target color_target)
}
}
void D3D12GSRender::flip(int buffer, bool emu_flip)
void D3D12GSRender::flip(const rsx::display_flip_info_t&)
{
ID3D12Resource *resource_to_flip;
float viewport_w, viewport_h;

View file

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "D3D12Utils.h"
#include "Emu/Memory/vm.h"
@ -177,7 +177,7 @@ protected:
virtual void do_local_task(rsx::FIFO_state state) override;
virtual bool do_method(u32 cmd, u32 arg) override;
virtual void end() override;
virtual void flip(int buffer, bool emu_flip = false) override;
virtual void flip(const rsx::display_flip_info_t&) override;
virtual bool on_access_violation(u32 address, bool is_writing) override;

View file

@ -174,7 +174,7 @@ void GLGSRender::begin()
{
rsx::thread::begin();
if (skip_frame ||
if (skip_current_frame ||
(conditional_render_enabled && conditional_render_test_failed))
return;
@ -185,7 +185,7 @@ void GLGSRender::end()
{
m_profiler.start();
if (skip_frame || !framebuffer_status_valid ||
if (skip_current_frame || !framebuffer_status_valid ||
(conditional_render_enabled && conditional_render_test_failed))
{
execute_nop_draw();
@ -193,7 +193,7 @@ void GLGSRender::end()
return;
}
m_begin_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
const auto do_heap_cleanup = [this]()
{
@ -294,7 +294,7 @@ void GLGSRender::end()
m_samplers_dirty.store(false);
m_textures_upload_time += m_profiler.duration();
m_frame_stats.textures_upload_time += m_profiler.duration();
}
// NOTE: Due to common OpenGL driver architecture, vertex data has to be uploaded as far away from the draw as possible
@ -312,7 +312,7 @@ void GLGSRender::end()
// Load program execution environment
load_program_env();
m_begin_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
//Bind textures and resolve external copy operations
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
@ -386,7 +386,7 @@ void GLGSRender::end()
}
}
m_textures_upload_time += m_profiler.duration();
m_frame_stats.textures_upload_time += m_profiler.duration();
// Optionally do memory synchronization if the texture stage has not yet triggered this
if (true)//g_cfg.video.strict_rendering_mode)
@ -636,7 +636,7 @@ void GLGSRender::end()
m_fragment_constants_buffer->notify();
m_transform_constants_buffer->notify();
m_draw_time += m_profiler.duration();
m_frame_stats.textures_upload_time += m_profiler.duration();
rsx::thread::end();
}
@ -930,19 +930,19 @@ void GLGSRender::on_init_thread()
{
const char *text = index == 0 ? "Loading pipeline object %u of %u" : "Compiling pipeline object %u of %u";
dlg->progress_bar_set_message(index, fmt::format(text, processed, entry_count));
owner->flip(0);
owner->flip({});
}
void inc_value(u32 index, u32 value) override
{
dlg->progress_bar_increment(index, (f32)value);
owner->flip(0);
owner->flip({});
}
void set_limit(u32 index, u32 limit) override
{
dlg->progress_bar_set_limit(index, limit);
owner->flip(0);
owner->flip({});
}
void refresh() override
@ -1081,7 +1081,7 @@ void GLGSRender::on_exit()
void GLGSRender::clear_surface(u32 arg)
{
if (skip_frame || !framebuffer_status_valid) return;
if (skip_current_frame || !framebuffer_status_valid) return;
// If stencil write mask is disabled, remove clear_stencil bit
if (!rsx::method_registers.stencil_mask()) arg &= ~0x2u;
@ -1546,30 +1546,21 @@ void GLGSRender::update_draw_state()
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
m_begin_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
}
void GLGSRender::flip(int buffer, bool emu_flip)
void GLGSRender::flip(const rsx::display_flip_info_t& info)
{
if (skip_frame)
if (info.skip_frame)
{
m_frame->flip(m_context, true);
rsx::thread::flip(buffer);
if (!skip_frame)
{
m_begin_time = 0;
m_draw_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
}
rsx::thread::flip(info);
return;
}
u32 buffer_width = display_buffers[buffer].width;
u32 buffer_height = display_buffers[buffer].height;
u32 buffer_pitch = display_buffers[buffer].pitch;
u32 buffer_width = display_buffers[info.buffer].width;
u32 buffer_height = display_buffers[info.buffer].height;
u32 buffer_pitch = display_buffers[info.buffer].pitch;
u32 av_format;
const auto avconfig = g_fxo->get<rsx::avconf>();
@ -1598,7 +1589,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
gl::screen.bind();
gl::screen.clear(gl::buffers::color);
if ((u32)buffer < display_buffers_count && buffer_width && buffer_height)
if ((u32)info.buffer < display_buffers_count && buffer_width && buffer_height)
{
// Calculate blit coordinates
coordi aspect_ratio;
@ -1626,7 +1617,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
aspect_ratio.size = new_size;
// Find the source image
const u32 absolute_address = rsx::get_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
const u32 absolute_address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL);
GLuint image = GL_NONE;
if (auto render_target_texture = m_rtts.get_color_surface_at(absolute_address))
@ -1658,7 +1649,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
// TODO: Should emit only once to avoid flooding the log file
// TODO: Take AA scaling into account
LOG_WARNING(RSX, "Selected output image does not satisfy the video configuration. Display buffer resolution=%dx%d, avconf resolution=%dx%d, surface=%dx%d",
display_buffers[buffer].width, display_buffers[buffer].height, avconfig->state * avconfig->resolution_x, avconfig->state * avconfig->resolution_y,
display_buffers[info.buffer].width, display_buffers[info.buffer].height, avconfig->state * avconfig->resolution_x, avconfig->state * avconfig->resolution_y,
render_target_texture->get_surface_width(rsx::surface_metrics::pixels), render_target_texture->get_surface_height(rsx::surface_metrics::pixels));
buffer_width = render_target_texture->width();
@ -1776,11 +1767,11 @@ void GLGSRender::flip(int buffer, bool emu_flip)
glViewport(0, 0, m_frame->client_width(), m_frame->client_height());
m_text_printer.print_text(0, 0, m_frame->client_width(), m_frame->client_height(), fmt::format("RSX Load: %3d%%", get_load()));
m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), fmt::format("draw calls: %16d", m_draw_calls));
m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), fmt::format("draw call setup: %11dus", m_begin_time));
m_text_printer.print_text(0, 54, m_frame->client_width(), m_frame->client_height(), fmt::format("vertex upload time: %8dus", m_vertex_upload_time));
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), fmt::format("textures upload time: %6dus", m_textures_upload_time));
m_text_printer.print_text(0, 90, m_frame->client_width(), m_frame->client_height(), fmt::format("draw call execution: %7dus", m_draw_time));
m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), fmt::format("draw calls: %16d", info.stats.draw_calls));
m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), fmt::format("draw call setup: %11dus", info.stats.setup_time));
m_text_printer.print_text(0, 54, m_frame->client_width(), m_frame->client_height(), fmt::format("vertex upload time: %8dus", info.stats.vertex_upload_time));
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), fmt::format("textures upload time: %6dus", info.stats.textures_upload_time));
m_text_printer.print_text(0, 90, m_frame->client_width(), m_frame->client_height(), fmt::format("draw call execution: %7dus", info.stats.draw_exec_time));
const auto num_dirty_textures = m_gl_texture_cache.get_unreleased_textures_count();
const auto texture_memory_size = m_gl_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
@ -1796,7 +1787,7 @@ void GLGSRender::flip(int buffer, bool emu_flip)
}
m_frame->flip(m_context);
rsx::thread::flip(buffer, emu_flip);
rsx::thread::flip(info);
// Cleanup
m_gl_texture_cache.on_frame_end();
@ -1818,14 +1809,6 @@ void GLGSRender::flip(int buffer, bool emu_flip)
set_viewport();
set_scissor(!!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped));
}
// If we are skipping the next frame, do not reset perf counters
if (skip_frame) return;
m_begin_time = 0;
m_draw_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
}
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
@ -1922,7 +1905,9 @@ void GLGSRender::do_local_task(rsx::FIFO_state state)
{
if (!in_begin_end && async_flip_requested & flip_request::native_ui)
{
flip((s32)current_display_buffer, false);
rsx::display_flip_info_t info{};
info.buffer = current_display_buffer;
flip(info);
}
}
}

View file

@ -86,11 +86,6 @@ private:
// Identity buffer used to fix broken gl_VertexID on ATI stack
std::unique_ptr<gl::buffer> m_identity_index_buffer;
s64 m_begin_time = 0;
s64 m_draw_time = 0;
s64 m_vertex_upload_time = 0;
s64 m_textures_upload_time = 0;
std::unique_ptr<gl::vertex_cache> m_vertex_cache;
std::unique_ptr<gl::shader_cache> m_shaders_cache;
@ -171,7 +166,7 @@ protected:
void on_init_thread() override;
void on_exit() override;
bool do_method(u32 cmd, u32 arg) override;
void flip(int buffer, bool emu_flip = false) override;
void flip(const rsx::display_flip_info_t& info) override;
void do_local_task(rsx::FIFO_state state) override;

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "GLGSRender.h"
#include "../Common/BufferUtils.h"
#include "GLHelpers.h"
@ -254,6 +254,6 @@ gl::vertex_upload_info GLGSRender::set_vertex_buffer()
//Write all the data
write_vertex_data_to_memory(m_vertex_layout, vertex_base, vertex_count, persistent_mapping.first, volatile_mapping.first);
m_vertex_upload_time += m_profiler.duration();
m_frame_stats.vertex_upload_time += m_profiler.duration();
return upload_info;
}

View file

@ -55,7 +55,7 @@ void GSRender::on_exit()
rsx::thread::on_exit();
}
void GSRender::flip(int buffer, bool emu_flip)
void GSRender::flip(const rsx::display_flip_info_t& info)
{
if (m_frame)
{

View file

@ -104,7 +104,7 @@ public:
void on_init_thread() override;
void on_exit() override;
void flip(int buffer, bool emu_flip = false) override;
void flip(const rsx::display_flip_info_t& info) override;
GSFrameBase* get_frame() { return m_frame; }
};

View file

@ -352,7 +352,7 @@ namespace rsx
capture::capture_draw_memory(this);
in_begin_end = false;
m_draw_calls++;
m_frame_stats.draw_calls++;
method_registers.current_draw_clause.post_execute_cleanup();
@ -2233,12 +2233,12 @@ namespace rsx
}
}
void thread::flip(int buffer, bool emu_flip)
void thread::flip(const display_flip_info_t& info)
{
if (async_flip_requested & flip_request::any)
{
// Deferred flip
if (emu_flip)
if (info.emu_flip)
{
async_flip_requested.clear(flip_request::emu_requested);
}
@ -2248,14 +2248,8 @@ namespace rsx
}
}
if (emu_flip)
if (info.emu_flip)
{
if (g_cfg.video.frame_skip_enabled)
{
skip_frame = (m_skip_frame_ctr < 0);
}
m_draw_calls = 0;
performance_counters.sampled_frames++;
}
}
@ -2543,13 +2537,18 @@ namespace rsx
zcull_ctrl->sync(this);
}
// Save current state
m_queued_flip.stats = m_frame_stats;
m_queued_flip.buffer = buffer;
m_queued_flip.skip_frame = skip_current_frame;
if (LIKELY(!forced))
{
if (!g_cfg.video.disable_FIFO_reordering)
{
// Try to enable FIFO optimizations
// Only rarely useful for some games like RE4
m_flattener.evaluate_performance(m_draw_calls);
m_flattener.evaluate_performance(m_frame_stats.draw_calls);
}
if (g_cfg.video.frame_skip_enabled)
@ -2558,6 +2557,8 @@ namespace rsx
if (m_skip_frame_ctr == g_cfg.video.consequtive_frames_to_draw)
m_skip_frame_ctr = -g_cfg.video.consequtive_frames_to_skip;
skip_current_frame = (m_skip_frame_ctr < 0);
}
}
else
@ -2574,7 +2575,8 @@ namespace rsx
}
}
queued_flip_index = int(buffer);
// Reset current stats
m_frame_stats = {};
}
void thread::request_emu_flip(u32 buffer)
@ -2602,7 +2604,7 @@ namespace rsx
void thread::handle_emu_flip(u32 buffer)
{
if (queued_flip_index < 0)
if (m_queued_flip.buffer == ~0u)
{
// Frame was not queued before flipping
on_frame_end(buffer, true);
@ -2649,12 +2651,15 @@ namespace rsx
}
int_flip_index++;
verify(HERE), m_queued_flip.buffer == buffer;
current_display_buffer = buffer;
flip(buffer, true);
m_queued_flip.emu_flip = true;
flip(m_queued_flip);
last_flip_time = get_system_time() - 1000000;
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
queued_flip_index = -1;
m_queued_flip.buffer = ~0u;
if (flip_handler)
{

View file

@ -413,6 +413,24 @@ namespace rsx
};
}
struct frame_statistics_t
{
u32 draw_calls;
s64 setup_time;
s64 vertex_upload_time;
s64 textures_upload_time;
s64 draw_exec_time;
s64 flip_time;
};
struct display_flip_info_t
{
u32 buffer;
bool skip_frame;
bool emu_flip;
frame_statistics_t stats;
};
struct sampled_image_descriptor_base;
class thread
@ -420,6 +438,8 @@ namespace rsx
u64 timestamp_ctrl = 0;
u64 timestamp_subvalue = 0;
display_flip_info_t m_queued_flip;
protected:
std::thread::id m_rsx_thread;
atomic_t<bool> m_rsx_thread_exiting{ true };
@ -428,7 +448,8 @@ namespace rsx
std::vector<u32> element_push_buffer;
s32 m_skip_frame_ctr = 0;
bool skip_frame = false;
bool skip_current_frame = false;
frame_statistics_t stats{};
bool supports_multidraw = false; // Draw call batching
bool supports_hw_a2c = false; // Alpha to coverage
@ -454,11 +475,9 @@ namespace rsx
// Invalidated memory range
address_range m_invalidated_memory_range;
// Draw call stats
u32 m_draw_calls = 0;
// Profiler
rsx::profiling_timer m_profiler;
frame_statistics_t m_frame_stats;
public:
RsxDmaControl* ctrl = nullptr;
@ -558,7 +577,6 @@ namespace rsx
u64 start_rsx_time = 0;
u64 int_flip_index = 0;
u64 last_flip_time;
int queued_flip_index = -1;
vm::ptr<void(u32)> flip_handler = vm::null;
vm::ptr<void(u32)> user_handler = vm::null;
vm::ptr<void(u32)> vblank_handler = vm::null;
@ -609,7 +627,7 @@ namespace rsx
virtual void on_init_thread() = 0;
virtual bool do_method(u32 /*cmd*/, u32 /*value*/) { return false; }
virtual void on_frame_end(u32 buffer, bool forced = false);
virtual void flip(int buffer, bool emu_flip = false) = 0;
virtual void flip(const display_flip_info_t& info) = 0;
virtual u64 timestamp();
virtual bool on_access_violation(u32 /*address*/, bool /*is_writing*/) { return false; }
virtual void on_invalidate_memory_range(const address_range & /*range*/, rsx::invalidation_cause) {}

View file

@ -863,7 +863,7 @@ void VKGSRender::check_heap_status(u32 flags)
frame_context_cleanup(target_frame, true);
}
m_flip_time += m_profiler.duration();
m_frame_stats.flip_time += m_profiler.duration();
}
}
@ -920,7 +920,7 @@ void VKGSRender::begin()
{
rsx::thread::begin();
if (skip_frame || swapchain_unavailable ||
if (skip_current_frame || swapchain_unavailable ||
(conditional_render_enabled && conditional_render_test_failed))
return;
@ -1009,7 +1009,7 @@ void VKGSRender::update_draw_state()
//TODO: Set up other render-state parameters into the program pipeline
m_setup_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
}
void VKGSRender::begin_render_pass()
@ -1085,7 +1085,7 @@ void VKGSRender::emit_geometry(u32 sub_index)
return;
}
m_vertex_upload_time += m_profiler.duration();
m_frame_stats.vertex_upload_time += m_profiler.duration();
auto persistent_buffer = m_persistent_attribute_storage ? m_persistent_attribute_storage->value : null_buffer_view->value;
auto volatile_buffer = m_volatile_attribute_storage ? m_volatile_attribute_storage->value : null_buffer_view->value;
@ -1149,7 +1149,7 @@ void VKGSRender::emit_geometry(u32 sub_index)
// Bind the new set of descriptors for use with this draw call
vkCmdBindDescriptorSets(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &m_current_frame->descriptor_set, 0, nullptr);
m_setup_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
if (!upload_info.index_info)
{
@ -1193,12 +1193,12 @@ void VKGSRender::emit_geometry(u32 sub_index)
}
}
m_draw_time += m_profiler.duration();
m_frame_stats.draw_exec_time += m_profiler.duration();
}
void VKGSRender::end()
{
if (skip_frame || !framebuffer_status_valid || swapchain_unavailable ||
if (skip_current_frame || !framebuffer_status_valid || swapchain_unavailable ||
(conditional_render_enabled && conditional_render_test_failed))
{
execute_nop_draw();
@ -1450,7 +1450,7 @@ void VKGSRender::end()
}
}
m_textures_upload_time += m_profiler.duration();
m_frame_stats.textures_upload_time += m_profiler.duration();
if (!load_program())
{
@ -1469,7 +1469,7 @@ void VKGSRender::end()
// Load program execution environment
load_program_env();
m_setup_time += m_profiler.duration();
m_frame_stats.setup_time += m_profiler.duration();
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
@ -1672,7 +1672,7 @@ void VKGSRender::end()
}
}
m_textures_upload_time += m_profiler.duration();
m_frame_stats.textures_upload_time += m_profiler.duration();
if (m_current_command_buffer->flags & vk::command_buffer::cb_load_occluson_task)
{
@ -1811,19 +1811,19 @@ void VKGSRender::on_init_thread()
{
const char *text = index == 0 ? "Loading pipeline object %u of %u" : "Compiling pipeline object %u of %u";
dlg->progress_bar_set_message(index, fmt::format(text, processed, entry_count));
owner->flip(0);
owner->flip({});
}
void inc_value(u32 index, u32 value) override
{
dlg->progress_bar_increment(index, (f32)value);
owner->flip(0);
owner->flip({});
}
void set_limit(u32 index, u32 limit) override
{
dlg->progress_bar_set_limit(index, limit);
owner->flip(0);
owner->flip({});
}
void refresh() override
@ -1852,7 +1852,7 @@ void VKGSRender::on_exit()
void VKGSRender::clear_surface(u32 mask)
{
if (skip_frame || swapchain_unavailable) return;
if (skip_current_frame || swapchain_unavailable) return;
// If stencil write mask is disabled, remove clear_stencil bit
if (!rsx::method_registers.stencil_mask()) mask &= ~0x2u;
@ -2393,7 +2393,9 @@ void VKGSRender::do_local_task(rsx::FIFO_state state)
if (!in_begin_end && async_flip_requested & flip_request::native_ui)
{
flush_command_queue(true);
flip((s32)current_display_buffer, false);
rsx::display_flip_info_t info{};
info.buffer = current_display_buffer;
flip(info);
}
}
}
@ -3093,7 +3095,7 @@ void VKGSRender::reinitialize_swapchain()
should_reinitialize_swapchain = false;
}
void VKGSRender::flip(int buffer, bool emu_flip)
void VKGSRender::flip(const rsx::display_flip_info_t& info)
{
// Check swapchain condition/status
if (!m_swapchain->supports_automatic_wm_reports())
@ -3127,7 +3129,7 @@ void VKGSRender::flip(int buffer, bool emu_flip)
}
else if (m_current_frame->swap_command_buffer)
{
if (m_draw_calls > 0)
if (info.stats.draw_calls > 0)
{
// This can be 'legal' if the window was being resized and no polling happened because of swapchain_unavailable flag
LOG_ERROR(RSX, "Possible data corruption on frame context storage detected");
@ -3137,9 +3139,9 @@ void VKGSRender::flip(int buffer, bool emu_flip)
frame_context_cleanup(m_current_frame, true);
}
if (skip_frame || swapchain_unavailable)
if (info.skip_frame || swapchain_unavailable)
{
if (!skip_frame)
if (!info.skip_frame)
{
verify(HERE), swapchain_unavailable;
@ -3148,21 +3150,16 @@ void VKGSRender::flip(int buffer, bool emu_flip)
flush_command_queue(true);
vk::advance_frame_counter();
frame_context_cleanup(m_current_frame, true);
m_draw_time = 0;
m_setup_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
}
m_frame->flip(m_context);
rsx::thread::flip(buffer, emu_flip);
rsx::thread::flip(info);
return;
}
u32 buffer_width = display_buffers[buffer].width;
u32 buffer_height = display_buffers[buffer].height;
u32 buffer_pitch = display_buffers[buffer].pitch;
u32 buffer_width = display_buffers[info.buffer].width;
u32 buffer_height = display_buffers[info.buffer].height;
u32 buffer_pitch = display_buffers[info.buffer].pitch;
u32 av_format;
const auto avconfig = g_fxo->get<rsx::avconf>();
@ -3251,9 +3248,9 @@ void VKGSRender::flip(int buffer, bool emu_flip)
//Blit contents to screen..
vk::image* image_to_flip = nullptr;
if ((u32)buffer < display_buffers_count && buffer_width && buffer_height)
if ((u32)info.buffer < display_buffers_count && buffer_width && buffer_height)
{
const u32 absolute_address = rsx::get_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
const u32 absolute_address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL);
if (auto render_target_texture = m_rtts.get_color_surface_at(absolute_address))
{
@ -3282,7 +3279,7 @@ void VKGSRender::flip(int buffer, bool emu_flip)
// TODO: Should emit only once to avoid flooding the log file
// TODO: Take AA scaling into account
LOG_WARNING(RSX, "Selected output image does not satisfy the video configuration. Display buffer resolution=%dx%d, avconf resolution=%dx%d, surface=%dx%d",
display_buffers[buffer].width, display_buffers[buffer].height, avconfig->state * avconfig->resolution_x, avconfig->state * avconfig->resolution_y,
display_buffers[info.buffer].width, display_buffers[info.buffer].height, avconfig->state * avconfig->resolution_x, avconfig->state * avconfig->resolution_y,
render_target_texture->get_surface_width(rsx::surface_metrics::pixels), render_target_texture->get_surface_height(rsx::surface_metrics::pixels));
buffer_width = render_target_texture->width();
@ -3435,12 +3432,12 @@ void VKGSRender::flip(int buffer, bool emu_flip)
if (g_cfg.video.overlay)
{
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 0, direct_fbo->width(), direct_fbo->height(), fmt::format("RSX Load: %3d%%", get_load()));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), fmt::format("draw calls: %17d", m_draw_calls));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), fmt::format("draw call setup: %12dus", m_setup_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), fmt::format("vertex upload time: %9dus", m_vertex_upload_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), fmt::format("texture upload time: %8dus", m_textures_upload_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), fmt::format("draw call execution: %8dus", m_draw_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 108, direct_fbo->width(), direct_fbo->height(), fmt::format("submit and flip: %12dus", m_flip_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), fmt::format("draw calls: %17d", info.stats.draw_calls));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), fmt::format("draw call setup: %12dus", info.stats.setup_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), fmt::format("vertex upload time: %9dus", info.stats.vertex_upload_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), fmt::format("texture upload time: %8dus", info.stats.textures_upload_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), fmt::format("draw call execution: %8dus", info.stats.draw_exec_time));
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 108, direct_fbo->width(), direct_fbo->height(), fmt::format("submit and flip: %12dus", info.stats.flip_time));
const auto num_dirty_textures = m_texture_cache.get_unreleased_textures_count();
const auto texture_memory_size = m_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
@ -3464,20 +3461,10 @@ void VKGSRender::flip(int buffer, bool emu_flip)
queue_swap_request();
m_flip_time = m_profiler.duration();
//NOTE:Resource destruction is handled within the real swap handler
m_frame_stats.flip_time = m_profiler.duration();
m_frame->flip(m_context);
rsx::thread::flip(buffer, emu_flip);
//Do not reset perf counters if we are skipping the next frame
if (skip_frame) return;
m_draw_time = 0;
m_setup_time = 0;
m_vertex_upload_time = 0;
m_textures_upload_time = 0;
rsx::thread::flip(info);
}
bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate)

View file

@ -398,13 +398,6 @@ private:
VkViewport m_viewport{};
VkRect2D m_scissor{};
// Timers
s64 m_setup_time = 0;
s64 m_vertex_upload_time = 0;
s64 m_textures_upload_time = 0;
s64 m_draw_time = 0;
s64 m_flip_time = 0;
std::vector<u8> m_draw_buffers;
shared_mutex m_flush_queue_mutex;
@ -492,7 +485,7 @@ protected:
void on_init_thread() override;
void on_exit() override;
bool do_method(u32 cmd, u32 arg) override;
void flip(int buffer, bool emu_flip = false) override;
void flip(const rsx::display_flip_info_t& info) override;
void do_local_task(rsx::FIFO_state state) override;
bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override;