Vk: allow to record overlays

This commit is contained in:
Megamouse 2025-03-03 22:44:43 +01:00
parent e2118cddad
commit 1b5a6a351f
3 changed files with 56 additions and 27 deletions

View file

@ -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<vk::image*>& 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<std::unique_ptr<vk::image_view>> 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<vk::image_view>(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)
{

View file

@ -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<vk::ui_overlay_renderer>();
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<vk::image> 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<vk::image>(*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<vk::ui_overlay_renderer>();
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)
{

View file

@ -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<vk::image*>& fbo_images, u32 width, u32 height)
bool matches(const std::vector<vk::image*>& fbo_images, u32 width, u32 height) const
{
if (m_width != width || m_height != height)
return false;