From f6b5735402d88bfd7d69ebe6d4cf04ad25746d5f Mon Sep 17 00:00:00 2001
From: psucien <bad_cast@protonmail.com>
Date: Thu, 21 Nov 2024 00:00:10 +0100
Subject: [PATCH] splash functionality restored

---
 src/core/libraries/videoout/driver.cpp        |  3 +
 .../renderer_vulkan/vk_presenter.cpp          | 63 ++++++++++++++++++-
 .../texture_cache/texture_cache.cpp           |  4 +-
 3 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp
index 6f524f934..13d67c4e7 100644
--- a/src/core/libraries/videoout/driver.cpp
+++ b/src/core/libraries/videoout/driver.cpp
@@ -201,6 +201,9 @@ void VideoOutDriver::Flip(const Request& req) {
 }
 
 void VideoOutDriver::DrawBlankFrame() {
+    if (presenter->ShowSplash(nullptr)) {
+        return;
+    }
     const auto empty_frame = presenter->PrepareBlankFrame(false);
     presenter->Present(empty_frame);
 }
diff --git a/src/video_core/renderer_vulkan/vk_presenter.cpp b/src/video_core/renderer_vulkan/vk_presenter.cpp
index 4cc0facc2..d4972cbad 100644
--- a/src/video_core/renderer_vulkan/vk_presenter.cpp
+++ b/src/video_core/renderer_vulkan/vk_presenter.cpp
@@ -407,6 +407,9 @@ bool Presenter::ShowSplash(Frame* frame /*= nullptr*/) {
         return false;
     }
 
+    draw_scheduler.EndRendering();
+    const auto cmdbuf = draw_scheduler.CommandBuffer();
+
     if (!frame) {
         if (!splash_img.has_value()) {
             VideoCore::ImageInfo info{};
@@ -417,11 +420,69 @@ bool Presenter::ShowSplash(Frame* frame /*= nullptr*/) {
             info.pitch = splash->GetImageInfo().width;
             info.guest_address = VAddr(splash->GetImageData().data());
             info.guest_size_bytes = splash->GetImageData().size();
+            info.mips_layout.emplace_back(splash->GetImageData().size(),
+                                          splash->GetImageInfo().width,
+                                          splash->GetImageInfo().height, 0);
             splash_img.emplace(instance, present_scheduler, info);
             texture_cache.RefreshImage(*splash_img);
+
+            splash_img->Transit(vk::ImageLayout::eTransferSrcOptimal,
+                                vk::AccessFlagBits2::eTransferRead, {}, cmdbuf);
         }
-        // frame = PrepareFrameInternal(*splash_img);
+
+        frame = GetRenderFrame();
     }
+
+    const auto frame_subresources = vk::ImageSubresourceRange{
+        .aspectMask = vk::ImageAspectFlagBits::eColor,
+        .baseMipLevel = 0,
+        .levelCount = 1,
+        .baseArrayLayer = 0,
+        .layerCount = VK_REMAINING_ARRAY_LAYERS,
+    };
+
+    const auto pre_barrier =
+        vk::ImageMemoryBarrier2{.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
+                                .srcAccessMask = vk::AccessFlagBits2::eTransferRead,
+                                .dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
+                                .dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
+                                .oldLayout = vk::ImageLayout::eUndefined,
+                                .newLayout = vk::ImageLayout::eTransferDstOptimal,
+                                .image = frame->image,
+                                .subresourceRange{frame_subresources}};
+
+    cmdbuf.pipelineBarrier2(vk::DependencyInfo{
+        .imageMemoryBarrierCount = 1,
+        .pImageMemoryBarriers = &pre_barrier,
+    });
+
+    cmdbuf.blitImage(splash_img->image, vk::ImageLayout::eTransferSrcOptimal, frame->image,
+                     vk::ImageLayout::eTransferDstOptimal,
+                     MakeImageBlitFit(splash->GetImageInfo().width, splash->GetImageInfo().height,
+                                      frame->width, frame->height),
+                     vk::Filter::eLinear);
+
+    const auto post_barrier =
+        vk::ImageMemoryBarrier2{.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
+                                .srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
+                                .dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
+                                .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
+                                .oldLayout = vk::ImageLayout::eTransferDstOptimal,
+                                .newLayout = vk::ImageLayout::eGeneral,
+                                .image = frame->image,
+                                .subresourceRange{frame_subresources}};
+
+    cmdbuf.pipelineBarrier2(vk::DependencyInfo{
+        .imageMemoryBarrierCount = 1,
+        .pImageMemoryBarriers = &post_barrier,
+    });
+
+    // Flush frame creation commands.
+    frame->ready_semaphore = draw_scheduler.GetMasterSemaphore()->Handle();
+    frame->ready_tick = draw_scheduler.CurrentTick();
+    SubmitInfo info{};
+    draw_scheduler.Flush(info);
+
     Present(frame);
     return true;
 }
diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp
index 27c288885..da7d0921b 100644
--- a/src/video_core/texture_cache/texture_cache.cpp
+++ b/src/video_core/texture_cache/texture_cache.cpp
@@ -28,7 +28,7 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
     info.num_bits = 32;
     info.UpdateSize();
     const ImageId null_id = slot_images.insert(instance, scheduler, info);
-    ASSERT(null_id.index == 0);
+    ASSERT(null_id.index == NULL_IMAGE_ID.index);
     const vk::Image& null_image = slot_images[null_id].image;
     Vulkan::SetObjectName(instance.GetDevice(), null_image, "Null Image");
     slot_images[null_id].flags = ImageFlagBits::Tracked;
@@ -36,7 +36,7 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
     ImageViewInfo view_info;
     const auto null_view_id =
         slot_image_views.insert(instance, view_info, slot_images[null_id], null_id);
-    ASSERT(null_view_id.index == 0);
+    ASSERT(null_view_id.index == NULL_IMAGE_VIEW_ID.index);
     const vk::ImageView& null_image_view = slot_image_views[null_view_id].image_view.get();
     Vulkan::SetObjectName(instance.GetDevice(), null_image_view, "Null Image View");
 }