forked from eden-emu/eden
		
	video_core: Integrate SMAA
Co-authored-by: goldenx86 <goldenx86@users.noreply.github.com> Co-authored-by: BreadFish64 <breadfish64@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									41461514d6
								
							
						
					
					
						commit
						5b837157bd
					
				
					 24 changed files with 13894 additions and 28 deletions
				
			
		|  | @ -76,7 +76,8 @@ enum class ScalingFilter : u32 { | ||||||
| enum class AntiAliasing : u32 { | enum class AntiAliasing : u32 { | ||||||
|     None = 0, |     None = 0, | ||||||
|     Fxaa = 1, |     Fxaa = 1, | ||||||
|     LastAA = Fxaa, |     Smaa = 2, | ||||||
|  |     LastAA = Smaa, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ResolutionScalingInfo { | struct ResolutionScalingInfo { | ||||||
|  |  | ||||||
|  | @ -178,6 +178,8 @@ 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 | ||||||
|  | @ -195,6 +197,8 @@ add_library(video_core STATIC | ||||||
|     shader_environment.h |     shader_environment.h | ||||||
|     shader_notify.cpp |     shader_notify.cpp | ||||||
|     shader_notify.h |     shader_notify.h | ||||||
|  |     smaa_area_tex.h | ||||||
|  |     smaa_search_tex.h | ||||||
|     surface.cpp |     surface.cpp | ||||||
|     surface.h |     surface.h | ||||||
|     texture_cache/accelerated_swizzle.cpp |     texture_cache/accelerated_swizzle.cpp | ||||||
|  |  | ||||||
|  | @ -26,9 +26,16 @@ set(SHADER_FILES | ||||||
|     opengl_present.frag |     opengl_present.frag | ||||||
|     opengl_present.vert |     opengl_present.vert | ||||||
|     opengl_present_scaleforce.frag |     opengl_present_scaleforce.frag | ||||||
|  |     opengl_smaa.glsl | ||||||
|     pitch_unswizzle.comp |     pitch_unswizzle.comp | ||||||
|     present_bicubic.frag |     present_bicubic.frag | ||||||
|     present_gaussian.frag |     present_gaussian.frag | ||||||
|  |     smaa_edge_detection.vert | ||||||
|  |     smaa_edge_detection.frag | ||||||
|  |     smaa_blending_weight_calculation.vert | ||||||
|  |     smaa_blending_weight_calculation.frag | ||||||
|  |     smaa_neighborhood_blending.vert | ||||||
|  |     smaa_neighborhood_blending.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_fp16.comp |     vulkan_fidelityfx_fsr_easu_fp16.comp | ||||||
|  |  | ||||||
|  | @ -11,10 +11,6 @@ string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | ||||||
| 
 | 
 | ||||||
| FILE(READ ${SOURCE_FILE} line_contents) | FILE(READ ${SOURCE_FILE} line_contents) | ||||||
| 
 | 
 | ||||||
| # Replace double quotes with single quotes, |  | ||||||
| # as double quotes will be used to wrap the lines |  | ||||||
| STRING(REGEX REPLACE "\"" "'" line_contents "${line_contents}") |  | ||||||
| 
 |  | ||||||
| # CMake separates list elements with semicolons, but semicolons | # CMake separates list elements with semicolons, but semicolons | ||||||
| # are used extensively in the shader code. | # are used extensively in the shader code. | ||||||
| # Replace with a temporary marker, to be reverted later. | # Replace with a temporary marker, to be reverted later. | ||||||
|  | @ -25,7 +21,7 @@ STRING(REGEX REPLACE "\n" ";" line_contents "${line_contents}") | ||||||
| 
 | 
 | ||||||
| # Build the shader string, wrapping each line in double quotes. | # Build the shader string, wrapping each line in double quotes. | ||||||
| foreach(line IN LISTS line_contents) | foreach(line IN LISTS line_contents) | ||||||
|     string(CONCAT CONTENTS "${CONTENTS}" \"${line}\\n\"\n) |     string(CONCAT CONTENTS "${CONTENTS}" "R\"(${line}\n)\" ") | ||||||
| endforeach() | endforeach() | ||||||
| 
 | 
 | ||||||
| # Revert the original semicolons in the source. | # Revert the original semicolons in the source. | ||||||
|  |  | ||||||
							
								
								
									
										1339
									
								
								src/video_core/host_shaders/opengl_smaa.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1339
									
								
								src/video_core/host_shaders/opengl_smaa.glsl
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D edges_tex; | ||||||
|  | layout (binding = 1) uniform sampler2D area_tex; | ||||||
|  | layout (binding = 2) uniform sampler2D search_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) in vec2 tex_coord; | ||||||
|  | layout (location = 1) in vec2 pix_coord; | ||||||
|  | layout (location = 2) in vec4 offset[3]; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec4 frag_color; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(edges_tex, 0), textureSize(edges_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 0 | ||||||
|  | #define SMAA_INCLUDE_PS 1 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     frag_color = SMAABlendingWeightCalculationPS(tex_coord, | ||||||
|  |                                        pix_coord, | ||||||
|  |                                        offset, | ||||||
|  |                                        edges_tex, | ||||||
|  |                                        area_tex, | ||||||
|  |                                        search_tex, | ||||||
|  |                                        vec4(0) | ||||||
|  |                                        ); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,43 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | #ifdef VULKAN | ||||||
|  | #define VERTEX_ID gl_VertexIndex | ||||||
|  | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||||||
|  | #define VERTEX_ID gl_VertexID | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | out gl_PerVertex { | ||||||
|  |     vec4 gl_Position; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const vec2 vertices[3] = | ||||||
|  |     vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3)); | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D edges_tex; | ||||||
|  | layout (binding = 1) uniform sampler2D area_tex; | ||||||
|  | layout (binding = 2) uniform sampler2D search_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec2 tex_coord; | ||||||
|  | layout (location = 1) out vec2 pix_coord; | ||||||
|  | layout (location = 2) out vec4 offset[3]; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(edges_tex, 0), textureSize(edges_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 1 | ||||||
|  | #define SMAA_INCLUDE_PS 0 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     vec2 vertex = vertices[VERTEX_ID]; | ||||||
|  |     gl_Position = vec4(vertex, 0.0, 1.0); | ||||||
|  |     tex_coord = (vertex + 1.0) / 2.0; | ||||||
|  |     SMAABlendingWeightCalculationVS(tex_coord, pix_coord, offset); | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/video_core/host_shaders/smaa_edge_detection.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/video_core/host_shaders/smaa_edge_detection.frag
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D input_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) in vec2 tex_coord; | ||||||
|  | layout (location = 1) in vec4 offset[3]; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec2 frag_color; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(input_tex, 0), textureSize(input_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 0 | ||||||
|  | #define SMAA_INCLUDE_PS 1 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     frag_color = SMAAColorEdgeDetectionPS(tex_coord, offset, input_tex); | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								src/video_core/host_shaders/smaa_edge_detection.vert
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/video_core/host_shaders/smaa_edge_detection.vert
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | #ifdef VULKAN | ||||||
|  | #define VERTEX_ID gl_VertexIndex | ||||||
|  | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||||||
|  | #define VERTEX_ID gl_VertexID | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | out gl_PerVertex { | ||||||
|  |     vec4 gl_Position; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const vec2 vertices[3] = | ||||||
|  |     vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3)); | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D input_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec2 tex_coord; | ||||||
|  | layout (location = 1) out vec4 offset[3]; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(input_tex, 0), textureSize(input_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 1 | ||||||
|  | #define SMAA_INCLUDE_PS 0 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     vec2 vertex = vertices[VERTEX_ID]; | ||||||
|  |     gl_Position = vec4(vertex, 0.0, 1.0); | ||||||
|  |     tex_coord = (vertex + 1.0) / 2.0; | ||||||
|  |     SMAAEdgeDetectionVS(tex_coord, offset); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/video_core/host_shaders/smaa_neighborhood_blending.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/video_core/host_shaders/smaa_neighborhood_blending.frag
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D input_tex; | ||||||
|  | layout (binding = 1) uniform sampler2D blend_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) in vec2 tex_coord; | ||||||
|  | layout (location = 1) in vec4 offset; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec4 frag_color; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(input_tex, 0), textureSize(input_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 0 | ||||||
|  | #define SMAA_INCLUDE_PS 1 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     frag_color = SMAANeighborhoodBlendingPS(tex_coord, | ||||||
|  |                                   offset, | ||||||
|  |                                   input_tex, | ||||||
|  |                                   blend_tex | ||||||
|  |                                   ); | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/video_core/host_shaders/smaa_neighborhood_blending.vert
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/video_core/host_shaders/smaa_neighborhood_blending.vert
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 | ||||||
|  | 
 | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | #ifdef VULKAN | ||||||
|  | #define VERTEX_ID gl_VertexIndex | ||||||
|  | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||||||
|  | #define VERTEX_ID gl_VertexID | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | out gl_PerVertex { | ||||||
|  |     vec4 gl_Position; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const vec2 vertices[3] = | ||||||
|  |     vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3)); | ||||||
|  | 
 | ||||||
|  | layout (binding = 0) uniform sampler2D input_tex; | ||||||
|  | layout (binding = 1) uniform sampler2D blend_tex; | ||||||
|  | 
 | ||||||
|  | layout (location = 0) out vec2 tex_coord; | ||||||
|  | layout (location = 1) out vec4 offset; | ||||||
|  | 
 | ||||||
|  | vec4 metrics = vec4(1.0 / textureSize(input_tex, 0), textureSize(input_tex, 0)); | ||||||
|  | #define SMAA_RT_METRICS metrics | ||||||
|  | #define SMAA_GLSL_4 | ||||||
|  | #define SMAA_PRESET_ULTRA | ||||||
|  | #define SMAA_INCLUDE_VS 1 | ||||||
|  | #define SMAA_INCLUDE_PS 0 | ||||||
|  | 
 | ||||||
|  | #include "opengl_smaa.glsl" | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     vec2 vertex = vertices[VERTEX_ID]; | ||||||
|  |     gl_Position = vec4(vertex, 0.0, 1.0); | ||||||
|  |     tex_coord = (vertex + 1.0) / 2.0; | ||||||
|  |     SMAANeighborhoodBlendingVS(tex_coord, offset); | ||||||
|  | } | ||||||
|  | @ -22,12 +22,21 @@ | ||||||
| #include "video_core/host_shaders/opengl_present_frag.h" | #include "video_core/host_shaders/opengl_present_frag.h" | ||||||
| #include "video_core/host_shaders/opengl_present_scaleforce_frag.h" | #include "video_core/host_shaders/opengl_present_scaleforce_frag.h" | ||||||
| #include "video_core/host_shaders/opengl_present_vert.h" | #include "video_core/host_shaders/opengl_present_vert.h" | ||||||
|  | #include "video_core/host_shaders/opengl_smaa_glsl.h" | ||||||
| #include "video_core/host_shaders/present_bicubic_frag.h" | #include "video_core/host_shaders/present_bicubic_frag.h" | ||||||
| #include "video_core/host_shaders/present_gaussian_frag.h" | #include "video_core/host_shaders/present_gaussian_frag.h" | ||||||
|  | #include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h" | ||||||
|  | #include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h" | ||||||
|  | #include "video_core/host_shaders/smaa_edge_detection_frag.h" | ||||||
|  | #include "video_core/host_shaders/smaa_edge_detection_vert.h" | ||||||
|  | #include "video_core/host_shaders/smaa_neighborhood_blending_frag.h" | ||||||
|  | #include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" | ||||||
| #include "video_core/renderer_opengl/gl_rasterizer.h" | #include "video_core/renderer_opengl/gl_rasterizer.h" | ||||||
| #include "video_core/renderer_opengl/gl_shader_manager.h" | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||||||
| #include "video_core/renderer_opengl/gl_shader_util.h" | #include "video_core/renderer_opengl/gl_shader_util.h" | ||||||
| #include "video_core/renderer_opengl/renderer_opengl.h" | #include "video_core/renderer_opengl/renderer_opengl.h" | ||||||
|  | #include "video_core/smaa_area_tex.h" | ||||||
|  | #include "video_core/smaa_search_tex.h" | ||||||
| #include "video_core/textures/decoders.h" | #include "video_core/textures/decoders.h" | ||||||
| 
 | 
 | ||||||
