Просмотр исходного кода

renderer_vulkan: isolate FXAA from blit screen

Liam 2 лет назад
Родитель
Сommit
9568b310be

+ 8 - 4
src/video_core/CMakeLists.txt

@@ -158,6 +158,14 @@ add_library(video_core STATIC
     renderer_opengl/renderer_opengl.h
     renderer_opengl/util_shaders.cpp
     renderer_opengl/util_shaders.h
+    renderer_vulkan/present/fsr.cpp
+    renderer_vulkan/present/fsr.h
+    renderer_vulkan/present/fxaa.cpp
+    renderer_vulkan/present/fxaa.h
+    renderer_vulkan/present/smaa.cpp
+    renderer_vulkan/present/smaa.h
+    renderer_vulkan/present/util.cpp
+    renderer_vulkan/present/util.h
     renderer_vulkan/blit_image.cpp
     renderer_vulkan/blit_image.h
     renderer_vulkan/fixed_pipeline_state.cpp
@@ -184,8 +192,6 @@ add_library(video_core STATIC
     renderer_vulkan/vk_descriptor_pool.h
     renderer_vulkan/vk_fence_manager.cpp
     renderer_vulkan/vk_fence_manager.h
-    renderer_vulkan/vk_fsr.cpp
-    renderer_vulkan/vk_fsr.h
     renderer_vulkan/vk_graphics_pipeline.cpp
     renderer_vulkan/vk_graphics_pipeline.h
     renderer_vulkan/vk_master_semaphore.cpp
@@ -206,8 +212,6 @@ add_library(video_core STATIC
     renderer_vulkan/vk_scheduler.h
     renderer_vulkan/vk_shader_util.cpp
     renderer_vulkan/vk_shader_util.h
-    renderer_vulkan/vk_smaa.cpp
-    renderer_vulkan/vk_smaa.h
     renderer_vulkan/vk_staging_buffer_pool.cpp
     renderer_vulkan/vk_staging_buffer_pool.h
     renderer_vulkan/vk_state_tracker.cpp

+ 27 - 0
src/video_core/renderer_vulkan/present/anti_alias_pass.h

@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+
+class Scheduler;
+
+class AntiAliasPass {
+public:
+    virtual ~AntiAliasPass() = default;
+    virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+                             VkImageView source_image_view) = 0;
+};
+
+class NoAA final : public AntiAliasPass {
+public:
+    virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+                             VkImageView source_image_view) {
+        return source_image_view;
+    }
+};
+
+} // namespace Vulkan

+ 1 - 1
src/video_core/renderer_vulkan/vk_fsr.cpp → src/video_core/renderer_vulkan/present/fsr.cpp

@@ -10,7 +10,7 @@
 #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h"
 #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h"
 #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h"
-#include "video_core/renderer_vulkan/vk_fsr.h"
+#include "video_core/renderer_vulkan/present/fsr.h"
 #include "video_core/renderer_vulkan/vk_scheduler.h"
 #include "video_core/renderer_vulkan/vk_shader_util.h"
 #include "video_core/vulkan_common/vulkan_device.h"

+ 0 - 0
src/video_core/renderer_vulkan/vk_fsr.h → src/video_core/renderer_vulkan/present/fsr.h


+ 144 - 0
src/video_core/renderer_vulkan/present/fxaa.cpp

@@ -0,0 +1,144 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/common_types.h"
+
+#include "video_core/host_shaders/fxaa_frag_spv.h"
+#include "video_core/host_shaders/fxaa_vert_spv.h"
+#include "video_core/renderer_vulkan/present/fxaa.h"
+#include "video_core/renderer_vulkan/present/util.h"
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/renderer_vulkan/vk_shader_util.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+
+namespace Vulkan {
+
+FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
+    : m_device(device), m_allocator(allocator), m_extent(extent),
+      m_image_count(static_cast<u32>(image_count)) {
+    CreateImages();
+    CreateRenderPasses();
+    CreateSampler();
+    CreateShaders();
+    CreateDescriptorPool();
+    CreateDescriptorSetLayouts();
+    CreateDescriptorSets();
+    CreatePipelineLayouts();
+    CreatePipelines();
+}
+
+FXAA::~FXAA() = default;
+
+void FXAA::CreateImages() {
+    for (u32 i = 0; i < m_image_count; i++) {
+        Image& image = m_dynamic_images.emplace_back();
+
+        image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
+        image.image_view =
+            CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
+    }
+}
+
+void FXAA::CreateRenderPasses() {
+    m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
+
+    for (auto& image : m_dynamic_images) {
+        image.framebuffer =
+            CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent);
+    }
+}
+
+void FXAA::CreateSampler() {
+    m_sampler = CreateWrappedSampler(m_device);
+}
+
+void FXAA::CreateShaders() {
+    m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV);
+    m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV);
+}
+
+void FXAA::CreateDescriptorPool() {
+    // 2 descriptors, 1 descriptor set per image
+    m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count);
+}
+
+void FXAA::CreateDescriptorSetLayouts() {
+    m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2);
+}
+
+void FXAA::CreateDescriptorSets() {
+    VkDescriptorSetLayout layout = *m_descriptor_set_layout;
+
+    for (auto& images : m_dynamic_images) {
+        images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout});
+    }
+}
+
+void FXAA::CreatePipelineLayouts() {
+    m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout);
+}
+
+void FXAA::CreatePipelines() {
+    m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
+                                       std::tie(m_vertex_shader, m_fragment_shader));
+}
+
+void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
+    Image& image = m_dynamic_images[image_index];
+    std::vector<VkDescriptorImageInfo> image_infos;
+    std::vector<VkWriteDescriptorSet> updates;
+    image_infos.reserve(2);
+
+    updates.push_back(
+        CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0));
+    updates.push_back(
+        CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
+
+    m_device.GetLogical().UpdateDescriptorSets(updates, {});
+}
+
+void FXAA::UploadImages(Scheduler& scheduler) {
+    if (m_images_ready) {
+        return;
+    }
+
+    scheduler.Record([&](vk::CommandBuffer cmdbuf) {
+        for (auto& image : m_dynamic_images) {
+            ClearColorImage(cmdbuf, *image.image);
+        }
+    });
+    scheduler.Finish();
+
+    m_images_ready = true;
+}
+
+VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+                       VkImageView source_image_view) {
+    const Image& image{m_dynamic_images[image_index]};
+    const VkImage output_image{*image.image};
+    const VkDescriptorSet descriptor_set{image.descriptor_sets[0]};
+    const VkFramebuffer framebuffer{*image.framebuffer};
+    const VkRenderPass renderpass{*m_renderpass};
+    const VkPipeline pipeline{*m_pipeline};
+    const VkPipelineLayout layout{*m_pipeline_layout};
+    const VkExtent2D extent{m_extent};
+
+    UploadImages(scheduler);
+    UpdateDescriptorSets(source_image_view, image_index);
+
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([=](vk::CommandBuffer cmdbuf) {
+        TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
+        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+        BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
+        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
+        cmdbuf.Draw(4, 1, 0, 0);
+        cmdbuf.EndRenderPass();
+        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+    });
+
+    return *image.image_view;
+}
+
+} // namespace Vulkan

