fxaa.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/common_types.h"
  4. #include "video_core/host_shaders/fxaa_frag_spv.h"
  5. #include "video_core/host_shaders/fxaa_vert_spv.h"
  6. #include "video_core/renderer_vulkan/present/fxaa.h"
  7. #include "video_core/renderer_vulkan/present/util.h"
  8. #include "video_core/renderer_vulkan/vk_scheduler.h"
  9. #include "video_core/renderer_vulkan/vk_shader_util.h"
  10. #include "video_core/vulkan_common/vulkan_device.h"
  11. namespace Vulkan {
  12. FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
  13. : m_device(device), m_allocator(allocator), m_extent(extent),
  14. m_image_count(static_cast<u32>(image_count)) {
  15. CreateImages();
  16. CreateRenderPasses();
  17. CreateSampler();
  18. CreateShaders();
  19. CreateDescriptorPool();
  20. CreateDescriptorSetLayouts();
  21. CreateDescriptorSets();
  22. CreatePipelineLayouts();
  23. CreatePipelines();
  24. }
  25. FXAA::~FXAA() = default;
  26. void FXAA::CreateImages() {
  27. for (u32 i = 0; i < m_image_count; i++) {
  28. Image& image = m_dynamic_images.emplace_back();
  29. image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
  30. image.image_view =
  31. CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
  32. }
  33. }
  34. void FXAA::CreateRenderPasses() {
  35. m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
  36. for (auto& image : m_dynamic_images) {
  37. image.framebuffer =
  38. CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent);
  39. }
  40. }
  41. void FXAA::CreateSampler() {
  42. m_sampler = CreateWrappedSampler(m_device);
  43. }
  44. void FXAA::CreateShaders() {
  45. m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV);
  46. m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV);
  47. }
  48. void FXAA::CreateDescriptorPool() {
  49. // 2 descriptors, 1 descriptor set per image
  50. m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count);
  51. }
  52. void FXAA::CreateDescriptorSetLayouts() {
  53. m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2);
  54. }
  55. void FXAA::CreateDescriptorSets() {
  56. VkDescriptorSetLayout layout = *m_descriptor_set_layout;
  57. for (auto& images : m_dynamic_images) {
  58. images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout});
  59. }
  60. }
  61. void FXAA::CreatePipelineLayouts() {
  62. m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout);
  63. }
  64. void FXAA::CreatePipelines() {
  65. m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
  66. std::tie(m_vertex_shader, m_fragment_shader));
  67. }
  68. void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
  69. Image& image = m_dynamic_images[image_index];
  70. std::vector<VkDescriptorImageInfo> image_infos;
  71. std::vector<VkWriteDescriptorSet> updates;
  72. image_infos.reserve(2);
  73. updates.push_back(
  74. CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0));
  75. updates.push_back(
  76. CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
  77. m_device.GetLogical().UpdateDescriptorSets(updates, {});
  78. }
  79. void FXAA::UploadImages(Scheduler& scheduler) {
  80. if (m_images_ready) {
  81. return;
  82. }
  83. scheduler.Record([&](vk::CommandBuffer cmdbuf) {
  84. for (auto& image : m_dynamic_images) {
  85. ClearColorImage(cmdbuf, *image.image);
  86. }
  87. });
  88. scheduler.Finish();
  89. m_images_ready = true;
  90. }
  91. VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
  92. VkImageView source_image_view) {
  93. const Image& image{m_dynamic_images[image_index]};
  94. const VkImage output_image{*image.image};
  95. const VkDescriptorSet descriptor_set{image.descriptor_sets[0]};
  96. const VkFramebuffer framebuffer{*image.framebuffer};
  97. const VkRenderPass renderpass{*m_renderpass};
  98. const VkPipeline pipeline{*m_pipeline};
  99. const VkPipelineLayout layout{*m_pipeline_layout};
  100. const VkExtent2D extent{m_extent};
  101. UploadImages(scheduler);
  102. UpdateDescriptorSets(source_image_view, image_index);
  103. scheduler.RequestOutsideRenderPassOperationContext();
  104. scheduler.Record([=](vk::CommandBuffer cmdbuf) {
  105. TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
  106. TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
  107. BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
  108. cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
  109. cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
  110. cmdbuf.Draw(3, 1, 0, 0);
  111. cmdbuf.EndRenderPass();
  112. TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
  113. });
  114. return *image.image_view;
  115. }
  116. } // namespace Vulkan