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

VideoCore: Add gaussian filtering.

FernandoS27 4 лет назад
Родитель
Сommit
9e065b9c7d

+ 3 - 2
src/common/settings.h

@@ -67,8 +67,9 @@ enum class ScalingFilter : u32 {
     NearestNeighbor = 0,
     NearestNeighbor = 0,
     Bilinear = 1,
     Bilinear = 1,
     Bicubic = 2,
     Bicubic = 2,
-    ScaleForce = 3,
-    Fsr = 4,
+    Gaussian = 3,
+    ScaleForce = 4,
+    Fsr = 5,
 };
 };
 
 
 struct ResolutionScalingInfo {
 struct ResolutionScalingInfo {

+ 1 - 0
src/video_core/host_shaders/CMakeLists.txt

@@ -19,6 +19,7 @@ set(SHADER_FILES
     pitch_unswizzle.comp
     pitch_unswizzle.comp
     present_scaleforce.frag
     present_scaleforce.frag
     present_bicubic.frag
     present_bicubic.frag
+    present_gaussian.frag
     vulkan_blit_color_float.frag
     vulkan_blit_color_float.frag
     vulkan_blit_depth_stencil.frag
     vulkan_blit_depth_stencil.frag
     vulkan_fidelityfx_fsr_easu.comp
     vulkan_fidelityfx_fsr_easu.comp

+ 74 - 0
src/video_core/host_shaders/present_gaussian.frag

@@ -0,0 +1,74 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#version 460 core
+
+#ifdef VULKAN
+
+#define BINDING_COLOR_TEXTURE 1
+
+#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
+
+#define BINDING_COLOR_TEXTURE 0
+
+#endif
+
+layout (location = 0) in vec2 frag_tex_coord;
+
+layout (location = 0) out vec4 color;
+
+layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D color_texture;
+
+const float offset[3] = float[](0.0, 1.3846153846, 3.2307692308);
+const float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703);
+
+vec4 blurVertical(sampler2D textureSampler, vec2 coord, vec2 norm) {
+    vec4 result = vec4(0.0f);
+    for (int i=1; i<3; i++) {
+        result +=
+            texture(textureSampler, vec2(coord) + (vec2(0.0, offset[i]) * norm))
+                * weight[i];
+        result +=
+            texture(textureSampler, vec2(coord) - (vec2(0.0, offset[i]) * norm))
+                * weight[i];
+    }
+    return result;
+}
+
+vec4 blurHorizontal(sampler2D textureSampler, vec2 coord, vec2 norm) {
+    vec4 result = vec4(0.0f);
+    for (int i=1; i<3; i++) {
+        result +=
+            texture(textureSampler, vec2(coord) + (vec2(offset[i], 0.0) * norm))
+                * weight[i];
+        result +=
+            texture(textureSampler, vec2(coord) - (vec2(offset[i], 0.0) * norm))
+                * weight[i];
+    }
+    return result;
+}
+
+vec4 blurDiagonal(sampler2D textureSampler, vec2 coord, vec2 norm) {
+    vec4 result = vec4(0.0f);
+    for (int i=1; i<3; i++) {
+        result +=
+            texture(textureSampler, vec2(coord) + (vec2(offset[i], offset[i]) * norm))
+                * weight[i];
+        result +=
+            texture(textureSampler, vec2(coord) - (vec2(offset[i], offset[i]) * norm))
+                * weight[i];
+    }
+    return result;
+}
+
+void main() {
+    vec3 base = texture(color_texture, vec2(frag_tex_coord)).rgb * weight[0];
+    vec2 tex_offset = 1.0f / textureSize(color_texture, 0);
+    vec3 horizontal = blurHorizontal(color_texture, frag_tex_coord, tex_offset).rgb;
+    vec3 vertical = blurVertical(color_texture, frag_tex_coord, tex_offset).rgb;
+    vec3 diagonalA = blurVertical(color_texture, frag_tex_coord, tex_offset).rgb;
+    vec3 diagonalB = blurVertical(color_texture, frag_tex_coord, -tex_offset).rgb;
+    vec3 combination = mix(mix(horizontal, vertical, 0.5f), mix(diagonalA, diagonalB, 0.5f), 0.5f);
+    color = vec4(combination + base, 1.0f);
+}

+ 5 - 0
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -256,6 +256,8 @@ void RendererOpenGL::InitOpenGLObjects() {
     present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
     present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
     present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
     present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
     present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
     present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
+    present_gaussian_fragment =
+        CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER);
     present_scaleforce_fragment =
     present_scaleforce_fragment =
         CreateProgram(HostShaders::PRESENT_SCALEFORCE_FRAG, GL_FRAGMENT_SHADER);
         CreateProgram(HostShaders::PRESENT_SCALEFORCE_FRAG, GL_FRAGMENT_SHADER);
 
 
@@ -359,6 +361,9 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
     case Settings::ScalingFilter::Bicubic:
     case Settings::ScalingFilter::Bicubic:
         fragment_handle = present_bicubic_fragment.handle;
         fragment_handle = present_bicubic_fragment.handle;
         break;
         break;
+    case Settings::ScalingFilter::Gaussian:
+        fragment_handle = present_gaussian_fragment.handle;
+        break;
     case Settings::ScalingFilter::ScaleForce:
     case Settings::ScalingFilter::ScaleForce:
         fragment_handle = present_scaleforce_fragment.handle;
         fragment_handle = present_scaleforce_fragment.handle;
         break;
         break;

+ 1 - 0
src/video_core/renderer_opengl/renderer_opengl.h

@@ -114,6 +114,7 @@ private:
     OGLProgram present_vertex;
     OGLProgram present_vertex;
     OGLProgram present_bilinear_fragment;
     OGLProgram present_bilinear_fragment;
     OGLProgram present_bicubic_fragment;
     OGLProgram present_bicubic_fragment;
+    OGLProgram present_gaussian_fragment;
     OGLProgram present_scaleforce_fragment;
     OGLProgram present_scaleforce_fragment;
     OGLFramebuffer screenshot_framebuffer;
     OGLFramebuffer screenshot_framebuffer;
 
 

+ 49 - 0
src/video_core/renderer_vulkan/vk_blit_screen.cpp

@@ -18,6 +18,7 @@
 #include "core/memory.h"
 #include "core/memory.h"
 #include "video_core/gpu.h"
 #include "video_core/gpu.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_scaleforce_frag_spv.h"
 #include "video_core/host_shaders/present_scaleforce_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_vert_spv.h"
 #include "video_core/host_shaders/vulkan_present_vert_spv.h"
@@ -297,6 +298,9 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
             case Settings::ScalingFilter::Bicubic:
             case Settings::ScalingFilter::Bicubic:
                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline);
                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline);
                 break;
                 break;