+ 63 - 0
src/video_core/renderer_vulkan/present/fxaa.h

@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "video_core/renderer_vulkan/present/anti_alias_pass.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+
+class Device;
+class Scheduler;
+class StagingBufferPool;
+
+class FXAA final : public AntiAliasPass {
+public:
+    explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
+                  VkExtent2D extent);
+    ~FXAA() override;
+
+    VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+                     VkImageView source_image_view) override;
+
+private:
+    void CreateImages();
+    void CreateRenderPasses();
+    void CreateSampler();
+    void CreateShaders();
+    void CreateDescriptorPool();
+    void CreateDescriptorSetLayouts();
+    void CreateDescriptorSets();
+    void CreatePipelineLayouts();
+    void CreatePipelines();
+    void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
+    void UploadImages(Scheduler& scheduler);
+
+    const Device& m_device;
+    MemoryAllocator& m_allocator;
+    const VkExtent2D m_extent;
+    const u32 m_image_count;
+
+    vk::ShaderModule m_vertex_shader{};
+    vk::ShaderModule m_fragment_shader{};
+    vk::DescriptorPool m_descriptor_pool{};
+    vk::DescriptorSetLayout m_descriptor_set_layout{};
+    vk::PipelineLayout m_pipeline_layout{};
+    vk::Pipeline m_pipeline{};
+    vk::RenderPass m_renderpass{};
+
+    struct Image {
+        vk::DescriptorSets descriptor_sets{};
+        vk::Framebuffer framebuffer{};
+        vk::Image image{};
+        vk::ImageView image_view{};
+    };
+    std::vector<Image> m_dynamic_images{};
+    bool m_images_ready{};
+
+    vk::Sampler m_sampler{};
+};
+
+} // namespace Vulkan

+ 270 - 0
src/video_core/renderer_vulkan/present/smaa.cpp

