mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 00:11:24 +12:00
rsx: Basic performance counters
This commit is contained in:
parent
2855869530
commit
84b8a08d26
5 changed files with 80 additions and 21 deletions
|
@ -1370,20 +1370,21 @@ void GLGSRender::flip(int buffer)
|
||||||
gl::screen.bind();
|
gl::screen.bind();
|
||||||
glViewport(0, 0, m_frame->client_width(), m_frame->client_height());
|
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(), "draw calls: " + std::to_string(m_draw_calls));
|
m_text_printer.print_text(0, 0, m_frame->client_width(), m_frame->client_height(), "RSX Load: " + std::to_string(get_load()) + "%");
|
||||||
m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), "draw call setup: " + std::to_string(m_begin_time) + "us");
|
m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), "draw calls: " + std::to_string(m_draw_calls));
|
||||||
m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), "draw call setup: " + std::to_string(m_begin_time) + "us");
|
||||||
m_text_printer.print_text(0, 54, m_frame->client_width(), m_frame->client_height(), "textures upload time: " + std::to_string(m_textures_upload_time) + "us");
|
m_text_printer.print_text(0, 54, m_frame->client_width(), m_frame->client_height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
||||||
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), "textures upload time: " + std::to_string(m_textures_upload_time) + "us");
|
||||||
|
m_text_printer.print_text(0, 90, m_frame->client_width(), m_frame->client_height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
||||||
|
|
||||||
const auto num_dirty_textures = m_gl_texture_cache.get_unreleased_textures_count();
|
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);
|
const auto texture_memory_size = m_gl_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
|
||||||
const auto num_flushes = m_gl_texture_cache.get_num_flush_requests();
|
const auto num_flushes = m_gl_texture_cache.get_num_flush_requests();
|
||||||
const auto num_mispredict = m_gl_texture_cache.get_num_cache_mispredictions();
|
const auto num_mispredict = m_gl_texture_cache.get_num_cache_mispredictions();
|
||||||
const auto cache_miss_ratio = (u32)ceil(m_gl_texture_cache.get_cache_miss_ratio() * 100);
|
const auto cache_miss_ratio = (u32)ceil(m_gl_texture_cache.get_cache_miss_ratio() * 100);
|
||||||
m_text_printer.print_text(0, 108, m_frame->client_width(), m_frame->client_height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
|
m_text_printer.print_text(0, 126, m_frame->client_width(), m_frame->client_height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
|
||||||
m_text_printer.print_text(0, 126, m_frame->client_width(), m_frame->client_height(), "Texture memory: " + std::to_string(texture_memory_size) + "M");
|
m_text_printer.print_text(0, 144, m_frame->client_width(), m_frame->client_height(), "Texture memory: " + std::to_string(texture_memory_size) + "M");
|
||||||
m_text_printer.print_text(0, 144, m_frame->client_width(), m_frame->client_height(), fmt::format("Flush requests: %d (%d%% hard faults, %d mispedictions)", num_flushes, cache_miss_ratio, num_mispredict));
|
m_text_printer.print_text(0, 162, m_frame->client_width(), m_frame->client_height(), fmt::format("Flush requests: %d (%d%% hard faults, %d mispedictions)", num_flushes, cache_miss_ratio, num_mispredict));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_frame->flip(m_context);
|
m_frame->flip(m_context);
|
||||||
|
|
|
@ -527,12 +527,26 @@ namespace rsx
|
||||||
if (put == internal_get || !Emu.IsRunning())
|
if (put == internal_get || !Emu.IsRunning())
|
||||||
{
|
{
|
||||||
if (has_deferred_call)
|
if (has_deferred_call)
|
||||||
|
{
|
||||||
flush_command_queue();
|
flush_command_queue();
|
||||||
|
}
|
||||||
|
else if (!performance_counters.FIFO_is_idle)
|
||||||
|
{
|
||||||
|
performance_counters.FIFO_idle_timestamp = get_system_time();
|
||||||
|
performance_counters.FIFO_is_idle = true;
|
||||||
|
}
|
||||||
|
|
||||||
do_internal_task();
|
do_internal_task();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (performance_counters.FIFO_is_idle)
|
||||||
|
{
|
||||||
|
//Update performance counters with time spent in idle mode
|
||||||
|
performance_counters.FIFO_is_idle = false;
|
||||||
|
performance_counters.idle_time += (get_system_time() - performance_counters.FIFO_idle_timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
//Validate put and get registers
|
//Validate put and get registers
|
||||||
//TODO: Who should handle graphics exceptions??
|
//TODO: Who should handle graphics exceptions??
|
||||||
const u32 get_address = RSXIOMem.RealAddr(internal_get);
|
const u32 get_address = RSXIOMem.RealAddr(internal_get);
|
||||||
|
@ -2027,6 +2041,8 @@ namespace rsx
|
||||||
|
|
||||||
skip_frame = (m_skip_frame_ctr < 0);
|
skip_frame = (m_skip_frame_ctr < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
performance_counters.sampled_frames++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread::check_zcull_status(bool framebuffer_swap, bool force_read)
|
void thread::check_zcull_status(bool framebuffer_swap, bool force_read)
|
||||||
|
@ -2223,6 +2239,28 @@ namespace rsx
|
||||||
external_interrupt_lock.store(false);
|
external_interrupt_lock.store(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 thread::get_load()
|
||||||
|
{
|
||||||
|
//Average load over around 30 frames
|
||||||
|
if (!performance_counters.last_update_timestamp || performance_counters.sampled_frames > 30)
|
||||||
|
{
|
||||||
|
const auto timestamp = get_system_time();
|
||||||
|
const auto idle = performance_counters.idle_time.load();
|
||||||
|
const auto elapsed = timestamp - performance_counters.last_update_timestamp;
|
||||||
|
|
||||||
|
if (elapsed > idle)
|
||||||
|
performance_counters.approximate_load = (elapsed - idle) * 100 / elapsed;
|
||||||
|
else
|
||||||
|
performance_counters.approximate_load = 0;
|
||||||
|
|
||||||
|
performance_counters.idle_time = 0;
|
||||||
|
performance_counters.sampled_frames = 0;
|
||||||
|
performance_counters.last_update_timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return performance_counters.approximate_load;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Move these helpers into a better class dedicated to shell interface handling (use idm?)
|
//TODO: Move these helpers into a better class dedicated to shell interface handling (use idm?)
|
||||||
//They are not dependent on rsx at all
|
//They are not dependent on rsx at all
|
||||||
rsx::overlays::save_dialog* thread::shell_open_save_dialog()
|
rsx::overlays::save_dialog* thread::shell_open_save_dialog()
|
||||||
|
|
|
@ -257,6 +257,18 @@ namespace rsx
|
||||||
atomic_t<bool> external_interrupt_lock{ false };
|
atomic_t<bool> external_interrupt_lock{ false };
|
||||||
atomic_t<bool> external_interrupt_ack{ false };
|
atomic_t<bool> external_interrupt_ack{ false };
|
||||||
|
|
||||||
|
//performance approximation counters
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
atomic_t<u64> idle_time{ 0 }; //Time spent idling in microseconds
|
||||||
|
u64 last_update_timestamp = 0; //Timestamp of last load update
|
||||||
|
u64 FIFO_idle_timestamp = 0; //Timestamp of when FIFO queue becomes idle
|
||||||
|
bool FIFO_is_idle = false; //True if FIFO is in idle state
|
||||||
|
u32 approximate_load = 0;
|
||||||
|
u32 sampled_frames = 0;
|
||||||
|
}
|
||||||
|
performance_counters;
|
||||||
|
|
||||||
//native UI interrupts
|
//native UI interrupts
|
||||||
atomic_t<bool> native_ui_flip_request{ false };
|
atomic_t<bool> native_ui_flip_request{ false };
|
||||||
|
|
||||||
|
@ -510,6 +522,9 @@ namespace rsx
|
||||||
void pause();
|
void pause();
|
||||||
void unpause();
|
void unpause();
|
||||||
|
|
||||||
|
//Get RSX approximate load in %
|
||||||
|
u32 get_load();
|
||||||
|
|
||||||
//HLE vsh stuff
|
//HLE vsh stuff
|
||||||
//TODO: Move into a separate helper
|
//TODO: Move into a separate helper
|
||||||
virtual rsx::overlays::save_dialog* shell_open_save_dialog();
|
virtual rsx::overlays::save_dialog* shell_open_save_dialog();
|
||||||
|
|
|
@ -3106,12 +3106,13 @@ void VKGSRender::flip(int buffer)
|
||||||
|
|
||||||
if (g_cfg.video.overlay)
|
if (g_cfg.video.overlay)
|
||||||
{
|
{
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 0, direct_fbo->width(), direct_fbo->height(), "draw calls: " + std::to_string(m_draw_calls));
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 0, direct_fbo->width(), direct_fbo->height(), "RSX Load: " + std::to_string(get_load()) + "%");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), "draw call setup: " + std::to_string(m_setup_time) + "us");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), "draw calls: " + std::to_string(m_draw_calls));
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), "draw call setup: " + std::to_string(m_setup_time) + "us");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), "texture upload time: " + std::to_string(m_textures_upload_time) + "us");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), "texture upload time: " + std::to_string(m_textures_upload_time) + "us");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), "submit and flip: " + std::to_string(m_flip_time) + "us");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
||||||
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 108, direct_fbo->width(), direct_fbo->height(), "submit and flip: " + std::to_string(m_flip_time) + "us");
|
||||||
|
|
||||||
const auto num_dirty_textures = m_texture_cache.get_unreleased_textures_count();
|
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);
|
const auto texture_memory_size = m_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
|
||||||
|
@ -3119,10 +3120,10 @@ void VKGSRender::flip(int buffer)
|
||||||
const auto num_flushes = m_texture_cache.get_num_flush_requests();
|
const auto num_flushes = m_texture_cache.get_num_flush_requests();
|
||||||
const auto num_mispredict = m_texture_cache.get_num_cache_mispredictions();
|
const auto num_mispredict = m_texture_cache.get_num_cache_mispredictions();
|
||||||
const auto cache_miss_ratio = (u32)ceil(m_texture_cache.get_cache_miss_ratio() * 100);
|
const auto cache_miss_ratio = (u32)ceil(m_texture_cache.get_cache_miss_ratio() * 100);
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 126, direct_fbo->width(), direct_fbo->height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 144, direct_fbo->width(), direct_fbo->height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 144, direct_fbo->width(), direct_fbo->height(), "Texture cache memory: " + std::to_string(texture_memory_size) + "M");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 162, direct_fbo->width(), direct_fbo->height(), "Texture cache memory: " + std::to_string(texture_memory_size) + "M");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 162, direct_fbo->width(), direct_fbo->height(), "Temporary texture memory: " + std::to_string(tmp_texture_memory_size) + "M");
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 180, direct_fbo->width(), direct_fbo->height(), "Temporary texture memory: " + std::to_string(tmp_texture_memory_size) + "M");
|
||||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 180, direct_fbo->width(), direct_fbo->height(), fmt::format("Flush requests: %d (%d%% hard faults, %d mispedictions)", num_flushes, cache_miss_ratio, num_mispredict));
|
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 198, direct_fbo->width(), direct_fbo->height(), fmt::format("Flush requests: %d (%d%% hard faults, %d mispedictions)", num_flushes, cache_miss_ratio, num_mispredict));
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, present_layout, subres);
|
vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, present_layout, subres);
|
||||||
|
|
|
@ -71,10 +71,10 @@ namespace rsx
|
||||||
{
|
{
|
||||||
// todo: LLE: why does this one keep hanging? is it vsh system semaphore? whats actually pushing this to the command buffer?!
|
// todo: LLE: why does this one keep hanging? is it vsh system semaphore? whats actually pushing this to the command buffer?!
|
||||||
if (addr == 0x40000030)
|
if (addr == 0x40000030)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
break;
|
return;
|
||||||
|
|
||||||
const auto tdr = (s64)g_cfg.video.driver_recovery_timeout;
|
const auto tdr = (s64)g_cfg.video.driver_recovery_timeout;
|
||||||
if (tdr == 0)
|
if (tdr == 0)
|
||||||
|
@ -106,6 +106,8 @@ namespace rsx
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rsx->performance_counters.idle_time += (get_system_time() - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void semaphore_release(thread* rsx, u32 _reg, u32 arg)
|
void semaphore_release(thread* rsx, u32 _reg, u32 arg)
|
||||||
|
@ -1024,7 +1026,9 @@ namespace rsx
|
||||||
|
|
||||||
if (expected > time + 1000)
|
if (expected > time + 1000)
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds{static_cast<s64>(expected - time) / 1000});
|
const auto delay_us = static_cast<s64>(expected - time);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds{delay_us / 1000});
|
||||||
|
rsx->performance_counters.idle_time += delay_us;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue