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;