@@ -0,0 +1,270 @@
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <list>
+
+#include "common/assert.h"
+#include "common/polyfill_ranges.h"
+
+#include "video_core/renderer_vulkan/present/smaa.h"
+#include "video_core/renderer_vulkan/present/util.h"
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/renderer_vulkan/vk_shader_util.h"
+#include "video_core/smaa_area_tex.h"
+#include "video_core/smaa_search_tex.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+
+#include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h"
+#include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h"
+#include "video_core/host_shaders/smaa_edge_detection_frag_spv.h"
+#include "video_core/host_shaders/smaa_edge_detection_vert_spv.h"
+#include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h"
+#include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h"
+
+namespace Vulkan {
+
+SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
+    : m_device(device), m_allocator(allocator), m_extent(extent),
+      m_image_count(static_cast<u32>(image_count)) {
+    CreateImages();
+    CreateRenderPasses();
+    CreateSampler();
+    CreateShaders();
+    CreateDescriptorPool();
+    CreateDescriptorSetLayouts();
+    CreateDescriptorSets();
+    CreatePipelineLayouts();
+    CreatePipelines();
+}
+
+SMAA::~SMAA() = default;
+
+void SMAA::CreateImages() {
+    static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
+    static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
+
+    m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM);
+    m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM);
+
+    m_static_image_views[Area] =
+        CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
+    m_static_image_views[Search] =
+        CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM);
+
+    for (u32 i = 0; i < m_image_count; i++) {
+        Images& images = m_dynamic_images.emplace_back();
+
+        images.images[Blend] =
+            CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
+        images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
+        images.images[Output] =
+            CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
+
+        images.image_views[Blend] =
+            CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
+        images.image_views[Edges] =
+            CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
+        images.image_views[Output] =
+            CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
+    }
+}
+
+void SMAA::CreateRenderPasses() {
+    m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT);
+    m_renderpasses[BlendingWeightCalculation] =
+        CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
+    m_renderpasses[NeighborhoodBlending] =
+        CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
+
+    for (auto& images : m_dynamic_images) {
+        images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
+            m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
+
+        images.framebuffers[BlendingWeightCalculation] =
+            CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation],
+                                     images.image_views[Blend], m_extent);
+
+        images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
+            m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
+    }
+}
+
+void SMAA::CreateSampler() {
+    m_sampler = CreateWrappedSampler(m_device);
+}
+
+void SMAA::CreateShaders() {
+    // These match the order of the SMAAStage enum
+    static constexpr std::array vert_shader_sources{
+        ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV),
+        ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV),
+        ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV),
+    };
+    static constexpr std::array frag_shader_sources{
+        ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV),
+        ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV),
+        ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV),
+    };
+
+    for (size_t i = 0; i < MaxSMAAStage; i++) {
+        m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]);
+        m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]);
+    }
+}
+
+void SMAA::CreateDescriptorPool() {
+    // Edge detection: 1 descriptor
+    // Blending weight calculation: 3 descriptors
+    // Neighborhood blending: 2 descriptors
+
+    // 6 descriptors, 3 descriptor sets per image
+    m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count);
+}
+
+void SMAA::CreateDescriptorSetLayouts() {
+    m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1);
+    m_descriptor_set_layouts[BlendingWeightCalculation] =
+        CreateWrappedDescriptorSetLayout(m_device, 3);
+    m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2);
+}
+
+void SMAA::CreateDescriptorSets() {
+    std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size());
+    std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
+                           [](auto& layout) { return *layout; });
+
+    for (auto& images : m_dynamic_images) {
+        images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
+    }
+}
+
+void SMAA::CreatePipelineLayouts() {
+    for (size_t i = 0; i < MaxSMAAStage; i++) {
+        m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]);
+    }
+}
+
+void SMAA::CreatePipelines() {
+    for (size_t i = 0; i < MaxSMAAStage; i++) {
+        m_pipelines[i] =
+            CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i],
+                                  std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
+    }
+}
+
+void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
+    Images& images = m_dynamic_images[image_index];
+    std::vector<VkDescriptorImageInfo> image_infos;
+    std::vector<VkWriteDescriptorSet> updates;
+    image_infos.reserve(6);
+
+    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
+                                               images.descriptor_sets[EdgeDetection], 0));
+
+    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges],
+                                               images.descriptor_sets[BlendingWeightCalculation],
+                                               0));
+    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area],
+                                               images.descriptor_sets[BlendingWeightCalculation],
+                                               1));
+    updates.push_back(
+        CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search],
+                                 images.descriptor_sets[BlendingWeightCalculation], 2));
+
+    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
+                                               images.descriptor_sets[NeighborhoodBlending], 0));
+    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
+                                               images.descriptor_sets[NeighborhoodBlending], 1));
+
+    m_device.GetLogical().UpdateDescriptorSets(updates, {});
+}
+
+void SMAA::UploadImages(Scheduler& scheduler) {
+    if (m_images_ready) {
+        return;
+    }
+
+    static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
+    static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
+
+    UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent,
+                VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes));
+    UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
+                VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
+
+    scheduler.Record([&](vk::CommandBuffer cmdbuf) {
+        for (auto& images : m_dynamic_images) {
+            for (size_t i = 0; i < MaxDynamicImage; i++) {
+                ClearColorImage(cmdbuf, *images.images[i]);
+            }
+        }
+    });
+    scheduler.Finish();
+
+    m_images_ready = true;
+}
+
+VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+                       VkImageView source_image_view) {
+    Images& images = m_dynamic_images[image_index];
+
+    VkImage output_image = *images.images[Output];
+    VkImage edges_image = *images.images[Edges];
+    VkImage blend_image = *images.images[Blend];
+
+    VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection];
+    VkDescriptorSet blending_weight_calculation_descriptor_set =
+        images.descriptor_sets[BlendingWeightCalculation];
+    VkDescriptorSet neighborhood_blending_descriptor_set =
+        images.descriptor_sets[NeighborhoodBlending];
+
+    VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection];
+    VkFramebuffer blending_weight_calculation_framebuffer =
+        *images.framebuffers[BlendingWeightCalculation];
+    VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
+
+    UploadImages(scheduler);
+    UpdateDescriptorSets(source_image_view, image_index);
+
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
+        TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
+        TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
+        BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer,
+                        m_extent);
+        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]);
+        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                  *m_pipeline_layouts[EdgeDetection], 0,
+                                  edge_detection_descriptor_set, {});
+        cmdbuf.Draw(3, 1, 0, 0);
+        cmdbuf.EndRenderPass();
+
+        TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
+        TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
+        BeginRenderPass(cmdbuf, *m_renderpasses[BlendingWeightCalculation],
+                        blending_weight_calculation_framebuffer, m_extent);
+        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
+                            *m_pipelines[BlendingWeightCalculation]);
+        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                  *m_pipeline_layouts[BlendingWeightCalculation], 0,
+                                  blending_weight_calculation_descriptor_set, {});
+        cmdbuf.Draw(3, 1, 0, 0);
+        cmdbuf.EndRenderPass();
+
+        TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
+        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+        BeginRenderPass(cmdbuf, *m_renderpasses[NeighborhoodBlending],
+                        neighborhood_blending_framebuffer, m_extent);
+        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]);
+        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                  *m_pipeline_layouts[NeighborhoodBlending], 0,
+                                  neighborhood_blending_descriptor_set, {});
+        cmdbuf.Draw(3, 1, 0, 0);
+        cmdbuf.EndRenderPass();
+        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+    });
+
+    return *images.image_views[Output];
+}
+
+} // namespace Vulkan

+ 5 - 2
src/video_core/renderer_vulkan/vk_smaa.h → src/video_core/renderer_vulkan/present/smaa.h

@@ -4,6 +4,7 @@
 #pragma once
 
 #include <array>
+#include "video_core/renderer_vulkan/present/anti_alias_pass.h"
 #include "video_core/vulkan_common/vulkan_memory_allocator.h"
 #include "video_core/vulkan_common/vulkan_wrapper.h"
 
@@ -13,12 +14,14 @@ class Device;
 class Scheduler;
 class StagingBufferPool;
 