| namespace OpenGL { | namespace OpenGL { | ||||||
|  | @ -258,6 +267,28 @@ void RendererOpenGL::InitOpenGLObjects() { | ||||||
|     // Create shader programs
 |     // Create shader programs
 | ||||||
|     fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER); |     fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER); | ||||||
|     fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER); |     fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER); | ||||||
|  | 
 | ||||||
|  |     const auto SmaaShader = [](std::string_view specialized_source, GLenum stage) { | ||||||
|  |         std::string shader_source{specialized_source}; | ||||||
|  |         constexpr std::string_view include_string = "#include \"opengl_smaa.glsl\""; | ||||||
|  |         const std::size_t pos = shader_source.find(include_string); | ||||||
|  |         ASSERT(pos != std::string::npos); | ||||||
|  |         shader_source.replace(pos, include_string.size(), HostShaders::OPENGL_SMAA_GLSL); | ||||||
|  |         return CreateProgram(shader_source, stage); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER); | ||||||
|  |     smaa_edge_detection_frag = | ||||||
|  |         SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER); | ||||||
|  |     smaa_blending_weight_calculation_vert = | ||||||
|  |         SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER); | ||||||
|  |     smaa_blending_weight_calculation_frag = | ||||||
|  |         SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER); | ||||||
|  |     smaa_neighborhood_blending_vert = | ||||||
|  |         SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER); | ||||||
|  |     smaa_neighborhood_blending_frag = | ||||||
|  |         SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER); | ||||||
|  | 
 | ||||||
