diff options
| author | 2024-01-15 10:19:02 -0500 | |
|---|---|---|
| committer | 2024-01-31 11:27:21 -0500 | |
| commit | 2ed9586130a7b1de6aefc2aede464c4d3430d484 (patch) | |
| tree | 0982d578a4fe40900ad53386092909f594c2422c /src/video_core/renderer_vulkan | |
| parent | renderer_opengl: move out FSR shader source construction (diff) | |
| download | yuzu-2ed9586130a7b1de6aefc2aede464c4d3430d484.tar.gz yuzu-2ed9586130a7b1de6aefc2aede464c4d3430d484.tar.xz yuzu-2ed9586130a7b1de6aefc2aede464c4d3430d484.zip | |
renderer_vulkan: convert FSR to graphics pipeline
Diffstat (limited to 'src/video_core/renderer_vulkan')
| -rw-r--r-- | src/video_core/renderer_vulkan/present/anti_alias_pass.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fsr.cpp | 510 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fsr.h | 71 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fxaa.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/fxaa.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/smaa.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/smaa.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/util.cpp | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/present/util.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.cpp | 6 |
10 files changed, 265 insertions, 426 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 index c1ec0b9a0..1f20fbd7f 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h | |||
| @@ -12,16 +12,14 @@ class Scheduler; | |||
| 12 | class AntiAliasPass { | 12 | class AntiAliasPass { |
| 13 | public: | 13 | public: |
| 14 | virtual ~AntiAliasPass() = default; | 14 | virtual ~AntiAliasPass() = default; |
| 15 | virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 15 | virtual void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 16 | VkImageView source_image_view) = 0; | 16 | VkImageView* inout_image_view) = 0; |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | class NoAA final : public AntiAliasPass { | 19 | class NoAA final : public AntiAliasPass { |
| 20 | public: | 20 | public: |
| 21 | virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 21 | void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 22 | VkImageView source_image_view) { | 22 | VkImageView* inout_image_view) override {} |
| 23 | return source_image_view; | ||
| 24 | } | ||
| 25 | }; | 23 | }; |
| 26 | 24 | ||
| 27 | } // namespace Vulkan | 25 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index 30a16a785..3f708be70 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp | |||
| @@ -6,11 +6,13 @@ | |||
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | 7 | ||
| 8 | #include "video_core/fsr.h" | 8 | #include "video_core/fsr.h" |
| 9 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_comp_spv.h" | 9 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_frag_spv.h" |
| 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_frag_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_frag_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_frag_spv.h" |
| 13 | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_vert_spv.h" | ||
| 13 | #include "video_core/renderer_vulkan/present/fsr.h" | 14 | #include "video_core/renderer_vulkan/present/fsr.h" |
| 15 | #include "video_core/renderer_vulkan/present/util.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 16 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 15 | #include "video_core/renderer_vulkan/vk_shader_util.h" | 17 | #include "video_core/renderer_vulkan/vk_shader_util.h" |
| 16 | #include "video_core/vulkan_common/vulkan_device.h" | 18 | #include "video_core/vulkan_common/vulkan_device.h" |
| @@ -18,403 +20,207 @@ | |||
| 18 | namespace Vulkan { | 20 | namespace Vulkan { |
| 19 | using namespace FSR; | 21 | using namespace FSR; |
| 20 | 22 | ||
| 21 | FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image_count_, | 23 | using PushConstants = std::array<u32, 4 * 4>; |
| 22 | VkExtent2D output_size_) | 24 | |
| 23 | : device{device_}, memory_allocator{memory_allocator_}, image_count{image_count_}, | 25 | FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, |
| 24 | output_size{output_size_} { | 26 | VkExtent2D extent) |
| 27 | : m_device{device}, m_memory_allocator{memory_allocator}, | ||
| 28 | m_image_count{image_count}, m_extent{extent} { | ||
| 25 | 29 | ||
| 26 | CreateImages(); | 30 | CreateImages(); |
| 31 | CreateRenderPasses(); | ||
| 27 | CreateSampler(); | 32 | CreateSampler(); |
| 28 | CreateShaders(); | 33 | CreateShaders(); |
| 29 | CreateDescriptorPool(); | 34 | CreateDescriptorPool(); |
| 30 | CreateDescriptorSetLayout(); | 35 | CreateDescriptorSetLayout(); |
| 31 | CreateDescriptorSets(); | 36 | CreateDescriptorSets(); |
| 32 | CreatePipelineLayout(); | 37 | CreatePipelineLayouts(); |
| 33 | CreatePipeline(); | 38 | CreatePipelines(); |
| 34 | } | 39 | } |
| 35 | 40 | ||
| 36 | VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view, | 41 | void FSR::CreateImages() { |
| 37 | VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect) { | 42 | m_dynamic_images.resize(m_image_count); |
| 38 | 43 | for (auto& images : m_dynamic_images) { | |
| 39 | UpdateDescriptorSet(image_index, image_view); | 44 | images.images[Easu] = |
| 40 | 45 | CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | |
| 41 | scheduler.Record([this, image_index, input_image_extent, crop_rect](vk::CommandBuffer cmdbuf) { | 46 | images.images[Rcas] = |
| 42 | const VkImageMemoryBarrier base_barrier{ | 47 | CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); |
| 43 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 48 | images.image_views[Easu] = |
| 44 | .pNext = nullptr, | 49 | CreateWrappedImageView(m_device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT); |
| 45 | .srcAccessMask = 0, | 50 | images.image_views[Rcas] = |
| 46 | .dstAccessMask = 0, | 51 | CreateWrappedImageView(m_device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT); |
| 47 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | 52 | } |
| 48 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | 53 | } |
| 49 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 50 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 51 | .image = {}, | ||
| 52 | .subresourceRange = | ||
| 53 | { | ||
| 54 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 55 | .baseMipLevel = 0, | ||
| 56 | .levelCount = 1, | ||
| 57 | .baseArrayLayer = 0, | ||
| 58 | .layerCount = 1, | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | |||
| 62 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *easu_pipeline); | ||
| 63 | |||
| 64 | const f32 input_image_width = static_cast<f32>(input_image_extent.width); | ||
| 65 | const f32 input_image_height = static_cast<f32>(input_image_extent.height); | ||
| 66 | const f32 output_image_width = static_cast<f32>(output_size.width); | ||
| 67 | const f32 output_image_height = static_cast<f32>(output_size.height); | ||
| 68 | const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; | ||
| 69 | const f32 viewport_x = crop_rect.left * input_image_width; | ||
| 70 | const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; | ||
| 71 | const f32 viewport_y = crop_rect.top * input_image_height; | ||
| 72 | |||
| 73 | std::array<u32, 4 * 4> push_constants; | ||
| 74 | FsrEasuConOffset(push_constants.data() + 0, push_constants.data() + 4, | ||
| 75 | push_constants.data() + 8, push_constants.data() + 12, | ||
| 76 | |||
| 77 | viewport_width, viewport_height, input_image_width, input_image_height, | ||
| 78 | output_image_width, output_image_height, viewport_x, viewport_y); | ||
| 79 | cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants); | ||
| 80 | |||
| 81 | { | ||
| 82 | VkImageMemoryBarrier fsr_write_barrier = base_barrier; | ||
| 83 | fsr_write_barrier.image = *images[image_index]; | ||
| 84 | fsr_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||
| 85 | |||
| 86 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 87 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, fsr_write_barrier); | ||
| 88 | } | ||
| 89 | |||
| 90 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, | ||
| 91 | descriptor_sets[image_index * 2], {}); | ||
| 92 | cmdbuf.Dispatch(Common::DivCeil(output_size.width, 16u), | ||
| 93 | Common::DivCeil(output_size.height, 16u), 1); | ||
| 94 | |||
| 95 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *rcas_pipeline); | ||
| 96 | |||
| 97 | const float sharpening = | ||
| 98 | static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; | ||
| 99 | |||
| 100 | FsrRcasCon(push_constants.data(), sharpening); | ||
| 101 | cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants); | ||
| 102 | |||
| 103 | { | ||
| 104 | std::array<VkImageMemoryBarrier, 2> barriers; | ||
| 105 | auto& fsr_read_barrier = barriers[0]; | ||
| 106 | auto& blit_write_barrier = barriers[1]; | ||
| 107 | |||
| 108 | fsr_read_barrier = base_barrier; | ||
| 109 | fsr_read_barrier.image = *images[image_index]; | ||
| 110 | fsr_read_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; | ||
| 111 | fsr_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; | ||
| 112 | |||
| 113 | blit_write_barrier = base_barrier; | ||
| 114 | blit_write_barrier.image = *images[image_count + image_index]; | ||
| 115 | blit_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||
| 116 | blit_write_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; | ||
| 117 | |||
| 118 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | ||
| 119 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, {}, {}, barriers); | ||
| 120 | } | ||
| 121 | 54 | ||
| 122 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, | 55 | void FSR::CreateRenderPasses() { |
| 123 | descriptor_sets[image_index * 2 + 1], {}); | 56 | m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); |
| 124 | cmdbuf.Dispatch(Common::DivCeil(output_size.width, 16u), | ||
| 125 | Common::DivCeil(output_size.height, 16u), 1); | ||
| 126 | 57 | ||
| 127 | { | 58 | for (auto& images : m_dynamic_images) { |
| 128 | std::array<VkImageMemoryBarrier, 1> barriers; | 59 | images.framebuffers[Easu] = |
| 129 | auto& blit_read_barrier = barriers[0]; | 60 | CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Easu], m_extent); |
| 61 | images.framebuffers[Rcas] = | ||
| 62 | CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent); | ||
| 63 | } | ||
| 64 | } | ||
| 130 | 65 | ||
| 131 | blit_read_barrier = base_barrier; | 66 | void FSR::CreateSampler() { |
| 132 | blit_read_barrier.image = *images[image_count + image_index]; | 67 | m_sampler = CreateBilinearSampler(m_device); |
| 133 | blit_read_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; | 68 | } |
| 134 | blit_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; | ||
| 135 | 69 | ||
| 136 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | 70 | void FSR::CreateShaders() { |
| 137 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, {}, {}, barriers); | 71 | m_vert_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_VERT_SPV); |
| 138 | } | ||
| 139 | }); | ||
| 140 | 72 | ||
| 141 | return *image_views[image_count + image_index]; | 73 | if (m_device.IsFloat16Supported()) { |
| 74 | m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV); | ||
| 75 | m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV); | ||
| 76 | } else { | ||
| 77 | m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV); | ||
| 78 | m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV); | ||
| 79 | } | ||
| 142 | } | 80 | } |
| 143 | 81 | ||
| 144 | void FSR::CreateDescriptorPool() { | 82 | void FSR::CreateDescriptorPool() { |
| 145 | const std::array<VkDescriptorPoolSize, 2> pool_sizes{{ | 83 | // EASU: 1 descriptor |
| 146 | { | 84 | // RCAS: 1 descriptor |
| 147 | .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | 85 | // 2 descriptors, 2 descriptor sets per invocation |
| 148 | .descriptorCount = static_cast<u32>(image_count * 2), | 86 | m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); |
| 149 | }, | ||
| 150 | { | ||
| 151 | .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 152 | .descriptorCount = static_cast<u32>(image_count * 2), | ||
| 153 | }, | ||
| 154 | }}; | ||
| 155 | |||
| 156 | const VkDescriptorPoolCreateInfo ci{ | ||
| 157 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | ||
| 158 | .pNext = nullptr, | ||
| 159 | .flags = 0, | ||
| 160 | .maxSets = static_cast<u32>(image_count * 2), | ||
| 161 | .poolSizeCount = static_cast<u32>(pool_sizes.size()), | ||
| 162 | .pPoolSizes = pool_sizes.data(), | ||
| 163 | }; | ||
| 164 | descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); | ||
| 165 | } | 87 | } |
| 166 | 88 | ||
| 167 | void FSR::CreateDescriptorSetLayout() { | 89 | void FSR::CreateDescriptorSetLayout() { |
| 168 | const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{ | 90 | m_descriptor_set_layout = |
| 169 | { | 91 | CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); |
| 170 | .binding = 0, | ||
| 171 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 172 | .descriptorCount = 1, | ||
| 173 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 174 | .pImmutableSamplers = sampler.address(), | ||
| 175 | }, | ||
| 176 | { | ||
| 177 | .binding = 1, | ||
| 178 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 179 | .descriptorCount = 1, | ||
| 180 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 181 | .pImmutableSamplers = sampler.address(), | ||
| 182 | }, | ||
| 183 | }}; | ||
| 184 | |||
| 185 | const VkDescriptorSetLayoutCreateInfo ci{ | ||
| 186 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||
| 187 | .pNext = nullptr, | ||
| 188 | .flags = 0, | ||
| 189 | .bindingCount = static_cast<u32>(layout_bindings.size()), | ||
| 190 | .pBindings = layout_bindings.data(), | ||
| 191 | }; | ||
| 192 | |||
| 193 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); | ||
| 194 | } | 92 | } |
| 195 | 93 | ||
| 196 | void FSR::CreateDescriptorSets() { | 94 | void FSR::CreateDescriptorSets() { |
| 197 | const u32 sets = static_cast<u32>(image_count * 2); | 95 | std::vector<VkDescriptorSetLayout> layouts(MaxFsrStage, *m_descriptor_set_layout); |
| 198 | const std::vector layouts(sets, *descriptor_set_layout); | ||
| 199 | |||
| 200 | const VkDescriptorSetAllocateInfo ai{ | ||
| 201 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | ||
| 202 | .pNext = nullptr, | ||
| 203 | .descriptorPool = *descriptor_pool, | ||
| 204 | .descriptorSetCount = sets, | ||
| 205 | .pSetLayouts = layouts.data(), | ||
| 206 | }; | ||
| 207 | 96 | ||
| 208 | descriptor_sets = descriptor_pool.Allocate(ai); | 97 | for (auto& images : m_dynamic_images) { |
| 209 | } | 98 | images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); |
| 210 | |||
| 211 | void FSR::CreateImages() { | ||
| 212 | images.resize(image_count * 2); | ||
| 213 | image_views.resize(image_count * 2); | ||
| 214 | |||
| 215 | for (size_t i = 0; i < image_count * 2; ++i) { | ||
| 216 | images[i] = memory_allocator.CreateImage(VkImageCreateInfo{ | ||
| 217 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | ||
| 218 | .pNext = nullptr, | ||
| 219 | .flags = 0, | ||
| 220 | .imageType = VK_IMAGE_TYPE_2D, | ||
| 221 | .format = VK_FORMAT_R16G16B16A16_SFLOAT, | ||
| 222 | .extent = | ||
| 223 | { | ||
| 224 | .width = output_size.width, | ||
| 225 | .height = output_size.height, | ||
| 226 | .depth = 1, | ||
| 227 | }, | ||
| 228 | .mipLevels = 1, | ||
| 229 | .arrayLayers = 1, | ||
| 230 | .samples = VK_SAMPLE_COUNT_1_BIT, | ||
| 231 | .tiling = VK_IMAGE_TILING_OPTIMAL, | ||
| 232 | .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT | | ||
| 233 | VK_IMAGE_USAGE_SAMPLED_BIT, | ||
| 234 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 235 | .queueFamilyIndexCount = 0, | ||
| 236 | .pQueueFamilyIndices = nullptr, | ||
| 237 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | ||
| 238 | }); | ||
| 239 | image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | ||
| 240 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||
| 241 | .pNext = nullptr, | ||
| 242 | .flags = 0, | ||
| 243 | .image = *images[i], | ||
| 244 | .viewType = VK_IMAGE_VIEW_TYPE_2D, | ||
| 245 | .format = VK_FORMAT_R16G16B16A16_SFLOAT, | ||
| 246 | .components = | ||
| 247 | { | ||
| 248 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 249 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 250 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 251 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 252 | }, | ||
| 253 | .subresourceRange = | ||
| 254 | { | ||
| 255 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 256 | .baseMipLevel = 0, | ||
| 257 | .levelCount = 1, | ||
| 258 | .baseArrayLayer = 0, | ||
| 259 | .layerCount = 1, | ||
| 260 | }, | ||
| 261 | }); | ||
| 262 | } | 99 | } |
| 263 | } | 100 | } |
| 264 | 101 | ||
| 265 | void FSR::CreatePipelineLayout() { | 102 | void FSR::CreatePipelineLayouts() { |
| 266 | VkPushConstantRange push_const{ | 103 | const VkPushConstantRange range{ |
| 267 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 104 | .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, |
| 268 | .offset = 0, | 105 | .offset = 0, |
| 269 | .size = sizeof(std::array<u32, 4 * 4>), | 106 | .size = sizeof(PushConstants), |
| 270 | }; | 107 | }; |
| 271 | VkPipelineLayoutCreateInfo ci{ | 108 | VkPipelineLayoutCreateInfo ci{ |
| 272 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 109 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| 273 | .pNext = nullptr, | 110 | .pNext = nullptr, |
| 274 | .flags = 0, | 111 | .flags = 0, |
| 275 | .setLayoutCount = 1, | 112 | .setLayoutCount = 1, |
| 276 | .pSetLayouts = descriptor_set_layout.address(), | 113 | .pSetLayouts = m_descriptor_set_layout.address(), |
| 277 | .pushConstantRangeCount = 1, | 114 | .pushConstantRangeCount = 1, |
| 278 | .pPushConstantRanges = &push_const, | 115 | .pPushConstantRanges = &range, |
| 279 | }; | 116 | }; |
| 280 | 117 | ||
| 281 | pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); | 118 | m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); |
| 282 | } | 119 | } |
| 283 | 120 | ||
| 284 | void FSR::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const { | 121 | void FSR::CreatePipelines() { |
| 285 | const auto fsr_image_view = *image_views[image_index]; | 122 | m_easu_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, |
| 286 | const auto blit_image_view = *image_views[image_count + image_index]; | 123 | std::tie(m_vert_shader, m_easu_shader)); |
| 287 | 124 | m_rcas_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, | |
| 288 | const VkDescriptorImageInfo image_info{ | 125 | std::tie(m_vert_shader, m_rcas_shader)); |
| 289 | .sampler = VK_NULL_HANDLE, | ||
| 290 | .imageView = image_view, | ||
| 291 | .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 292 | }; | ||
| 293 | const VkDescriptorImageInfo fsr_image_info{ | ||
| 294 | .sampler = VK_NULL_HANDLE, | ||
| 295 | .imageView = fsr_image_view, | ||
| 296 | .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 297 | }; | ||
| 298 | const VkDescriptorImageInfo blit_image_info{ | ||
| 299 | .sampler = VK_NULL_HANDLE, | ||
| 300 | .imageView = blit_image_view, | ||
| 301 | .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 302 | }; | ||
| 303 | |||
| 304 | VkWriteDescriptorSet sampler_write{ | ||
| 305 | .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||
| 306 | .pNext = nullptr, | ||
| 307 | .dstSet = descriptor_sets[image_index * 2], | ||
| 308 | .dstBinding = 0, | ||
| 309 | .dstArrayElement = 0, | ||
| 310 | .descriptorCount = 1, | ||
| 311 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 312 | .pImageInfo = &image_info, | ||
| 313 | .pBufferInfo = nullptr, | ||
| 314 | .pTexelBufferView = nullptr, | ||
| 315 | }; | ||
| 316 | |||
| 317 | VkWriteDescriptorSet output_write{ | ||
| 318 | .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||
| 319 | .pNext = nullptr, | ||
| 320 | .dstSet = descriptor_sets[image_index * 2], | ||
| 321 | .dstBinding = 1, | ||
| 322 | .dstArrayElement = 0, | ||
| 323 | .descriptorCount = 1, | ||
| 324 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 325 | .pImageInfo = &fsr_image_info, | ||
| 326 | .pBufferInfo = nullptr, | ||
| 327 | .pTexelBufferView = nullptr, | ||
| 328 | }; | ||
| 329 | |||
| 330 | device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, output_write}, {}); | ||
| 331 | |||
| 332 | sampler_write.dstSet = descriptor_sets[image_index * 2 + 1]; | ||
| 333 | sampler_write.pImageInfo = &fsr_image_info; | ||
| 334 | output_write.dstSet = descriptor_sets[image_index * 2 + 1]; | ||
| 335 | output_write.pImageInfo = &blit_image_info; | ||
| 336 | |||
| 337 | device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, output_write}, {}); | ||
| 338 | } | 126 | } |
| 339 | 127 | ||
| 340 | void FSR::CreateSampler() { | 128 | void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { |
| 341 | const VkSamplerCreateInfo ci{ | 129 | Images& images = m_dynamic_images[image_index]; |
| 342 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | 130 | std::vector<VkDescriptorImageInfo> image_infos; |
| 343 | .pNext = nullptr, | 131 | std::vector<VkWriteDescriptorSet> updates; |
| 344 | .flags = 0, | 132 | image_infos.reserve(2); |
| 345 | .magFilter = VK_FILTER_LINEAR, | ||
| 346 | .minFilter = VK_FILTER_LINEAR, | ||
| 347 | .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, | ||
| 348 | .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||
| 349 | .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||
| 350 | .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||
| 351 | .mipLodBias = 0.0f, | ||
| 352 | .anisotropyEnable = VK_FALSE, | ||
| 353 | .maxAnisotropy = 0.0f, | ||
| 354 | .compareEnable = VK_FALSE, | ||
| 355 | .compareOp = VK_COMPARE_OP_NEVER, | ||
| 356 | .minLod = 0.0f, | ||
| 357 | .maxLod = 0.0f, | ||
| 358 | .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, | ||
| 359 | .unnormalizedCoordinates = VK_FALSE, | ||
| 360 | }; | ||
| 361 | 133 | ||
| 362 | sampler = device.GetLogical().CreateSampler(ci); | 134 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, |
| 363 | } | 135 | images.descriptor_sets[Easu], 0)); |
| 136 | updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], | ||
| 137 | images.descriptor_sets[Rcas], 0)); | ||
| 364 | 138 | ||
| 365 | void FSR::CreateShaders() { | 139 | m_device.GetLogical().UpdateDescriptorSets(updates, {}); |
| 366 | if (device.IsFloat16Supported()) { | ||
| 367 | easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP16_COMP_SPV); | ||
| 368 | rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_COMP_SPV); | ||
| 369 | } else { | ||
| 370 | easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP32_COMP_SPV); | ||
| 371 | rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_COMP_SPV); | ||
| 372 | } | ||
| 373 | } | 140 | } |
| 374 | 141 | ||
| 375 | void FSR::CreatePipeline() { | 142 | void FSR::UploadImages(Scheduler& scheduler) { |
| 376 | VkPipelineShaderStageCreateInfo shader_stage_easu{ | 143 | if (m_images_ready) { |
| 377 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 144 | return; |
| 378 | .pNext = nullptr, | 145 | } |
| 379 | .flags = 0, | ||
| 380 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 381 | .module = *easu_shader, | ||
| 382 | .pName = "main", | ||
| 383 | .pSpecializationInfo = nullptr, | ||
| 384 | }; | ||
| 385 | 146 | ||
| 386 | VkPipelineShaderStageCreateInfo shader_stage_rcas{ | 147 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { |
| 387 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 148 | for (auto& image : m_dynamic_images) { |
| 388 | .pNext = nullptr, | 149 | ClearColorImage(cmdbuf, *image.images[Easu]); |
| 389 | .flags = 0, | 150 | ClearColorImage(cmdbuf, *image.images[Rcas]); |
| 390 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | 151 | } |
| 391 | .module = *rcas_shader, | 152 | }); |
| 392 | .pName = "main", | 153 | scheduler.Finish(); |
| 393 | .pSpecializationInfo = nullptr, | ||
| 394 | }; | ||
| 395 | 154 | ||
| 396 | VkComputePipelineCreateInfo pipeline_ci_easu{ | 155 | m_images_ready = true; |
| 397 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | 156 | } |
| 398 | .pNext = nullptr, | ||
| 399 | .flags = 0, | ||
| 400 | .stage = shader_stage_easu, | ||
| 401 | .layout = *pipeline_layout, | ||
| 402 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 403 | .basePipelineIndex = 0, | ||
| 404 | }; | ||
| 405 | 157 | ||
| 406 | VkComputePipelineCreateInfo pipeline_ci_rcas{ | 158 | VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, |
| 407 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | 159 | VkImageView source_image_view, VkExtent2D input_image_extent, |
| 408 | .pNext = nullptr, | 160 | const Common::Rectangle<f32>& crop_rect) { |
| 409 | .flags = 0, | 161 | Images& images = m_dynamic_images[image_index]; |
| 410 | .stage = shader_stage_rcas, | 162 | |
| 411 | .layout = *pipeline_layout, | 163 | VkImage easu_image = *images.images[Easu]; |
| 412 | .basePipelineHandle = VK_NULL_HANDLE, | 164 | VkImage rcas_image = *images.images[Rcas]; |
| 413 | .basePipelineIndex = 0, | 165 | VkDescriptorSet easu_descriptor_set = images.descriptor_sets[Easu]; |
| 414 | }; | 166 | VkDescriptorSet rcas_descriptor_set = images.descriptor_sets[Rcas]; |
| 167 | VkFramebuffer easu_framebuffer = *images.framebuffers[Easu]; | ||
| 168 | VkFramebuffer rcas_framebuffer = *images.framebuffers[Rcas]; | ||
| 169 | VkPipeline easu_pipeline = *m_easu_pipeline; | ||
| 170 | VkPipeline rcas_pipeline = *m_rcas_pipeline; | ||
| 171 | VkPipelineLayout pipeline_layout = *m_pipeline_layout; | ||
| 172 | VkRenderPass renderpass = *m_renderpass; | ||
| 173 | VkExtent2D extent = m_extent; | ||
| 174 | |||
| 175 | const f32 input_image_width = static_cast<f32>(input_image_extent.width); | ||
| 176 | const f32 input_image_height = static_cast<f32>(input_image_extent.height); | ||
| 177 | const f32 output_image_width = static_cast<f32>(extent.width); | ||
| 178 | const f32 output_image_height = static_cast<f32>(extent.height); | ||
| 179 | const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; | ||
| 180 | const f32 viewport_x = crop_rect.left * input_image_width; | ||
| 181 | const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; | ||
| 182 | const f32 viewport_y = crop_rect.top * input_image_height; | ||
| 183 | |||
| 184 | PushConstants easu_con{}; | ||
| 185 | PushConstants rcas_con{}; | ||
| 186 | FsrEasuConOffset(easu_con.data() + 0, easu_con.data() + 4, easu_con.data() + 8, | ||
| 187 | easu_con.data() + 12, viewport_width, viewport_height, input_image_width, | ||
| 188 | input_image_height, output_image_width, output_image_height, viewport_x, | ||
| 189 | viewport_y); | ||
| 190 | |||
| 191 | const float sharpening = | ||
| 192 | static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; | ||
| 193 | FsrRcasCon(rcas_con.data(), sharpening); | ||
| 194 | |||
| 195 | UploadImages(scheduler); | ||
| 196 | UpdateDescriptorSets(source_image_view, image_index); | ||
| 197 | |||
| 198 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 199 | scheduler.Record([=](vk::CommandBuffer cmdbuf) { | ||
| 200 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 201 | TransitionImageLayout(cmdbuf, easu_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 202 | BeginRenderPass(cmdbuf, renderpass, easu_framebuffer, extent); | ||
| 203 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, easu_pipeline); | ||
| 204 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, | ||
| 205 | easu_descriptor_set, {}); | ||
| 206 | cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, easu_con); | ||
| 207 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 208 | cmdbuf.EndRenderPass(); | ||
| 209 | |||
| 210 | TransitionImageLayout(cmdbuf, easu_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 211 | TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 212 | BeginRenderPass(cmdbuf, renderpass, rcas_framebuffer, extent); | ||
| 213 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, rcas_pipeline); | ||
| 214 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, | ||
| 215 | rcas_descriptor_set, {}); | ||
| 216 | cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, rcas_con); | ||
| 217 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 218 | cmdbuf.EndRenderPass(); | ||
| 219 | |||
| 220 | TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL); | ||
| 221 | }); | ||
| 415 | 222 | ||
| 416 | easu_pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci_easu); | 223 | return *images.image_views[Rcas]; |
| 417 | rcas_pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci_rcas); | ||
| 418 | } | 224 | } |
| 419 | 225 | ||
| 420 | } // namespace Vulkan | 226 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/fsr.h b/src/video_core/renderer_vulkan/present/fsr.h index 3505c1416..8602e8146 100644 --- a/src/video_core/renderer_vulkan/present/fsr.h +++ b/src/video_core/renderer_vulkan/present/fsr.h | |||
| @@ -15,38 +15,55 @@ class Scheduler; | |||
| 15 | class FSR { | 15 | class FSR { |
| 16 | public: | 16 | public: |
| 17 | explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, | 17 | explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, |
| 18 | VkExtent2D output_size); | 18 | VkExtent2D extent); |
| 19 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view, | 19 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, |
| 20 | VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect); | 20 | VkImageView source_image_view, VkExtent2D input_image_extent, |
| 21 | const Common::Rectangle<f32>& crop_rect); | ||
| 21 | 22 | ||
| 22 | private: | 23 | private: |
| 23 | void CreateDescriptorPool(); | ||
| 24 | void CreateDescriptorSetLayout(); | ||
| 25 | void CreateDescriptorSets(); | ||
| 26 | void CreateImages(); | 24 | void CreateImages(); |
| 25 | void CreateRenderPasses(); | ||
| 27 | void CreateSampler(); | 26 | void CreateSampler(); |
| 28 | void CreateShaders(); | 27 | void CreateShaders(); |
| 29 | void CreatePipeline(); | 28 | void CreateDescriptorPool(); |
| 30 | void CreatePipelineLayout(); | 29 | void CreateDescriptorSetLayout(); |
| 31 | 30 | void CreateDescriptorSets(); | |
| 32 | void UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const; | 31 | void CreatePipelineLayouts(); |
| 33 | 32 | void CreatePipelines(); | |
| 34 | const Device& device; | 33 | |
| 35 | MemoryAllocator& memory_allocator; | 34 | void UploadImages(Scheduler& scheduler); |
| 36 | size_t image_count; | 35 | void UpdateDescriptorSets(VkImageView image_view, size_t image_index); |
| 37 | VkExtent2D output_size; | 36 | |
| 38 | 37 | const Device& m_device; | |
| 39 | vk::DescriptorPool descriptor_pool; | 38 | MemoryAllocator& m_memory_allocator; |
| 40 | vk::DescriptorSetLayout descriptor_set_layout; | 39 | const size_t m_image_count; |
| 41 | vk::DescriptorSets descriptor_sets; | 40 | const VkExtent2D m_extent; |
| 42 | vk::PipelineLayout pipeline_layout; | 41 | |
| 43 | vk::ShaderModule easu_shader; | 42 | enum FsrStage { |
| 44 | vk::ShaderModule rcas_shader; | 43 | Easu, |
| 45 | vk::Pipeline easu_pipeline; | 44 | Rcas, |
| 46 | vk::Pipeline rcas_pipeline; | 45 | MaxFsrStage, |
| 47 | vk::Sampler sampler; | 46 | }; |
| 48 | std::vector<vk::Image> images; | 47 | |
| 49 | std::vector<vk::ImageView> image_views; | 48 | vk::DescriptorPool m_descriptor_pool; |
| 49 | vk::DescriptorSetLayout m_descriptor_set_layout; | ||
| 50 | vk::PipelineLayout m_pipeline_layout; | ||
| 51 | vk::ShaderModule m_vert_shader; | ||
| 52 | vk::ShaderModule m_easu_shader; | ||
| 53 | vk::ShaderModule m_rcas_shader; | ||
| 54 | vk::Pipeline m_easu_pipeline; | ||
| 55 | vk::Pipeline m_rcas_pipeline; | ||
| 56 | vk::RenderPass m_renderpass; | ||
| 57 | vk::Sampler m_sampler; | ||
| 58 | |||
| 59 | struct Images { | ||
| 60 | vk::DescriptorSets descriptor_sets; | ||
| 61 | std::array<vk::Image, MaxFsrStage> images; | ||
| 62 | std::array<vk::ImageView, MaxFsrStage> image_views; | ||
| 63 | std::array<vk::Framebuffer, MaxFsrStage> framebuffers; | ||
| 64 | }; | ||
| 65 | std::vector<Images> m_dynamic_images; | ||
| 66 | bool m_images_ready{}; | ||
| 50 | }; | 67 | }; |
| 51 | 68 | ||
| 52 | } // namespace Vulkan | 69 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp index 6c772ada3..bdafd1f4d 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.cpp +++ b/src/video_core/renderer_vulkan/present/fxaa.cpp | |||
| @@ -63,7 +63,9 @@ void FXAA::CreateDescriptorPool() { | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void FXAA::CreateDescriptorSetLayouts() { | 65 | void FXAA::CreateDescriptorSetLayouts() { |
| 66 | m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2); | 66 | m_descriptor_set_layout = |
| 67 | CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 68 | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); | ||
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | void FXAA::CreateDescriptorSets() { | 71 | void FXAA::CreateDescriptorSets() { |
| @@ -112,9 +114,10 @@ void FXAA::UploadImages(Scheduler& scheduler) { | |||
| 112 | m_images_ready = true; | 114 | m_images_ready = true; |
| 113 | } | 115 | } |
| 114 | 116 | ||
| 115 | VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 117 | void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 116 | VkImageView source_image_view) { | 118 | VkImageView* inout_image_view) { |
| 117 | const Image& image{m_dynamic_images[image_index]}; | 119 | const Image& image{m_dynamic_images[image_index]}; |
| 120 | const VkImage input_image{*inout_image}; | ||
| 118 | const VkImage output_image{*image.image}; | 121 | const VkImage output_image{*image.image}; |
| 119 | const VkDescriptorSet descriptor_set{image.descriptor_sets[0]}; | 122 | const VkDescriptorSet descriptor_set{image.descriptor_sets[0]}; |
| 120 | const VkFramebuffer framebuffer{*image.framebuffer}; | 123 | const VkFramebuffer framebuffer{*image.framebuffer}; |
| @@ -124,11 +127,11 @@ VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ | |||
| 124 | const VkExtent2D extent{m_extent}; | 127 | const VkExtent2D extent{m_extent}; |
| 125 | 128 | ||
| 126 | UploadImages(scheduler); | 129 | UploadImages(scheduler); |
| 127 | UpdateDescriptorSets(source_image_view, image_index); | 130 | UpdateDescriptorSets(*inout_image_view, image_index); |
| 128 | 131 | ||
| 129 | scheduler.RequestOutsideRenderPassOperationContext(); | 132 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 130 | scheduler.Record([=](vk::CommandBuffer cmdbuf) { | 133 | scheduler.Record([=](vk::CommandBuffer cmdbuf) { |
| 131 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | 134 | TransitionImageLayout(cmdbuf, input_image, VK_IMAGE_LAYOUT_GENERAL); |
| 132 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | 135 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); |
| 133 | BeginRenderPass(cmdbuf, renderpass, framebuffer, extent); | 136 | BeginRenderPass(cmdbuf, renderpass, framebuffer, extent); |
| 134 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | 137 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); |
| @@ -138,7 +141,8 @@ VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ | |||
| 138 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | 141 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); |
| 139 | }); | 142 | }); |
| 140 | 143 | ||
| 141 | return *image.image_view; | 144 | *inout_image = *image.image; |
| 145 | *inout_image_view = *image.image_view; | ||
| 142 | } | 146 | } |
| 143 | 147 | ||
| 144 | } // namespace Vulkan | 148 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/fxaa.h b/src/video_core/renderer_vulkan/present/fxaa.h index c083f3ff0..97a2e5c1c 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.h +++ b/src/video_core/renderer_vulkan/present/fxaa.h | |||
| @@ -19,8 +19,8 @@ public: | |||
| 19 | VkExtent2D extent); | 19 | VkExtent2D extent); |
| 20 | ~FXAA() override; | 20 | ~FXAA() override; |
| 21 | 21 | ||
| 22 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 22 | void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 23 | VkImageView source_image_view) override; | 23 | VkImageView* inout_image_view) override; |
| 24 | 24 | ||
| 25 | private: | 25 | private: |
| 26 | void CreateImages(); | 26 | void CreateImages(); |
diff --git a/src/video_core/renderer_vulkan/present/smaa.cpp b/src/video_core/renderer_vulkan/present/smaa.cpp index 68cd22b08..39645fd1d 100644 --- a/src/video_core/renderer_vulkan/present/smaa.cpp +++ b/src/video_core/renderer_vulkan/present/smaa.cpp | |||
| @@ -122,10 +122,15 @@ void SMAA::CreateDescriptorPool() { | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void SMAA::CreateDescriptorSetLayouts() { | 124 | void SMAA::CreateDescriptorSetLayouts() { |
| 125 | m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1); | 125 | m_descriptor_set_layouts[EdgeDetection] = |
| 126 | CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); | ||
| 126 | m_descriptor_set_layouts[BlendingWeightCalculation] = | 127 | m_descriptor_set_layouts[BlendingWeightCalculation] = |
| 127 | CreateWrappedDescriptorSetLayout(m_device, 3); | 128 | CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| 128 | m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2); | 129 | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| 130 | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); | ||
| 131 | m_descriptor_set_layouts[NeighborhoodBlending] = | ||
| 132 | CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||
| 133 | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); | ||
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | void SMAA::CreateDescriptorSets() { | 136 | void SMAA::CreateDescriptorSets() { |
| @@ -204,10 +209,11 @@ void SMAA::UploadImages(Scheduler& scheduler) { | |||
| 204 | m_images_ready = true; | 209 | m_images_ready = true; |
| 205 | } | 210 | } |
| 206 | 211 | ||
| 207 | VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 212 | void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 208 | VkImageView source_image_view) { | 213 | VkImageView* inout_image_view) { |
| 209 | Images& images = m_dynamic_images[image_index]; | 214 | Images& images = m_dynamic_images[image_index]; |
| 210 | 215 | ||
| 216 | VkImage input_image = *inout_image; | ||
| 211 | VkImage output_image = *images.images[Output]; | 217 | VkImage output_image = *images.images[Output]; |
| 212 | VkImage edges_image = *images.images[Edges]; | 218 | VkImage edges_image = *images.images[Edges]; |
| 213 | VkImage blend_image = *images.images[Blend]; | 219 | VkImage blend_image = *images.images[Blend]; |
| @@ -224,11 +230,11 @@ VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ | |||
| 224 | VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; | 230 | VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; |
| 225 | 231 | ||
| 226 | UploadImages(scheduler); | 232 | UploadImages(scheduler); |
| 227 | UpdateDescriptorSets(source_image_view, image_index); | 233 | UpdateDescriptorSets(*inout_image_view, image_index); |
| 228 | 234 | ||
| 229 | scheduler.RequestOutsideRenderPassOperationContext(); | 235 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 230 | scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { | 236 | scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { |
| 231 | TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); | 237 | TransitionImageLayout(cmdbuf, input_image, VK_IMAGE_LAYOUT_GENERAL); |
| 232 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); | 238 | TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL); |
| 233 | BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer, | 239 | BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer, |
| 234 | m_extent); | 240 | m_extent); |
| @@ -264,7 +270,8 @@ VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ | |||
| 264 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); | 270 | TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); |
| 265 | }); | 271 | }); |
| 266 | 272 | ||
| 267 | return *images.image_views[Output]; | 273 | *inout_image = *images.images[Output]; |
| 274 | *inout_image_view = *images.image_views[Output]; | ||
| 268 | } | 275 | } |
| 269 | 276 | ||
| 270 | } // namespace Vulkan | 277 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/smaa.h b/src/video_core/renderer_vulkan/present/smaa.h index 3d6707d48..fdf6def07 100644 --- a/src/video_core/renderer_vulkan/present/smaa.h +++ b/src/video_core/renderer_vulkan/present/smaa.h | |||
| @@ -20,8 +20,8 @@ public: | |||
| 20 | VkExtent2D extent); | 20 | VkExtent2D extent); |
| 21 | ~SMAA() override; | 21 | ~SMAA() override; |
| 22 | 22 | ||
| 23 | VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | 23 | void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, |
| 24 | VkImageView source_image_view) override; | 24 | VkImageView* inout_image_view) override; |
| 25 | 25 | ||
| 26 | private: | 26 | private: |
| 27 | enum SMAAStage { | 27 | enum SMAAStage { |
diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index cd6061101..9c08ac613 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp | |||
| @@ -215,32 +215,37 @@ vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const | |||
| 215 | }); | 215 | }); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_descriptors, | 218 | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, size_t max_descriptors, |
| 219 | u32 max_sets) { | 219 | size_t max_sets, |
| 220 | const VkDescriptorPoolSize pool_size{ | 220 | std::initializer_list<VkDescriptorType> types) { |
| 221 | .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | 221 | std::vector<VkDescriptorPoolSize> pool_sizes(types.size()); |
| 222 | .descriptorCount = static_cast<u32>(max_descriptors), | 222 | for (u32 i = 0; i < types.size(); i++) { |
| 223 | }; | 223 | pool_sizes[i] = VkDescriptorPoolSize{ |
| 224 | .type = std::data(types)[i], | ||
| 225 | .descriptorCount = static_cast<u32>(max_descriptors), | ||
| 226 | }; | ||
| 227 | } | ||
| 224 | 228 | ||
| 225 | return device.GetLogical().CreateDescriptorPool(VkDescriptorPoolCreateInfo{ | 229 | return device.GetLogical().CreateDescriptorPool(VkDescriptorPoolCreateInfo{ |
| 226 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 230 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| 227 | .pNext = nullptr, | 231 | .pNext = nullptr, |
| 228 | .flags = 0, | 232 | .flags = 0, |
| 229 | .maxSets = max_sets, | 233 | .maxSets = static_cast<u32>(max_sets), |
| 230 | .poolSizeCount = 1, | 234 | .poolSizeCount = static_cast<u32>(pool_sizes.size()), |
| 231 | .pPoolSizes = &pool_size, | 235 | .pPoolSizes = pool_sizes.data(), |
| 232 | }); | 236 | }); |
| 233 | } | 237 | } |
| 234 | 238 | ||
| 235 | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device, | 239 | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout( |
| 236 | u32 max_sampler_bindings) { | 240 | const Device& device, std::initializer_list<VkDescriptorType> types) { |
| 237 | std::vector<VkDescriptorSetLayoutBinding> bindings(max_sampler_bindings); | 241 | std::vector<VkDescriptorSetLayoutBinding> bindings(types.size()); |
| 238 | for (u32 i = 0; i < max_sampler_bindings; i++) { | 242 | for (size_t i = 0; i < types.size(); i++) { |
| 239 | bindings[i] = { | 243 | bindings[i] = { |
| 240 | .binding = i, | 244 | .binding = static_cast<u32>(i), |
| 241 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | 245 | .descriptorType = std::data(types)[i], |
| 242 | .descriptorCount = 1, | 246 | .descriptorCount = 1, |
| 243 | .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, | 247 | .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | |
| 248 | VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 244 | .pImmutableSamplers = nullptr, | 249 | .pImmutableSamplers = nullptr, |
| 245 | }; | 250 | }; |
| 246 | } | 251 | } |
diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h index ea9a26c3d..2f3a538fa 100644 --- a/src/video_core/renderer_vulkan/present/util.h +++ b/src/video_core/renderer_vulkan/present/util.h | |||
| @@ -25,10 +25,12 @@ vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& r | |||
| 25 | vk::ImageView& dest_image, VkExtent2D extent); | 25 | vk::ImageView& dest_image, VkExtent2D extent); |
| 26 | vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR); | 26 | vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR); |
| 27 | vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code); | 27 | vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code); |
| 28 | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_sampler_bindings, | 28 | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, size_t max_descriptors, |
| 29 | u32 max_sets); | 29 | size_t max_sets, |
| 30 | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device, | 30 | std::initializer_list<VkDescriptorType> types = { |
| 31 | u32 max_sampler_bindings); | 31 | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); |
| 32 | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout( | ||
| 33 | const Device& device, std::initializer_list<VkDescriptorType> types); | ||
| 32 | vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool, | 34 | vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool, |
| 33 | vk::Span<VkDescriptorSetLayout> layouts); | 35 | vk::Span<VkDescriptorSetLayout> layouts); |
| 34 | vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, | 36 | vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index fd7c28779..8d01ec9fc 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -234,7 +234,7 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf | |||
| 234 | }); | 234 | }); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | source_image_view = anti_alias->Draw(scheduler, image_index, source_image, source_image_view); | 237 | anti_alias->Draw(scheduler, image_index, &source_image, &source_image_view); |
| 238 | 238 | ||
| 239 | const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); | 239 | const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); |
| 240 | const VkExtent2D render_extent{ | 240 | const VkExtent2D render_extent{ |
| @@ -248,8 +248,8 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf | |||
| 248 | .height = layout.screen.GetHeight(), | 248 | .height = layout.screen.GetHeight(), |
| 249 | }; | 249 | }; |
| 250 | 250 | ||
| 251 | source_image_view = | 251 | source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, |
| 252 | fsr->Draw(scheduler, image_index, source_image_view, render_extent, crop_rect); | 252 | render_extent, crop_rect); |
| 253 | 253 | ||
| 254 | const Common::Rectangle<f32> output_crop{0, 0, 1, 1}; | 254 | const Common::Rectangle<f32> output_crop{0, 0, 1, 1}; |
| 255 | window_adapt->Draw(scheduler, image_index, source_image_view, adapt_size, output_crop, | 255 | window_adapt->Draw(scheduler, image_index, source_image_view, adapt_size, output_crop, |