-class SMAA {
+class SMAA final : public AntiAliasPass {
 public:
     explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
                   VkExtent2D extent);
+    ~SMAA() override;
+
     VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
-                     VkImageView source_image_view);
+                     VkImageView source_image_view) override;
 
 private:
     enum SMAAStage {

+ 10 - 272
src/video_core/renderer_vulkan/vk_smaa.cpp → src/video_core/renderer_vulkan/present/util.cpp

@@ -1,29 +1,11 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include <list>
-
 #include "common/assert.h"
 #include "common/polyfill_ranges.h"
-
-#include "video_core/renderer_vulkan/vk_scheduler.h"
-#include "video_core/renderer_vulkan/vk_shader_util.h"
-#include "video_core/renderer_vulkan/vk_smaa.h"
-#include "video_core/smaa_area_tex.h"
-#include "video_core/smaa_search_tex.h"
-#include "video_core/vulkan_common/vulkan_device.h"
-
-#include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h"
-#include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h"
-#include "video_core/host_shaders/smaa_edge_detection_frag_spv.h"
-#include "video_core/host_shaders/smaa_edge_detection_vert_spv.h"
-#include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h"
-#include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h"
+#include "video_core/renderer_vulkan/present/util.h"
 
 namespace Vulkan {
-namespace {
-
-#define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0])))
 
 vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) {
     const VkImageCreateInfo image_ci{
@@ -48,7 +30,7 @@ vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions,
 }
 
 void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
-                           VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) {
+                           VkImageLayout source_layout) {
     constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT};
     const VkImageMemoryBarrier barrier{
@@ -75,7 +57,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
 
 void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
                  vk::Image& image, VkExtent2D dimensions, VkFormat format,
-                 std::span<const u8> initial_contents = {}) {
+                 std::span<const u8> initial_contents) {
     const VkBufferCreateInfo upload_ci = {
         .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
         .pNext = nullptr,
@@ -200,13 +182,13 @@ vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& r
     });
 }
 
-vk::Sampler CreateWrappedSampler(const Device& device) {
+vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter) {
     return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
         .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
         .pNext = nullptr,
         .flags = 0,
-        .magFilter = VK_FILTER_LINEAR,
-        .minFilter = VK_FILTER_LINEAR,
+        .magFilter = filter,
+        .minFilter = filter,
         .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
         .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
         .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
@@ -471,12 +453,12 @@ void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) {
     cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources);
 }
 