|     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); | ||||||
|  | @ -293,7 +324,16 @@ void RendererOpenGL::InitOpenGLObjects() { | ||||||
|     // Clear screen to black
 |     // Clear screen to black
 | ||||||
|     LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); |     LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); | ||||||
| 
 | 
 | ||||||
|     fxaa_framebuffer.Create(); |     aa_framebuffer.Create(); | ||||||
|  | 
 | ||||||
|  |     smaa_area_tex.Create(GL_TEXTURE_2D); | ||||||
|  |     glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT); | ||||||
|  |     glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG, | ||||||
|  |                         GL_UNSIGNED_BYTE, areaTexBytes); | ||||||
|  |     smaa_search_tex.Create(GL_TEXTURE_2D); | ||||||
|  |     glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT); | ||||||
|  |     glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED, | ||||||
|  |                         GL_UNSIGNED_BYTE, searchTexBytes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RendererOpenGL::AddTelemetryFields() { | void RendererOpenGL::AddTelemetryFields() { | ||||||
|  | @ -346,13 +386,22 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | ||||||
|     texture.resource.Release(); |     texture.resource.Release(); | ||||||
|     texture.resource.Create(GL_TEXTURE_2D); |     texture.resource.Create(GL_TEXTURE_2D); | ||||||
|     glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); |     glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); | ||||||
|     fxaa_texture.Release(); |     aa_texture.Release(); | ||||||
|     fxaa_texture.Create(GL_TEXTURE_2D); |     aa_texture.Create(GL_TEXTURE_2D); | ||||||
|     glTextureStorage2D(fxaa_texture.handle, 1, GL_RGBA16F, |     glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, | ||||||
|  |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | ||||||
|  |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | ||||||
|  |     glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); | ||||||
|  |     smaa_edges_tex.Release(); | ||||||
|  |     smaa_edges_tex.Create(GL_TEXTURE_2D); | ||||||
|  |     glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, | ||||||
|  |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | ||||||
|  |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | ||||||
|  |     smaa_blend_tex.Release(); | ||||||
|  |     smaa_blend_tex.Create(GL_TEXTURE_2D); | ||||||
|  |     glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, | ||||||
|                        Settings::values.resolution_info.ScaleUp(screen_info.texture.width), |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.width), | ||||||
|                        Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); |                        Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); | ||||||
|     glNamedFramebufferTexture(fxaa_framebuffer.handle, GL_COLOR_ATTACHMENT0, fxaa_texture.handle, |  | ||||||
|                               0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|  | @ -377,11 +426,6 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
| 
 | 
 | ||||||
|     state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); |     state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); | ||||||
| 
 | 
 | ||||||
|     // Update background color before drawing
 |  | ||||||
|     glClearColor(Settings::values.bg_red.GetValue() / 255.0f, |  | ||||||
|                  Settings::values.bg_green.GetValue() / 255.0f, |  | ||||||
|                  Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); |  | ||||||
| 
 |  | ||||||
|     glEnable(GL_CULL_FACE); |     glEnable(GL_CULL_FACE); | ||||||
|     glDisable(GL_COLOR_LOGIC_OP); |     glDisable(GL_COLOR_LOGIC_OP); | ||||||
|     glDisable(GL_DEPTH_TEST); |     glDisable(GL_DEPTH_TEST); | ||||||
|  | @ -394,12 +438,12 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|     glCullFace(GL_BACK); |     glCullFace(GL_BACK); | ||||||
|     glFrontFace(GL_CW); |     glFrontFace(GL_CW); | ||||||
|     glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |     glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||||||
|  |     glDepthRangeIndexed(0, 0.0, 0.0); | ||||||
| 
 | 
 | ||||||
|     glBindTextureUnit(0, screen_info.display_texture); |     glBindTextureUnit(0, screen_info.display_texture); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa) { |     const auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); | ||||||
|         program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle); |     if (anti_aliasing != Settings::AntiAliasing::None) { | ||||||
| 
 |  | ||||||
|         glEnablei(GL_SCISSOR_TEST, 0); |         glEnablei(GL_SCISSOR_TEST, 0); | ||||||
|         auto viewport_width = screen_info.texture.width; |         auto viewport_width = screen_info.texture.width; | ||||||
|         auto scissor_width = framebuffer_crop_rect.GetWidth(); |         auto scissor_width = framebuffer_crop_rect.GetWidth(); | ||||||
|  | @ -420,21 +464,60 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|         glScissorIndexed(0, 0, 0, scissor_width, scissor_height); |         glScissorIndexed(0, 0, 0, scissor_width, scissor_height); | ||||||
|         glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width), |         glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width), | ||||||
|                            static_cast<GLfloat>(viewport_height)); |                            static_cast<GLfloat>(viewport_height)); | ||||||
|         glDepthRangeIndexed(0, 0.0, 0.0); |  | ||||||
| 
 | 
 | ||||||
|         glBindSampler(0, present_sampler.handle); |         glBindSampler(0, present_sampler.handle); | ||||||
|         GLint old_read_fb; |         GLint old_read_fb; | ||||||
|         GLint old_draw_fb; |         GLint old_draw_fb; | ||||||
|         glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); |         glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); | ||||||
|         glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); |         glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); | ||||||
|         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fxaa_framebuffer.handle); |  | ||||||
| 
 | 
 | ||||||
|  |         switch (anti_aliasing) { | ||||||
|  |         case Settings::AntiAliasing::Fxaa: { | ||||||
|  |             program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle); | ||||||
|  |             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); | ||||||
|             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||||
|  |         } break; | ||||||
|  |         case Settings::AntiAliasing::Smaa: { | ||||||
|  |             glClearColor(0, 0, 0, 0); | ||||||
|  |             glFrontFace(GL_CCW); | ||||||
|  |             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); | ||||||
|  |             glBindSampler(1, present_sampler.handle); | ||||||
|  |             glBindSampler(2, present_sampler.handle); | ||||||
|  | 
 | ||||||
|  |             glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, | ||||||
|  |                                       smaa_edges_tex.handle, 0); | ||||||
|  |             glClear(GL_COLOR_BUFFER_BIT); | ||||||
|  |             program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle, | ||||||
|  |                                                 smaa_edge_detection_frag.handle); | ||||||
|  |             glDrawArrays(GL_TRIANGLES, 0, 3); | ||||||
|  | 
 | ||||||
|  |             glBindTextureUnit(0, smaa_edges_tex.handle); | ||||||
|  |             glBindTextureUnit(1, smaa_area_tex.handle); | ||||||
|  |             glBindTextureUnit(2, smaa_search_tex.handle); | ||||||
|  |             glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, | ||||||
|  |                                       smaa_blend_tex.handle, 0); | ||||||
|  |             glClear(GL_COLOR_BUFFER_BIT); | ||||||
|  |             program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle, | ||||||
|  |                                                 smaa_blending_weight_calculation_frag.handle); | ||||||
|  |             glDrawArrays(GL_TRIANGLES, 0, 3); | ||||||
|  | 
 | ||||||
