From f913edede47554eac54a7231f31a0f649a614dd2 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 18:41:42 +0100 Subject: [PATCH 1/7] Use move semantics for present_frame --- rpcs3/Emu/RSX/GL/GLPresent.cpp | 2 +- rpcs3/Emu/RSX/GSFrameBase.h | 2 +- rpcs3/Emu/RSX/VK/VKPresent.cpp | 4 ++-- rpcs3/rpcs3qt/gs_frame.cpp | 4 ++-- rpcs3/rpcs3qt/gs_frame.h | 2 +- rpcs3/util/video_provider.cpp | 2 +- rpcs3/util/video_provider.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index c73415edb2..6287b50721 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -296,7 +296,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) } else { - m_frame->present_frame(sshot_frame, buffer_width * 4, buffer_width, buffer_height, false); + m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, false); } } diff --git a/rpcs3/Emu/RSX/GSFrameBase.h b/rpcs3/Emu/RSX/GSFrameBase.h index ef17378dd3..69d2832c55 100644 --- a/rpcs3/Emu/RSX/GSFrameBase.h +++ b/rpcs3/Emu/RSX/GSFrameBase.h @@ -31,6 +31,6 @@ public: virtual display_handle_t handle() const = 0; virtual bool can_consume_frame() const = 0; - virtual void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const = 0; + virtual void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const = 0; virtual void take_screenshot(std::vector&& sshot_data, u32 sshot_width, u32 sshot_height, bool is_bgra) = 0; }; diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 6bc09588d4..a682750f69 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -749,7 +749,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) image_to_flip->pop_layout(*m_current_command_buffer); flush_command_queue(true); - auto src = sshot_vkbuf.map(0, sshot_size); + const auto src = sshot_vkbuf.map(0, sshot_size); std::vector sshot_frame(sshot_size); memcpy(sshot_frame.data(), src, sshot_size); sshot_vkbuf.unmap(); @@ -762,7 +762,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } else { - m_frame->present_frame(sshot_frame, buffer_width * 4, buffer_width, buffer_height, is_bgra); + m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, is_bgra); } } } diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 7b5481d2d4..c6bd3090fa 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -787,10 +787,10 @@ bool gs_frame::can_consume_frame() const return video_provider.can_consume_frame(); } -void gs_frame::present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const +void gs_frame::present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const { utils::video_provider& video_provider = g_fxo->get(); - video_provider.present_frame(data, pitch, width, height, is_bgra); + video_provider.present_frame(std::move(data), pitch, width, height, is_bgra); } void gs_frame::take_screenshot(std::vector&& data, u32 sshot_width, u32 sshot_height, bool is_bgra) diff --git a/rpcs3/rpcs3qt/gs_frame.h b/rpcs3/rpcs3qt/gs_frame.h index 38bbaa0a3e..858a06340d 100644 --- a/rpcs3/rpcs3qt/gs_frame.h +++ b/rpcs3/rpcs3qt/gs_frame.h @@ -78,7 +78,7 @@ public: bool get_mouse_lock_state(); bool can_consume_frame() const override; - void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const override; + void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const override; void take_screenshot(std::vector&& data, u32 sshot_width, u32 sshot_height, bool is_bgra) override; protected: diff --git a/rpcs3/util/video_provider.cpp b/rpcs3/util/video_provider.cpp index 70888447f4..4b93c50b69 100644 --- a/rpcs3/util/video_provider.cpp +++ b/rpcs3/util/video_provider.cpp @@ -122,7 +122,7 @@ namespace utils return pts > m_last_video_pts_incoming; } - void video_provider::present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) + void video_provider::present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) { if (!m_active) { diff --git a/rpcs3/util/video_provider.h b/rpcs3/util/video_provider.h index 0d2c29edfe..b18e6c35d4 100644 --- a/rpcs3/util/video_provider.h +++ b/rpcs3/util/video_provider.h @@ -21,7 +21,7 @@ namespace utils void set_pause_time_us(usz pause_time_us); bool can_consume_frame(); - void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra); + void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra); void present_samples(u8* buf, u32 sample_count, u16 channels); From 78401f22f42c2ec910dbff82c7a2365f3a6f7a84 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 23:08:40 +0100 Subject: [PATCH 2/7] Add new option for recording overlays --- rpcs3/Emu/system_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 7035fff5d0..e96927c8c0 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -180,6 +180,7 @@ struct cfg_root : cfg::node cfg::_bool disable_msl_fast_math{ this, "Disable MSL Fast Math", false }; cfg::_bool disable_async_host_memory_manager{ this, "Disable Asynchronous Memory Manager", false, true }; cfg::_enum output_scaling{ this, "Output Scaling Mode", output_scaling_mode::bilinear, true }; + cfg::_bool record_with_overlays{ this, "Record With Overlays", true, true }; struct node_vk : cfg::node { From e2118cddad1b40fd9cad6db7aad08bc13e8a063a Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 20:15:18 +0100 Subject: [PATCH 3/7] GL: allow to record overlays --- rpcs3/Emu/RSX/GL/GLDraw.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.h | 2 + rpcs3/Emu/RSX/GL/GLPresent.cpp | 111 +++++++++++++++++++++---------- rpcs3/Emu/RSX/GL/glutils/image.h | 2 +- 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index c02f12c8c4..2fd5ed5b09 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -475,7 +475,7 @@ void GLGSRender::bind_texture_env() } else { - auto target = gl::get_target(current_fragment_program.get_texture_dimension(i)); + const auto target = gl::get_target(current_fragment_program.get_texture_dimension(i)); cmd->bind_texture(GL_FRAGMENT_TEXTURES_START + i, target, m_null_textures[target]->id()); if (current_fragment_program.texture_state.redirected_textures & (1 << i)) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 59a7e075b9..4cf79c50de 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -137,6 +137,8 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control std::unique_ptr m_flip_tex_color[2]; // Present + gl::fbo m_sshot_fbo; + std::unique_ptr m_sshot_tex; std::unique_ptr m_upscaler; output_scaling_mode m_output_scaling = output_scaling_mode::bilinear; diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index 6287b50721..6787303691 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -204,7 +204,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) // Enable drawing to window backbuffer gl::screen.bind(); - gl::texture *image_to_flip = nullptr, *image_to_flip2 = nullptr; + gl::texture* image_to_flip = nullptr; + gl::texture* image_to_flip2 = nullptr; if (info.buffer < display_buffers_count && buffer_width && buffer_height) { @@ -276,15 +277,86 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) gl::screen.clear(gl::buffers::color); } + if (m_overlay_manager && m_overlay_manager->has_dirty()) + { + m_overlay_manager->lock_shared(); + + std::vector uids_to_dispose; + uids_to_dispose.reserve(m_overlay_manager->get_dirty().size()); + + for (const auto& view : m_overlay_manager->get_dirty()) + { + m_ui_renderer.remove_temp_resources(view->uid); + uids_to_dispose.push_back(view->uid); + } + + m_overlay_manager->unlock_shared(); + m_overlay_manager->dispose(uids_to_dispose); + } + + const auto render_overlays = [this, &cmd](gl::texture* dst, const areau& aspect_ratio) + { + if (m_overlay_manager && m_overlay_manager->has_visible()) + { + GLuint target = 0; + + if (dst) + { + m_sshot_fbo.bind(); + m_sshot_fbo.color = dst->id(); + target = dst->id(); + } + else + { + gl::screen.bind(); + } + + // Lock to avoid modification during run-update chain + std::lock_guard lock(*m_overlay_manager); + + for (const auto& view : m_overlay_manager->get_views()) + { + m_ui_renderer.run(cmd, aspect_ratio, target, *view.get()); + } + } + }; + if (image_to_flip) { if (g_user_asked_for_screenshot || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame())) { + static const gl::pixel_pack_settings pack_settings{}; + + gl::texture* tex = image_to_flip; + + if (g_cfg.video.record_with_overlays) + { + m_sshot_fbo.create(); + m_sshot_tex = std::make_unique( + GLenum(image_to_flip->get_target()), + image_to_flip->width(), + image_to_flip->height(), + image_to_flip->depth(), + image_to_flip->levels(), + image_to_flip->samples(), + GLenum(image_to_flip->get_internal_format()), + image_to_flip->format_class()); + + tex = m_sshot_tex.get(); + + static const position3u offset{}; + gl::g_hw_blitter->copy_image(cmd, image_to_flip, tex, 0, 0, offset, offset, { tex->width(), tex->height(), 1 }); + + render_overlays(tex, areau(0, 0, image_to_flip->width(), image_to_flip->height())); + m_sshot_fbo.remove(); + } + std::vector sshot_frame(buffer_height * buffer_width * 4); glGetError(); - gl::pixel_pack_settings pack_settings{}; - image_to_flip->copy_to(sshot_frame.data(), gl::texture::format::rgba, gl::texture::type::ubyte, pack_settings); + tex->copy_to(sshot_frame.data(), gl::texture::format::rgba, gl::texture::type::ubyte, pack_settings); + + m_sshot_tex.reset(); if (GLenum err = glGetError(); err != GL_NO_ERROR) { @@ -349,38 +421,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) } } - if (m_overlay_manager) - { - if (m_overlay_manager->has_dirty()) - { - m_overlay_manager->lock_shared(); - - std::vector uids_to_dispose; - uids_to_dispose.reserve(m_overlay_manager->get_dirty().size()); - - for (const auto& view : m_overlay_manager->get_dirty()) - { - m_ui_renderer.remove_temp_resources(view->uid); - uids_to_dispose.push_back(view->uid); - } - - m_overlay_manager->unlock_shared(); - m_overlay_manager->dispose(uids_to_dispose); - } - - if (m_overlay_manager->has_visible()) - { - gl::screen.bind(); - - // Lock to avoid modification during run-update chain - std::lock_guard lock(*m_overlay_manager); - - for (const auto& view : m_overlay_manager->get_views()) - { - m_ui_renderer.run(cmd, areau(aspect_ratio), 0, *view.get()); - } - } - } + render_overlays(nullptr, areau(aspect_ratio)); if (g_cfg.video.debug_overlay) { diff --git a/rpcs3/Emu/RSX/GL/glutils/image.h b/rpcs3/Emu/RSX/GL/glutils/image.h index 896c3ee088..6617caa54c 100644 --- a/rpcs3/Emu/RSX/GL/glutils/image.h +++ b/rpcs3/Emu/RSX/GL/glutils/image.h @@ -353,7 +353,7 @@ namespace gl GLenum m_aspect_flags = 0; texture* m_image_data = nullptr; - GLenum component_swizzle[4]; + GLenum component_swizzle[4] {}; texture_view() = default; From 1b5a6a351f5826d7c587a3122109840eb1dc20e2 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 22:44:43 +0100 Subject: [PATCH 4/7] Vk: allow to record overlays --- rpcs3/Emu/RSX/VK/VKFramebuffer.cpp | 10 +-- rpcs3/Emu/RSX/VK/VKPresent.cpp | 61 ++++++++++++++----- .../Emu/RSX/VK/vkutils/framebuffer_object.hpp | 12 ++-- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp index e0bbad628a..d1fc5a4764 100644 --- a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp +++ b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp @@ -29,9 +29,9 @@ namespace vk vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector& image_list) { framebuffer_storage_key key(width, height, has_input_attachments); - auto &queue = g_framebuffers_cache[key.encoded]; + auto& queue = g_framebuffers_cache[key.encoded]; - for (auto &fbo : queue) + for (const auto& fbo : queue) { if (fbo->matches(image_list, width, height)) { @@ -42,7 +42,7 @@ namespace vk std::vector> image_views; image_views.reserve(image_list.size()); - for (auto &e : image_list) + for (const auto& e : image_list) { const VkImageSubresourceRange subres = { e->aspect(), 0, 1, 0, 1 }; image_views.push_back(std::make_unique(dev, e, VK_IMAGE_VIEW_TYPE_2D, vk::default_component_map, subres)); @@ -58,9 +58,9 @@ namespace vk vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment) { framebuffer_storage_key key(width, height, has_input_attachments); - auto &queue = g_framebuffers_cache[key.encoded]; + auto& queue = g_framebuffers_cache[key.encoded]; - for (const auto &e : queue) + for (const auto& e : queue) { if (e->attachments[0]->info.image == attachment) { diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index a682750f69..0a79637862 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -658,6 +658,21 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } } + const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); + const auto render_overlays = [&](vk::framebuffer_holder* fbo, const areau& area) + { + if (!has_overlay) return; + + // Lock to avoid modification during run-update chain + auto ui_renderer = vk::get_overlay_pass(); + std::lock_guard lock(*m_overlay_manager); + + for (const auto& view : m_overlay_manager->get_views()) + { + ui_renderer->run(*m_current_command_buffer, area, fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); + } + }; + if (image_to_flip) { const bool use_full_rgb_range_output = g_cfg.video.full_rgb_range_output.get(); @@ -744,9 +759,34 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) copy_info.imageExtent.height = buffer_height; copy_info.imageExtent.depth = 1; - image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - vk::copy_image_to_buffer(*m_current_command_buffer, image_to_flip, &sshot_vkbuf, copy_info); - image_to_flip->pop_layout(*m_current_command_buffer); + std::unique_ptr tmp_tex; + vk::image* image_to_copy = image_to_flip; + + if (g_cfg.video.record_with_overlays && has_overlay) + { + const auto key = vk::get_renderpass_key(m_swapchain->get_surface_format()); + single_target_pass = vk::get_renderpass(*m_device, key); + ensure(single_target_pass != VK_NULL_HANDLE); + + tmp_tex = std::make_unique(*m_device, m_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + image_to_flip->type(), image_to_flip->format(), image_to_flip->width(), image_to_flip->height(), 1, 1, image_to_flip->layers(), VK_SAMPLE_COUNT_1_BIT, image_to_flip->current_layout, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, VMM_ALLOCATION_POOL_UNDEFINED); + + const areai rect = areai(0, 0, buffer_width, buffer_height); + vk::copy_image(*m_current_command_buffer, image_to_flip, tmp_tex.get(), rect, rect, 1); + + vk::framebuffer_holder* sshot_fbo = vk::get_framebuffer(*m_device, buffer_width, buffer_height, VK_FALSE, single_target_pass, { tmp_tex.get() }); + sshot_fbo->add_ref(); + render_overlays(sshot_fbo, areau(rect)); + sshot_fbo->release(); + + image_to_copy = tmp_tex.get(); + } + + image_to_copy->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + vk::copy_image_to_buffer(*m_current_command_buffer, image_to_copy, &sshot_vkbuf, copy_info); + image_to_copy->pop_layout(*m_current_command_buffer); flush_command_queue(true); const auto src = sshot_vkbuf.map(0, sshot_size); @@ -754,7 +794,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) memcpy(sshot_frame.data(), src, sshot_size); sshot_vkbuf.unmap(); - const bool is_bgra = image_to_flip->format() == VK_FORMAT_B8G8R8A8_UNORM; + const bool is_bgra = image_to_copy->format() == VK_FORMAT_B8G8R8A8_UNORM; if (g_user_asked_for_screenshot.exchange(false)) { @@ -767,7 +807,6 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } } - const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); if (g_cfg.video.debug_overlay || has_overlay) { if (target_layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) @@ -799,17 +838,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) direct_fbo->add_ref(); - if (has_overlay) - { - // Lock to avoid modification during run-update chain - auto ui_renderer = vk::get_overlay_pass(); - std::lock_guard lock(*m_overlay_manager); - - for (const auto& view : m_overlay_manager->get_views()) - { - ui_renderer->run(*m_current_command_buffer, areau(aspect_ratio), direct_fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); - } - } + render_overlays(direct_fbo, areau(aspect_ratio)); if (g_cfg.video.debug_overlay) { diff --git a/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp b/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp index 03ce077bcc..257d93e42e 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp @@ -47,35 +47,35 @@ namespace vk vkDestroyFramebuffer(m_device, value, nullptr); } - u32 width() + u32 width() const { return m_width; } - u32 height() + u32 height() const { return m_height; } - u8 samples() + u8 samples() const { ensure(!attachments.empty()); return attachments[0]->image()->samples(); } - VkFormat format() + VkFormat format() const { ensure(!attachments.empty()); return attachments[0]->image()->format(); } - VkFormat depth_format() + VkFormat depth_format() const { ensure(!attachments.empty()); return attachments.back()->image()->format(); } - bool matches(const std::vector& fbo_images, u32 width, u32 height) + bool matches(const std::vector& fbo_images, u32 width, u32 height) const { if (m_width != width || m_height != height) return false; From 16a60f02f1fdd53d4ac4fb1195762b9cf073979d Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 23:16:04 +0100 Subject: [PATCH 5/7] overlays: add record with overlays setting to home menu --- rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp | 1 + rpcs3/Emu/localized_string_id.h | 1 + rpcs3/rpcs3qt/localized_emu.h | 1 + 3 files changed, 3 insertions(+) diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp index 119f411a24..fe55a4aaa4 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp @@ -99,6 +99,7 @@ namespace rsx add_checkbox(&g_cfg.misc.show_pressure_intensity_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT); add_checkbox(&g_cfg.misc.show_analog_limiter_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT); add_checkbox(&g_cfg.misc.show_mouse_and_keyboard_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT); + add_checkbox(&g_cfg.video.record_with_overlays, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS); apply_layout(); } diff --git a/rpcs3/Emu/localized_string_id.h b/rpcs3/Emu/localized_string_id.h index 5f19c9d6d4..d67446418e 100644 --- a/rpcs3/Emu/localized_string_id.h +++ b/rpcs3/Emu/localized_string_id.h @@ -243,6 +243,7 @@ enum class localized_string_id HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT, HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT, HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT, + HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMERATE_GRAPH, diff --git a/rpcs3/rpcs3qt/localized_emu.h b/rpcs3/rpcs3qt/localized_emu.h index 293ad42bde..44322d24bd 100644 --- a/rpcs3/rpcs3qt/localized_emu.h +++ b/rpcs3/rpcs3qt/localized_emu.h @@ -264,6 +264,7 @@ private: case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT: return tr("Show Pressure Intensity Toggle Hint", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT: return tr( "Show Analog Limiter Toggle Hint", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT: return tr("Show Mouse And Keyboard Toggle Hint", "Overlays"); + case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS: return tr("Record With Overlays", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY: return tr("Performance Overlay"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE: return tr("Enable Performance Overlay", "Performance Overlay"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMERATE_GRAPH: return tr("Enable Framerate Graph", "Performance Overlay"); From e0539eec2cfde7e693397bebf6b261a9a5b46218 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 3 Mar 2025 23:24:20 +0100 Subject: [PATCH 6/7] overlays: add record with overlays setting to settings dialog --- rpcs3/rpcs3qt/emu_settings_type.h | 2 ++ rpcs3/rpcs3qt/settings_dialog.cpp | 3 +++ rpcs3/rpcs3qt/settings_dialog.ui | 7 +++++++ rpcs3/rpcs3qt/tooltips.h | 1 + 4 files changed, 13 insertions(+) diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 845e21a8d8..8acc6bde6f 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -105,6 +105,7 @@ enum class emu_settings_type OutputScalingMode, ForceHwMSAAResolve, DisableAsyncHostMM, + RecordWithOverlays, // Performance Overlay PerfOverlayEnabled, @@ -299,6 +300,7 @@ inline static const std::map settings_location { emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}}, { emu_settings_type::ForceHwMSAAResolve, { "Video", "Force Hardware MSAA Resolve"}}, { emu_settings_type::DisableAsyncHostMM, { "Video", "Disable Asynchronous Memory Manager"}}, + { emu_settings_type::RecordWithOverlays, { "Video", "Record With Overlays"}}, // Vulkan { emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming 2"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 77790ac0a0..6b6756788a 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1859,6 +1859,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->showMouseAndKeyboardToggleHint, emu_settings_type::ShowMouseAndKeyboardToggleHint); SubscribeTooltip(ui->showMouseAndKeyboardToggleHint, tooltips.settings.show_mouse_and_keyboard_toggle_hint); + m_emu_settings->EnhanceCheckBox(ui->recordWithOverlays, emu_settings_type::RecordWithOverlays); + SubscribeTooltip(ui->recordWithOverlays, tooltips.settings.record_with_overlays); + m_emu_settings->EnhanceCheckBox(ui->pauseDuringHomeMenu, emu_settings_type::PauseDuringHomeMenu); SubscribeTooltip(ui->pauseDuringHomeMenu, tooltips.settings.pause_during_home_menu); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 08a453d1f6..c947a078cc 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -3015,6 +3015,13 @@ + + + + Record with overlays + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 9ac64c495a..3c993bc310 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -149,6 +149,7 @@ public: const QString show_analog_limiter_toggle_hint = tr("Shows analog limiter toggle hint using the native overlay."); const QString show_mouse_and_keyboard_toggle_hint = tr("Shows mouse and keyboard toggle hint using the native overlay."); const QString use_native_interface = tr("Enables use of native HUD within the game window that can interact with game controllers.\nWhen disabled, regular Qt dialogs are used instead.\nCurrently, the on-screen keyboard only supports the English key layout."); + const QString record_with_overlays = tr("Enables recording with overlays.\nThis also affects screenshots."); const QString pause_during_home_menu = tr("When enabled, opening the home menu will also pause emulation.\nWhile most games pause themselves while the home menu is shown, some do not.\nIn that case it can be helpful to pause the emulation whenever the home menu is open."); const QString perf_overlay_enabled = tr("Enables or disables the performance overlay."); From cbb02f9447e31f12235506011e0882ab8f50d60f Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 5 Mar 2025 00:02:41 +0100 Subject: [PATCH 7/7] VK: add memory barriers to copy_image --- rpcs3/Emu/RSX/VK/VKPresent.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 0a79637862..d0ad054f71 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -773,9 +773,15 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); + tmp_tex->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + const areai rect = areai(0, 0, buffer_width, buffer_height); vk::copy_image(*m_current_command_buffer, image_to_flip, tmp_tex.get(), rect, rect, 1); + image_to_flip->pop_layout(*m_current_command_buffer); + tmp_tex->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + vk::framebuffer_holder* sshot_fbo = vk::get_framebuffer(*m_device, buffer_width, buffer_height, VK_FALSE, single_target_pass, { tmp_tex.get() }); sshot_fbo->add_ref(); render_overlays(sshot_fbo, areau(rect));