-void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass,
-                     VkFramebuffer framebuffer, VkExtent2D extent) {
+void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
+                     VkExtent2D extent) {
     const VkRenderPassBeginInfo renderpass_bi{
         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
         .pNext = nullptr,
-        .renderPass = *render_pass,
+        .renderPass = render_pass,
         .framebuffer = framebuffer,
         .renderArea{
             .offset{},
@@ -503,248 +485,4 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass,
     cmdbuf.SetScissor(0, scissor);
 }
 
-} // Anonymous namespace
-
-SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
-    : m_device(device), m_allocator(allocator), m_extent(extent),
-      m_image_count(static_cast<u32>(image_count)) {
-    CreateImages();
-    CreateRenderPasses();
-    CreateSampler();
-    CreateShaders();
-    CreateDescriptorPool();
-    CreateDescriptorSetLayouts();
-    CreateDescriptorSets();
-    CreatePipelineLayouts();
-    CreatePipelines();
-}
-
-void SMAA::CreateImages() {
-    static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
-    static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
-
-    m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM);
-    m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM);
-
-    m_static_image_views[Area] =
-        CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
-    m_static_image_views[Search] =
-        CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM);
-
-    for (u32 i = 0; i < m_image_count; i++) {
-        Images& images = m_dynamic_images.emplace_back();
-
-        images.images[Blend] =
-            CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
-        images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
-        images.images[Output] =
-            CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
-
-        images.image_views[Blend] =
-            CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
-        images.image_views[Edges] =
-            CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
-        images.image_views[Output] =
-            CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
-    }
-}
-
-void SMAA::CreateRenderPasses() {
-    m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT);
-    m_renderpasses[BlendingWeightCalculation] =
-        CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
-    m_renderpasses[NeighborhoodBlending] =
-        CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
-
-    for (auto& images : m_dynamic_images) {
-        images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
-            m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
-
-        images.framebuffers[BlendingWeightCalculation] =
-            CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation],
-                                     images.image_views[Blend], m_extent);
-
-        images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
-            m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
-    }
-}
-
-void SMAA::CreateSampler() {
-    m_sampler = CreateWrappedSampler(m_device);
-}
-
-void SMAA::CreateShaders() {
-    // These match the order of the SMAAStage enum
-    static constexpr std::array vert_shader_sources{
-        ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV),
-        ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV),
-        ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV),
-    };
-    static constexpr std::array frag_shader_sources{
-        ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV),
-        ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV),
-        ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV),
-    };
-
-    for (size_t i = 0; i < MaxSMAAStage; i++) {
-        m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]);
-        m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]);
-    }
-}
-
-void SMAA::CreateDescriptorPool() {
-    // Edge detection: 1 descriptor
-    // Blending weight calculation: 3 descriptors
-    // Neighborhood blending: 2 descriptors
-
-    // 6 descriptors, 3 descriptor sets per image
-    m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count);
-}
-
-void SMAA::CreateDescriptorSetLayouts() {
-    m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1);
-    m_descriptor_set_layouts[BlendingWeightCalculation] =
-        CreateWrappedDescriptorSetLayout(m_device, 3);
-    m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2);
-}
-
-void SMAA::CreateDescriptorSets() {
-    std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size());
-    std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
-                           [](auto& layout) { return *layout; });
-
-    for (auto& images : m_dynamic_images) {
-        images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
-    }
-}
-
-void SMAA::CreatePipelineLayouts() {
-    for (size_t i = 0; i < MaxSMAAStage; i++) {
-        m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]);
-    }
-}
-
-void SMAA::CreatePipelines() {
-    for (size_t i = 0; i < MaxSMAAStage; i++) {
-        m_pipelines[i] =
-            CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i],
-                                  std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
-    }
-}
-
-void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
-    Images& images = m_dynamic_images[image_index];
-    std::vector<VkDescriptorImageInfo> image_infos;
-    std::vector<VkWriteDescriptorSet> updates;
-    image_infos.reserve(6);
-
-    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
-                                               images.descriptor_sets[EdgeDetection], 0));
-
-    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges],
-                                               images.descriptor_sets[BlendingWeightCalculation],
-                                               0));
-    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area],
-                                               images.descriptor_sets[BlendingWeightCalculation],
-                                               1));
-    updates.push_back(
-        CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search],
-                                 images.descriptor_sets[BlendingWeightCalculation], 2));
-
-    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
-                                               images.descriptor_sets[NeighborhoodBlending], 0));
-    updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
-                                               images.descriptor_sets[NeighborhoodBlending], 1));
-
-    m_device.GetLogical().UpdateDescriptorSets(updates, {});
-}
-
-void SMAA::UploadImages(Scheduler& scheduler) {
-    if (m_images_ready) {
-        return;
-    }
-
-    static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
-    static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
-
-    UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent,
-                VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes));
-    UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
-                VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
-
-    scheduler.Record([&](vk::CommandBuffer cmdbuf) {
-        for (auto& images : m_dynamic_images) {
-            for (size_t i = 0; i < MaxDynamicImage; i++) {
-                ClearColorImage(cmdbuf, *images.images[i]);
-            }
-        }
-    });
-    scheduler.Finish();
-
-    m_images_ready = true;
-}
-
-VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
-                       VkImageView source_image_view) {
-    Images& images = m_dynamic_images[image_index];
-
-    VkImage output_image = *images.images[Output];
-    VkImage edges_image = *images.images[Edges];
-    VkImage blend_image = *images.images[Blend];
-
-    VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection];
-    VkDescriptorSet blending_weight_calculation_descriptor_set =
-        images.descriptor_sets[BlendingWeightCalculation];
-    VkDescriptorSet neighborhood_blending_descriptor_set =
-        images.descriptor_sets[NeighborhoodBlending];
-
-    VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection];
-    VkFramebuffer blending_weight_calculation_framebuffer =
-        *images.framebuffers[BlendingWeightCalculation];
-    VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
-
-    UploadImages(scheduler);
-    UpdateDescriptorSets(source_image_view, image_index);
-
-    scheduler.RequestOutsideRenderPassOperationContext();
-    scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
-        TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
-        TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
-        BeginRenderPass(cmdbuf, m_renderpasses[EdgeDetection], edge_detection_framebuffer,
-                        m_extent);
-        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]);
-        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                  *m_pipeline_layouts[EdgeDetection], 0,
-                                  edge_detection_descriptor_set, {});
-        cmdbuf.Draw(3, 1, 0, 0);
-        cmdbuf.EndRenderPass();
-
-        TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
-        TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
-        BeginRenderPass(cmdbuf, m_renderpasses[BlendingWeightCalculation],
-                        blending_weight_calculation_framebuffer, m_extent);
-        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
-                            *m_pipelines[BlendingWeightCalculation]);
-        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                  *m_pipeline_layouts[BlendingWeightCalculation], 0,
-                                  blending_weight_calculation_descriptor_set, {});
-        cmdbuf.Draw(3, 1, 0, 0);
-        cmdbuf.EndRenderPass();
-
-        TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
-        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
-        BeginRenderPass(cmdbuf, m_renderpasses[NeighborhoodBlending],
-                        neighborhood_blending_framebuffer, m_extent);
-        cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]);
-        cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                  *m_pipeline_layouts[NeighborhoodBlending], 0,
-                                  neighborhood_blending_descriptor_set, {});
-        cmdbuf.Draw(3, 1, 0, 0);
-        cmdbuf.EndRenderPass();
-        TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
-    });
-
-    return *images.image_views[Output];
-}
-
 } // namespace Vulkan

+ 46 - 0
src/video_core/renderer_vulkan/present/util.h

@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+
+#define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0])))
+
+vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format);
+void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
+                           VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL);
+void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
+                 vk::Image& image, VkExtent2D dimensions, VkFormat format,
+                 std::span<const u8> initial_contents = {});
+void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image);
+
+vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format);
+vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format);
+vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass,
+                                         vk::ImageView& dest_image, VkExtent2D extent);
+vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR);
+vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code);
+vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_sampler_bindings,
+                                               u32 max_sets);
+vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device,
+                                                         u32 max_sampler_bindings);
+vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool,
+                                               vk::Span<VkDescriptorSetLayout> layouts);
+vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device,
+                                               vk::DescriptorSetLayout& layout);
+vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass,
+                                   vk::PipelineLayout& layout,
+                                   std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders);
+VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images,
+                                              VkSampler sampler, VkImageView view,
+                                              VkDescriptorSet set, u32 binding);
+
+void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
+                     VkExtent2D extent);
+
+} // namespace Vulkan

+ 14 - 358
src/video_core/renderer_vulkan/vk_blit_screen.cpp

@@ -16,20 +16,19 @@
 #include "core/frontend/emu_window.h"
 #include "video_core/gpu.h"
 #include "video_core/host1x/gpu_device_memory_manager.h"
-#include "video_core/host_shaders/fxaa_frag_spv.h"
-#include "video_core/host_shaders/fxaa_vert_spv.h"
 #include "video_core/host_shaders/present_bicubic_frag_spv.h"
 #include "video_core/host_shaders/present_gaussian_frag_spv.h"
 #include "video_core/host_shaders/vulkan_present_frag_spv.h"
 #include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
 #include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"
 #include "video_core/host_shaders/vulkan_present_vert_spv.h"
