diff options
| author | 2024-01-13 22:52:04 -0500 | |
|---|---|---|
| committer | 2024-01-31 11:27:20 -0500 | |
| commit | 9568b310befe19154511afe14709188f641e4951 (patch) | |
| tree | 4ed2a065b68970747f2c8280de273d280a1cd985 /src/video_core/renderer_vulkan | |
| parent | renderer_opengl: isolate core presentation code (diff) | |
| download | yuzu-9568b310befe19154511afe14709188f641e4951.tar.gz yuzu-9568b310befe19154511afe14709188f641e4951.tar.xz yuzu-9568b310befe19154511afe14709188f641e4951.zip | |
renderer_vulkan: isolate FXAA from blit screen
Diffstat (limited to 'src/video_core/renderer_vulkan')
| -rw-r--r-- | src/video_core/renderer_vulkan/present/anti_alias_pass.h | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fsr.cpp (renamed from src/video_core/renderer_vulkan/vk_fsr.cpp) | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fsr.h (renamed from src/video_core/renderer_vulkan/vk_fsr.h) | 0 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fxaa.cpp | 144 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fxaa.h | 63 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/smaa.cpp | 270 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/smaa.h (renamed from src/video_core/renderer_vulkan/vk_smaa.h) | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/util.cpp (renamed from src/video_core/renderer_vulkan/vk_smaa.cpp) | 282 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/util.h | 46 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.cpp | 372 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.h | 16 |
11 files changed, 582 insertions, 647 deletions
diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h new file mode 100644 index 000000000..c1ec0b9a0 --- /dev/null +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 7 | |||
| 8 | namespace Vulkan { | ||
| 9 | |||
| 10 | class Scheduler; | ||
| 11 | |||
| 12 | class AntiAliasPass { | ||
| 13 | public: | ||
| 14 | virtual ~AntiAliasPass() = default; | ||
| 15 | virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 16 | VkImageView source_image_view) = 0; | ||
| 17 | }; | ||
| 18 | |||
| 19 | class NoAA final : public AntiAliasPass { | ||
| 20 | public: | ||
| 21 | virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 22 | VkImageView source_image_view) { | ||
| 23 | return source_image_view; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index f7a05fbc0..30a16a785 100644 --- a/src/video_core/renderer_vulkan/vk_fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h" | 10 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h" |
| 11 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h" | 11 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h" |
| 12 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h" | 12 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h" |
| 13 | #include "video_core/renderer_vulkan/vk_fsr.h" | 13 | #include "video_core/renderer_vulkan/present/fsr.h" |
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 15 | #include "video_core/renderer_vulkan/vk_shader_util.h" | 15 | #include "video_core/renderer_vulkan/vk_shader_util.h" |
| 16 | #include "video_core/vulkan_common/vulkan_device.h" | 16 | #include "video_core/vulkan_common/vulkan_device.h" |
diff --git a/src/video_core/renderer_vulkan/vk_fsr.h b/src/video_core/renderer_vulkan/present/fsr.h index 3505c1416..3505c1416 100644 --- a/src/video_core/renderer_vulkan/vk_fsr.h +++ b/src/video_core/renderer_vulkan/present/fsr.h | |||
diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp new file mode 100644 index 000000000..6f87ddebb --- /dev/null +++ b/src/video_core/renderer_vulkan/present/fxaa.cpp | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/common_types.h" | ||
| 5 | |||
| 6 | #include "video_core/host_shaders/fxaa_frag_spv.h" | ||
| 7 | #include "video_core/host_shaders/fxaa_vert_spv.h" | ||
| 8 | #include "video_core/renderer_vulkan/present/fxaa.h" | ||
| 9 | #include "video_core/renderer_vulkan/present/util.h" | ||
| 10 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 11 | #include "video_core/renderer_vulkan/vk_shader_util.h" | ||
| 12 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 13 | |||
| 14 | namespace Vulkan { | ||
| 15 | |||
| 16 | FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) | ||
| 17 | : m_device(device), m_allocator(allocator), m_extent(extent), | ||
| 18 | m_image_count(static_cast<u32>(image_count)) { | ||
| 19 | CreateImages(); | ||
| 20 | CreateRenderPasses(); | ||
| 21 | CreateSampler(); | ||
| 22 | CreateShaders(); | ||
| 23 | CreateDescriptorPool(); | ||
| 24 | CreateDescriptorSetLayouts(); | ||
| 25 | CreateDescriptorSets(); | ||
| 26 | CreatePipelineLayouts(); | ||
| 27 | CreatePipelines(); | ||
| 28 | } | ||
| 29 | |||
| 30 | FXAA::~FXAA() = default; | ||
| 31 | |||
| 32 | void FXAA::CreateImages() { | ||
| 33 | for (u32 i = 0; i < m_image_count; i++) { | ||
| 34 | Image& image = m_dynamic_images.emplace_back(); | ||
| 35 | |||
| 36 | image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 37 | image.image_view = | ||
| 38 | CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | void FXAA::CreateRenderPasses() { | ||
| 43 | m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 44 | |||
| 45 | for (auto& image : m_dynamic_images) { | ||
| 46 | image.framebuffer = | ||
| 47 | CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void FXAA::CreateSampler() { | ||
| 52 | m_sampler = CreateWrappedSampler(m_device); | ||
| 53 | } | ||
| 54 | |||
| 55 | void FXAA::CreateShaders() { | ||
| 56 | m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV); | ||
| 57 | m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV); | ||
| 58 | } | ||
| 59 | |||
| 60 | void FXAA::CreateDescriptorPool() { | ||
| 61 | // 2 descriptors, 1 descriptor set per image | ||
| 62 | m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count); | ||
| 63 | } | ||
| 64 | |||
| 65 | void FXAA::CreateDescriptorSetLayouts() { | ||
| 66 | m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2); | ||
| 67 | } | ||
| 68 | |||
| 69 | void FXAA::CreateDescriptorSets() { | ||
| 70 | VkDescriptorSetLayout layout = *m_descriptor_set_layout; | ||
| 71 | |||
| 72 | for (auto& images : m_dynamic_images) { | ||
| 73 | images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout}); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | void FXAA::CreatePipelineLayouts() { | ||
| 78 | m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout); | ||
| 79 | } | ||
| 80 | |||
| 81 | void FXAA::CreatePipelines() { | ||
| 82 | m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, | ||
| 83 | std::tie(m_vertex_shader, m_fragment_shader)); | ||
| 84 | } | ||
| 85 | |||
| 86 | void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { | ||
| 87 | Image& image = m_dynamic_images[image_index]; | ||
| 88 | std::vector<VkDescriptorImageInfo> image_infos; | ||
| 89 | std::vector<VkWriteDescriptorSet> updates; | ||
| 90 | image_infos.reserve(2); | ||
| 91 | |||
| 92 | updates.push_back( | ||
| 93 | CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0)); | ||
| 94 | updates.push_back( | ||
| 95 | CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1)); | ||
| 96 | |||
| 97 | m_device.GetLogical().UpdateDescriptorSets(updates, {}); | ||
| 98 | } | ||
| 99 | |||
| 100 | void FXAA::UploadImages(Scheduler& scheduler) { | ||
| 101 | if (m_images_ready) { | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { | ||
| 106 | for (auto& image : m_dynamic_images) { | ||
| 107 | ClearColorImage(cmdbuf, *image.image); | ||
| 108 | } | ||
| 109 | }); | ||
| 110 | scheduler.Finish(); | ||
| 111 | |||
| 112 | m_images_ready = true; | ||
| 113 | } | ||
| 114 | |||
| 115 | VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 116 | VkImageView source_image_view) { | ||
| 117 | const Image& image{m_dynamic_images[image_index]}; | ||
| 118 | const VkImage output_image{*image.image}; | ||
| 119 | const VkDescriptorSet descriptor_set{image.descriptor_sets[0]}; | ||
| 120 | const VkFramebuffer framebuffer{*image.framebuffer}; | ||
| 121 | const VkRenderPass renderpass{*m_renderpass}; | ||
| 122 | const VkPipeline pipeline{*m_pipeline}; | ||
| 123 | const VkPipelineLayout layout{*m_pipeline_layout}; | ||
| 124 | const VkExtent2D extent{m_extent}; | ||
| 125 | |||
| 126 | UploadImages(scheduler); | ||
| 127 | UpdateDescriptorSets(source_image_view, image_index); | ||
| 128 | |||
| 129 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 130 | scheduler.Record([=](vk::CommandBuffer cmdbuf) { | ||
| 131 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 132 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 133 | BeginRenderPass(cmdbuf, renderpass, framebuffer, extent); | ||
| 134 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
| 135 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {}); | ||
| 136 | cmdbuf.Draw(4, 1, 0, 0); | ||
| 137 | cmdbuf.EndRenderPass(); | ||
| 138 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 139 | }); | ||
| 140 | |||
| 141 | return *image.image_view; | ||
| 142 | } | ||
| 143 | |||
| 144 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/present/fxaa.h b/src/video_core/renderer_vulkan/present/fxaa.h new file mode 100644 index 000000000..c083f3ff0 --- /dev/null +++ b/src/video_core/renderer_vulkan/present/fxaa.h | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "video_core/renderer_vulkan/present/anti_alias_pass.h" | ||
| 7 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
| 8 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 9 | |||
| 10 | namespace Vulkan { | ||
| 11 | |||
| 12 | class Device; | ||
| 13 | class Scheduler; | ||
| 14 | class StagingBufferPool; | ||
| 15 | |||
| 16 | class FXAA final : public AntiAliasPass { | ||
| 17 | public: | ||
| 18 | explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, | ||
| 19 | VkExtent2D extent); | ||
| 20 | ~FXAA() override; | ||
| 21 | |||
| 22 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 23 | VkImageView source_image_view) override; | ||
| 24 | |||
| 25 | private: | ||
| 26 | void CreateImages(); | ||
| 27 | void CreateRenderPasses(); | ||
| 28 | void CreateSampler(); | ||
| 29 | void CreateShaders(); | ||
| 30 | void CreateDescriptorPool(); | ||
| 31 | void CreateDescriptorSetLayouts(); | ||
| 32 | void CreateDescriptorSets(); | ||
| 33 | void CreatePipelineLayouts(); | ||
| 34 | void CreatePipelines(); | ||
| 35 | void UpdateDescriptorSets(VkImageView image_view, size_t image_index); | ||
| 36 | void UploadImages(Scheduler& scheduler); | ||
| 37 | |||
| 38 | const Device& m_device; | ||
| 39 | MemoryAllocator& m_allocator; | ||
| 40 | const VkExtent2D m_extent; | ||
| 41 | const u32 m_image_count; | ||
| 42 | |||
| 43 | vk::ShaderModule m_vertex_shader{}; | ||
| 44 | vk::ShaderModule m_fragment_shader{}; | ||
| 45 | vk::DescriptorPool m_descriptor_pool{}; | ||
| 46 | vk::DescriptorSetLayout m_descriptor_set_layout{}; | ||
| 47 | vk::PipelineLayout m_pipeline_layout{}; | ||
| 48 | vk::Pipeline m_pipeline{}; | ||
| 49 | vk::RenderPass m_renderpass{}; | ||
| 50 | |||
| 51 | struct Image { | ||
| 52 | vk::DescriptorSets descriptor_sets{}; | ||
| 53 | vk::Framebuffer framebuffer{}; | ||
| 54 | vk::Image image{}; | ||
| 55 | vk::ImageView image_view{}; | ||
| 56 | }; | ||
| 57 | std::vector<Image> m_dynamic_images{}; | ||
| 58 | bool m_images_ready{}; | ||
| 59 | |||
| 60 | vk::Sampler m_sampler{}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/present/smaa.cpp b/src/video_core/renderer_vulkan/present/smaa.cpp new file mode 100644 index 000000000..68cd22b08 --- /dev/null +++ b/src/video_core/renderer_vulkan/present/smaa.cpp | |||
| @@ -0,0 +1,270 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <list> | ||
| 5 | |||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/polyfill_ranges.h" | ||
| 8 | |||
| 9 | #include "video_core/renderer_vulkan/present/smaa.h" | ||
| 10 | #include "video_core/renderer_vulkan/present/util.h" | ||
| 11 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 12 | #include "video_core/renderer_vulkan/vk_shader_util.h" | ||
| 13 | #include "video_core/smaa_area_tex.h" | ||
| 14 | #include "video_core/smaa_search_tex.h" | ||
| 15 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 16 | |||
| 17 | #include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h" | ||
| 18 | #include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h" | ||
| 19 | #include "video_core/host_shaders/smaa_edge_detection_frag_spv.h" | ||
| 20 | #include "video_core/host_shaders/smaa_edge_detection_vert_spv.h" | ||
| 21 | #include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h" | ||
| 22 | #include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h" | ||
| 23 | |||
| 24 | namespace Vulkan { | ||
| 25 | |||
| 26 | SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) | ||
| 27 | : m_device(device), m_allocator(allocator), m_extent(extent), | ||
| 28 | m_image_count(static_cast<u32>(image_count)) { | ||
| 29 | CreateImages(); | ||
| 30 | CreateRenderPasses(); | ||
| 31 | CreateSampler(); | ||
| 32 | CreateShaders(); | ||
| 33 | CreateDescriptorPool(); | ||
| 34 | CreateDescriptorSetLayouts(); | ||
| 35 | CreateDescriptorSets(); | ||
| 36 | CreatePipelineLayouts(); | ||
| 37 | CreatePipelines(); | ||
| 38 | } | ||
| 39 | |||
| 40 | SMAA::~SMAA() = default; | ||
| 41 | |||
| 42 | void SMAA::CreateImages() { | ||
| 43 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||
| 44 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | ||
| 45 | |||
| 46 | m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM); | ||
| 47 | m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM); | ||
| 48 | |||
| 49 | m_static_image_views[Area] = | ||
| 50 | CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); | ||
| 51 | m_static_image_views[Search] = | ||
| 52 | CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM); | ||
| 53 | |||
| 54 | for (u32 i = 0; i < m_image_count; i++) { | ||
| 55 | Images& images = m_dynamic_images.emplace_back(); | ||
| 56 | |||
| 57 | images.images[Blend] = | ||
| 58 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 59 | images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT); | ||
| 60 | images.images[Output] = | ||
| 61 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 62 | |||
| 63 | images.image_views[Blend] = | ||
| 64 | CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 65 | images.image_views[Edges] = | ||
| 66 | CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); | ||
| 67 | images.image_views[Output] = | ||
| 68 | CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | void SMAA::CreateRenderPasses() { | ||
| 73 | m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT); | ||
| 74 | m_renderpasses[BlendingWeightCalculation] = | ||
| 75 | CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 76 | m_renderpasses[NeighborhoodBlending] = | ||
| 77 | CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 78 | |||
| 79 | for (auto& images : m_dynamic_images) { | ||
| 80 | images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer( | ||
| 81 | m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); | ||
| 82 | |||
| 83 | images.framebuffers[BlendingWeightCalculation] = | ||
| 84 | CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation], | ||
| 85 | images.image_views[Blend], m_extent); | ||
| 86 | |||
| 87 | images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer( | ||
| 88 | m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | void SMAA::CreateSampler() { | ||
| 93 | m_sampler = CreateWrappedSampler(m_device); | ||
| 94 | } | ||
| 95 | |||
| 96 | void SMAA::CreateShaders() { | ||
| 97 | // These match the order of the SMAAStage enum | ||
| 98 | static constexpr std::array vert_shader_sources{ | ||
| 99 | ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV), | ||
| 100 | ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV), | ||
| 101 | ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV), | ||
| 102 | }; | ||
| 103 | static constexpr std::array frag_shader_sources{ | ||
| 104 | ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV), | ||
| 105 | ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV), | ||
| 106 | ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV), | ||
| 107 | }; | ||
| 108 | |||
| 109 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 110 | m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]); | ||
| 111 | m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | void SMAA::CreateDescriptorPool() { | ||
| 116 | // Edge detection: 1 descriptor | ||
| 117 | // Blending weight calculation: 3 descriptors | ||
| 118 | // Neighborhood blending: 2 descriptors | ||
| 119 | |||
| 120 | // 6 descriptors, 3 descriptor sets per image | ||
| 121 | m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count); | ||
| 122 | } | ||
| 123 | |||
| 124 | void SMAA::CreateDescriptorSetLayouts() { | ||
| 125 | m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1); | ||
| 126 | m_descriptor_set_layouts[BlendingWeightCalculation] = | ||
| 127 | CreateWrappedDescriptorSetLayout(m_device, 3); | ||
| 128 | m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2); | ||
| 129 | } | ||
| 130 | |||
| 131 | void SMAA::CreateDescriptorSets() { | ||
| 132 | std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size()); | ||
| 133 | std::ranges::transform(m_descriptor_set_layouts, layouts.begin(), | ||
| 134 | [](auto& layout) { return *layout; }); | ||
| 135 | |||
| 136 | for (auto& images : m_dynamic_images) { | ||
| 137 | images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | void SMAA::CreatePipelineLayouts() { | ||
| 142 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 143 | m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | void SMAA::CreatePipelines() { | ||
| 148 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 149 | m_pipelines[i] = | ||
| 150 | CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i], | ||
| 151 | std::tie(m_vertex_shaders[i], m_fragment_shaders[i])); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { | ||
| 156 | Images& images = m_dynamic_images[image_index]; | ||
| 157 | std::vector<VkDescriptorImageInfo> image_infos; | ||
| 158 | std::vector<VkWriteDescriptorSet> updates; | ||
| 159 | image_infos.reserve(6); | ||
| 160 | |||
| 161 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, | ||
| 162 | images.descriptor_sets[EdgeDetection], 0)); | ||
| 163 | |||
| 164 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges], | ||
| 165 | images.descriptor_sets[BlendingWeightCalculation], | ||
| 166 | 0)); | ||
| 167 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area], | ||
| 168 | images.descriptor_sets[BlendingWeightCalculation], | ||
| 169 | 1)); | ||
| 170 | updates.push_back( | ||
| 171 | CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search], | ||
| 172 | images.descriptor_sets[BlendingWeightCalculation], 2)); | ||
| 173 | |||
| 174 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, | ||
| 175 | images.descriptor_sets[NeighborhoodBlending], 0)); | ||
| 176 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend], | ||
| 177 | images.descriptor_sets[NeighborhoodBlending], 1)); | ||
| 178 | |||
| 179 | m_device.GetLogical().UpdateDescriptorSets(updates, {}); | ||
| 180 | } | ||
| 181 | |||
| 182 | void SMAA::UploadImages(Scheduler& scheduler) { | ||
| 183 | if (m_images_ready) { | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||
| 188 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | ||
| 189 | |||
| 190 | UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent, | ||
| 191 | VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes)); | ||
| 192 | UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent, | ||
| 193 | VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes)); | ||
| 194 | |||
| 195 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { | ||
| 196 | for (auto& images : m_dynamic_images) { | ||
| 197 | for (size_t i = 0; i < MaxDynamicImage; i++) { | ||
| 198 | ClearColorImage(cmdbuf, *images.images[i]); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | }); | ||
| 202 | scheduler.Finish(); | ||
| 203 | |||
| 204 | m_images_ready = true; | ||
| 205 | } | ||
| 206 | |||
| 207 | VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 208 | VkImageView source_image_view) { | ||
| 209 | Images& images = m_dynamic_images[image_index]; | ||
| 210 | |||
| 211 | VkImage output_image = *images.images[Output]; | ||
| 212 | VkImage edges_image = *images.images[Edges]; | ||
| 213 | VkImage blend_image = *images.images[Blend]; | ||
| 214 | |||
| 215 | VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection]; | ||
| 216 | VkDescriptorSet blending_weight_calculation_descriptor_set = | ||
| 217 | images.descriptor_sets[BlendingWeightCalculation]; | ||
| 218 | VkDescriptorSet neighborhood_blending_descriptor_set = | ||
| 219 | images.descriptor_sets[NeighborhoodBlending]; | ||
| 220 | |||
| 221 | VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection]; | ||
| 222 | VkFramebuffer blending_weight_calculation_framebuffer = | ||
| 223 | *images.framebuffers[BlendingWeightCalculation]; | ||
| 224 | VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; | ||
| 225 | |||
| 226 | UploadImages(scheduler); | ||
| 227 | UpdateDescriptorSets(source_image_view, image_index); | ||
| 228 | |||
| 229 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 230 | scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { | ||
| 231 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 232 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 233 | BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer, | ||
| 234 | m_extent); | ||
| 235 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]); | ||
| 236 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 237 | *m_pipeline_layouts[EdgeDetection], 0, | ||
| 238 | edge_detection_descriptor_set, {}); | ||
| 239 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 240 | cmdbuf.EndRenderPass(); | ||
| 241 | |||
| 242 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 243 | TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 244 | BeginRenderPass(cmdbuf, *m_renderpasses[BlendingWeightCalculation], | ||
| 245 | blending_weight_calculation_framebuffer, m_extent); | ||
| 246 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 247 | *m_pipelines[BlendingWeightCalculation]); | ||
| 248 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 249 | *m_pipeline_layouts[BlendingWeightCalculation], 0, | ||
| 250 | blending_weight_calculation_descriptor_set, {}); | ||
| 251 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 252 | cmdbuf.EndRenderPass(); | ||
| 253 | |||
| 254 | TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 255 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 256 | BeginRenderPass(cmdbuf, *m_renderpasses[NeighborhoodBlending], | ||
| 257 | neighborhood_blending_framebuffer, m_extent); | ||
| 258 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]); | ||
| 259 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 260 | *m_pipeline_layouts[NeighborhoodBlending], 0, | ||
| 261 | neighborhood_blending_descriptor_set, {}); | ||
| 262 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 263 | cmdbuf.EndRenderPass(); | ||
| 264 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 265 | }); | ||
| 266 | |||
| 267 | return *images.image_views[Output]; | ||
| 268 | } | ||
| 269 | |||
| 270 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_smaa.h b/src/video_core/renderer_vulkan/present/smaa.h index 0e214258a..3d6707d48 100644 --- a/src/video_core/renderer_vulkan/vk_smaa.h +++ b/src/video_core/renderer_vulkan/present/smaa.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include "video_core/renderer_vulkan/present/anti_alias_pass.h" | ||
| 7 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 8 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 8 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 9 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 9 | 10 | ||
| @@ -13,12 +14,14 @@ class Device; | |||
| 13 | class Scheduler; | 14 | class Scheduler; |
| 14 | class StagingBufferPool; | 15 | class StagingBufferPool; |
| 15 | 16 | ||
| 16 | class SMAA { | 17 | class SMAA final : public AntiAliasPass { |
| 17 | public: | 18 | public: |
| 18 | explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, | 19 | explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, |
| 19 | VkExtent2D extent); | 20 | VkExtent2D extent); |
| 21 | ~SMAA() override; | ||
| 22 | |||
| 20 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 23 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, |
| 21 | VkImageView source_image_view); | 24 | VkImageView source_image_view) override; |
| 22 | 25 | ||
| 23 | private: | 26 | private: |
| 24 | enum SMAAStage { | 27 | enum SMAAStage { |
diff --git a/src/video_core/renderer_vulkan/vk_smaa.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 70644ea82..a445b213e 100644 --- a/src/video_core/renderer_vulkan/vk_smaa.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp | |||
| @@ -1,29 +1,11 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <list> | ||
| 5 | |||
| 6 | #include "common/assert.h" | 4 | #include "common/assert.h" |
| 7 | #include "common/polyfill_ranges.h" | 5 | #include "common/polyfill_ranges.h" |
| 8 | 6 | #include "video_core/renderer_vulkan/present/util.h" | |
| 9 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 10 | #include "video_core/renderer_vulkan/vk_shader_util.h" | ||
| 11 | #include "video_core/renderer_vulkan/vk_smaa.h" | ||
| 12 | #include "video_core/smaa_area_tex.h" | ||
| 13 | #include "video_core/smaa_search_tex.h" | ||
| 14 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 15 | |||
| 16 | #include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h" | ||
| 17 | #include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h" | ||
| 18 | #include "video_core/host_shaders/smaa_edge_detection_frag_spv.h" | ||
| 19 | #include "video_core/host_shaders/smaa_edge_detection_vert_spv.h" | ||
| 20 | #include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h" | ||
| 21 | #include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h" | ||
| 22 | 7 | ||
| 23 | namespace Vulkan { | 8 | namespace Vulkan { |
| 24 | namespace { | ||
| 25 | |||
| 26 | #define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0]))) | ||
| 27 | 9 | ||
| 28 | vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) { | 10 | vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) { |
| 29 | const VkImageCreateInfo image_ci{ | 11 | const VkImageCreateInfo image_ci{ |
| @@ -48,7 +30,7 @@ vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, | |||
| 48 | } | 30 | } |
| 49 | 31 | ||
| 50 | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, | 32 | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, |
| 51 | VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) { | 33 | VkImageLayout source_layout) { |
| 52 | constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | 34 | constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | |
| 53 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; | 35 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; |
| 54 | const VkImageMemoryBarrier barrier{ | 36 | const VkImageMemoryBarrier barrier{ |
| @@ -75,7 +57,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo | |||
| 75 | 57 | ||
| 76 | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, | 58 | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, |
| 77 | vk::Image& image, VkExtent2D dimensions, VkFormat format, | 59 | vk::Image& image, VkExtent2D dimensions, VkFormat format, |
| 78 | std::span<const u8> initial_contents = {}) { | 60 | std::span<const u8> initial_contents) { |
| 79 | const VkBufferCreateInfo upload_ci = { | 61 | const VkBufferCreateInfo upload_ci = { |
| 80 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 62 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 81 | .pNext = nullptr, | 63 | .pNext = nullptr, |
| @@ -200,13 +182,13 @@ vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& r | |||
| 200 | }); | 182 | }); |
| 201 | } | 183 | } |
| 202 | 184 | ||
| 203 | vk::Sampler CreateWrappedSampler(const Device& device) { | 185 | vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter) { |
| 204 | return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ | 186 | return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ |
| 205 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | 187 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| 206 | .pNext = nullptr, | 188 | .pNext = nullptr, |
| 207 | .flags = 0, | 189 | .flags = 0, |
| 208 | .magFilter = VK_FILTER_LINEAR, | 190 | .magFilter = filter, |
| 209 | .minFilter = VK_FILTER_LINEAR, | 191 | .minFilter = filter, |
| 210 | .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, | 192 | .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, |
| 211 | .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | 193 | .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, |
| 212 | .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | 194 | .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, |
| @@ -471,12 +453,12 @@ void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) { | |||
| 471 | cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources); | 453 | cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources); |
| 472 | } | 454 | } |
| 473 | 455 | ||
| 474 | void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass, | 456 | void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer, |
| 475 | VkFramebuffer framebuffer, VkExtent2D extent) { | 457 | VkExtent2D extent) { |
| 476 | const VkRenderPassBeginInfo renderpass_bi{ | 458 | const VkRenderPassBeginInfo renderpass_bi{ |
| 477 | .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | 459 | .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
| 478 | .pNext = nullptr, | 460 | .pNext = nullptr, |
| 479 | .renderPass = *render_pass, | 461 | .renderPass = render_pass, |
| 480 | .framebuffer = framebuffer, | 462 | .framebuffer = framebuffer, |
| 481 | .renderArea{ | 463 | .renderArea{ |
| 482 | .offset{}, | 464 | .offset{}, |
| @@ -503,248 +485,4 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass, | |||
| 503 | cmdbuf.SetScissor(0, scissor); | 485 | cmdbuf.SetScissor(0, scissor); |
| 504 | } | 486 | } |
| 505 | 487 | ||
| 506 | } // Anonymous namespace | ||
| 507 | |||
| 508 | SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) | ||
| 509 | : m_device(device), m_allocator(allocator), m_extent(extent), | ||
| 510 | m_image_count(static_cast<u32>(image_count)) { | ||
| 511 | CreateImages(); | ||
| 512 | CreateRenderPasses(); | ||
| 513 | CreateSampler(); | ||
| 514 | CreateShaders(); | ||
| 515 | CreateDescriptorPool(); | ||
| 516 | CreateDescriptorSetLayouts(); | ||
| 517 | CreateDescriptorSets(); | ||
| 518 | CreatePipelineLayouts(); | ||
| 519 | CreatePipelines(); | ||
| 520 | } | ||
| 521 | |||
| 522 | void SMAA::CreateImages() { | ||
| 523 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||
| 524 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | ||
| 525 | |||
| 526 | m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM); | ||
| 527 | m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM); | ||
| 528 | |||
| 529 | m_static_image_views[Area] = | ||
| 530 | CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); | ||
| 531 | m_static_image_views[Search] = | ||
| 532 | CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM); | ||
| 533 | |||
| 534 | for (u32 i = 0; i < m_image_count; i++) { | ||
| 535 | Images& images = m_dynamic_images.emplace_back(); | ||
| 536 | |||
| 537 | images.images[Blend] = | ||
| 538 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 539 | images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT); | ||
| 540 | images.images[Output] = | ||
| 541 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 542 | |||
| 543 | images.image_views[Blend] = | ||
| 544 | CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 545 | images.image_views[Edges] = | ||
| 546 | CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); | ||
| 547 | images.image_views[Output] = | ||
| 548 | CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | void SMAA::CreateRenderPasses() { | ||
| 553 | m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT); | ||
| 554 | m_renderpasses[BlendingWeightCalculation] = | ||
| 555 | CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 556 | m_renderpasses[NeighborhoodBlending] = | ||
| 557 | CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 558 | |||
| 559 | for (auto& images : m_dynamic_images) { | ||
| 560 | images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer( | ||
| 561 | m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); | ||
| 562 | |||
| 563 | images.framebuffers[BlendingWeightCalculation] = | ||
| 564 | CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation], | ||
| 565 | images.image_views[Blend], m_extent); | ||
| 566 | |||
| 567 | images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer( | ||
| 568 | m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | void SMAA::CreateSampler() { | ||
| 573 | m_sampler = CreateWrappedSampler(m_device); | ||
| 574 | } | ||
| 575 | |||
| 576 | void SMAA::CreateShaders() { | ||
| 577 | // These match the order of the SMAAStage enum | ||
| 578 | static constexpr std::array vert_shader_sources{ | ||
| 579 | ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV), | ||
| 580 | ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV), | ||
| 581 | ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV), | ||
| 582 | }; | ||
| 583 | static constexpr std::array frag_shader_sources{ | ||
| 584 | ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV), | ||
| 585 | ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV), | ||
| 586 | ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV), | ||
| 587 | }; | ||
| 588 | |||
| 589 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 590 | m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]); | ||
| 591 | m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]); | ||
| 592 | } | ||
| 593 | } | ||
| 594 | |||
| 595 | void SMAA::CreateDescriptorPool() { | ||
| 596 | // Edge detection: 1 descriptor | ||
| 597 | // Blending weight calculation: 3 descriptors | ||
| 598 | // Neighborhood blending: 2 descriptors | ||
| 599 | |||
| 600 | // 6 descriptors, 3 descriptor sets per image | ||
| 601 | m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count); | ||
| 602 | } | ||
| 603 | |||
| 604 | void SMAA::CreateDescriptorSetLayouts() { | ||
| 605 | m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1); | ||
| 606 | m_descriptor_set_layouts[BlendingWeightCalculation] = | ||
| 607 | CreateWrappedDescriptorSetLayout(m_device, 3); | ||
| 608 | m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2); | ||
| 609 | } | ||
| 610 | |||
| 611 | void SMAA::CreateDescriptorSets() { | ||
| 612 | std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size()); | ||
| 613 | std::ranges::transform(m_descriptor_set_layouts, layouts.begin(), | ||
| 614 | [](auto& layout) { return *layout; }); | ||
| 615 | |||
| 616 | for (auto& images : m_dynamic_images) { | ||
| 617 | images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | void SMAA::CreatePipelineLayouts() { | ||
| 622 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 623 | m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]); | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | void SMAA::CreatePipelines() { | ||
| 628 | for (size_t i = 0; i < MaxSMAAStage; i++) { | ||
| 629 | m_pipelines[i] = | ||
| 630 | CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i], | ||
| 631 | std::tie(m_vertex_shaders[i], m_fragment_shaders[i])); | ||
| 632 | } | ||
| 633 | } | ||
| 634 | |||
| 635 | void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { | ||
| 636 | Images& images = m_dynamic_images[image_index]; | ||
| 637 | std::vector<VkDescriptorImageInfo> image_infos; | ||
| 638 | std::vector<VkWriteDescriptorSet> updates; | ||
| 639 | image_infos.reserve(6); | ||
| 640 | |||
| 641 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, | ||
| 642 | images.descriptor_sets[EdgeDetection], 0)); | ||
| 643 | |||
| 644 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges], | ||
| 645 | images.descriptor_sets[BlendingWeightCalculation], | ||
| 646 | 0)); | ||
| 647 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area], | ||
| 648 | images.descriptor_sets[BlendingWeightCalculation], | ||
| 649 | 1)); | ||
| 650 | updates.push_back( | ||
| 651 | CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search], | ||
| 652 | images.descriptor_sets[BlendingWeightCalculation], 2)); | ||
| 653 | |||
| 654 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, | ||
| 655 | images.descriptor_sets[NeighborhoodBlending], 0)); | ||
| 656 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend], | ||
| 657 | images.descriptor_sets[NeighborhoodBlending], 1)); | ||
| 658 | |||
| 659 | m_device.GetLogical().UpdateDescriptorSets(updates, {}); | ||
| 660 | } | ||
| 661 | |||
| 662 | void SMAA::UploadImages(Scheduler& scheduler) { | ||
| 663 | if (m_images_ready) { | ||
| 664 | return; | ||
| 665 | } | ||
| 666 | |||
| 667 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||
| 668 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | ||
| 669 | |||
| 670 | UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent, | ||
| 671 | VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes)); | ||
| 672 | UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent, | ||
| 673 | VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes)); | ||
| 674 | |||
| 675 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { | ||
| 676 | for (auto& images : m_dynamic_images) { | ||
| 677 | for (size_t i = 0; i < MaxDynamicImage; i++) { | ||
| 678 | ClearColorImage(cmdbuf, *images.images[i]); | ||
| 679 | } | ||
| 680 | } | ||
| 681 | }); | ||
| 682 | scheduler.Finish(); | ||
| 683 | |||
| 684 | m_images_ready = true; | ||
| 685 | } | ||
| 686 | |||
| 687 | VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||
| 688 | VkImageView source_image_view) { | ||
| 689 | Images& images = m_dynamic_images[image_index]; | ||
| 690 | |||
| 691 | VkImage output_image = *images.images[Output]; | ||
| 692 | VkImage edges_image = *images.images[Edges]; | ||
| 693 | VkImage blend_image = *images.images[Blend]; | ||
| 694 | |||
| 695 | VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection]; | ||
| 696 | VkDescriptorSet blending_weight_calculation_descriptor_set = | ||
| 697 | images.descriptor_sets[BlendingWeightCalculation]; | ||
| 698 | VkDescriptorSet neighborhood_blending_descriptor_set = | ||
| 699 | images.descriptor_sets[NeighborhoodBlending]; | ||
| 700 | |||
| 701 | VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection]; | ||
| 702 | VkFramebuffer blending_weight_calculation_framebuffer = | ||
| 703 | *images.framebuffers[BlendingWeightCalculation]; | ||
| 704 | VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; | ||
| 705 | |||
| 706 | UploadImages(scheduler); | ||
| 707 | UpdateDescriptorSets(source_image_view, image_index); | ||
| 708 | |||
| 709 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 710 | scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { | ||
| 711 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 712 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 713 | BeginRenderPass(cmdbuf, m_renderpasses[EdgeDetection], edge_detection_framebuffer, | ||
| 714 | m_extent); | ||
| 715 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]); | ||
| 716 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 717 | *m_pipeline_layouts[EdgeDetection], 0, | ||
| 718 | edge_detection_descriptor_set, {}); | ||
| 719 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 720 | cmdbuf.EndRenderPass(); | ||
| 721 | |||
| 722 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 723 | TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 724 | BeginRenderPass(cmdbuf, m_renderpasses[BlendingWeightCalculation], | ||
| 725 | blending_weight_calculation_framebuffer, m_extent); | ||
| 726 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 727 | *m_pipelines[BlendingWeightCalculation]); | ||
| 728 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 729 | *m_pipeline_layouts[BlendingWeightCalculation], 0, | ||
| 730 | blending_weight_calculation_descriptor_set, {}); | ||
| 731 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 732 | cmdbuf.EndRenderPass(); | ||
| 733 | |||
| 734 | TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 735 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 736 | BeginRenderPass(cmdbuf, m_renderpasses[NeighborhoodBlending], | ||
| 737 | neighborhood_blending_framebuffer, m_extent); | ||
| 738 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]); | ||
| 739 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, | ||
| 740 | *m_pipeline_layouts[NeighborhoodBlending], 0, | ||
| 741 | neighborhood_blending_descriptor_set, {}); | ||
| 742 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 743 | cmdbuf.EndRenderPass(); | ||
| 744 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 745 | }); | ||
| 746 | |||
| 747 | return *images.image_views[Output]; | ||
| 748 | } | ||
| 749 | |||
| 750 | } // namespace Vulkan | 488 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h new file mode 100644 index 000000000..93cfdd16b --- /dev/null +++ b/src/video_core/renderer_vulkan/present/util.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 7 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
| 8 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 9 | |||
| 10 | namespace Vulkan { | ||
| 11 | |||
| 12 | #define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0]))) | ||
| 13 | |||
| 14 | vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format); | ||
| 15 | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, | ||
| 16 | VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL); | ||
| 17 | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, | ||
| 18 | vk::Image& image, VkExtent2D dimensions, VkFormat format, | ||
| 19 | std::span<const u8> initial_contents = {}); | ||
| 20 | void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image); | ||
| 21 | |||
| 22 | vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format); | ||
| 23 | vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format); | ||
| 24 | vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass, | ||
| 25 | vk::ImageView& dest_image, VkExtent2D extent); | ||
| 26 | vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR); | ||
| 27 | vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code); | ||
| 28 | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_sampler_bindings, | ||
| 29 | u32 max_sets); | ||
| 30 | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device, | ||
| 31 | u32 max_sampler_bindings); | ||
| 32 | vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool, | ||
| 33 | vk::Span<VkDescriptorSetLayout> layouts); | ||
| 34 | vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, | ||
| 35 | vk::DescriptorSetLayout& layout); | ||
| 36 | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, | ||
| 37 | vk::PipelineLayout& layout, | ||
| 38 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders); | ||
| 39 | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, | ||
| 40 | VkSampler sampler, VkImageView view, | ||
| 41 | VkDescriptorSet set, u32 binding); | ||
| 42 | |||
| 43 | void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer, | ||
| 44 | VkExtent2D extent); | ||
| 45 | |||
| 46 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 24781860b..fe1a7b0cd 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -16,20 +16,19 @@ | |||
| 16 | #include "core/frontend/emu_window.h" | 16 | #include "core/frontend/emu_window.h" |
| 17 | #include "video_core/gpu.h" | 17 | #include "video_core/gpu.h" |
| 18 | #include "video_core/host1x/gpu_device_memory_manager.h" | 18 | #include "video_core/host1x/gpu_device_memory_manager.h" |
| 19 | #include "video_core/host_shaders/fxaa_frag_spv.h" | ||
| 20 | #include "video_core/host_shaders/fxaa_vert_spv.h" | ||
| 21 | #include "video_core/host_shaders/present_bicubic_frag_spv.h" | 19 | #include "video_core/host_shaders/present_bicubic_frag_spv.h" |
| 22 | #include "video_core/host_shaders/present_gaussian_frag_spv.h" | 20 | #include "video_core/host_shaders/present_gaussian_frag_spv.h" |
| 23 | #include "video_core/host_shaders/vulkan_present_frag_spv.h" | 21 | #include "video_core/host_shaders/vulkan_present_frag_spv.h" |
| 24 | #include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h" | 22 | #include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h" |
| 25 | #include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h" | 23 | #include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h" |
| 26 | #include "video_core/host_shaders/vulkan_present_vert_spv.h" | 24 | #include "video_core/host_shaders/vulkan_present_vert_spv.h" |
| 25 | #include "video_core/renderer_vulkan/present/fsr.h" | ||
| 26 | #include "video_core/renderer_vulkan/present/fxaa.h" | ||
| 27 | #include "video_core/renderer_vulkan/present/smaa.h" | ||
| 27 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 28 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| 28 | #include "video_core/renderer_vulkan/vk_blit_screen.h" | 29 | #include "video_core/renderer_vulkan/vk_blit_screen.h" |
| 29 | #include "video_core/renderer_vulkan/vk_fsr.h" | ||
| 30 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 30 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 31 | #include "video_core/renderer_vulkan/vk_shader_util.h" | 31 | #include "video_core/renderer_vulkan/vk_shader_util.h" |
| 32 | #include "video_core/renderer_vulkan/vk_smaa.h" | ||
| 33 | #include "video_core/renderer_vulkan/vk_swapchain.h" | 32 | #include "video_core/renderer_vulkan/vk_swapchain.h" |
| 34 | #include "video_core/surface.h" | 33 | #include "video_core/surface.h" |
| 35 | #include "video_core/textures/decoders.h" | 34 | #include "video_core/textures/decoders.h" |
| @@ -252,103 +251,17 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf | |||
| 252 | 251 | ||
| 253 | const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue(); | 252 | const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue(); |
| 254 | if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) { | 253 | if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) { |
| 255 | UpdateAADescriptorSet(source_image_view, false); | 254 | if (!fxaa) { |
| 256 | const u32 up_scale = Settings::values.resolution_info.up_scale; | 255 | const u32 up_scale = Settings::values.resolution_info.up_scale; |
| 257 | const u32 down_shift = Settings::values.resolution_info.down_shift; | 256 | const u32 down_shift = Settings::values.resolution_info.down_shift; |
| 258 | VkExtent2D size{ | 257 | const VkExtent2D fxaa_size{ |
| 259 | .width = (up_scale * framebuffer.width) >> down_shift, | 258 | .width = (up_scale * framebuffer.width) >> down_shift, |
| 260 | .height = (up_scale * framebuffer.height) >> down_shift, | 259 | .height = (up_scale * framebuffer.height) >> down_shift, |
| 261 | }; | ||
| 262 | scheduler.Record([this, index = image_index, size, | ||
| 263 | anti_alias_pass](vk::CommandBuffer cmdbuf) { | ||
| 264 | const VkImageMemoryBarrier base_barrier{ | ||
| 265 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 266 | .pNext = nullptr, | ||
| 267 | .srcAccessMask = 0, | ||
| 268 | .dstAccessMask = 0, | ||
| 269 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 270 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 271 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 272 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 273 | .image = {}, | ||
| 274 | .subresourceRange = | ||
| 275 | { | ||
| 276 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 277 | .baseMipLevel = 0, | ||
| 278 | .levelCount = 1, | ||
| 279 | .baseArrayLayer = 0, | ||
| 280 | .layerCount = 1, | ||
| 281 | }, | ||
| 282 | }; | ||
| 283 | |||
| 284 | { | ||
| 285 | VkImageMemoryBarrier fsr_write_barrier = base_barrier; | ||
| 286 | fsr_write_barrier.image = *aa_image; | ||
| 287 | fsr_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||
| 288 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 289 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, fsr_write_barrier); | ||
| 290 | } | ||
| 291 | |||
| 292 | const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f; | ||
| 293 | const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f; | ||
| 294 | const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f; | ||
| 295 | const VkClearValue clear_color{ | ||
| 296 | .color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}}, | ||
| 297 | }; | ||
| 298 | const VkRenderPassBeginInfo renderpass_bi{ | ||
| 299 | .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | ||
| 300 | .pNext = nullptr, | ||
| 301 | .renderPass = *aa_renderpass, | ||
| 302 | .framebuffer = *aa_framebuffer, | ||
| 303 | .renderArea = | ||
| 304 | { | ||
| 305 | .offset = {0, 0}, | ||
| 306 | .extent = size, | ||
| 307 | }, | ||
| 308 | .clearValueCount = 1, | ||
| 309 | .pClearValues = &clear_color, | ||
| 310 | }; | ||
| 311 | const VkViewport viewport{ | ||
| 312 | .x = 0.0f, | ||
| 313 | .y = 0.0f, | ||
| 314 | .width = static_cast<float>(size.width), | ||
| 315 | .height = static_cast<float>(size.height), | ||
| 316 | .minDepth = 0.0f, | ||
| 317 | .maxDepth = 1.0f, | ||
| 318 | }; | ||
| 319 | const VkRect2D scissor{ | ||
| 320 | .offset = {0, 0}, | ||
| 321 | .extent = size, | ||
| 322 | }; | 260 | }; |
| 323 | cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); | 261 | fxaa = std::make_unique<FXAA>(device, memory_allocator, image_count, fxaa_size); |
| 324 | switch (anti_alias_pass) { | 262 | } |
| 325 | case Settings::AntiAliasing::Fxaa: | ||
| 326 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline); | ||
| 327 | break; | ||
| 328 | default: | ||
| 329 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline); | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | cmdbuf.SetViewport(0, viewport); | ||
| 333 | cmdbuf.SetScissor(0, scissor); | ||
| 334 | |||
| 335 | cmdbuf.BindVertexBuffer(0, *buffer, offsetof(BufferData, vertices)); | ||
| 336 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline_layout, 0, | ||
| 337 | aa_descriptor_sets[index], {}); | ||
| 338 | cmdbuf.Draw(4, 1, 0, 0); | ||
| 339 | cmdbuf.EndRenderPass(); | ||
| 340 | |||
| 341 | { | ||
| 342 | VkImageMemoryBarrier blit_read_barrier = base_barrier; | ||
| 343 | blit_read_barrier.image = *aa_image; | ||
| 344 | blit_read_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; | ||
| 345 | blit_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; | ||
| 346 | 263 | ||
| 347 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | 264 | source_image_view = fxaa->Draw(scheduler, image_index, source_image, source_image_view); |
| 348 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, blit_read_barrier); | ||
| 349 | } | ||
| 350 | }); | ||
| 351 | source_image_view = *aa_image_view; | ||
| 352 | } | 265 | } |
| 353 | if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) { | 266 | if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) { |
| 354 | if (!smaa) { | 267 | if (!smaa) { |
| @@ -496,6 +409,7 @@ void BlitScreen::CreateDynamicResources() { | |||
| 496 | CreateRenderPass(); | 409 | CreateRenderPass(); |
| 497 | CreateGraphicsPipeline(); | 410 | CreateGraphicsPipeline(); |
| 498 | fsr.reset(); | 411 | fsr.reset(); |
| 412 | fxaa.reset(); | ||
| 499 | smaa.reset(); | 413 | smaa.reset(); |
| 500 | if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { | 414 | if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { |
| 501 | CreateFSR(); | 415 | CreateFSR(); |
| @@ -520,6 +434,7 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { | |||
| 520 | raw_height = framebuffer.height; | 434 | raw_height = framebuffer.height; |
| 521 | pixel_format = framebuffer.pixel_format; | 435 | pixel_format = framebuffer.pixel_format; |
| 522 | 436 | ||
| 437 | fxaa.reset(); | ||
| 523 | smaa.reset(); | 438 | smaa.reset(); |
| 524 | ReleaseRawImages(); | 439 | ReleaseRawImages(); |
| 525 | 440 | ||
| @@ -529,8 +444,6 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { | |||
| 529 | 444 | ||
| 530 | void BlitScreen::CreateShaders() { | 445 | void BlitScreen::CreateShaders() { |
| 531 | vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); | 446 | vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); |
| 532 | fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV); | ||
| 533 | fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV); | ||
| 534 | bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV); | 447 | bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV); |
| 535 | bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV); | 448 | bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV); |
| 536 | gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV); | 449 | gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV); |
| @@ -553,13 +466,6 @@ void BlitScreen::CreateDescriptorPool() { | |||
| 553 | }, | 466 | }, |
| 554 | }}; | 467 | }}; |
| 555 | 468 | ||
| 556 | const std::array<VkDescriptorPoolSize, 1> pool_sizes_aa{{ | ||
| 557 | { | ||
| 558 | .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 559 | .descriptorCount = static_cast<u32>(image_count * 2), | ||
| 560 | }, | ||
| 561 | }}; | ||
| 562 | |||
| 563 | const VkDescriptorPoolCreateInfo ci{ | 469 | const VkDescriptorPoolCreateInfo ci{ |
| 564 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 470 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| 565 | .pNext = nullptr, | 471 | .pNext = nullptr, |
| @@ -569,16 +475,6 @@ void BlitScreen::CreateDescriptorPool() { | |||
| 569 | .pPoolSizes = pool_sizes.data(), | 475 | .pPoolSizes = pool_sizes.data(), |
| 570 | }; | 476 | }; |
| 571 | descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); | 477 | descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); |
| 572 | |||
| 573 | const VkDescriptorPoolCreateInfo ci_aa{ | ||
| 574 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | ||
| 575 | .pNext = nullptr, | ||
| 576 | .flags = 0, | ||
| 577 | .maxSets = static_cast<u32>(image_count), | ||
| 578 | .poolSizeCount = static_cast<u32>(pool_sizes_aa.size()), | ||
| 579 | .pPoolSizes = pool_sizes_aa.data(), | ||
| 580 | }; | ||
| 581 | aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa); | ||
| 582 | } | 478 | } |
| 583 | 479 | ||
| 584 | void BlitScreen::CreateRenderPass() { | 480 | void BlitScreen::CreateRenderPass() { |
| @@ -659,23 +555,6 @@ void BlitScreen::CreateDescriptorSetLayout() { | |||
| 659 | }, | 555 | }, |
| 660 | }}; | 556 | }}; |
| 661 | 557 | ||
| 662 | const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings_aa{{ | ||
| 663 | { | ||
| 664 | .binding = 0, | ||
| 665 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 666 | .descriptorCount = 1, | ||
| 667 | .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | ||
| 668 | .pImmutableSamplers = nullptr, | ||
| 669 | }, | ||
| 670 | { | ||
| 671 | .binding = 1, | ||
| 672 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 673 | .descriptorCount = 1, | ||
| 674 | .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, | ||
| 675 | .pImmutableSamplers = nullptr, | ||
| 676 | }, | ||
| 677 | }}; | ||
| 678 | |||
| 679 | const VkDescriptorSetLayoutCreateInfo ci{ | 558 | const VkDescriptorSetLayoutCreateInfo ci{ |
| 680 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | 559 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 681 | .pNext = nullptr, | 560 | .pNext = nullptr, |
| @@ -684,21 +563,11 @@ void BlitScreen::CreateDescriptorSetLayout() { | |||
| 684 | .pBindings = layout_bindings.data(), | 563 | .pBindings = layout_bindings.data(), |
| 685 | }; | 564 | }; |
| 686 | 565 | ||
| 687 | const VkDescriptorSetLayoutCreateInfo ci_aa{ | ||
| 688 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||
| 689 | .pNext = nullptr, | ||
| 690 | .flags = 0, | ||
| 691 | .bindingCount = static_cast<u32>(layout_bindings_aa.size()), | ||
| 692 | .pBindings = layout_bindings_aa.data(), | ||
| 693 | }; | ||
| 694 | |||
| 695 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); | 566 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); |
| 696 | aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa); | ||
| 697 | } | 567 | } |
| 698 | 568 | ||
| 699 | void BlitScreen::CreateDescriptorSets() { | 569 | void BlitScreen::CreateDescriptorSets() { |
| 700 | const std::vector layouts(image_count, *descriptor_set_layout); | 570 | const std::vector layouts(image_count, *descriptor_set_layout); |
| 701 | const std::vector layouts_aa(image_count, *aa_descriptor_set_layout); | ||
| 702 | 571 | ||
| 703 | const VkDescriptorSetAllocateInfo ai{ | 572 | const VkDescriptorSetAllocateInfo ai{ |
| 704 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 573 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
| @@ -708,16 +577,7 @@ void BlitScreen::CreateDescriptorSets() { | |||
| 708 | .pSetLayouts = layouts.data(), | 577 | .pSetLayouts = layouts.data(), |
| 709 | }; | 578 | }; |
| 710 | 579 | ||
| 711 | const VkDescriptorSetAllocateInfo ai_aa{ | ||
| 712 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | ||
| 713 | .pNext = nullptr, | ||
| 714 | .descriptorPool = *aa_descriptor_pool, | ||
| 715 | .descriptorSetCount = static_cast<u32>(image_count), | ||
| 716 | .pSetLayouts = layouts_aa.data(), | ||
| 717 | }; | ||
| 718 | |||
| 719 | descriptor_sets = descriptor_pool.Allocate(ai); | 580 | descriptor_sets = descriptor_pool.Allocate(ai); |
| 720 | aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa); | ||
| 721 | } | 581 | } |
| 722 | 582 | ||
| 723 | void BlitScreen::CreatePipelineLayout() { | 583 | void BlitScreen::CreatePipelineLayout() { |
| @@ -730,17 +590,7 @@ void BlitScreen::CreatePipelineLayout() { | |||
| 730 | .pushConstantRangeCount = 0, | 590 | .pushConstantRangeCount = 0, |
| 731 | .pPushConstantRanges = nullptr, | 591 | .pPushConstantRanges = nullptr, |
| 732 | }; | 592 | }; |
| 733 | const VkPipelineLayoutCreateInfo ci_aa{ | ||
| 734 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||
| 735 | .pNext = nullptr, | ||
| 736 | .flags = 0, | ||
| 737 | .setLayoutCount = 1, | ||
| 738 | .pSetLayouts = aa_descriptor_set_layout.address(), | ||
| 739 | .pushConstantRangeCount = 0, | ||
| 740 | .pPushConstantRanges = nullptr, | ||
| 741 | }; | ||
| 742 | pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); | 593 | pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); |
| 743 | aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa); | ||
| 744 | } | 594 | } |
| 745 | 595 | ||
| 746 | void BlitScreen::CreateGraphicsPipeline() { | 596 | void BlitScreen::CreateGraphicsPipeline() { |
| @@ -1068,8 +918,6 @@ void BlitScreen::ReleaseRawImages() { | |||
| 1068 | scheduler.Wait(tick); | 918 | scheduler.Wait(tick); |
| 1069 | } | 919 | } |
| 1070 | raw_images.clear(); | 920 | raw_images.clear(); |
| 1071 | aa_image_view.reset(); | ||
| 1072 | aa_image.reset(); | ||
| 1073 | buffer.reset(); | 921 | buffer.reset(); |
| 1074 | } | 922 | } |
| 1075 | 923 | ||
| @@ -1150,198 +998,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | |||
| 1150 | raw_images[i] = create_image(); | 998 | raw_images[i] = create_image(); |
| 1151 | raw_image_views[i] = create_image_view(raw_images[i]); | 999 | raw_image_views[i] = create_image_view(raw_images[i]); |
| 1152 | } | 1000 | } |
| 1153 | |||
| 1154 | // AA Resources | ||
| 1155 | const u32 up_scale = Settings::values.resolution_info.up_scale; | ||
| 1156 | const u32 down_shift = Settings::values.resolution_info.down_shift; | ||
| 1157 | aa_image = create_image(true, up_scale, down_shift); | ||
| 1158 | aa_image_view = create_image_view(aa_image, true); | ||
| 1159 | VkExtent2D size{ | ||
| 1160 | .width = (up_scale * framebuffer.width) >> down_shift, | ||
| 1161 | .height = (up_scale * framebuffer.height) >> down_shift, | ||
| 1162 | }; | ||
| 1163 | if (aa_renderpass) { | ||
| 1164 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | ||
| 1165 | return; | ||
| 1166 | } | ||
| 1167 | aa_renderpass = CreateRenderPassImpl(VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 1168 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | ||
| 1169 | |||
| 1170 | const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{ | ||
| 1171 | { | ||
| 1172 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||
| 1173 | .pNext = nullptr, | ||
| 1174 | .flags = 0, | ||
| 1175 | .stage = VK_SHADER_STAGE_VERTEX_BIT, | ||
| 1176 | .module = *fxaa_vertex_shader, | ||
| 1177 | .pName = "main", | ||
| 1178 | .pSpecializationInfo = nullptr, | ||
| 1179 | }, | ||
| 1180 | { | ||
| 1181 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||
| 1182 | .pNext = nullptr, | ||
| 1183 | .flags = 0, | ||
| 1184 | .stage = VK_SHADER_STAGE_FRAGMENT_BIT, | ||
| 1185 | .module = *fxaa_fragment_shader, | ||
| 1186 | .pName = "main", | ||
| 1187 | .pSpecializationInfo = nullptr, | ||
| 1188 | }, | ||
| 1189 | }}; | ||
| 1190 | |||
| 1191 | const auto vertex_binding_description = ScreenRectVertex::GetDescription(); | ||
| 1192 | const auto vertex_attrs_description = ScreenRectVertex::GetAttributes(); | ||
| 1193 | |||
| 1194 | const VkPipelineVertexInputStateCreateInfo vertex_input_ci{ | ||
| 1195 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 1196 | .pNext = nullptr, | ||
| 1197 | .flags = 0, | ||
| 1198 | .vertexBindingDescriptionCount = 1, | ||
| 1199 | .pVertexBindingDescriptions = &vertex_binding_description, | ||
| 1200 | .vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()}, | ||
| 1201 | .pVertexAttributeDescriptions = vertex_attrs_description.data(), | ||
| 1202 | }; | ||
| 1203 | |||
| 1204 | const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{ | ||
| 1205 | .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 1206 | .pNext = nullptr, | ||
| 1207 | .flags = 0, | ||
| 1208 | .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, | ||
| 1209 | .primitiveRestartEnable = VK_FALSE, | ||
| 1210 | }; | ||
| 1211 | |||
| 1212 | const VkPipelineViewportStateCreateInfo viewport_state_ci{ | ||
| 1213 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 1214 | .pNext = nullptr, | ||
| 1215 | .flags = 0, | ||
| 1216 | .viewportCount = 1, | ||
| 1217 | .pViewports = nullptr, | ||
| 1218 | .scissorCount = 1, | ||
| 1219 | .pScissors = nullptr, | ||
| 1220 | }; | ||
| 1221 | |||
| 1222 | const VkPipelineRasterizationStateCreateInfo rasterization_ci{ | ||
| 1223 | .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 1224 | .pNext = nullptr, | ||
| 1225 | .flags = 0, | ||
| 1226 | .depthClampEnable = VK_FALSE, | ||
| 1227 | .rasterizerDiscardEnable = VK_FALSE, | ||
| 1228 | .polygonMode = VK_POLYGON_MODE_FILL, | ||
| 1229 | .cullMode = VK_CULL_MODE_NONE, | ||
| 1230 | .frontFace = VK_FRONT_FACE_CLOCKWISE, | ||
| 1231 | .depthBiasEnable = VK_FALSE, | ||
| 1232 | .depthBiasConstantFactor = 0.0f, | ||
| 1233 | .depthBiasClamp = 0.0f, | ||
| 1234 | .depthBiasSlopeFactor = 0.0f, | ||
| 1235 | .lineWidth = 1.0f, | ||
| 1236 | }; | ||
| 1237 | |||
| 1238 | const VkPipelineMultisampleStateCreateInfo multisampling_ci{ | ||
| 1239 | .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 1240 | .pNext = nullptr, | ||
| 1241 | .flags = 0, | ||
| 1242 | .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, | ||
| 1243 | .sampleShadingEnable = VK_FALSE, | ||
| 1244 | .minSampleShading = 0.0f, | ||
| 1245 | .pSampleMask = nullptr, | ||
| 1246 | .alphaToCoverageEnable = VK_FALSE, | ||
| 1247 | .alphaToOneEnable = VK_FALSE, | ||
| 1248 | }; | ||
| 1249 | |||
| 1250 | const VkPipelineColorBlendAttachmentState color_blend_attachment{ | ||
| 1251 | .blendEnable = VK_FALSE, | ||
| 1252 | .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 1253 | .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 1254 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 1255 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 1256 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 1257 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 1258 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 1259 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 1260 | }; | ||
| 1261 | |||
| 1262 | const VkPipelineColorBlendStateCreateInfo color_blend_ci{ | ||
| 1263 | .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, | ||
| 1264 | .pNext = nullptr, | ||
| 1265 | .flags = 0, | ||
| 1266 | .logicOpEnable = VK_FALSE, | ||
| 1267 | .logicOp = VK_LOGIC_OP_COPY, | ||
| 1268 | .attachmentCount = 1, | ||
| 1269 | .pAttachments = &color_blend_attachment, | ||
| 1270 | .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, | ||
| 1271 | }; | ||
| 1272 | |||
| 1273 | static constexpr std::array dynamic_states{ | ||
| 1274 | VK_DYNAMIC_STATE_VIEWPORT, | ||
| 1275 | VK_DYNAMIC_STATE_SCISSOR, | ||
| 1276 | }; | ||
| 1277 | const VkPipelineDynamicStateCreateInfo dynamic_state_ci{ | ||
| 1278 | .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 1279 | .pNext = nullptr, | ||
| 1280 | .flags = 0, | ||
| 1281 | .dynamicStateCount = static_cast<u32>(dynamic_states.size()), | ||
| 1282 | .pDynamicStates = dynamic_states.data(), | ||
| 1283 | }; | ||
| 1284 | |||
| 1285 | const VkGraphicsPipelineCreateInfo fxaa_pipeline_ci{ | ||
| 1286 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 1287 | .pNext = nullptr, | ||
| 1288 | .flags = 0, | ||
| 1289 | .stageCount = static_cast<u32>(fxaa_shader_stages.size()), | ||
| 1290 | .pStages = fxaa_shader_stages.data(), | ||
| 1291 | .pVertexInputState = &vertex_input_ci, | ||
| 1292 | .pInputAssemblyState = &input_assembly_ci, | ||
| 1293 | .pTessellationState = nullptr, | ||
| 1294 | .pViewportState = &viewport_state_ci, | ||
| 1295 | .pRasterizationState = &rasterization_ci, | ||
| 1296 | .pMultisampleState = &multisampling_ci, | ||
| 1297 | .pDepthStencilState = nullptr, | ||
| 1298 | .pColorBlendState = &color_blend_ci, | ||
| 1299 | .pDynamicState = &dynamic_state_ci, | ||
| 1300 | .layout = *aa_pipeline_layout, | ||
| 1301 | .renderPass = *aa_renderpass, | ||
| 1302 | .subpass = 0, | ||
| 1303 | .basePipelineHandle = 0, | ||
| 1304 | .basePipelineIndex = 0, | ||
| 1305 | }; | ||
| 1306 | |||
| 1307 | // AA | ||
| 1308 | aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | void BlitScreen::UpdateAADescriptorSet(VkImageView image_view, bool nn) const { | ||
| 1312 | const VkDescriptorImageInfo image_info{ | ||
| 1313 | .sampler = nn ? *nn_sampler : *sampler, | ||
| 1314 | .imageView = image_view, | ||
| 1315 | .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 1316 | }; | ||
| 1317 | |||
| 1318 | const VkWriteDescriptorSet sampler_write{ | ||
| 1319 | .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||
| 1320 | .pNext = nullptr, | ||
| 1321 | .dstSet = aa_descriptor_sets[image_index], | ||
| 1322 | .dstBinding = 0, | ||
| 1323 | .dstArrayElement = 0, | ||
| 1324 | .descriptorCount = 1, | ||
| 1325 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 1326 | .pImageInfo = &image_info, | ||
| 1327 | .pBufferInfo = nullptr, | ||
| 1328 | .pTexelBufferView = nullptr, | ||
| 1329 | }; | ||
| 1330 | |||
| 1331 | const VkWriteDescriptorSet sampler_write_2{ | ||
| 1332 | .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||
| 1333 | .pNext = nullptr, | ||
| 1334 | .dstSet = aa_descriptor_sets[image_index], | ||
| 1335 | .dstBinding = 1, | ||
| 1336 | .dstArrayElement = 0, | ||
| 1337 | .descriptorCount = 1, | ||
| 1338 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 1339 | .pImageInfo = &image_info, | ||
| 1340 | .pBufferInfo = nullptr, | ||
| 1341 | .pTexelBufferView = nullptr, | ||
| 1342 | }; | ||
| 1343 | |||
| 1344 | device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {}); | ||
| 1345 | } | 1001 | } |
| 1346 | 1002 | ||
| 1347 | void BlitScreen::UpdateDescriptorSet(VkImageView image_view, bool nn) const { | 1003 | void BlitScreen::UpdateDescriptorSet(VkImageView image_view, bool nn) const { |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 56ac47f08..d7f8effa2 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h | |||
| @@ -34,6 +34,7 @@ namespace Vulkan { | |||
| 34 | 34 | ||
| 35 | class Device; | 35 | class Device; |
| 36 | class FSR; | 36 | class FSR; |
| 37 | class FXAA; | ||
| 37 | class RasterizerVulkan; | 38 | class RasterizerVulkan; |
| 38 | class Scheduler; | 39 | class Scheduler; |
| 39 | class SMAA; | 40 | class SMAA; |
| @@ -96,7 +97,6 @@ private: | |||
| 96 | void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); | 97 | void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); |
| 97 | 98 | ||
| 98 | void UpdateDescriptorSet(VkImageView image_view, bool nn) const; | 99 | void UpdateDescriptorSet(VkImageView image_view, bool nn) const; |
| 99 | void UpdateAADescriptorSet(VkImageView image_view, bool nn) const; | ||
| 100 | void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const; | 100 | void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const; |
| 101 | void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, | 101 | void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, |
| 102 | const Layout::FramebufferLayout layout, u32 texture_width, | 102 | const Layout::FramebufferLayout layout, u32 texture_width, |
| @@ -119,8 +119,6 @@ private: | |||
| 119 | std::size_t image_index{}; | 119 | std::size_t image_index{}; |
| 120 | 120 | ||
| 121 | vk::ShaderModule vertex_shader; | 121 | vk::ShaderModule vertex_shader; |
| 122 | vk::ShaderModule fxaa_vertex_shader; | ||
| 123 | vk::ShaderModule fxaa_fragment_shader; | ||
| 124 | vk::ShaderModule bilinear_fragment_shader; | 122 | vk::ShaderModule bilinear_fragment_shader; |
| 125 | vk::ShaderModule bicubic_fragment_shader; | 123 | vk::ShaderModule bicubic_fragment_shader; |
| 126 | vk::ShaderModule gaussian_fragment_shader; | 124 | vk::ShaderModule gaussian_fragment_shader; |
| @@ -128,7 +126,6 @@ private: | |||
| 128 | vk::DescriptorPool descriptor_pool; | 126 | vk::DescriptorPool descriptor_pool; |
| 129 | vk::DescriptorSetLayout descriptor_set_layout; | 127 | vk::DescriptorSetLayout descriptor_set_layout; |
| 130 | vk::PipelineLayout pipeline_layout; | 128 | vk::PipelineLayout pipeline_layout; |
| 131 | vk::Pipeline nearest_neighbor_pipeline; | ||
| 132 | vk::Pipeline bilinear_pipeline; | 129 | vk::Pipeline bilinear_pipeline; |
| 133 | vk::Pipeline bicubic_pipeline; | 130 | vk::Pipeline bicubic_pipeline; |
| 134 | vk::Pipeline gaussian_pipeline; | 131 | vk::Pipeline gaussian_pipeline; |
| @@ -145,16 +142,6 @@ private: | |||
| 145 | std::vector<vk::Image> raw_images; | 142 | std::vector<vk::Image> raw_images; |
| 146 | std::vector<vk::ImageView> raw_image_views; | 143 | std::vector<vk::ImageView> raw_image_views; |
| 147 | 144 | ||
| 148 | vk::DescriptorPool aa_descriptor_pool; | ||
| 149 | vk::DescriptorSetLayout aa_descriptor_set_layout; | ||
| 150 | vk::PipelineLayout aa_pipeline_layout; | ||
| 151 | vk::Pipeline aa_pipeline; | ||
| 152 | vk::RenderPass aa_renderpass; | ||
| 153 | vk::Framebuffer aa_framebuffer; | ||
| 154 | vk::DescriptorSets aa_descriptor_sets; | ||
| 155 | vk::Image aa_image; | ||
| 156 | vk::ImageView aa_image_view; | ||
| 157 | |||
| 158 | u32 raw_width = 0; | 145 | u32 raw_width = 0; |
| 159 | u32 raw_height = 0; | 146 | u32 raw_height = 0; |
| 160 | Service::android::PixelFormat pixel_format{}; | 147 | Service::android::PixelFormat pixel_format{}; |
| @@ -163,6 +150,7 @@ private: | |||
| 163 | 150 | ||
| 164 | std::unique_ptr<FSR> fsr; | 151 | std::unique_ptr<FSR> fsr; |
| 165 | std::unique_ptr<SMAA> smaa; | 152 | std::unique_ptr<SMAA> smaa; |
| 153 | std::unique_ptr<FXAA> fxaa; | ||
| 166 | }; | 154 | }; |
| 167 | 155 | ||
| 168 | } // namespace Vulkan | 156 | } // namespace Vulkan |