From 9fc7ca1731862354ef70bfaf34d2c807a904a27b Mon Sep 17 00:00:00 2001
From: Feng Chen <vonchenplus@gmail.com>
Date: Wed, 11 Jan 2023 11:10:48 +0800
Subject: [PATCH] Address feedback

---
 src/video_core/engines/draw_manager.cpp       |  4 +-
 .../host_shaders/full_screen_triangle.vert    |  2 +-
 src/video_core/renderer_vulkan/blit_image.cpp | 61 ++++++++++++++++---
 src/video_core/renderer_vulkan/blit_image.h   |  4 +-
 .../renderer_vulkan/vk_rasterizer.cpp         |  5 +-
 5 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp
index 2685481f95..1d22d25f12 100644
--- a/src/video_core/engines/draw_manager.cpp
+++ b/src/video_core/engines/draw_manager.cpp
@@ -199,10 +199,10 @@ void DrawManager::DrawTexture() {
     draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f;
     draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f;
     draw_texture_state.src_x1 =
-        (static_cast<float>(regs.draw_texture.dx_du) / 4294967295.f) * dst_width +
+        (static_cast<float>(regs.draw_texture.dx_du) / 4294967296.f) * dst_width +
         draw_texture_state.src_x0;
     draw_texture_state.src_y1 =
-        (static_cast<float>(regs.draw_texture.dy_dv) / 4294967295.f) * dst_height +
+        (static_cast<float>(regs.draw_texture.dy_dv) / 4294967296.f) * dst_height +
         draw_texture_state.src_y0;
     draw_texture_state.src_sampler = regs.draw_texture.src_sampler;
     draw_texture_state.src_texture = regs.draw_texture.src_texture;
diff --git a/src/video_core/host_shaders/full_screen_triangle.vert b/src/video_core/host_shaders/full_screen_triangle.vert
index 8ac936efdf..d16d989956 100644
--- a/src/video_core/host_shaders/full_screen_triangle.vert
+++ b/src/video_core/host_shaders/full_screen_triangle.vert
@@ -32,4 +32,4 @@ void main() {
     float y = float((VERTEX_ID & 2) << 1);
     gl_Position = vec4(x - 1.0, FLIPY * (y - 1.0), 0.0, 1.0);
     texcoord = fma(vec2(x, y) / 2.0, tex_scale, tex_offset);
-}
\ No newline at end of file
+}
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index d728e5c6c9..dd00d3edfa 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -350,6 +350,51 @@ VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
         .height = is_rescaled ? resolution.ScaleUp(height) : height,
     };
 }
+
+void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
+                           VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) {
+    constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+                            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT};
+    const VkImageMemoryBarrier barrier{
+        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+        .pNext = nullptr,
+        .srcAccessMask = flags,
+        .dstAccessMask = flags,
+        .oldLayout = source_layout,
+        .newLayout = target_layout,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .image = image,
+        .subresourceRange{
+            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+            .baseMipLevel = 0,
+            .levelCount = 1,
+            .baseArrayLayer = 0,
+            .layerCount = 1,
+        },
+    };
+    cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                           0, barrier);
+}
+
+void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) {
+    const VkRenderPass render_pass = framebuffer->RenderPass();
+    const VkFramebuffer framebuffer_handle = framebuffer->Handle();
+    const VkExtent2D render_area = framebuffer->RenderArea();
+    const VkRenderPassBeginInfo renderpass_bi{
+        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+        .pNext = nullptr,
+        .renderPass = render_pass,
+        .framebuffer = framebuffer_handle,
+        .renderArea{
+            .offset{},
+            .extent = render_area,
+        },
+        .clearValueCount = 0,
+        .pClearValues = nullptr,
+    };
+    cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
+}
 } // Anonymous namespace
 
 BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
@@ -408,18 +453,20 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
 }
 
 void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
-                                VkSampler src_sampler, const Region2D& dst_region,
-                                const Region2D& src_region, const Extent3D& src_size) {
+                                VkImage src_image, VkSampler src_sampler,
+                                const Region2D& dst_region, const Region2D& src_region,
+                                const Extent3D& src_size) {
     const BlitImagePipelineKey key{
         .renderpass = dst_framebuffer->RenderPass(),
         .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy,
     };
     const VkPipelineLayout layout = *one_texture_pipeline_layout;
     const VkPipeline pipeline = FindOrEmplaceColorPipeline(key);
-    scheduler.RequestRenderpass(dst_framebuffer);
-    scheduler.Record([this, dst_region, src_region, src_size, pipeline, layout, src_sampler,
-                      src_image_view](vk::CommandBuffer cmdbuf) {
-        // TODO: Barriers
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region,
+                      src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) {
+        TransitionImageLayout(cmdbuf, src_image, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
+        BeginRenderPass(cmdbuf, dst_framebuffer);
         const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
         UpdateOneTextureDescriptorSet(device, descriptor_set, src_sampler, src_image_view);
         cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@@ -427,8 +474,8 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
                                   nullptr);
         BindBlitState(cmdbuf, layout, dst_region, src_region, src_size);
         cmdbuf.Draw(3, 1, 0, 0);
+        cmdbuf.EndRenderPass();
     });
-    scheduler.InvalidateState();
 }
 
 void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index e2db33f563..be8a9a2f67 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -39,8 +39,8 @@ public:
                    Tegra::Engines::Fermi2D::Operation operation);
 
     void BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
-                   VkSampler src_sampler, const Region2D& dst_region, const Region2D& src_region,
-                   const Extent3D& src_size);
+                   VkImage src_image, VkSampler src_sampler, const Region2D& dst_region,
+                   const Region2D& src_region, const Extent3D& src_size);
 
     void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view,
                           VkImageView src_stencil_view, const Region2D& dst_region,
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 153096fa40..e45512d4fd 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -289,8 +289,9 @@ void RasterizerVulkan::DrawTexture() {
                                     .y = static_cast<s32>(draw_texture_state.src_y0)},
                            Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1),
                                     .y = static_cast<s32>(draw_texture_state.src_y1)}};
-    blit_image.BlitColor(texture_cache.GetFramebuffer(), texture.RenderTarget(), sampler->Handle(),
-                         dst_region, src_region, texture.size);
+    blit_image.BlitColor(texture_cache.GetFramebuffer(), texture.RenderTarget(),
+                         texture.ImageHandle(), sampler->Handle(), dst_region, src_region,
+                         texture.size);
 }
 
 void RasterizerVulkan::Clear(u32 layer_count) {