+#include "video_core/renderer_vulkan/present/fsr.h"
+#include "video_core/renderer_vulkan/present/fxaa.h"
+#include "video_core/renderer_vulkan/present/smaa.h"
 #include "video_core/renderer_vulkan/renderer_vulkan.h"
 #include "video_core/renderer_vulkan/vk_blit_screen.h"
-#include "video_core/renderer_vulkan/vk_fsr.h"
 #include "video_core/renderer_vulkan/vk_scheduler.h"
 #include "video_core/renderer_vulkan/vk_shader_util.h"
-#include "video_core/renderer_vulkan/vk_smaa.h"
 #include "video_core/renderer_vulkan/vk_swapchain.h"
 #include "video_core/surface.h"
 #include "video_core/textures/decoders.h"
@@ -252,103 +251,17 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf
 
     const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue();
     if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) {
-        UpdateAADescriptorSet(source_image_view, false);
-        const u32 up_scale = Settings::values.resolution_info.up_scale;
-        const u32 down_shift = Settings::values.resolution_info.down_shift;
-        VkExtent2D size{
-            .width = (up_scale * framebuffer.width) >> down_shift,
-            .height = (up_scale * framebuffer.height) >> down_shift,
-        };
-        scheduler.Record([this, index = image_index, size,
-                          anti_alias_pass](vk::CommandBuffer cmdbuf) {
-            const VkImageMemoryBarrier base_barrier{
-                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
-                .pNext = nullptr,
-                .srcAccessMask = 0,
-                .dstAccessMask = 0,
-                .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
-                .newLayout = VK_IMAGE_LAYOUT_GENERAL,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .image = {},
-                .subresourceRange =
-                    {
-                        .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                        .baseMipLevel = 0,
-                        .levelCount = 1,
-                        .baseArrayLayer = 0,
-                        .layerCount = 1,
-                    },
-            };
-
-            {
-                VkImageMemoryBarrier fsr_write_barrier = base_barrier;
-                fsr_write_barrier.image = *aa_image;
-                fsr_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-                cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
-                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, fsr_write_barrier);
-            }
-
-            const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f;
-            const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f;
-            const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f;
-            const VkClearValue clear_color{
-                .color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
-            };
-            const VkRenderPassBeginInfo renderpass_bi{
-                .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-                .pNext = nullptr,
-                .renderPass = *aa_renderpass,
-                .framebuffer = *aa_framebuffer,
-                .renderArea =
-                    {
-                        .offset = {0, 0},
-                        .extent = size,
-                    },
-                .clearValueCount = 1,
-                .pClearValues = &clear_color,
-            };
-            const VkViewport viewport{
-                .x = 0.0f,
-                .y = 0.0f,
-                .width = static_cast<float>(size.width),
-                .height = static_cast<float>(size.height),
-                .minDepth = 0.0f,
-                .maxDepth = 1.0f,
-            };
-            const VkRect2D scissor{
-                .offset = {0, 0},
-                .extent = size,
+        if (!fxaa) {
+            const u32 up_scale = Settings::values.resolution_info.up_scale;
+            const u32 down_shift = Settings::values.resolution_info.down_shift;
+            const VkExtent2D fxaa_size{
+                .width = (up_scale * framebuffer.width) >> down_shift,
+                .height = (up_scale * framebuffer.height) >> down_shift,
             };
-            cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
-            switch (anti_alias_pass) {
-            case Settings::AntiAliasing::Fxaa:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline);
-                break;
-            default:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline);
-                break;
-            }
-            cmdbuf.SetViewport(0, viewport);
-            cmdbuf.SetScissor(0, scissor);
-
-            cmdbuf.BindVertexBuffer(0, *buffer, offsetof(BufferData, vertices));
-            cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline_layout, 0,
-                                      aa_descriptor_sets[index], {});
-            cmdbuf.Draw(4, 1, 0, 0);
-            cmdbuf.EndRenderPass();
-
-            {
-                VkImageMemoryBarrier blit_read_barrier = base_barrier;
-                blit_read_barrier.image = *aa_image;
-                blit_read_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-                blit_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+            fxaa = std::make_unique<FXAA>(device, memory_allocator, image_count, fxaa_size);
+        }
 
-                cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
-                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, blit_read_barrier);
-            }
-        });
-        source_image_view = *aa_image_view;
+        source_image_view = fxaa->Draw(scheduler, image_index, source_image, source_image_view);
     }
     if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) {
         if (!smaa) {
@@ -496,6 +409,7 @@ void BlitScreen::CreateDynamicResources() {
     CreateRenderPass();
     CreateGraphicsPipeline();
     fsr.reset();
+    fxaa.reset();
     smaa.reset();
     if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
         CreateFSR();
@@ -520,6 +434,7 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
     raw_height = framebuffer.height;
     pixel_format = framebuffer.pixel_format;
 
+    fxaa.reset();
     smaa.reset();
     ReleaseRawImages();
 
@@ -529,8 +444,6 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
 
 void BlitScreen::CreateShaders() {
     vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
-    fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV);
-    fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV);
     bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV);
     bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV);
     gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV);
@@ -553,13 +466,6 @@ void BlitScreen::CreateDescriptorPool() {
         },
     }};
 
