VideoCore: Add gaussian filtering.
This commit is contained in:
parent
bf01b7993d
commit
9e065b9c7d
|
@ -67,8 +67,9 @@ enum class ScalingFilter : u32 {
|
||||||
NearestNeighbor = 0,
|
NearestNeighbor = 0,
|
||||||
Bilinear = 1,
|
Bilinear = 1,
|
||||||
Bicubic = 2,
|
Bicubic = 2,
|
||||||
ScaleForce = 3,
|
Gaussian = 3,
|
||||||
Fsr = 4,
|
ScaleForce = 4,
|
||||||
|
Fsr = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResolutionScalingInfo {
|
struct ResolutionScalingInfo {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Reference in New Issue