From e0005ec347087e552c6e8c20a4e3f8b69b9d04dd Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 19 Sep 2019 20:08:06 +0300 Subject: [PATCH] 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. --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 2 +- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 4 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 75 ++++++++++------------- rpcs3/Emu/RSX/GL/GLGSRender.h | 7 +-- rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp | 4 +- rpcs3/Emu/RSX/GSRender.cpp | 2 +- rpcs3/Emu/RSX/GSRender.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 35 ++++++----- rpcs3/Emu/RSX/RSXThread.h | 30 ++++++++-- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 85 ++++++++++++--------------- rpcs3/Emu/RSX/VK/VKGSRender.h | 9 +-- 11 files changed, 119 insertions(+), 136 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 422e656f83..818497f9ee 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 4c2f93f3bf..24e95e5e13 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -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; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 0082f71cf7..1a8569d6fc 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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(); @@ -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); } } } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 4de1004715..b8edc866cb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -86,11 +86,6 @@ private: // Identity buffer used to fix broken gl_VertexID on ATI stack std::unique_ptr 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 m_vertex_cache; std::unique_ptr 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; diff --git a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp index 0e1e426bfc..2148d8c50c 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp @@ -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; } diff --git a/rpcs3/Emu/RSX/GSRender.cpp b/rpcs3/Emu/RSX/GSRender.cpp index 1d4502c158..77bf2b2e6c 100644 --- a/rpcs3/Emu/RSX/GSRender.cpp +++ b/rpcs3/Emu/RSX/GSRender.cpp @@ -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) { diff --git a/rpcs3/Emu/RSX/GSRender.h b/rpcs3/Emu/RSX/GSRender.h index 2979338ff2..126b661749 100644 --- a/rpcs3/Emu/RSX/GSRender.h +++ b/rpcs3/Emu/RSX/GSRender.h @@ -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; } }; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 441d05c673..a2f0d58828 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -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) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 2db654a8c4..502f5553d3 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -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 m_rsx_thread_exiting{ true }; @@ -428,7 +448,8 @@ namespace rsx std::vector 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 flip_handler = vm::null; vm::ptr user_handler = vm::null; vm::ptr 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) {} diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 78a0fafd0c..e3ccc2e041 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -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(); @@ -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) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index c65c2152da..af431435f0 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -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 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;