-    const std::array<VkDescriptorPoolSize, 1> pool_sizes_aa{{
-        {
-            .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .descriptorCount = static_cast<u32>(image_count * 2),
-        },
-    }};
-
     const VkDescriptorPoolCreateInfo ci{
         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
         .pNext = nullptr,
@@ -569,16 +475,6 @@ void BlitScreen::CreateDescriptorPool() {
         .pPoolSizes = pool_sizes.data(),
     };
     descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
-
-    const VkDescriptorPoolCreateInfo ci_aa{
-        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .maxSets = static_cast<u32>(image_count),
-        .poolSizeCount = static_cast<u32>(pool_sizes_aa.size()),
-        .pPoolSizes = pool_sizes_aa.data(),
-    };
-    aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa);
 }
 
 void BlitScreen::CreateRenderPass() {
@@ -659,23 +555,6 @@ void BlitScreen::CreateDescriptorSetLayout() {
         },
     }};
 
-    const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings_aa{{
-        {
-            .binding = 0,
-            .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .descriptorCount = 1,
-            .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
-            .pImmutableSamplers = nullptr,
-        },
-        {
-            .binding = 1,
-            .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .descriptorCount = 1,
-            .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
-            .pImmutableSamplers = nullptr,
-        },
-    }};
-
     const VkDescriptorSetLayoutCreateInfo ci{
         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
         .pNext = nullptr,
@@ -684,21 +563,11 @@ void BlitScreen::CreateDescriptorSetLayout() {
         .pBindings = layout_bindings.data(),
     };
 
-    const VkDescriptorSetLayoutCreateInfo ci_aa{
-        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .bindingCount = static_cast<u32>(layout_bindings_aa.size()),
-        .pBindings = layout_bindings_aa.data(),
-    };
-
     descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
-    aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa);
 }
 
 void BlitScreen::CreateDescriptorSets() {
     const std::vector layouts(image_count, *descriptor_set_layout);
-    const std::vector layouts_aa(image_count, *aa_descriptor_set_layout);
 
     const VkDescriptorSetAllocateInfo ai{
         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
@@ -708,16 +577,7 @@ void BlitScreen::CreateDescriptorSets() {
         .pSetLayouts = layouts.data(),
     };
 
-    const VkDescriptorSetAllocateInfo ai_aa{
-        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
-        .pNext = nullptr,
-        .descriptorPool = *aa_descriptor_pool,
-        .descriptorSetCount = static_cast<u32>(image_count),
-        .pSetLayouts = layouts_aa.data(),
-    };
-
     descriptor_sets = descriptor_pool.Allocate(ai);
-    aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa);
 }
 
 void BlitScreen::CreatePipelineLayout() {
@@ -730,17 +590,7 @@ void BlitScreen::CreatePipelineLayout() {
         .pushConstantRangeCount = 0,
         .pPushConstantRanges = nullptr,
     };
-    const VkPipelineLayoutCreateInfo ci_aa{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .setLayoutCount = 1,
-        .pSetLayouts = aa_descriptor_set_layout.address(),
-        .pushConstantRangeCount = 0,
-        .pPushConstantRanges = nullptr,
-    };
     pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
-    aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa);
 }
 
 void BlitScreen::CreateGraphicsPipeline() {
@@ -1068,8 +918,6 @@ void BlitScreen::ReleaseRawImages() {
         scheduler.Wait(tick);
     }
     raw_images.clear();
-    aa_image_view.reset();
-    aa_image.reset();
     buffer.reset();
 }
 
@@ -1150,198 +998,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
         raw_images[i] = create_image();
         raw_image_views[i] = create_image_view(raw_images[i]);
     }
