VideoCore: Add gaussian filtering.
This commit is contained in:
		 FernandoS27
					FernandoS27
				
			
				
					committed by
					
						 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
			
				
	
			
			
			 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
						parent
						
							bf01b7993d
						
					
				
				
					commit
					9e065b9c7d
				
			| @@ -19,6 +19,7 @@ set(SHADER_FILES | ||||
|     pitch_unswizzle.comp | ||||
|     present_scaleforce.frag | ||||
|     present_bicubic.frag | ||||
|     present_gaussian.frag | ||||
|     vulkan_blit_color_float.frag | ||||
|     vulkan_blit_depth_stencil.frag | ||||
|     vulkan_fidelityfx_fsr_easu.comp | ||||
|   | ||||
							
								
								
									
										74
									
								
								src/video_core/host_shaders/present_gaussian.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/video_core/host_shaders/present_gaussian.frag
									
									
									
									
									
										Normal file
									
								
							| @@ -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_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_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 = | ||||
|         CreateProgram(HostShaders::PRESENT_SCALEFORCE_FRAG, GL_FRAGMENT_SHADER); | ||||
|  | ||||
| @@ -359,6 +361,9 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||
|     case Settings::ScalingFilter::Bicubic: | ||||
|         fragment_handle = present_bicubic_fragment.handle; | ||||
|         break; | ||||
|     case Settings::ScalingFilter::Gaussian: | ||||
|         fragment_handle = present_gaussian_fragment.handle; | ||||
|         break; | ||||
|     case Settings::ScalingFilter::ScaleForce: | ||||
|         fragment_handle = present_scaleforce_fragment.handle; | ||||
|         break; | ||||
|   | ||||
| @@ -114,6 +114,7 @@ private: | ||||
|     OGLProgram present_vertex; | ||||
|     OGLProgram present_bilinear_fragment; | ||||
|     OGLProgram present_bicubic_fragment; | ||||
|     OGLProgram present_gaussian_fragment; | ||||
|     OGLProgram present_scaleforce_fragment; | ||||
|     OGLFramebuffer screenshot_framebuffer; | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "core/memory.h" | ||||
| #include "video_core/gpu.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/vulkan_present_frag_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: | ||||
|                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline); | ||||
|                 break; | ||||
|             case Settings::ScalingFilter::Gaussian: | ||||
|                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline); | ||||
|                 break; | ||||
|             case Settings::ScalingFilter::ScaleForce: | ||||
|                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline); | ||||
|                 break; | ||||
| @@ -388,6 +392,7 @@ void VKBlitScreen::CreateShaders() { | ||||
|     vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); | ||||
|     bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_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); | ||||
| } | ||||
|  | ||||
| @@ -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{{ | ||||
|         { | ||||
|             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||
| @@ -733,6 +759,28 @@ void VKBlitScreen::CreateGraphicsPipeline() { | ||||
|         .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{ | ||||
|         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
| @@ -757,6 +805,7 @@ void VKBlitScreen::CreateGraphicsPipeline() { | ||||
|  | ||||
|     bilinear_pipeline = device.GetLogical().CreateGraphicsPipeline(bilinear_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); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -111,6 +111,7 @@ private: | ||||
|     vk::ShaderModule vertex_shader; | ||||
|     vk::ShaderModule bilinear_fragment_shader; | ||||
|     vk::ShaderModule bicubic_fragment_shader; | ||||
|     vk::ShaderModule gaussian_fragment_shader; | ||||
|     vk::ShaderModule scaleforce_fragment_shader; | ||||
|     vk::DescriptorPool descriptor_pool; | ||||
|     vk::DescriptorSetLayout descriptor_set_layout; | ||||
| @@ -118,6 +119,7 @@ private: | ||||
|     vk::Pipeline nearest_neightbor_pipeline; | ||||
|     vk::Pipeline bilinear_pipeline; | ||||
|     vk::Pipeline bicubic_pipeline; | ||||
|     vk::Pipeline gaussian_pipeline; | ||||
|     vk::Pipeline scaleforce_pipeline; | ||||
|     vk::RenderPass renderpass; | ||||
|     std::vector<vk::Framebuffer> framebuffers; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user