|  |             glBindTextureUnit(0, screen_info.display_texture); | ||||||
|  |             glBindTextureUnit(1, smaa_blend_tex.handle); | ||||||
|  |             glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, | ||||||
|  |                                       aa_texture.handle, 0); | ||||||
|  |             program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle, | ||||||
|  |                                                 smaa_neighborhood_blending_frag.handle); | ||||||
|  |             glDrawArrays(GL_TRIANGLES, 0, 3); | ||||||
|  |             glFrontFace(GL_CW); | ||||||
|  |         } break; | ||||||
|  |         default: | ||||||
|  |             UNREACHABLE(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); |         glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); | ||||||
|         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); |         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); | ||||||
| 
 | 
 | ||||||
|         glBindTextureUnit(0, fxaa_texture.handle); |         glBindTextureUnit(0, aa_texture.handle); | ||||||
|     } |     } | ||||||
|     const std::array ortho_matrix = |     const std::array ortho_matrix = | ||||||
|         MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); |         MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); | ||||||
|  | @ -551,6 +634,11 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|         glBindSampler(0, present_sampler_nn.handle); |         glBindSampler(0, present_sampler_nn.handle); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // Update background color before drawing
 | ||||||
|  |     glClearColor(Settings::values.bg_red.GetValue() / 255.0f, | ||||||
|  |                  Settings::values.bg_green.GetValue() / 255.0f, | ||||||
|  |                  Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); | ||||||
|  | 
 | ||||||
|     glClear(GL_COLOR_BUFFER_BIT); |     glClear(GL_COLOR_BUFFER_BIT); | ||||||
|     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,8 +127,19 @@ private: | ||||||
| 
 | 
 | ||||||
|     /// Display information for Switch screen
 |     /// Display information for Switch screen
 | ||||||
|     ScreenInfo screen_info; |     ScreenInfo screen_info; | ||||||
|     OGLTexture fxaa_texture; |     OGLTexture aa_texture; | ||||||
|     OGLFramebuffer fxaa_framebuffer; |     OGLFramebuffer aa_framebuffer; | ||||||
|  | 
 | ||||||
|  |     OGLProgram smaa_edge_detection_vert; | ||||||
|  |     OGLProgram smaa_blending_weight_calculation_vert; | ||||||
|  |     OGLProgram smaa_neighborhood_blending_vert; | ||||||
|  |     OGLProgram smaa_edge_detection_frag; | ||||||
|  |     OGLProgram smaa_blending_weight_calculation_frag; | ||||||
|  |     OGLProgram smaa_neighborhood_blending_frag; | ||||||
|  |     OGLTexture smaa_area_tex; | ||||||
|  |     OGLTexture smaa_search_tex; | ||||||
|  |     OGLTexture smaa_edges_tex; | ||||||
|  |     OGLTexture smaa_blend_tex; | ||||||
| 
 | 
 | ||||||
|     /// OpenGL framebuffer data
 |     /// OpenGL framebuffer data
 | ||||||
|     std::vector<u8> gl_framebuffer_data; |     std::vector<u8> gl_framebuffer_data; | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
| #include "video_core/renderer_vulkan/vk_fsr.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" | ||||||
|  | @ -156,6 +157,7 @@ VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||||
|     scheduler.Wait(resource_ticks[image_index]); |     scheduler.Wait(resource_ticks[image_index]); | ||||||
|     resource_ticks[image_index] = scheduler.CurrentTick(); |     resource_ticks[image_index] = scheduler.CurrentTick(); | ||||||
| 
 | 
 | ||||||
|  |     VkImage source_image = use_accelerated ? screen_info.image : *raw_images[image_index]; | ||||||
|     VkImageView source_image_view = |     VkImageView source_image_view = | ||||||
|         use_accelerated ? screen_info.image_view : *raw_image_views[image_index]; |         use_accelerated ? screen_info.image_view : *raw_image_views[image_index]; | ||||||
| 
 | 
 | ||||||