-
-    // AA Resources
-    const u32 up_scale = Settings::values.resolution_info.up_scale;
-    const u32 down_shift = Settings::values.resolution_info.down_shift;
-    aa_image = create_image(true, up_scale, down_shift);
-    aa_image_view = create_image_view(aa_image, true);
-    VkExtent2D size{
-        .width = (up_scale * framebuffer.width) >> down_shift,
-        .height = (up_scale * framebuffer.height) >> down_shift,
-    };
-    if (aa_renderpass) {
-        aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass);
-        return;
-    }
-    aa_renderpass = CreateRenderPassImpl(VK_FORMAT_R16G16B16A16_SFLOAT);
-    aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass);
-
-    const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{
-        {
-            .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-            .pNext = nullptr,
-            .flags = 0,
-            .stage = VK_SHADER_STAGE_VERTEX_BIT,
-            .module = *fxaa_vertex_shader,
-            .pName = "main",
-            .pSpecializationInfo = nullptr,
-        },
-        {
-            .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-            .pNext = nullptr,
-            .flags = 0,
-            .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
-            .module = *fxaa_fragment_shader,
-            .pName = "main",
-            .pSpecializationInfo = nullptr,
-        },
-    }};
-
-    const auto vertex_binding_description = ScreenRectVertex::GetDescription();
-    const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
-
-    const VkPipelineVertexInputStateCreateInfo vertex_input_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .vertexBindingDescriptionCount = 1,
-        .pVertexBindingDescriptions = &vertex_binding_description,
-        .vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()},
-        .pVertexAttributeDescriptions = vertex_attrs_description.data(),
-    };
-
-    const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
-        .primitiveRestartEnable = VK_FALSE,
-    };
-
-    const VkPipelineViewportStateCreateInfo viewport_state_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .viewportCount = 1,
-        .pViewports = nullptr,
-        .scissorCount = 1,
-        .pScissors = nullptr,
-    };
-
-    const VkPipelineRasterizationStateCreateInfo rasterization_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .depthClampEnable = VK_FALSE,
-        .rasterizerDiscardEnable = VK_FALSE,
-        .polygonMode = VK_POLYGON_MODE_FILL,
-        .cullMode = VK_CULL_MODE_NONE,
-        .frontFace = VK_FRONT_FACE_CLOCKWISE,
-        .depthBiasEnable = VK_FALSE,
-        .depthBiasConstantFactor = 0.0f,
-        .depthBiasClamp = 0.0f,
-        .depthBiasSlopeFactor = 0.0f,
-        .lineWidth = 1.0f,
-    };
-
-    const VkPipelineMultisampleStateCreateInfo multisampling_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
-        .sampleShadingEnable = VK_FALSE,
-        .minSampleShading = 0.0f,
-        .pSampleMask = nullptr,
-        .alphaToCoverageEnable = VK_FALSE,
-        .alphaToOneEnable = VK_FALSE,
-    };
-
-    const VkPipelineColorBlendAttachmentState color_blend_attachment{
-        .blendEnable = VK_FALSE,
-        .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
-        .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
-        .colorBlendOp = VK_BLEND_OP_ADD,
-        .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
-        .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
-        .alphaBlendOp = VK_BLEND_OP_ADD,
-        .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
-                          VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
-    };
-
-    const VkPipelineColorBlendStateCreateInfo color_blend_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .logicOpEnable = VK_FALSE,
-        .logicOp = VK_LOGIC_OP_COPY,
-        .attachmentCount = 1,
-        .pAttachments = &color_blend_attachment,
-        .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
-    };
-
-    static constexpr std::array dynamic_states{
-        VK_DYNAMIC_STATE_VIEWPORT,
-        VK_DYNAMIC_STATE_SCISSOR,
-    };
-    const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
-        .pDynamicStates = dynamic_states.data(),
-    };
-
-    const VkGraphicsPipelineCreateInfo fxaa_pipeline_ci{
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .stageCount = static_cast<u32>(fxaa_shader_stages.size()),
-        .pStages = fxaa_shader_stages.data(),
-        .pVertexInputState = &vertex_input_ci,
-        .pInputAssemblyState = &input_assembly_ci,
-        .pTessellationState = nullptr,
-        .pViewportState = &viewport_state_ci,
-        .pRasterizationState = &rasterization_ci,
-        .pMultisampleState = &multisampling_ci,
-        .pDepthStencilState = nullptr,
-        .pColorBlendState = &color_blend_ci,
-        .pDynamicState = &dynamic_state_ci,
-        .layout = *aa_pipeline_layout,
-        .renderPass = *aa_renderpass,
-        .subpass = 0,
-        .basePipelineHandle = 0,
-        .basePipelineIndex = 0,
-    };
-
-    // AA
-    aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci);
-}
-
-void BlitScreen::UpdateAADescriptorSet(VkImageView image_view, bool nn) const {
-    const VkDescriptorImageInfo image_info{
-        .sampler = nn ? *nn_sampler : *sampler,
-        .imageView = image_view,
-        .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
-    };
-
-    const VkWriteDescriptorSet sampler_write{
-        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-        .pNext = nullptr,
-        .dstSet = aa_descriptor_sets[image_index],
-        .dstBinding = 0,
-        .dstArrayElement = 0,
-        .descriptorCount = 1,
-        .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-        .pImageInfo = &image_info,
-        .pBufferInfo = nullptr,
-        .pTexelBufferView = nullptr,
-    };
-
-    const VkWriteDescriptorSet sampler_write_2{
-        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-        .pNext = nullptr,
-        .dstSet = aa_descriptor_sets[image_index],
-        .dstBinding = 1,
-        .dstArrayElement = 0,
-        .descriptorCount = 1,
-        .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-        .pImageInfo = &image_info,
-        .pBufferInfo = nullptr,
-        .pTexelBufferView = nullptr,
-    };
-
-    device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {});
 }
 
 void BlitScreen::UpdateDescriptorSet(VkImageView image_view, bool nn) const {

+ 2 - 14
src/video_core/renderer_vulkan/vk_blit_screen.h

@@ -34,6 +34,7 @@ namespace Vulkan {
 
 class Device;
 class FSR;
+class FXAA;
 class RasterizerVulkan;
 class Scheduler;
 class SMAA;
@@ -96,7 +97,6 @@ private:
     void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
 
     void UpdateDescriptorSet(VkImageView image_view, bool nn) const;
-    void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
     void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
     void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
                        const Layout::FramebufferLayout layout, u32 texture_width,
@@ -119,8 +119,6 @@ private:
     std::size_t image_index{};
 
     vk::ShaderModule vertex_shader;
-    vk::ShaderModule fxaa_vertex_shader;
-    vk::ShaderModule fxaa_fragment_shader;
     vk::ShaderModule bilinear_fragment_shader;
     vk::ShaderModule bicubic_fragment_shader;
     vk::ShaderModule gaussian_fragment_shader;
@@ -128,7 +126,6 @@ private:
     vk::DescriptorPool descriptor_pool;
     vk::DescriptorSetLayout descriptor_set_layout;
     vk::PipelineLayout pipeline_layout;
-    vk::Pipeline nearest_neighbor_pipeline;
     vk::Pipeline bilinear_pipeline;
     vk::Pipeline bicubic_pipeline;
     vk::Pipeline gaussian_pipeline;
@@ -145,16 +142,6 @@ private:
     std::vector<vk::Image> raw_images;
     std::vector<vk::ImageView> raw_image_views;
 
-    vk::DescriptorPool aa_descriptor_pool;
-    vk::DescriptorSetLayout aa_descriptor_set_layout;
-    vk::PipelineLayout aa_pipeline_layout;
-    vk::Pipeline aa_pipeline;
-    vk::RenderPass aa_renderpass;
-    vk::Framebuffer aa_framebuffer;
-    vk::DescriptorSets aa_descriptor_sets;
-    vk::Image aa_image;
-    vk::ImageView aa_image_view;
-
     u32 raw_width = 0;
     u32 raw_height = 0;
     Service::android::PixelFormat pixel_format{};
@@ -163,6 +150,7 @@ private:
 
     std::unique_ptr<FSR> fsr;
     std::unique_ptr<SMAA> smaa;
+    std::unique_ptr<FXAA> fxaa;
 };
 
 } // namespace Vulkan