+            case Settings::ScalingFilter::Gaussian:
+                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline);
+                break;
             case Settings::ScalingFilter::ScaleForce:
             case Settings::ScalingFilter::ScaleForce:
                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline);
                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline);
                 break;
                 break;
@@ -388,6 +392,7 @@ void VKBlitScreen::CreateShaders() {
     vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
     vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_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);
     scaleforce_fragment_shader = BuildShader(device, PRESENT_SCALEFORCE_FRAG_SPV);
     scaleforce_fragment_shader = BuildShader(device, PRESENT_SCALEFORCE_FRAG_SPV);
 }
 }
 
 
@@ -574,6 +579,27 @@ void VKBlitScreen::CreateGraphicsPipeline() {
         },
         },
     }};
     }};
 
 
+    const std::array<VkPipelineShaderStageCreateInfo, 2> gaussian_shader_stages{{
+        {
+            .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+            .pNext = nullptr,
+            .flags = 0,
+            .stage = VK_SHADER_STAGE_VERTEX_BIT,
+            .module = *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 = *gaussian_fragment_shader,
+            .pName = "main",
+            .pSpecializationInfo = nullptr,
+        },
+    }};
+
     const std::array<VkPipelineShaderStageCreateInfo, 2> scaleforce_shader_stages{{
     const std::array<VkPipelineShaderStageCreateInfo, 2> scaleforce_shader_stages{{
         {
         {
             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
@@ -733,6 +759,28 @@ void VKBlitScreen::CreateGraphicsPipeline() {
         .basePipelineIndex = 0,
         .basePipelineIndex = 0,
     };
     };
 
 
+    const VkGraphicsPipelineCreateInfo gaussian_pipeline_ci{
+        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+        .pNext = nullptr,
+        .flags = 0,
+        .stageCount = static_cast<u32>(gaussian_shader_stages.size()),
+        .pStages = gaussian_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 = *pipeline_layout,
+        .renderPass = *renderpass,
+        .subpass = 0,
+        .basePipelineHandle = 0,
+        .basePipelineIndex = 0,
+    };
+
     const VkGraphicsPipelineCreateInfo scaleforce_pipeline_ci{
     const VkGraphicsPipelineCreateInfo scaleforce_pipeline_ci{
         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
         .pNext = nullptr,
         .pNext = nullptr,
@@ -757,6 +805,7 @@ void VKBlitScreen::CreateGraphicsPipeline() {
 
 
     bilinear_pipeline = device.GetLogical().CreateGraphicsPipeline(bilinear_pipeline_ci);
     bilinear_pipeline = device.GetLogical().CreateGraphicsPipeline(bilinear_pipeline_ci);
     bicubic_pipeline = device.GetLogical().CreateGraphicsPipeline(bicubic_pipeline_ci);
     bicubic_pipeline = device.GetLogical().CreateGraphicsPipeline(bicubic_pipeline_ci);
+    gaussian_pipeline = device.GetLogical().CreateGraphicsPipeline(gaussian_pipeline_ci);
     scaleforce_pipeline = device.GetLogical().CreateGraphicsPipeline(scaleforce_pipeline_ci);
     scaleforce_pipeline = device.GetLogical().CreateGraphicsPipeline(scaleforce_pipeline_ci);
 }
 }
 
 

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

@@ -111,6 +111,7 @@ private:
     vk::ShaderModule vertex_shader;
     vk::ShaderModule vertex_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 scaleforce_fragment_shader;
     vk::ShaderModule scaleforce_fragment_shader;
     vk::DescriptorPool descriptor_pool;
     vk::DescriptorPool descriptor_pool;
     vk::DescriptorSetLayout descriptor_set_layout;
     vk::DescriptorSetLayout descriptor_set_layout;
@@ -118,6 +119,7 @@ private:
     vk::Pipeline nearest_neightbor_pipeline;
     vk::Pipeline nearest_neightbor_pipeline;
     vk::Pipeline bilinear_pipeline;
     vk::Pipeline bilinear_pipeline;
     vk::Pipeline bicubic_pipeline;
     vk::Pipeline bicubic_pipeline;
+    vk::Pipeline gaussian_pipeline;
     vk::Pipeline scaleforce_pipeline;
     vk::Pipeline scaleforce_pipeline;
     vk::RenderPass renderpass;
     vk::RenderPass renderpass;
     std::vector<vk::Framebuffer> framebuffers;
     std::vector<vk::Framebuffer> framebuffers;

+ 5 - 0
src/yuzu/configuration/configure_graphics.ui

@@ -417,6 +417,11 @@
                <string>Bicubic</string>
                <string>Bicubic</string>
               </property>
               </property>
              </item>
              </item>
+             <item>
+              <property name="text">
+               <string>Gaussian</string>
+              </property>
+             </item>
              <item>
              <item>
               <property name="text">
               <property name="text">
                <string>ScaleForce</string>
                <string>ScaleForce</string>