renderer_vulkan: isolate FXAA from blit screen
This commit is contained in:
parent
2b1dd3bef5
commit
9568b310be
|
@ -158,6 +158,14 @@ add_library(video_core STATIC
|
||||||
renderer_opengl/renderer_opengl.h
|
renderer_opengl/renderer_opengl.h
|
||||||
renderer_opengl/util_shaders.cpp
|
renderer_opengl/util_shaders.cpp
|
||||||
renderer_opengl/util_shaders.h
|
renderer_opengl/util_shaders.h
|
||||||
|
renderer_vulkan/present/fsr.cpp
|
||||||
|
renderer_vulkan/present/fsr.h
|
||||||
|
renderer_vulkan/present/fxaa.cpp
|
||||||
|
renderer_vulkan/present/fxaa.h
|
||||||
|
renderer_vulkan/present/smaa.cpp
|
||||||
|
renderer_vulkan/present/smaa.h
|
||||||
|
renderer_vulkan/present/util.cpp
|
||||||
|
renderer_vulkan/present/util.h
|
||||||
renderer_vulkan/blit_image.cpp
|
renderer_vulkan/blit_image.cpp
|
||||||
renderer_vulkan/blit_image.h
|
renderer_vulkan/blit_image.h
|
||||||
renderer_vulkan/fixed_pipeline_state.cpp
|
renderer_vulkan/fixed_pipeline_state.cpp
|
||||||
|
@ -184,8 +192,6 @@ add_library(video_core STATIC
|
||||||
renderer_vulkan/vk_descriptor_pool.h
|
renderer_vulkan/vk_descriptor_pool.h
|
||||||
renderer_vulkan/vk_fence_manager.cpp
|
renderer_vulkan/vk_fence_manager.cpp
|
||||||
renderer_vulkan/vk_fence_manager.h
|
renderer_vulkan/vk_fence_manager.h
|
||||||
renderer_vulkan/vk_fsr.cpp
|
|
||||||
renderer_vulkan/vk_fsr.h
|
|
||||||
renderer_vulkan/vk_graphics_pipeline.cpp
|
renderer_vulkan/vk_graphics_pipeline.cpp
|
||||||
renderer_vulkan/vk_graphics_pipeline.h
|
renderer_vulkan/vk_graphics_pipeline.h
|
||||||
renderer_vulkan/vk_master_semaphore.cpp
|
renderer_vulkan/vk_master_semaphore.cpp
|
||||||
|
@ -206,8 +212,6 @@ add_library(video_core STATIC
|
||||||
renderer_vulkan/vk_scheduler.h
|
renderer_vulkan/vk_scheduler.h
|
||||||
renderer_vulkan/vk_shader_util.cpp
|
renderer_vulkan/vk_shader_util.cpp
|
||||||
renderer_vulkan/vk_shader_util.h
|
renderer_vulkan/vk_shader_util.h
|
||||||
renderer_vulkan/vk_smaa.cpp
|
|
||||||
renderer_vulkan/vk_smaa.h
|
|
||||||
renderer_vulkan/vk_staging_buffer_pool.cpp
|
renderer_vulkan/vk_staging_buffer_pool.cpp
|
||||||
renderer_vulkan/vk_staging_buffer_pool.h
|
renderer_vulkan/vk_staging_buffer_pool.h
|
||||||
renderer_vulkan/vk_state_tracker.cpp
|
renderer_vulkan/vk_state_tracker.cpp
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
class Scheduler;
|
||||||
|
|
||||||
|
class AntiAliasPass {
|
||||||
|
public:
|
||||||
|
virtual ~AntiAliasPass() = default;
|
||||||
|
virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
|
VkImageView source_image_view) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NoAA final : public AntiAliasPass {
|
||||||
|
public:
|
||||||
|
virtual VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
|
VkImageView source_image_view) {
|
||||||
|
return source_image_view;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
|
@ -10,7 +10,7 @@
|
||||||
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h"
|
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h"
|
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h"
|
#include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h"
|
||||||
#include "video_core/renderer_vulkan/vk_fsr.h"
|
#include "video_core/renderer_vulkan/present/fsr.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
|
@ -0,0 +1,144 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
#include "video_core/host_shaders/fxaa_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/fxaa_vert_spv.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/fxaa.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/util.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
|
||||||
|
: m_device(device), m_allocator(allocator), m_extent(extent),
|
||||||
|
m_image_count(static_cast<u32>(image_count)) {
|
||||||
|
CreateImages();
|
||||||
|
CreateRenderPasses();
|
||||||
|
CreateSampler();
|
||||||
|
CreateShaders();
|
||||||
|
CreateDescriptorPool();
|
||||||
|
CreateDescriptorSetLayouts();
|
||||||
|
CreateDescriptorSets();
|
||||||
|
CreatePipelineLayouts();
|
||||||
|
CreatePipelines();
|
||||||
|
}
|
||||||
|
|
||||||
|
FXAA::~FXAA() = default;
|
||||||
|
|
||||||
|
void FXAA::CreateImages() {
|
||||||
|
for (u32 i = 0; i < m_image_count; i++) {
|
||||||
|
Image& image = m_dynamic_images.emplace_back();
|
||||||
|
|
||||||
|
image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
image.image_view =
|
||||||
|
CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateRenderPasses() {
|
||||||
|
m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
|
||||||
|
for (auto& image : m_dynamic_images) {
|
||||||
|
image.framebuffer =
|
||||||
|
CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateSampler() {
|
||||||
|
m_sampler = CreateWrappedSampler(m_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateShaders() {
|
||||||
|
m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV);
|
||||||
|
m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateDescriptorPool() {
|
||||||
|
// 2 descriptors, 1 descriptor set per image
|
||||||
|
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateDescriptorSetLayouts() {
|
||||||
|
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreateDescriptorSets() {
|
||||||
|
VkDescriptorSetLayout layout = *m_descriptor_set_layout;
|
||||||
|
|
||||||
|
for (auto& images : m_dynamic_images) {
|
||||||
|
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreatePipelineLayouts() {
|
||||||
|
m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::CreatePipelines() {
|
||||||
|
m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
|
||||||
|
std::tie(m_vertex_shader, m_fragment_shader));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
|
||||||
|
Image& image = m_dynamic_images[image_index];
|
||||||
|
std::vector<VkDescriptorImageInfo> image_infos;
|
||||||
|
std::vector<VkWriteDescriptorSet> updates;
|
||||||
|
image_infos.reserve(2);
|
||||||
|
|
||||||
|
updates.push_back(
|
||||||
|
CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0));
|
||||||
|
updates.push_back(
|
||||||
|
CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
|
||||||
|
|
||||||
|
m_device.GetLogical().UpdateDescriptorSets(updates, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FXAA::UploadImages(Scheduler& scheduler) {
|
||||||
|
if (m_images_ready) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
|
||||||
|
for (auto& image : m_dynamic_images) {
|
||||||
|
ClearColorImage(cmdbuf, *image.image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scheduler.Finish();
|
||||||
|
|
||||||
|
m_images_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
|
VkImageView source_image_view) {
|
||||||
|
const Image& image{m_dynamic_images[image_index]};
|
||||||
|
const VkImage output_image{*image.image};
|
||||||
|
const VkDescriptorSet descriptor_set{image.descriptor_sets[0]};
|
||||||
|
const VkFramebuffer framebuffer{*image.framebuffer};
|
||||||
|
const VkRenderPass renderpass{*m_renderpass};
|
||||||
|
const VkPipeline pipeline{*m_pipeline};
|
||||||
|
const VkPipelineLayout layout{*m_pipeline_layout};
|
||||||
|
const VkExtent2D extent{m_extent};
|
||||||
|
|
||||||
|
UploadImages(scheduler);
|
||||||
|
UpdateDescriptorSets(source_image_view, image_index);
|
||||||
|
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([=](vk::CommandBuffer cmdbuf) {
|
||||||
|
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
|
||||||
|
cmdbuf.Draw(4, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
return *image.image_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
|
@ -0,0 +1,63 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "video_core/renderer_vulkan/present/anti_alias_pass.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
class Scheduler;
|
||||||
|
class StagingBufferPool;
|
||||||
|
|
||||||
|
class FXAA final : public AntiAliasPass {
|
||||||
|
public:
|
||||||
|
explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
|
||||||
|
VkExtent2D extent);
|
||||||
|
~FXAA() override;
|
||||||
|
|
||||||
|
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
|
VkImageView source_image_view) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateImages();
|
||||||
|
void CreateRenderPasses();
|
||||||
|
void CreateSampler();
|
||||||
|
void CreateShaders();
|
||||||
|
void CreateDescriptorPool();
|
||||||
|
void CreateDescriptorSetLayouts();
|
||||||
|
void CreateDescriptorSets();
|
||||||
|
void CreatePipelineLayouts();
|
||||||
|
void CreatePipelines();
|
||||||
|
void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
|
||||||
|
void UploadImages(Scheduler& scheduler);
|
||||||
|
|
||||||
|
const Device& m_device;
|
||||||
|
MemoryAllocator& m_allocator;
|
||||||
|
const VkExtent2D m_extent;
|
||||||
|
const u32 m_image_count;
|
||||||
|
|
||||||
|
vk::ShaderModule m_vertex_shader{};
|
||||||
|
vk::ShaderModule m_fragment_shader{};
|
||||||
|
vk::DescriptorPool m_descriptor_pool{};
|
||||||
|
vk::DescriptorSetLayout m_descriptor_set_layout{};
|
||||||
|
vk::PipelineLayout m_pipeline_layout{};
|
||||||
|
vk::Pipeline m_pipeline{};
|
||||||
|
vk::RenderPass m_renderpass{};
|
||||||
|
|
||||||
|
struct Image {
|
||||||
|
vk::DescriptorSets descriptor_sets{};
|
||||||
|
vk::Framebuffer framebuffer{};
|
||||||
|
vk::Image image{};
|
||||||
|
vk::ImageView image_view{};
|
||||||
|
};
|
||||||
|
std::vector<Image> m_dynamic_images{};
|
||||||
|
bool m_images_ready{};
|
||||||
|
|
||||||
|
vk::Sampler m_sampler{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
|
@ -0,0 +1,270 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/polyfill_ranges.h"
|
||||||
|
|
||||||
|
#include "video_core/renderer_vulkan/present/smaa.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/util.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
|
#include "video_core/smaa_area_tex.h"
|
||||||
|
#include "video_core/smaa_search_tex.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
|
|
||||||
|
#include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h"
|
||||||
|
#include "video_core/host_shaders/smaa_edge_detection_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/smaa_edge_detection_vert_spv.h"
|
||||||
|
#include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
|
||||||
|
: m_device(device), m_allocator(allocator), m_extent(extent),
|
||||||
|
m_image_count(static_cast<u32>(image_count)) {
|
||||||
|
CreateImages();
|
||||||
|
CreateRenderPasses();
|
||||||
|
CreateSampler();
|
||||||
|
CreateShaders();
|
||||||
|
CreateDescriptorPool();
|
||||||
|
CreateDescriptorSetLayouts();
|
||||||
|
CreateDescriptorSets();
|
||||||
|
CreatePipelineLayouts();
|
||||||
|
CreatePipelines();
|
||||||
|
}
|
||||||
|
|
||||||
|
SMAA::~SMAA() = default;
|
||||||
|
|
||||||
|
void SMAA::CreateImages() {
|
||||||
|
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
|
||||||
|
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
|
||||||
|
|
||||||
|
m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM);
|
||||||
|
m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM);
|
||||||
|
|
||||||
|
m_static_image_views[Area] =
|
||||||
|
CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
|
||||||
|
m_static_image_views[Search] =
|
||||||
|
CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_image_count; i++) {
|
||||||
|
Images& images = m_dynamic_images.emplace_back();
|
||||||
|
|
||||||
|
images.images[Blend] =
|
||||||
|
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
|
||||||
|
images.images[Output] =
|
||||||
|
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
|
||||||
|
images.image_views[Blend] =
|
||||||
|
CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
images.image_views[Edges] =
|
||||||
|
CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
|
||||||
|
images.image_views[Output] =
|
||||||
|
CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateRenderPasses() {
|
||||||
|
m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT);
|
||||||
|
m_renderpasses[BlendingWeightCalculation] =
|
||||||
|
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
m_renderpasses[NeighborhoodBlending] =
|
||||||
|
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||||
|
|
||||||
|
for (auto& images : m_dynamic_images) {
|
||||||
|
images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
|
||||||
|
m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
|
||||||
|
|
||||||
|
images.framebuffers[BlendingWeightCalculation] =
|
||||||
|
CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation],
|
||||||
|
images.image_views[Blend], m_extent);
|
||||||
|
|
||||||
|
images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
|
||||||
|
m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateSampler() {
|
||||||
|
m_sampler = CreateWrappedSampler(m_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateShaders() {
|
||||||
|
// These match the order of the SMAAStage enum
|
||||||
|
static constexpr std::array vert_shader_sources{
|
||||||
|
ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV),
|
||||||
|
ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV),
|
||||||
|
ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV),
|
||||||
|
};
|
||||||
|
static constexpr std::array frag_shader_sources{
|
||||||
|
ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV),
|
||||||
|
ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV),
|
||||||
|
ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
||||||
|
m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]);
|
||||||
|
m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateDescriptorPool() {
|
||||||
|
// Edge detection: 1 descriptor
|
||||||
|
// Blending weight calculation: 3 descriptors
|
||||||
|
// Neighborhood blending: 2 descriptors
|
||||||
|
|
||||||
|
// 6 descriptors, 3 descriptor sets per image
|
||||||
|
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateDescriptorSetLayouts() {
|
||||||
|
m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1);
|
||||||
|
m_descriptor_set_layouts[BlendingWeightCalculation] =
|
||||||
|
CreateWrappedDescriptorSetLayout(m_device, 3);
|
||||||
|
m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreateDescriptorSets() {
|
||||||
|
std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size());
|
||||||
|
std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
|
||||||
|
[](auto& layout) { return *layout; });
|
||||||
|
|
||||||
|
for (auto& images : m_dynamic_images) {
|
||||||
|
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreatePipelineLayouts() {
|
||||||
|
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
||||||
|
m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::CreatePipelines() {
|
||||||
|
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
||||||
|
m_pipelines[i] =
|
||||||
|
CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i],
|
||||||
|
std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
|
||||||
|
Images& images = m_dynamic_images[image_index];
|
||||||
|
std::vector<VkDescriptorImageInfo> image_infos;
|
||||||
|
std::vector<VkWriteDescriptorSet> updates;
|
||||||
|
image_infos.reserve(6);
|
||||||
|
|
||||||
|
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
|
||||||
|
images.descriptor_sets[EdgeDetection], 0));
|
||||||
|
|
||||||
|
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges],
|
||||||
|
images.descriptor_sets[BlendingWeightCalculation],
|
||||||
|
0));
|
||||||
|
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area],
|
||||||
|
images.descriptor_sets[BlendingWeightCalculation],
|
||||||
|
1));
|
||||||
|
updates.push_back(
|
||||||
|
CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search],
|
||||||
|
images.descriptor_sets[BlendingWeightCalculation], 2));
|
||||||
|
|
||||||
|
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
|
||||||
|
images.descriptor_sets[NeighborhoodBlending], 0));
|
||||||
|
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
|
||||||
|
images.descriptor_sets[NeighborhoodBlending], 1));
|
||||||
|
|
||||||
|
m_device.GetLogical().UpdateDescriptorSets(updates, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMAA::UploadImages(Scheduler& scheduler) {
|
||||||
|
if (m_images_ready) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
|
||||||
|
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
|
||||||
|
|
||||||
|
UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent,
|
||||||
|
VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes));
|
||||||
|
UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
|
||||||
|
VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
|
||||||
|
|
||||||
|
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
|
||||||
|
for (auto& images : m_dynamic_images) {
|
||||||
|
for (size_t i = 0; i < MaxDynamicImage; i++) {
|
||||||
|
ClearColorImage(cmdbuf, *images.images[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scheduler.Finish();
|
||||||
|
|
||||||
|
m_images_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
|
VkImageView source_image_view) {
|
||||||
|
Images& images = m_dynamic_images[image_index];
|
||||||
|
|
||||||
|
VkImage output_image = *images.images[Output];
|
||||||
|
VkImage edges_image = *images.images[Edges];
|
||||||
|
VkImage blend_image = *images.images[Blend];
|
||||||
|
|
||||||
|
VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection];
|
||||||
|
VkDescriptorSet blending_weight_calculation_descriptor_set =
|
||||||
|
images.descriptor_sets[BlendingWeightCalculation];
|
||||||
|
VkDescriptorSet neighborhood_blending_descriptor_set =
|
||||||
|
images.descriptor_sets[NeighborhoodBlending];
|
||||||
|
|
||||||
|
VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection];
|
||||||
|
VkFramebuffer blending_weight_calculation_framebuffer =
|
||||||
|
*images.framebuffers[BlendingWeightCalculation];
|
||||||
|
VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
|
||||||
|
|
||||||
|
UploadImages(scheduler);
|
||||||
|
UpdateDescriptorSets(source_image_view, image_index);
|
||||||
|
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
|
||||||
|
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer,
|
||||||
|
m_extent);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
*m_pipeline_layouts[EdgeDetection], 0,
|
||||||
|
edge_detection_descriptor_set, {});
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
|
||||||
|
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
BeginRenderPass(cmdbuf, *m_renderpasses[BlendingWeightCalculation],
|
||||||
|
blending_weight_calculation_framebuffer, m_extent);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
*m_pipelines[BlendingWeightCalculation]);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
*m_pipeline_layouts[BlendingWeightCalculation], 0,
|
||||||
|
blending_weight_calculation_descriptor_set, {});
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
|
||||||
|
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
BeginRenderPass(cmdbuf, *m_renderpasses[NeighborhoodBlending],
|
||||||
|
neighborhood_blending_framebuffer, m_extent);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
*m_pipeline_layouts[NeighborhoodBlending], 0,
|
||||||
|
neighborhood_blending_descriptor_set, {});
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
return *images.image_views[Output];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include "video_core/renderer_vulkan/present/anti_alias_pass.h"
|
||||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
|
@ -13,12 +14,14 @@ class Device;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
class StagingBufferPool;
|
class StagingBufferPool;
|
||||||
|
|
||||||
class SMAA {
|
class SMAA final : public AntiAliasPass {
|
||||||
public:
|
public:
|
||||||
explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
|
explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
|
||||||
VkExtent2D extent);
|
VkExtent2D extent);
|
||||||
|
~SMAA() override;
|
||||||
|
|
||||||
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
||||||
VkImageView source_image_view);
|
VkImageView source_image_view) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum SMAAStage {
|
enum SMAAStage {
|
|
@ -1,29 +1,11 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/polyfill_ranges.h"
|
#include "common/polyfill_ranges.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/util.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_smaa.h"
|
|
||||||
#include "video_core/smaa_area_tex.h"
|
|
||||||
#include "video_core/smaa_search_tex.h"
|
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
|
||||||
|
|
||||||
#include "video_core/host_shaders/smaa_blending_weight_calculation_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/smaa_blending_weight_calculation_vert_spv.h"
|
|
||||||
#include "video_core/host_shaders/smaa_edge_detection_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/smaa_edge_detection_vert_spv.h"
|
|
||||||
#include "video_core/host_shaders/smaa_neighborhood_blending_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/smaa_neighborhood_blending_vert_spv.h"
|
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
namespace {
|
|
||||||
|
|
||||||
#define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0])))
|
|
||||||
|
|
||||||
vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) {
|
vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) {
|
||||||
const VkImageCreateInfo image_ci{
|
const VkImageCreateInfo image_ci{
|
||||||
|
@ -48,7 +30,7 @@ vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
|
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
|
||||||
VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) {
|
VkImageLayout source_layout) {
|
||||||
constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT};
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT};
|
||||||
const VkImageMemoryBarrier barrier{
|
const VkImageMemoryBarrier barrier{
|
||||||
|
@ -75,7 +57,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
|
||||||
|
|
||||||
void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
|
void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
|
||||||
vk::Image& image, VkExtent2D dimensions, VkFormat format,
|
vk::Image& image, VkExtent2D dimensions, VkFormat format,
|
||||||
std::span<const u8> initial_contents = {}) {
|
std::span<const u8> initial_contents) {
|
||||||
const VkBufferCreateInfo upload_ci = {
|
const VkBufferCreateInfo upload_ci = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -200,13 +182,13 @@ vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& r
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Sampler CreateWrappedSampler(const Device& device) {
|
vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter) {
|
||||||
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
|
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.magFilter = VK_FILTER_LINEAR,
|
.magFilter = filter,
|
||||||
.minFilter = VK_FILTER_LINEAR,
|
.minFilter = filter,
|
||||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
@ -471,12 +453,12 @@ void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) {
|
||||||
cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources);
|
cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass,
|
void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
|
||||||
VkFramebuffer framebuffer, VkExtent2D extent) {
|
VkExtent2D extent) {
|
||||||
const VkRenderPassBeginInfo renderpass_bi{
|
const VkRenderPassBeginInfo renderpass_bi{
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.renderPass = *render_pass,
|
.renderPass = render_pass,
|
||||||
.framebuffer = framebuffer,
|
.framebuffer = framebuffer,
|
||||||
.renderArea{
|
.renderArea{
|
||||||
.offset{},
|
.offset{},
|
||||||
|
@ -503,248 +485,4 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass,
|
||||||
cmdbuf.SetScissor(0, scissor);
|
cmdbuf.SetScissor(0, scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
|
||||||
|
|
||||||
SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
|
|
||||||
: m_device(device), m_allocator(allocator), m_extent(extent),
|
|
||||||
m_image_count(static_cast<u32>(image_count)) {
|
|
||||||
CreateImages();
|
|
||||||
CreateRenderPasses();
|
|
||||||
CreateSampler();
|
|
||||||
CreateShaders();
|
|
||||||
CreateDescriptorPool();
|
|
||||||
CreateDescriptorSetLayouts();
|
|
||||||
CreateDescriptorSets();
|
|
||||||
CreatePipelineLayouts();
|
|
||||||
CreatePipelines();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateImages() {
|
|
||||||
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
|
|
||||||
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
|
|
||||||
|
|
||||||
m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM);
|
|
||||||
m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM);
|
|
||||||
|
|
||||||
m_static_image_views[Area] =
|
|
||||||
CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
|
|
||||||
m_static_image_views[Search] =
|
|
||||||
CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m_image_count; i++) {
|
|
||||||
Images& images = m_dynamic_images.emplace_back();
|
|
||||||
|
|
||||||
images.images[Blend] =
|
|
||||||
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
|
|
||||||
images.images[Output] =
|
|
||||||
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
|
|
||||||
images.image_views[Blend] =
|
|
||||||
CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
images.image_views[Edges] =
|
|
||||||
CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
|
|
||||||
images.image_views[Output] =
|
|
||||||
CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateRenderPasses() {
|
|
||||||
m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT);
|
|
||||||
m_renderpasses[BlendingWeightCalculation] =
|
|
||||||
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
m_renderpasses[NeighborhoodBlending] =
|
|
||||||
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
|
|
||||||
for (auto& images : m_dynamic_images) {
|
|
||||||
images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
|
|
||||||
m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
|
|
||||||
|
|
||||||
images.framebuffers[BlendingWeightCalculation] =
|
|
||||||
CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation],
|
|
||||||
images.image_views[Blend], m_extent);
|
|
||||||
|
|
||||||
images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
|
|
||||||
m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateSampler() {
|
|
||||||
m_sampler = CreateWrappedSampler(m_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateShaders() {
|
|
||||||
// These match the order of the SMAAStage enum
|
|
||||||
static constexpr std::array vert_shader_sources{
|
|
||||||
ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV),
|
|
||||||
ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_VERT_SPV),
|
|
||||||
ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_VERT_SPV),
|
|
||||||
};
|
|
||||||
static constexpr std::array frag_shader_sources{
|
|
||||||
ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_FRAG_SPV),
|
|
||||||
ARRAY_TO_SPAN(SMAA_BLENDING_WEIGHT_CALCULATION_FRAG_SPV),
|
|
||||||
ARRAY_TO_SPAN(SMAA_NEIGHBORHOOD_BLENDING_FRAG_SPV),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
|
||||||
m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]);
|
|
||||||
m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateDescriptorPool() {
|
|
||||||
// Edge detection: 1 descriptor
|
|
||||||
// Blending weight calculation: 3 descriptors
|
|
||||||
// Neighborhood blending: 2 descriptors
|
|
||||||
|
|
||||||
// 6 descriptors, 3 descriptor sets per image
|
|
||||||
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateDescriptorSetLayouts() {
|
|
||||||
m_descriptor_set_layouts[EdgeDetection] = CreateWrappedDescriptorSetLayout(m_device, 1);
|
|
||||||
m_descriptor_set_layouts[BlendingWeightCalculation] =
|
|
||||||
CreateWrappedDescriptorSetLayout(m_device, 3);
|
|
||||||
m_descriptor_set_layouts[NeighborhoodBlending] = CreateWrappedDescriptorSetLayout(m_device, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreateDescriptorSets() {
|
|
||||||
std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size());
|
|
||||||
std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
|
|
||||||
[](auto& layout) { return *layout; });
|
|
||||||
|
|
||||||
for (auto& images : m_dynamic_images) {
|
|
||||||
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreatePipelineLayouts() {
|
|
||||||
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
|
||||||
m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::CreatePipelines() {
|
|
||||||
for (size_t i = 0; i < MaxSMAAStage; i++) {
|
|
||||||
m_pipelines[i] =
|
|
||||||
CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i],
|
|
||||||
std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
|
|
||||||
Images& images = m_dynamic_images[image_index];
|
|
||||||
std::vector<VkDescriptorImageInfo> image_infos;
|
|
||||||
std::vector<VkWriteDescriptorSet> updates;
|
|
||||||
image_infos.reserve(6);
|
|
||||||
|
|
||||||
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
|
|
||||||
images.descriptor_sets[EdgeDetection], 0));
|
|
||||||
|
|
||||||
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges],
|
|
||||||
images.descriptor_sets[BlendingWeightCalculation],
|
|
||||||
0));
|
|
||||||
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area],
|
|
||||||
images.descriptor_sets[BlendingWeightCalculation],
|
|
||||||
1));
|
|
||||||
updates.push_back(
|
|
||||||
CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search],
|
|
||||||
images.descriptor_sets[BlendingWeightCalculation], 2));
|
|
||||||
|
|
||||||
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
|
|
||||||
images.descriptor_sets[NeighborhoodBlending], 0));
|
|
||||||
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
|
|
||||||
images.descriptor_sets[NeighborhoodBlending], 1));
|
|
||||||
|
|
||||||
m_device.GetLogical().UpdateDescriptorSets(updates, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMAA::UploadImages(Scheduler& scheduler) {
|
|
||||||
if (m_images_ready) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
|
|
||||||
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
|
|
||||||
|
|
||||||
UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent,
|
|
||||||
VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes));
|
|
||||||
UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
|
|
||||||
VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
|
|
||||||
|
|
||||||
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
|
|
||||||
for (auto& images : m_dynamic_images) {
|
|
||||||
for (size_t i = 0; i < MaxDynamicImage; i++) {
|
|
||||||
ClearColorImage(cmdbuf, *images.images[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
scheduler.Finish();
|
|
||||||
|
|
||||||
m_images_ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
|
|
||||||
VkImageView source_image_view) {
|
|
||||||
Images& images = m_dynamic_images[image_index];
|
|
||||||
|
|
||||||
VkImage output_image = *images.images[Output];
|
|
||||||
VkImage edges_image = *images.images[Edges];
|
|
||||||
VkImage blend_image = *images.images[Blend];
|
|
||||||
|
|
||||||
VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection];
|
|
||||||
VkDescriptorSet blending_weight_calculation_descriptor_set =
|
|
||||||
images.descriptor_sets[BlendingWeightCalculation];
|
|
||||||
VkDescriptorSet neighborhood_blending_descriptor_set =
|
|
||||||
images.descriptor_sets[NeighborhoodBlending];
|
|
||||||
|
|
||||||
VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection];
|
|
||||||
VkFramebuffer blending_weight_calculation_framebuffer =
|
|
||||||
*images.framebuffers[BlendingWeightCalculation];
|
|
||||||
VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
|
|
||||||
|
|
||||||
UploadImages(scheduler);
|
|
||||||
UpdateDescriptorSets(source_image_view, image_index);
|
|
||||||
|
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
|
||||||
scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
|
|
||||||
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
BeginRenderPass(cmdbuf, m_renderpasses[EdgeDetection], edge_detection_framebuffer,
|
|
||||||
m_extent);
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]);
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
*m_pipeline_layouts[EdgeDetection], 0,
|
|
||||||
edge_detection_descriptor_set, {});
|
|
||||||
cmdbuf.Draw(3, 1, 0, 0);
|
|
||||||
cmdbuf.EndRenderPass();
|
|
||||||
|
|
||||||
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
BeginRenderPass(cmdbuf, m_renderpasses[BlendingWeightCalculation],
|
|
||||||
blending_weight_calculation_framebuffer, m_extent);
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
*m_pipelines[BlendingWeightCalculation]);
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
*m_pipeline_layouts[BlendingWeightCalculation], 0,
|
|
||||||
blending_weight_calculation_descriptor_set, {});
|
|
||||||
cmdbuf.Draw(3, 1, 0, 0);
|
|
||||||
cmdbuf.EndRenderPass();
|
|
||||||
|
|
||||||
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
BeginRenderPass(cmdbuf, m_renderpasses[NeighborhoodBlending],
|
|
||||||
neighborhood_blending_framebuffer, m_extent);
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]);
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
*m_pipeline_layouts[NeighborhoodBlending], 0,
|
|
||||||
neighborhood_blending_descriptor_set, {});
|
|
||||||
cmdbuf.Draw(3, 1, 0, 0);
|
|
||||||
cmdbuf.EndRenderPass();
|
|
||||||
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
});
|
|
||||||
|
|
||||||
return *images.image_views[Output];
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
|
@ -0,0 +1,46 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
#define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0])))
|
||||||
|
|
||||||
|
vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format);
|
||||||
|
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
|
||||||
|
VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
|
||||||
|
vk::Image& image, VkExtent2D dimensions, VkFormat format,
|
||||||
|
std::span<const u8> initial_contents = {});
|
||||||
|
void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image);
|
||||||
|
|
||||||
|
vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format);
|
||||||
|
vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format);
|
||||||
|
vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass,
|
||||||
|
vk::ImageView& dest_image, VkExtent2D extent);
|
||||||
|
vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR);
|
||||||
|
vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code);
|
||||||
|
vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_sampler_bindings,
|
||||||
|
u32 max_sets);
|
||||||
|
vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device,
|
||||||
|
u32 max_sampler_bindings);
|
||||||
|
vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool,
|
||||||
|
vk::Span<VkDescriptorSetLayout> layouts);
|
||||||
|
vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device,
|
||||||
|
vk::DescriptorSetLayout& layout);
|
||||||
|
vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass,
|
||||||
|
vk::PipelineLayout& layout,
|
||||||
|
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders);
|
||||||
|
VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images,
|
||||||
|
VkSampler sampler, VkImageView view,
|
||||||
|
VkDescriptorSet set, u32 binding);
|
||||||
|
|
||||||
|
void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
|
||||||
|
VkExtent2D extent);
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
|
@ -16,20 +16,19 @@
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||||
#include "video_core/host_shaders/fxaa_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/fxaa_vert_spv.h"
|
|
||||||
#include "video_core/host_shaders/present_bicubic_frag_spv.h"
|
#include "video_core/host_shaders/present_bicubic_frag_spv.h"
|
||||||
#include "video_core/host_shaders/present_gaussian_frag_spv.h"
|
#include "video_core/host_shaders/present_gaussian_frag_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_vert_spv.h"
|
#include "video_core/host_shaders/vulkan_present_vert_spv.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/fsr.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/fxaa.h"
|
||||||
|
#include "video_core/renderer_vulkan/present/smaa.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
||||||
#include "video_core/renderer_vulkan/vk_fsr.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
#include "video_core/renderer_vulkan/vk_smaa.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
#include "video_core/surface.h"
|
#include "video_core/surface.h"
|
||||||
#include "video_core/textures/decoders.h"
|
#include "video_core/textures/decoders.h"
|
||||||
|
@ -252,103 +251,17 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf
|
||||||
|
|
||||||
const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue();
|
const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue();
|
||||||
if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) {
|
if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) {
|
||||||
UpdateAADescriptorSet(source_image_view, false);
|
if (!fxaa) {
|
||||||
const u32 up_scale = Settings::values.resolution_info.up_scale;
|
const u32 up_scale = Settings::values.resolution_info.up_scale;
|
||||||
const u32 down_shift = Settings::values.resolution_info.down_shift;
|
const u32 down_shift = Settings::values.resolution_info.down_shift;
|
||||||
VkExtent2D size{
|
const VkExtent2D fxaa_size{
|
||||||
.width = (up_scale * framebuffer.width) >> down_shift,
|
.width = (up_scale * framebuffer.width) >> down_shift,
|
||||||
.height = (up_scale * framebuffer.height) >> down_shift,
|
.height = (up_scale * framebuffer.height) >> down_shift,
|
||||||
};
|
|
||||||
scheduler.Record([this, index = image_index, size,
|
|
||||||
anti_alias_pass](vk::CommandBuffer cmdbuf) {
|
|
||||||
const VkImageMemoryBarrier base_barrier{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.srcAccessMask = 0,
|
|
||||||
.dstAccessMask = 0,
|
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.image = {},
|
|
||||||
.subresourceRange =
|
|
||||||
{
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
fxaa = std::make_unique<FXAA>(device, memory_allocator, image_count, fxaa_size);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
source_image_view = fxaa->Draw(scheduler, image_index, source_image, source_image_view);
|
||||||
VkImageMemoryBarrier fsr_write_barrier = base_barrier;
|
|
||||||
fsr_write_barrier.image = *aa_image;
|
|
||||||
fsr_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, fsr_write_barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f;
|
|
||||||
const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f;
|
|
||||||
const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f;
|
|
||||||
const VkClearValue clear_color{
|
|
||||||
.color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
|
|
||||||
};
|
|
||||||
const VkRenderPassBeginInfo renderpass_bi{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.renderPass = *aa_renderpass,
|
|
||||||
.framebuffer = *aa_framebuffer,
|
|
||||||
.renderArea =
|
|
||||||
{
|
|
||||||
.offset = {0, 0},
|
|
||||||
.extent = size,
|
|
||||||
},
|
|
||||||
.clearValueCount = 1,
|
|
||||||
.pClearValues = &clear_color,
|
|
||||||
};
|
|
||||||
const VkViewport viewport{
|
|
||||||
.x = 0.0f,
|
|
||||||
.y = 0.0f,
|
|
||||||
.width = static_cast<float>(size.width),
|
|
||||||
.height = static_cast<float>(size.height),
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f,
|
|
||||||
};
|
|
||||||
const VkRect2D scissor{
|
|
||||||
.offset = {0, 0},
|
|
||||||
.extent = size,
|
|
||||||
};
|
|
||||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
switch (anti_alias_pass) {
|
|
||||||
case Settings::AntiAliasing::Fxaa:
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmdbuf.SetViewport(0, viewport);
|
|
||||||
cmdbuf.SetScissor(0, scissor);
|
|
||||||
|
|
||||||
cmdbuf.BindVertexBuffer(0, *buffer, offsetof(BufferData, vertices));
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline_layout, 0,
|
|
||||||
aa_descriptor_sets[index], {});
|
|
||||||
cmdbuf.Draw(4, 1, 0, 0);
|
|
||||||
cmdbuf.EndRenderPass();
|
|
||||||
|
|
||||||
{
|
|
||||||
VkImageMemoryBarrier blit_read_barrier = base_barrier;
|
|
||||||
blit_read_barrier.image = *aa_image;
|
|
||||||
blit_read_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
blit_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, blit_read_barrier);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
source_image_view = *aa_image_view;
|
|
||||||
}
|
}
|
||||||
if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) {
|
if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) {
|
||||||
if (!smaa) {
|
if (!smaa) {
|
||||||
|
@ -496,6 +409,7 @@ void BlitScreen::CreateDynamicResources() {
|
||||||
CreateRenderPass();
|
CreateRenderPass();
|
||||||
CreateGraphicsPipeline();
|
CreateGraphicsPipeline();
|
||||||
fsr.reset();
|
fsr.reset();
|
||||||
|
fxaa.reset();
|
||||||
smaa.reset();
|
smaa.reset();
|
||||||
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
|
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
|
||||||
CreateFSR();
|
CreateFSR();
|
||||||
|
@ -520,6 +434,7 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
raw_height = framebuffer.height;
|
raw_height = framebuffer.height;
|
||||||
pixel_format = framebuffer.pixel_format;
|
pixel_format = framebuffer.pixel_format;
|
||||||
|
|
||||||
|
fxaa.reset();
|
||||||
smaa.reset();
|
smaa.reset();
|
||||||
ReleaseRawImages();
|
ReleaseRawImages();
|
||||||
|
|
||||||
|
@ -529,8 +444,6 @@ void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
|
|
||||||
void BlitScreen::CreateShaders() {
|
void BlitScreen::CreateShaders() {
|
||||||
vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
|
vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
|
||||||
fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV);
|
|
||||||
fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV);
|
|
||||||
bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV);
|
bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV);
|
||||||
bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV);
|
bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV);
|
||||||
gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV);
|
gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV);
|
||||||
|
@ -553,13 +466,6 @@ void BlitScreen::CreateDescriptorPool() {
|
||||||
},
|
},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const std::array<VkDescriptorPoolSize, 1> pool_sizes_aa{{
|
|
||||||
{
|
|
||||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.descriptorCount = static_cast<u32>(image_count * 2),
|
|
||||||
},
|
|
||||||
}};
|
|
||||||
|
|
||||||
const VkDescriptorPoolCreateInfo ci{
|
const VkDescriptorPoolCreateInfo ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -569,16 +475,6 @@ void BlitScreen::CreateDescriptorPool() {
|
||||||
.pPoolSizes = pool_sizes.data(),
|
.pPoolSizes = pool_sizes.data(),
|
||||||
};
|
};
|
||||||
descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
|
descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
|
||||||
|
|
||||||
const VkDescriptorPoolCreateInfo ci_aa{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.maxSets = static_cast<u32>(image_count),
|
|
||||||
.poolSizeCount = static_cast<u32>(pool_sizes_aa.size()),
|
|
||||||
.pPoolSizes = pool_sizes_aa.data(),
|
|
||||||
};
|
|
||||||
aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::CreateRenderPass() {
|
void BlitScreen::CreateRenderPass() {
|
||||||
|
@ -659,23 +555,6 @@ void BlitScreen::CreateDescriptorSetLayout() {
|
||||||
},
|
},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings_aa{{
|
|
||||||
{
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
.pImmutableSamplers = nullptr,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.binding = 1,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
||||||
.pImmutableSamplers = nullptr,
|
|
||||||
},
|
|
||||||
}};
|
|
||||||
|
|
||||||
const VkDescriptorSetLayoutCreateInfo ci{
|
const VkDescriptorSetLayoutCreateInfo ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -684,21 +563,11 @@ void BlitScreen::CreateDescriptorSetLayout() {
|
||||||
.pBindings = layout_bindings.data(),
|
.pBindings = layout_bindings.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const VkDescriptorSetLayoutCreateInfo ci_aa{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.bindingCount = static_cast<u32>(layout_bindings_aa.size()),
|
|
||||||
.pBindings = layout_bindings_aa.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
|
descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
|
||||||
aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::CreateDescriptorSets() {
|
void BlitScreen::CreateDescriptorSets() {
|
||||||
const std::vector layouts(image_count, *descriptor_set_layout);
|
const std::vector layouts(image_count, *descriptor_set_layout);
|
||||||
const std::vector layouts_aa(image_count, *aa_descriptor_set_layout);
|
|
||||||
|
|
||||||
const VkDescriptorSetAllocateInfo ai{
|
const VkDescriptorSetAllocateInfo ai{
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
@ -708,16 +577,7 @@ void BlitScreen::CreateDescriptorSets() {
|
||||||
.pSetLayouts = layouts.data(),
|
.pSetLayouts = layouts.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const VkDescriptorSetAllocateInfo ai_aa{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.descriptorPool = *aa_descriptor_pool,
|
|
||||||
.descriptorSetCount = static_cast<u32>(image_count),
|
|
||||||
.pSetLayouts = layouts_aa.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
descriptor_sets = descriptor_pool.Allocate(ai);
|
descriptor_sets = descriptor_pool.Allocate(ai);
|
||||||
aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::CreatePipelineLayout() {
|
void BlitScreen::CreatePipelineLayout() {
|
||||||
|
@ -730,17 +590,7 @@ void BlitScreen::CreatePipelineLayout() {
|
||||||
.pushConstantRangeCount = 0,
|
.pushConstantRangeCount = 0,
|
||||||
.pPushConstantRanges = nullptr,
|
.pPushConstantRanges = nullptr,
|
||||||
};
|
};
|
||||||
const VkPipelineLayoutCreateInfo ci_aa{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.setLayoutCount = 1,
|
|
||||||
.pSetLayouts = aa_descriptor_set_layout.address(),
|
|
||||||
.pushConstantRangeCount = 0,
|
|
||||||
.pPushConstantRanges = nullptr,
|
|
||||||
};
|
|
||||||
pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
|
pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
|
||||||
aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::CreateGraphicsPipeline() {
|
void BlitScreen::CreateGraphicsPipeline() {
|
||||||
|
@ -1068,8 +918,6 @@ void BlitScreen::ReleaseRawImages() {
|
||||||
scheduler.Wait(tick);
|
scheduler.Wait(tick);
|
||||||
}
|
}
|
||||||
raw_images.clear();
|
raw_images.clear();
|
||||||
aa_image_view.reset();
|
|
||||||
aa_image.reset();
|
|
||||||
buffer.reset();
|
buffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,198 +998,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
raw_images[i] = create_image();
|
raw_images[i] = create_image();
|
||||||
raw_image_views[i] = create_image_view(raw_images[i]);
|
raw_image_views[i] = create_image_view(raw_images[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AA Resources
|
|
||||||
const u32 up_scale = Settings::values.resolution_info.up_scale;
|
|
||||||
const u32 down_shift = Settings::values.resolution_info.down_shift;
|
|
||||||
aa_image = create_image(true, up_scale, down_shift);
|
|
||||||
aa_image_view = create_image_view(aa_image, true);
|
|
||||||
VkExtent2D size{
|
|
||||||
.width = (up_scale * framebuffer.width) >> down_shift,
|
|
||||||
.height = (up_scale * framebuffer.height) >> down_shift,
|
|
||||||
};
|
|
||||||
if (aa_renderpass) {
|
|
||||||
aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aa_renderpass = CreateRenderPassImpl(VK_FORMAT_R16G16B16A16_SFLOAT);
|
|
||||||
aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass);
|
|
||||||
|
|
||||||
const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{
|
|
||||||
{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
.module = *fxaa_vertex_shader,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
||||||
.module = *fxaa_fragment_shader,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr,
|
|
||||||
},
|
|
||||||
}};
|
|
||||||
|
|
||||||
const auto vertex_binding_description = ScreenRectVertex::GetDescription();
|
|
||||||
const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
|
|
||||||
|
|
||||||
const VkPipelineVertexInputStateCreateInfo vertex_input_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.vertexBindingDescriptionCount = 1,
|
|
||||||
.pVertexBindingDescriptions = &vertex_binding_description,
|
|
||||||
.vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()},
|
|
||||||
.pVertexAttributeDescriptions = vertex_attrs_description.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
|
||||||
.primitiveRestartEnable = VK_FALSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineViewportStateCreateInfo viewport_state_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.viewportCount = 1,
|
|
||||||
.pViewports = nullptr,
|
|
||||||
.scissorCount = 1,
|
|
||||||
.pScissors = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineRasterizationStateCreateInfo rasterization_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.depthClampEnable = VK_FALSE,
|
|
||||||
.rasterizerDiscardEnable = VK_FALSE,
|
|
||||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
||||||
.cullMode = VK_CULL_MODE_NONE,
|
|
||||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
|
||||||
.depthBiasEnable = VK_FALSE,
|
|
||||||
.depthBiasConstantFactor = 0.0f,
|
|
||||||
.depthBiasClamp = 0.0f,
|
|
||||||
.depthBiasSlopeFactor = 0.0f,
|
|
||||||
.lineWidth = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineMultisampleStateCreateInfo multisampling_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
.sampleShadingEnable = VK_FALSE,
|
|
||||||
.minSampleShading = 0.0f,
|
|
||||||
.pSampleMask = nullptr,
|
|
||||||
.alphaToCoverageEnable = VK_FALSE,
|
|
||||||
.alphaToOneEnable = VK_FALSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineColorBlendAttachmentState color_blend_attachment{
|
|
||||||
.blendEnable = VK_FALSE,
|
|
||||||
.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
|
||||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
|
||||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
|
||||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
|
||||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
|
||||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
|
||||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
|
||||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkPipelineColorBlendStateCreateInfo color_blend_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.logicOpEnable = VK_FALSE,
|
|
||||||
.logicOp = VK_LOGIC_OP_COPY,
|
|
||||||
.attachmentCount = 1,
|
|
||||||
.pAttachments = &color_blend_attachment,
|
|
||||||
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr std::array dynamic_states{
|
|
||||||
VK_DYNAMIC_STATE_VIEWPORT,
|
|
||||||
VK_DYNAMIC_STATE_SCISSOR,
|
|
||||||
};
|
|
||||||
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
|
|
||||||
.pDynamicStates = dynamic_states.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkGraphicsPipelineCreateInfo fxaa_pipeline_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stageCount = static_cast<u32>(fxaa_shader_stages.size()),
|
|
||||||
.pStages = fxaa_shader_stages.data(),
|
|
||||||
.pVertexInputState = &vertex_input_ci,
|
|
||||||
.pInputAssemblyState = &input_assembly_ci,
|
|
||||||
.pTessellationState = nullptr,
|
|
||||||
.pViewportState = &viewport_state_ci,
|
|
||||||
.pRasterizationState = &rasterization_ci,
|
|
||||||
.pMultisampleState = &multisampling_ci,
|
|
||||||
.pDepthStencilState = nullptr,
|
|
||||||
.pColorBlendState = &color_blend_ci,
|
|
||||||
.pDynamicState = &dynamic_state_ci,
|
|
||||||
.layout = *aa_pipeline_layout,
|
|
||||||
.renderPass = *aa_renderpass,
|
|
||||||
.subpass = 0,
|
|
||||||
.basePipelineHandle = 0,
|
|
||||||
.basePipelineIndex = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// AA
|
|
||||||
aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitScreen::UpdateAADescriptorSet(VkImageView image_view, bool nn) const {
|
|
||||||
const VkDescriptorImageInfo image_info{
|
|
||||||
.sampler = nn ? *nn_sampler : *sampler,
|
|
||||||
.imageView = image_view,
|
|
||||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkWriteDescriptorSet sampler_write{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.dstSet = aa_descriptor_sets[image_index],
|
|
||||||
.dstBinding = 0,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.pImageInfo = &image_info,
|
|
||||||
.pBufferInfo = nullptr,
|
|
||||||
.pTexelBufferView = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VkWriteDescriptorSet sampler_write_2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.dstSet = aa_descriptor_sets[image_index],
|
|
||||||
.dstBinding = 1,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.pImageInfo = &image_info,
|
|
||||||
.pBufferInfo = nullptr,
|
|
||||||
.pTexelBufferView = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::UpdateDescriptorSet(VkImageView image_view, bool nn) const {
|
void BlitScreen::UpdateDescriptorSet(VkImageView image_view, bool nn) const {
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace Vulkan {
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
class FSR;
|
class FSR;
|
||||||
|
class FXAA;
|
||||||
class RasterizerVulkan;
|
class RasterizerVulkan;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
class SMAA;
|
class SMAA;
|
||||||
|
@ -96,7 +97,6 @@ private:
|
||||||
void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
|
void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
void UpdateDescriptorSet(VkImageView image_view, bool nn) const;
|
void UpdateDescriptorSet(VkImageView image_view, bool nn) const;
|
||||||
void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
|
|
||||||
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
|
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
|
||||||
void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
||||||
const Layout::FramebufferLayout layout, u32 texture_width,
|
const Layout::FramebufferLayout layout, u32 texture_width,
|
||||||
|
@ -119,8 +119,6 @@ private:
|
||||||
std::size_t image_index{};
|
std::size_t image_index{};
|
||||||
|
|
||||||
vk::ShaderModule vertex_shader;
|
vk::ShaderModule vertex_shader;
|
||||||
vk::ShaderModule fxaa_vertex_shader;
|
|
||||||
vk::ShaderModule fxaa_fragment_shader;
|
|
||||||
vk::ShaderModule bilinear_fragment_shader;
|
vk::ShaderModule bilinear_fragment_shader;
|
||||||
vk::ShaderModule bicubic_fragment_shader;
|
vk::ShaderModule bicubic_fragment_shader;
|
||||||
vk::ShaderModule gaussian_fragment_shader;
|
vk::ShaderModule gaussian_fragment_shader;
|
||||||
|
@ -128,7 +126,6 @@ private:
|
||||||
vk::DescriptorPool descriptor_pool;
|
vk::DescriptorPool descriptor_pool;
|
||||||
vk::DescriptorSetLayout descriptor_set_layout;
|
vk::DescriptorSetLayout descriptor_set_layout;
|
||||||
vk::PipelineLayout pipeline_layout;
|
vk::PipelineLayout pipeline_layout;
|
||||||
vk::Pipeline nearest_neighbor_pipeline;
|
|
||||||
vk::Pipeline bilinear_pipeline;
|
vk::Pipeline bilinear_pipeline;
|
||||||
vk::Pipeline bicubic_pipeline;
|
vk::Pipeline bicubic_pipeline;
|
||||||
vk::Pipeline gaussian_pipeline;
|
vk::Pipeline gaussian_pipeline;
|
||||||
|
@ -145,16 +142,6 @@ private:
|
||||||
std::vector<vk::Image> raw_images;
|
std::vector<vk::Image> raw_images;
|
||||||
std::vector<vk::ImageView> raw_image_views;
|
std::vector<vk::ImageView> raw_image_views;
|
||||||
|
|
||||||
vk::DescriptorPool aa_descriptor_pool;
|
|
||||||
vk::DescriptorSetLayout aa_descriptor_set_layout;
|
|
||||||
vk::PipelineLayout aa_pipeline_layout;
|
|
||||||
vk::Pipeline aa_pipeline;
|
|
||||||
vk::RenderPass aa_renderpass;
|
|
||||||
vk::Framebuffer aa_framebuffer;
|
|
||||||
vk::DescriptorSets aa_descriptor_sets;
|
|
||||||
vk::Image aa_image;
|
|
||||||
vk::ImageView aa_image_view;
|
|
||||||
|
|
||||||
u32 raw_width = 0;
|
u32 raw_width = 0;
|
||||||
u32 raw_height = 0;
|
u32 raw_height = 0;
|
||||||
Service::android::PixelFormat pixel_format{};
|
Service::android::PixelFormat pixel_format{};
|
||||||
|
@ -163,6 +150,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<FSR> fsr;
|
std::unique_ptr<FSR> fsr;
|
||||||
std::unique_ptr<SMAA> smaa;
|
std::unique_ptr<SMAA> smaa;
|
||||||
|
std::unique_ptr<FXAA> fxaa;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
Reference in New Issue