|  | @ -242,7 +244,7 @@ VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     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::None) { |     if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Fxaa) { | ||||||
|         UpdateAADescriptorSet(image_index, source_image_view, false); |         UpdateAADescriptorSet(image_index, source_image_view, false); | ||||||
|         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; | ||||||
|  | @ -340,7 +342,18 @@ VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||||
|         }); |         }); | ||||||
|         source_image_view = *aa_image_view; |         source_image_view = *aa_image_view; | ||||||
|     } |     } | ||||||
| 
 |     if (use_accelerated && anti_alias_pass == Settings::AntiAliasing::Smaa) { | ||||||
|  |         if (!smaa) { | ||||||
|  |             const u32 up_scale = Settings::values.resolution_info.up_scale; | ||||||
|  |             const u32 down_shift = Settings::values.resolution_info.down_shift; | ||||||
|  |             const VkExtent2D smaa_size{ | ||||||
|  |                 .width = (up_scale * framebuffer.width) >> down_shift, | ||||||
|  |                 .height = (up_scale * framebuffer.height) >> down_shift, | ||||||
|  |             }; | ||||||
|  |             CreateSMAA(smaa_size); | ||||||
|  |         } | ||||||
|  |         source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view); | ||||||
|  |     } | ||||||
|     if (fsr) { |     if (fsr) { | ||||||
|         auto crop_rect = framebuffer.crop_rect; |         auto crop_rect = framebuffer.crop_rect; | ||||||
|         if (crop_rect.GetWidth() == 0) { |         if (crop_rect.GetWidth() == 0) { | ||||||
|  | @ -467,6 +480,7 @@ void BlitScreen::CreateDynamicResources() { | ||||||
|     CreateFramebuffers(); |     CreateFramebuffers(); | ||||||
|     CreateGraphicsPipeline(); |     CreateGraphicsPipeline(); | ||||||
|     fsr.reset(); |     fsr.reset(); | ||||||
|  |     smaa.reset(); | ||||||
|     if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { |     if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { | ||||||
|         CreateFSR(); |         CreateFSR(); | ||||||
|     } |     } | ||||||
|  | @ -490,6 +504,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; | ||||||
| 
 | 
 | ||||||
|  |     smaa.reset(); | ||||||
|     ReleaseRawImages(); |     ReleaseRawImages(); | ||||||
| 
 | 
 | ||||||
|     CreateStagingBuffer(framebuffer); |     CreateStagingBuffer(framebuffer); | ||||||
|  | @ -1448,6 +1463,10 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& | ||||||
|         ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, left_start + right * scale_v); |         ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, left_start + right * scale_v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void BlitScreen::CreateSMAA(VkExtent2D smaa_size) { | ||||||
|  |     smaa = std::make_unique<SMAA>(device, memory_allocator, image_count, smaa_size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void BlitScreen::CreateFSR() { | void BlitScreen::CreateFSR() { | ||||||
|     const auto& layout = render_window.GetFramebufferLayout(); |     const auto& layout = render_window.GetFramebufferLayout(); | ||||||
|     const VkExtent2D fsr_size{ |     const VkExtent2D fsr_size{ | ||||||
|  |  | ||||||
|  | @ -40,9 +40,11 @@ class Device; | ||||||
| class FSR; | class FSR; | ||||||
| class RasterizerVulkan; | class RasterizerVulkan; | ||||||
| class Scheduler; | class Scheduler; | ||||||
|  | class SMAA; | ||||||
| class Swapchain; | class Swapchain; | ||||||
| 
 | 
 | ||||||
| struct ScreenInfo { | struct ScreenInfo { | ||||||
|  |     VkImage image{}; | ||||||
|     VkImageView image_view{}; |     VkImageView image_view{}; | ||||||
|     u32 width{}; |     u32 width{}; | ||||||
|     u32 height{}; |     u32 height{}; | ||||||
|  | @ -101,6 +103,7 @@ private: | ||||||
|     void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, |     void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, | ||||||
|                        const Layout::FramebufferLayout layout) const; |                        const Layout::FramebufferLayout layout) const; | ||||||
| 
 | 
 | ||||||
|  |     void CreateSMAA(VkExtent2D smaa_size); | ||||||
|     void CreateFSR(); |     void CreateFSR(); | ||||||
| 
 | 
 | ||||||
|     u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; |     u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; | ||||||
|  | @ -163,6 +166,7 @@ private: | ||||||
|     Service::android::PixelFormat pixel_format{}; |     Service::android::PixelFormat pixel_format{}; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<FSR> fsr; |     std::unique_ptr<FSR> fsr; | ||||||
|  |     std::unique_ptr<SMAA> smaa; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Vulkan
 | } // namespace Vulkan
 | ||||||
|  |  | ||||||
|  | @ -583,6 +583,7 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, | ||||||
|     if (!image_view) { |     if (!image_view) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |     screen_info.image = image_view->ImageHandle(); | ||||||
|     screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); |     screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); | ||||||
|     screen_info.width = image_view->size.width; |     screen_info.width = image_view->size.width; | ||||||
|     screen_info.height = image_view->size.height; |     screen_info.height = image_view->size.height; | ||||||
|  |  | ||||||
							
								
								
									
										761
									
								
								src/video_core/renderer_vulkan/vk_smaa.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										761
									
								
								src/video_core/renderer_vulkan/vk_smaa.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,761 @@ | ||||||
|  | // 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/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 { | ||||||
|  | 
 | ||||||
|  | #define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0]))) | ||||||
|  | 
 | ||||||
|  | std::pair<vk::Image, MemoryCommit> CreateWrappedImage(const Device& device, | ||||||
|  |                                                       MemoryAllocator& allocator, | ||||||
|  |                                                       VkExtent2D dimensions, VkFormat format) { | ||||||
|  |     const VkImageCreateInfo image_ci{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .imageType = VK_IMAGE_TYPE_2D, | ||||||
|  |         .format = format, | ||||||
|  |         .extent = {.width = dimensions.width, .height = dimensions.height, .depth = 1}, | ||||||
|  |         .mipLevels = 1, | ||||||
|  |         .arrayLayers = 1, | ||||||
|  |         .samples = VK_SAMPLE_COUNT_1_BIT, | ||||||
|  |         .tiling = VK_IMAGE_TILING_OPTIMAL, | ||||||
|  |         .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | | ||||||
|  |                  VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, | ||||||
|  |         .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||||||
|  |         .queueFamilyIndexCount = 0, | ||||||
|  |         .pQueueFamilyIndices = nullptr, | ||||||
|  |         .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     auto image = device.GetLogical().CreateImage(image_ci); | ||||||
|  |     auto commit = allocator.Commit(image, Vulkan::MemoryUsage::DeviceLocal); | ||||||
|  | 
 | ||||||
|  |     return std::make_pair(std::move(image), std::move(commit)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, | ||||||
|  |                            VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) { | ||||||
|  |     constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||||||
|  |                             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; | ||||||
|  |     const VkImageMemoryBarrier barrier{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .srcAccessMask = flags, | ||||||
|  |         .dstAccessMask = flags, | ||||||
|  |         .oldLayout = source_layout, | ||||||
|  |         .newLayout = target_layout, | ||||||
|  |         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||||
|  |         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||||
|  |         .image = image, | ||||||
|  |         .subresourceRange{ | ||||||
|  |             .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|  |             .baseMipLevel = 0, | ||||||
|  |             .levelCount = 1, | ||||||
|  |             .baseArrayLayer = 0, | ||||||
|  |             .layerCount = 1, | ||||||
|  |         }, | ||||||
|  |     }; | ||||||
|  |     cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||||||
|  |                            0, barrier); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, | ||||||
|  |                  vk::Image& image, VkExtent2D dimensions, VkFormat format, | ||||||
|  |                  std::span<const u8> initial_contents = {}) { | ||||||
|  |     auto upload_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .size = initial_contents.size_bytes(), | ||||||
|  |         .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, | ||||||
|  |         .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||||||
|  |         .queueFamilyIndexCount = 0, | ||||||
|  |         .pQueueFamilyIndices = nullptr, | ||||||
|  |     }); | ||||||
|  |     auto upload_commit = allocator.Commit(upload_buffer, MemoryUsage::Upload); | ||||||
|  |     std::ranges::copy(initial_contents, upload_commit.Map().begin()); | ||||||
|  | 
 | ||||||
|  |     const std::array<VkBufferImageCopy, 1> regions{{{ | ||||||
|  |         .bufferOffset = 0, | ||||||
|  |         .bufferRowLength = dimensions.width, | ||||||
|  |         .bufferImageHeight = dimensions.height, | ||||||
|  |         .imageSubresource{.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|  |                           .mipLevel = 0, | ||||||
|  |                           .baseArrayLayer = 0, | ||||||
|  |                           .layerCount = 1}, | ||||||
|  |         .imageOffset{}, | ||||||
|  |         .imageExtent{.width = dimensions.width, .height = dimensions.height, .depth = 1}, | ||||||
|  |     }}}; | ||||||
|  | 
 | ||||||
|  |     scheduler.RequestOutsideRenderPassOperationContext(); | ||||||
|  |     scheduler.Record([&](vk::CommandBuffer cmdbuf) { | ||||||
|  |         TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||||
|  |                               VK_IMAGE_LAYOUT_UNDEFINED); | ||||||
|  |         cmdbuf.CopyBufferToImage(*upload_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||||
|  |                                  regions); | ||||||
|  |         TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_GENERAL, | ||||||
|  |                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); | ||||||
|  |     }); | ||||||
|  |     scheduler.Finish(); | ||||||
|  | 
 | ||||||
|  |     // This should go out of scope before the commit
 | ||||||
|  |     auto upload_buffer2 = std::move(upload_buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) { | ||||||
|  |     return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .image = *image, | ||||||
|  |         .viewType = VK_IMAGE_VIEW_TYPE_2D, | ||||||
|  |         .format = format, | ||||||
|  |         .components{}, | ||||||
|  |         .subresourceRange{.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|  |                           .baseMipLevel = 0, | ||||||
|  |                           .levelCount = 1, | ||||||
|  |                           .baseArrayLayer = 0, | ||||||
|  |                           .layerCount = 1}, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format) { | ||||||
|  |     const VkAttachmentDescription attachment{ | ||||||
|  |         .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, | ||||||
|  |         .format = format, | ||||||
|  |         .samples = VK_SAMPLE_COUNT_1_BIT, | ||||||
|  |         .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, | ||||||
|  |         .storeOp = VK_ATTACHMENT_STORE_OP_STORE, | ||||||
|  |         .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, | ||||||
|  |         .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, | ||||||
|  |         .initialLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||||
|  |         .finalLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr VkAttachmentReference color_attachment_ref{ | ||||||
|  |         .attachment = 0, | ||||||
|  |         .layout = VK_IMAGE_LAYOUT_GENERAL, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const VkSubpassDescription subpass_description{ | ||||||
|  |         .flags = 0, | ||||||
|  |         .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, | ||||||
|  |         .inputAttachmentCount = 0, | ||||||
|  |         .pInputAttachments = nullptr, | ||||||
|  |         .colorAttachmentCount = 1, | ||||||
|  |         .pColorAttachments = &color_attachment_ref, | ||||||
|  |         .pResolveAttachments = nullptr, | ||||||
|  |         .pDepthStencilAttachment = nullptr, | ||||||
|  |         .preserveAttachmentCount = 0, | ||||||
|  |         .pPreserveAttachments = nullptr, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr VkSubpassDependency dependency{ | ||||||
|  |         .srcSubpass = VK_SUBPASS_EXTERNAL, | ||||||
|  |         .dstSubpass = 0, | ||||||
|  |         .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | ||||||
|  |         .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | ||||||
|  |         .srcAccessMask = 0, | ||||||
|  |         .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | ||||||
|  |         .dependencyFlags = 0, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     return device.GetLogical().CreateRenderPass(VkRenderPassCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .attachmentCount = 1, | ||||||
|  |         .pAttachments = &attachment, | ||||||
|  |         .subpassCount = 1, | ||||||
|  |         .pSubpasses = &subpass_description, | ||||||
|  |         .dependencyCount = 1, | ||||||
|  |         .pDependencies = &dependency, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass, | ||||||
|  |                                          vk::ImageView& dest_image, VkExtent2D extent) { | ||||||
|  |     return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .renderPass = *render_pass, | ||||||
|  |         .attachmentCount = 1, | ||||||
|  |         .pAttachments = dest_image.address(), | ||||||
|  |         .width = extent.width, | ||||||
|  |         .height = extent.height, | ||||||
|  |         .layers = 1, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::Sampler CreateWrappedSampler(const Device& device) { | ||||||
|  |     return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .magFilter = VK_FILTER_LINEAR, | ||||||
|  |         .minFilter = VK_FILTER_LINEAR, | ||||||
|  |         .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, | ||||||
|  |         .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||||||
|  |         .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||||||
|  |         .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, | ||||||
|  |         .mipLodBias = 0.0f, | ||||||
|  |         .anisotropyEnable = VK_FALSE, | ||||||
|  |         .maxAnisotropy = 0.0f, | ||||||
|  |         .compareEnable = VK_FALSE, | ||||||
|  |         .compareOp = VK_COMPARE_OP_NEVER, | ||||||
|  |         .minLod = 0.0f, | ||||||
|  |         .maxLod = 0.0f, | ||||||
|  |         .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, | ||||||
|  |         .unnormalizedCoordinates = VK_FALSE, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code) { | ||||||
|  |     return device.GetLogical().CreateShaderModule(VkShaderModuleCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .codeSize = code.size_bytes(), | ||||||
|  |         .pCode = code.data(), | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, u32 max_descriptors, | ||||||
|  |                                                u32 max_sets) { | ||||||
|  |     const VkDescriptorPoolSize pool_size{ | ||||||
|  |         .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||||
|  |         .descriptorCount = static_cast<u32>(max_descriptors), | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     return device.GetLogical().CreateDescriptorPool(VkDescriptorPoolCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .maxSets = max_sets, | ||||||
|  |         .poolSizeCount = 1, | ||||||
|  |         .pPoolSizes = &pool_size, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::DescriptorSetLayout CreateWrappedDescriptorSetLayout(const Device& device, | ||||||
|  |                                                          u32 max_sampler_bindings) { | ||||||
|  |     std::vector<VkDescriptorSetLayoutBinding> bindings(max_sampler_bindings); | ||||||
|  |     for (u32 i = 0; i < max_sampler_bindings; i++) { | ||||||
|  |         bindings[i] = { | ||||||
|  |             .binding = i, | ||||||
|  |             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||||
|  |             .descriptorCount = 1, | ||||||
|  |             .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, | ||||||
|  |             .pImmutableSamplers = nullptr, | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return device.GetLogical().CreateDescriptorSetLayout(VkDescriptorSetLayoutCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .bindingCount = static_cast<u32>(bindings.size()), | ||||||
|  |         .pBindings = bindings.data(), | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool, | ||||||
|  |                                                vk::Span<VkDescriptorSetLayout> layouts) { | ||||||
|  |     return pool.Allocate(VkDescriptorSetAllocateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .descriptorPool = *pool, | ||||||
|  |         .descriptorSetCount = layouts.size(), | ||||||
|  |         .pSetLayouts = layouts.data(), | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, | ||||||
|  |                                                vk::DescriptorSetLayout& layout) { | ||||||
|  |     return device.GetLogical().CreatePipelineLayout(VkPipelineLayoutCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .setLayoutCount = 1, | ||||||
|  |         .pSetLayouts = layout.address(), | ||||||
|  |         .pushConstantRangeCount = 0, | ||||||
|  |         .pPushConstantRanges = nullptr, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, | ||||||
|  |                                    vk::PipelineLayout& layout, | ||||||
|  |                                    std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) { | ||||||
|  |     const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{ | ||||||
|  |         { | ||||||
|  |             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||||
|  |             .pNext = nullptr, | ||||||
|  |             .flags = 0, | ||||||
|  |             .stage = VK_SHADER_STAGE_VERTEX_BIT, | ||||||
|  |             .module = *std::get<0>(shaders), | ||||||
|  |             .pName = "main", | ||||||
|  |             .pSpecializationInfo = nullptr, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||||
|  |             .pNext = nullptr, | ||||||
|  |             .flags = 0, | ||||||
|  |             .stage = VK_SHADER_STAGE_FRAGMENT_BIT, | ||||||
|  |             .module = *std::get<1>(shaders), | ||||||
|  |             .pName = "main", | ||||||
|  |             .pSpecializationInfo = nullptr, | ||||||
|  |         }, | ||||||
|  |     }}; | ||||||
|  | 
 | ||||||
|  |     constexpr VkPipelineVertexInputStateCreateInfo vertex_input_ci{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .vertexBindingDescriptionCount = 0, | ||||||
|  |         .pVertexBindingDescriptions = nullptr, | ||||||
|  |         .vertexAttributeDescriptionCount = 0, | ||||||
|  |         .pVertexAttributeDescriptions = nullptr, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr 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, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr 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, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr 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, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr 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, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr 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}, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     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(), | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     return device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .stageCount = static_cast<u32>(shader_stages.size()), | ||||||
|  |         .pStages = 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 = *layout, | ||||||
|  |         .renderPass = *renderpass, | ||||||
|  |         .subpass = 0, | ||||||
|  |         .basePipelineHandle = 0, | ||||||
|  |         .basePipelineIndex = 0, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, | ||||||
|  |                                               VkSampler sampler, VkImageView view, | ||||||
|  |                                               VkDescriptorSet set, u32 binding) { | ||||||
|  |     ASSERT(images.capacity() > images.size()); | ||||||
|  |     auto& image_info = images.emplace_back(VkDescriptorImageInfo{ | ||||||
|  |         .sampler = sampler, | ||||||
|  |         .imageView = view, | ||||||
|  |         .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return VkWriteDescriptorSet{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .dstSet = set, | ||||||
|  |         .dstBinding = binding, | ||||||
|  |         .dstArrayElement = 0, | ||||||
|  |         .descriptorCount = 1, | ||||||
|  |         .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||||
|  |         .pImageInfo = &image_info, | ||||||
|  |         .pBufferInfo = nullptr, | ||||||
|  |         .pTexelBufferView = nullptr, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) { | ||||||
|  |     constexpr std::array<VkImageSubresourceRange, 1> subresources{{{ | ||||||
|  |         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|  |         .baseMipLevel = 0, | ||||||
|  |         .levelCount = 1, | ||||||
|  |         .baseArrayLayer = 0, | ||||||
|  |         .layerCount = 1, | ||||||
|  |     }}}; | ||||||
|  |     TransitionImageLayout(cmdbuf, image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_UNDEFINED); | ||||||
|  |     cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BeginRenderPass(vk::CommandBuffer& cmdbuf, vk::RenderPass& render_pass, | ||||||
|  |                      VkFramebuffer framebuffer, VkExtent2D extent) { | ||||||
|  |     const VkRenderPassBeginInfo renderpass_bi{ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .renderPass = *render_pass, | ||||||
|  |         .framebuffer = framebuffer, | ||||||
|  |         .renderArea{ | ||||||
|  |             .offset{}, | ||||||
|  |             .extent = extent, | ||||||
|  |         }, | ||||||
|  |         .clearValueCount = 0, | ||||||
|  |         .pClearValues = nullptr, | ||||||
|  |     }; | ||||||
|  |     cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); | ||||||
|  | 
 | ||||||
|  |     const VkViewport viewport{ | ||||||
|  |         .x = 0.0f, | ||||||
|  |         .y = 0.0f, | ||||||
|  |         .width = static_cast<float>(extent.width), | ||||||
|  |         .height = static_cast<float>(extent.height), | ||||||
|  |         .minDepth = 0.0f, | ||||||
|  |         .maxDepth = 1.0f, | ||||||
|  |     }; | ||||||
|  |     const VkRect2D scissor{ | ||||||
|  |         .offset = {0, 0}, | ||||||
|  |         .extent = extent, | ||||||
|  |     }; | ||||||
|  |     cmdbuf.SetViewport(0, viewport); | ||||||
|  |     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() { | ||||||
|  |     constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||||||
|  |     constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | ||||||
|  | 
 | ||||||
|  |     std::tie(m_static_images[Area], m_static_buffer_commits[Area]) = | ||||||
|  |         CreateWrappedImage(m_device, m_allocator, area_extent, VK_FORMAT_R8G8_UNORM); | ||||||
|  |     std::tie(m_static_images[Search], m_static_buffer_commits[Search]) = | ||||||
|  |         CreateWrappedImage(m_device, 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(); | ||||||
|  | 
 | ||||||
|  |         std::tie(images.images[Blend], images.buffer_commits[Blend]) = | ||||||
|  |             CreateWrappedImage(m_device, m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||||||
|  |         std::tie(images.images[Edges], images.buffer_commits[Edges]) = | ||||||
|  |             CreateWrappedImage(m_device, m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT); | ||||||
|  |         std::tie(images.images[Output], images.buffer_commits[Output]) = | ||||||
|  |             CreateWrappedImage(m_device, 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
 | ||||||
|  |     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), | ||||||
|  |     }; | ||||||
|  |     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; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | ||||||
|  |     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
 | ||||||
							
								
								
									
										86
									
								
								src/video_core/renderer_vulkan/vk_smaa.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/video_core/renderer_vulkan/vk_smaa.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <array> | ||||||
|  | #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 SMAA { | ||||||
|  | public: | ||||||
|  |     explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, | ||||||
|  |                   VkExtent2D extent); | ||||||
|  |     VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, | ||||||
|  |                      VkImageView source_image_view); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     enum SMAAStage { | ||||||
|  |         EdgeDetection = 0, | ||||||
|  |         BlendingWeightCalculation = 1, | ||||||
|  |         NeighborhoodBlending = 2, | ||||||
|  |         MaxSMAAStage = 3, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     enum StaticImageType { | ||||||
|  |         Area = 0, | ||||||
|  |         Search = 1, | ||||||
|  |         MaxStaticImage = 2, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     enum DynamicImageType { | ||||||
|  |         Blend = 0, | ||||||
|  |         Edges = 1, | ||||||
|  |         Output = 2, | ||||||
|  |         MaxDynamicImage = 3, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     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::DescriptorPool m_descriptor_pool{}; | ||||||
|  |     std::array<vk::DescriptorSetLayout, MaxSMAAStage> m_descriptor_set_layouts{}; | ||||||
|  |     std::array<vk::PipelineLayout, MaxSMAAStage> m_pipeline_layouts{}; | ||||||
|  |     std::array<vk::ShaderModule, MaxSMAAStage> m_vertex_shaders{}; | ||||||
|  |     std::array<vk::ShaderModule, MaxSMAAStage> m_fragment_shaders{}; | ||||||
|  |     std::array<vk::Pipeline, MaxSMAAStage> m_pipelines{}; | ||||||
|  |     std::array<vk::RenderPass, MaxSMAAStage> m_renderpasses{}; | ||||||
|  | 
 | ||||||
|  |     std::array<MemoryCommit, MaxStaticImage> m_static_buffer_commits; | ||||||
|  |     std::array<vk::Image, MaxStaticImage> m_static_images{}; | ||||||
|  |     std::array<vk::ImageView, MaxStaticImage> m_static_image_views{}; | ||||||
|  | 
 | ||||||
|  |     struct Images { | ||||||
|  |         vk::DescriptorSets descriptor_sets{}; | ||||||
|  |         std::array<MemoryCommit, MaxDynamicImage> buffer_commits; | ||||||
|  |         std::array<vk::Image, MaxDynamicImage> images{}; | ||||||
|  |         std::array<vk::ImageView, MaxDynamicImage> image_views{}; | ||||||
|  |         std::array<vk::Framebuffer, MaxSMAAStage> framebuffers{}; | ||||||
|  |     }; | ||||||
|  |     std::vector<Images> m_dynamic_images{}; | ||||||
|  |     bool m_images_ready{}; | ||||||
|  | 
 | ||||||
|  |     vk::Sampler m_sampler{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace Vulkan
 | ||||||
							
								
								
									
										11223
									
								
								src/video_core/smaa_area_tex.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11223
									
								
								src/video_core/smaa_area_tex.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										88
									
								
								src/video_core/smaa_search_tex.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/video_core/smaa_search_tex.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | ||||||
|  | // SPDX-FileCopyrightText: 2013 Jorge Jimenez (jorge@iryoku.com)
 | ||||||
|  | // SPDX-FileCopyrightText: 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
 | ||||||
|  | // SPDX-FileCopyrightText: 2013 Belen Masia (bmasia@unizar.es)
 | ||||||
|  | // SPDX-FileCopyrightText: 2013 Fernando Navarro (fernandn@microsoft.com)
 | ||||||
|  | // SPDX-FileCopyrightText: 2013 Diego Gutierrez (diegog@unizar.es)
 | ||||||
|  | // SPDX-License-Identifier: MIT
 | ||||||
|  | 
 | ||||||
|  | #ifndef SEARCHTEX_H | ||||||
|  | #define SEARCHTEX_H | ||||||
|  | 
 | ||||||
|  | #define SEARCHTEX_WIDTH 64 | ||||||
|  | #define SEARCHTEX_HEIGHT 16 | ||||||
|  | #define SEARCHTEX_PITCH SEARCHTEX_WIDTH | ||||||
|  | #define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH) | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Stored in R8 format. Load it in the following format: | ||||||
|  |  *  - DX9:  D3DFMT_L8 | ||||||
|  |  *  - DX10: DXGI_FORMAT_R8_UNORM | ||||||
|  |  */ | ||||||
|  | static const unsigned char searchTexBytes[] = { | ||||||
|  |     0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, | ||||||
|  |     0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -86,6 +86,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | ||||||
|     X(vkCmdBindVertexBuffers); |     X(vkCmdBindVertexBuffers); | ||||||
|     X(vkCmdBlitImage); |     X(vkCmdBlitImage); | ||||||
|     X(vkCmdClearAttachments); |     X(vkCmdClearAttachments); | ||||||
|  |     X(vkCmdClearColorImage); | ||||||
|     X(vkCmdCopyBuffer); |     X(vkCmdCopyBuffer); | ||||||
|     X(vkCmdCopyBufferToImage); |     X(vkCmdCopyBufferToImage); | ||||||
|     X(vkCmdCopyImage); |     X(vkCmdCopyImage); | ||||||
|  |  | ||||||
|  | @ -205,6 +205,7 @@ struct DeviceDispatch : InstanceDispatch { | ||||||
|     PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{}; |     PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{}; | ||||||
|     PFN_vkCmdBlitImage vkCmdBlitImage{}; |     PFN_vkCmdBlitImage vkCmdBlitImage{}; | ||||||
|     PFN_vkCmdClearAttachments vkCmdClearAttachments{}; |     PFN_vkCmdClearAttachments vkCmdClearAttachments{}; | ||||||
|  |     PFN_vkCmdClearColorImage vkCmdClearColorImage{}; | ||||||
|     PFN_vkCmdCopyBuffer vkCmdCopyBuffer{}; |     PFN_vkCmdCopyBuffer vkCmdCopyBuffer{}; | ||||||
|     PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{}; |     PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{}; | ||||||
|     PFN_vkCmdCopyImage vkCmdCopyImage{}; |     PFN_vkCmdCopyImage vkCmdCopyImage{}; | ||||||
|  | @ -1024,6 +1025,11 @@ public: | ||||||
|                                    rects.data()); |                                    rects.data()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void ClearColorImage(VkImage image, VkImageLayout layout, VkClearColorValue color, | ||||||
|  |                          Span<VkImageSubresourceRange> ranges) { | ||||||
|  |         dld->vkCmdClearColorImage(handle, image, layout, &color, ranges.size(), ranges.data()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, |     void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, | ||||||
|                    VkImageLayout dst_layout, Span<VkImageBlit> regions, |                    VkImageLayout dst_layout, Span<VkImageBlit> regions, | ||||||
|                    VkFilter filter) const noexcept { |                    VkFilter filter) const noexcept { | ||||||
|  |  | ||||||
|  | @ -487,6 +487,11 @@ | ||||||
|                <string>FXAA</string> |                <string>FXAA</string> | ||||||
|               </property> |               </property> | ||||||
|              </item> |              </item> | ||||||
|  |              <item> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>SMAA</string> | ||||||
|  |               </property> | ||||||
|  |              </item> | ||||||
|             </widget> |             </widget> | ||||||
|            </item> |            </item> | ||||||
|           </layout> |           </layout> | ||||||
|  | @ -524,6 +529,12 @@ | ||||||
|            </property> |            </property> | ||||||
|            <item> |            <item> | ||||||
|             <layout class="QHBoxLayout" name="fsr_sharpening_label_group"> |             <layout class="QHBoxLayout" name="fsr_sharpening_label_group"> | ||||||
|  |              <property name="rightMargin"> | ||||||
|  |               <number>0</number> | ||||||
|  |              </property> | ||||||
|  |              <property name="bottomMargin"> | ||||||
|  |               <number>0</number> | ||||||
|  |              </property> | ||||||
|              <item> |              <item> | ||||||
|               <widget class="QComboBox" name="fsr_sharpening_combobox"> |               <widget class="QComboBox" name="fsr_sharpening_combobox"> | ||||||
|                <property name="sizePolicy"> |                <property name="sizePolicy"> | ||||||
|  |  | ||||||
|  | @ -3628,6 +3628,9 @@ void GMainWindow::UpdateAAText() { | ||||||
|     case Settings::AntiAliasing::Fxaa: |     case Settings::AntiAliasing::Fxaa: | ||||||
|         aa_status_button->setText(tr("FXAA")); |         aa_status_button->setText(tr("FXAA")); | ||||||
|         break; |         break; | ||||||
|  |     case Settings::AntiAliasing::Smaa: | ||||||
|  |         aa_status_button->setText(tr("SMAA")); | ||||||
|  |         break; | ||||||
|     default: |     default: | ||||||
|         aa_status_button->setText(tr("NO AA")); |         aa_status_button->setText(tr("NO AA")); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liam
						Liam