forked from eden-emu/eden
		
	Merge pull request #9539 from Wollnashorn/opengl-fsr
video_core/opengl: Added FSR upscaling filter to the OpenGL renderer
This commit is contained in:
		
						commit
						6fa86989f1
					
				
					 14 changed files with 547 additions and 172 deletions
				
			
		|  | @ -52,6 +52,8 @@ add_library(video_core STATIC | ||||||
|     engines/puller.cpp |     engines/puller.cpp | ||||||
|     engines/puller.h |     engines/puller.h | ||||||
|     framebuffer_config.h |     framebuffer_config.h | ||||||
|  |     fsr.cpp | ||||||
|  |     fsr.h | ||||||
|     host1x/codecs/codec.cpp |     host1x/codecs/codec.cpp | ||||||
|     host1x/codecs/codec.h |     host1x/codecs/codec.h | ||||||
|     host1x/codecs/h264.cpp |     host1x/codecs/h264.cpp | ||||||
|  | @ -110,6 +112,8 @@ add_library(video_core STATIC | ||||||
|     renderer_opengl/gl_device.h |     renderer_opengl/gl_device.h | ||||||
|     renderer_opengl/gl_fence_manager.cpp |     renderer_opengl/gl_fence_manager.cpp | ||||||
|     renderer_opengl/gl_fence_manager.h |     renderer_opengl/gl_fence_manager.h | ||||||
|  |     renderer_opengl/gl_fsr.cpp | ||||||
|  |     renderer_opengl/gl_fsr.h | ||||||
|     renderer_opengl/gl_graphics_pipeline.cpp |     renderer_opengl/gl_graphics_pipeline.cpp | ||||||
|     renderer_opengl/gl_graphics_pipeline.h |     renderer_opengl/gl_graphics_pipeline.h | ||||||
|     renderer_opengl/gl_rasterizer.cpp |     renderer_opengl/gl_rasterizer.cpp | ||||||
|  |  | ||||||
							
								
								
									
										148
									
								
								src/video_core/fsr.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/video_core/fsr.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,148 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #include <cmath> | ||||||
|  | #include "video_core/fsr.h" | ||||||
|  | 
 | ||||||
|  | namespace FSR { | ||||||
|  | namespace { | ||||||
|  | // Reimplementations of the constant generating functions in ffx_fsr1.h
 | ||||||
|  | // GCC generated a lot of warnings when using the official header.
 | ||||||
|  | u32 AU1_AH1_AF1(f32 f) { | ||||||
|  |     static constexpr u32 base[512]{ | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||||||
|  |         0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, | ||||||
|  |         0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00, 0x2000, | ||||||
|  |         0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400, 0x4800, 0x4c00, | ||||||
|  |         0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, | ||||||
|  |         0x7bff, 0x7bff, 0x7bff, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, | ||||||
|  |         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008, | ||||||
|  |         0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400, | ||||||
|  |         0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00, 0xc000, | ||||||
|  |         0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, 0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00, | ||||||
|  |         0xf000, 0xf400, 0xf800, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, | ||||||
|  |     }; | ||||||
|  |     static constexpr s8 shift[512]{ | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, | ||||||
|  |         0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||||||
|  |         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||||||
|  |         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, | ||||||
|  |         0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||||||
|  |         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||||||
|  |         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||||||
|  |         0x18, 0x18, | ||||||
|  |     }; | ||||||
|  |     const u32 u = Common::BitCast<u32>(f); | ||||||
|  |     const u32 i = u >> 23; | ||||||
|  |     return base[i] + ((u & 0x7fffff) >> shift[i]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | u32 AU1_AH2_AF2(f32 a[2]) { | ||||||
|  |     return AU1_AH1_AF1(a[0]) + (AU1_AH1_AF1(a[1]) << 16); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FsrEasuCon(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], f32 inputViewportInPixelsX, | ||||||
|  |                 f32 inputViewportInPixelsY, f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, | ||||||
|  |                 f32 outputSizeInPixelsX, f32 outputSizeInPixelsY) { | ||||||
|  |     con0[0] = Common::BitCast<u32>(inputViewportInPixelsX / outputSizeInPixelsX); | ||||||
|  |     con0[1] = Common::BitCast<u32>(inputViewportInPixelsY / outputSizeInPixelsY); | ||||||
|  |     con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f); | ||||||
|  |     con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f); | ||||||
|  |     con1[0] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); | ||||||
|  |     con1[1] = Common::BitCast<u32>(1.0f / inputSizeInPixelsY); | ||||||
|  |     con1[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); | ||||||
|  |     con1[3] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsY); | ||||||
|  |     con2[0] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsX); | ||||||
|  |     con2[1] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY); | ||||||
|  |     con2[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); | ||||||
|  |     con2[3] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY); | ||||||
|  |     con3[0] = Common::BitCast<u32>(0.0f / inputSizeInPixelsX); | ||||||
|  |     con3[1] = Common::BitCast<u32>(4.0f / inputSizeInPixelsY); | ||||||
|  |     con3[2] = con3[3] = 0; | ||||||
|  | } | ||||||
|  | } // Anonymous namespace
 | ||||||
|  | 
 | ||||||
|  | void FsrEasuConOffset(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], | ||||||
|  |                       f32 inputViewportInPixelsX, f32 inputViewportInPixelsY, | ||||||
|  |                       f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, f32 outputSizeInPixelsX, | ||||||
|  |                       f32 outputSizeInPixelsY, f32 inputOffsetInPixelsX, f32 inputOffsetInPixelsY) { | ||||||
|  |     FsrEasuCon(con0, con1, con2, con3, inputViewportInPixelsX, inputViewportInPixelsY, | ||||||
|  |                inputSizeInPixelsX, inputSizeInPixelsY, outputSizeInPixelsX, outputSizeInPixelsY); | ||||||
|  |     con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f + | ||||||
|  |                                    inputOffsetInPixelsX); | ||||||
|  |     con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f + | ||||||
|  |                                    inputOffsetInPixelsY); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FsrRcasCon(u32* con, f32 sharpness) { | ||||||
|  |     sharpness = std::exp2f(-sharpness); | ||||||
|  |     f32 hSharp[2]{sharpness, sharpness}; | ||||||
|  |     con[0] = Common::BitCast<u32>(sharpness); | ||||||
|  |     con[1] = AU1_AH2_AF2(hSharp); | ||||||
|  |     con[2] = 0; | ||||||
|  |     con[3] = 0; | ||||||
|  | } | ||||||
|  | } // namespace FSR
 | ||||||
							
								
								
									
										19
									
								
								src/video_core/fsr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/video_core/fsr.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/bit_cast.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | namespace FSR { | ||||||
|  | // Reimplementations of the constant generating functions in ffx_fsr1.h
 | ||||||
|  | // GCC generated a lot of warnings when using the official header.
 | ||||||
|  | void FsrEasuConOffset(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], | ||||||
|  |                       f32 inputViewportInPixelsX, f32 inputViewportInPixelsY, | ||||||
|  |                       f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, f32 outputSizeInPixelsX, | ||||||
|  |                       f32 outputSizeInPixelsY, f32 inputOffsetInPixelsX, f32 inputOffsetInPixelsY); | ||||||
|  | 
 | ||||||
|  | void FsrRcasCon(u32* con, f32 sharpness); | ||||||
|  | 
 | ||||||
|  | } // namespace FSR
 | ||||||
|  | @ -3,12 +3,16 @@ | ||||||
| 
 | 
 | ||||||
| set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr) | set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr) | ||||||
| 
 | 
 | ||||||
| set(GLSL_INCLUDES | set(FIDELITYFX_FILES | ||||||
|     fidelityfx_fsr.comp |  | ||||||
|     ${FIDELITYFX_INCLUDE_DIR}/ffx_a.h |     ${FIDELITYFX_INCLUDE_DIR}/ffx_a.h | ||||||
|     ${FIDELITYFX_INCLUDE_DIR}/ffx_fsr1.h |     ${FIDELITYFX_INCLUDE_DIR}/ffx_fsr1.h | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | set(GLSL_INCLUDES | ||||||
|  |     fidelityfx_fsr.comp | ||||||
|  |     ${FIDELITYFX_FILES} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| set(SHADER_FILES | set(SHADER_FILES | ||||||
|     astc_decoder.comp |     astc_decoder.comp | ||||||
|     blit_color_float.frag |     blit_color_float.frag | ||||||
|  | @ -24,6 +28,9 @@ set(SHADER_FILES | ||||||
|     fxaa.vert |     fxaa.vert | ||||||
|     opengl_convert_s8d24.comp |     opengl_convert_s8d24.comp | ||||||
|     opengl_copy_bc4.comp |     opengl_copy_bc4.comp | ||||||
|  |     opengl_fidelityfx_fsr.frag | ||||||
|  |     opengl_fidelityfx_fsr_easu.frag | ||||||
|  |     opengl_fidelityfx_fsr_rcas.frag | ||||||
|     opengl_present.frag |     opengl_present.frag | ||||||
|     opengl_present.vert |     opengl_present.vert | ||||||
|     opengl_present_scaleforce.frag |     opengl_present_scaleforce.frag | ||||||
|  | @ -118,6 +125,25 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES}) | ||||||
|     endif() |     endif() | ||||||
| endforeach() | endforeach() | ||||||
| 
 | 
 | ||||||
|  | foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES}) | ||||||
|  |     get_filename_component(FILENAME ${FILEPATH} NAME) | ||||||
|  |     string(REPLACE "." "_" HEADER_NAME ${FILENAME}) | ||||||
|  |     set(SOURCE_FILE ${FILEPATH}) | ||||||
|  |     set(SOURCE_HEADER_FILE ${SHADER_DIR}/${HEADER_NAME}.h) | ||||||
|  |     add_custom_command( | ||||||
|  |         OUTPUT | ||||||
|  |             ${SOURCE_HEADER_FILE} | ||||||
|  |         COMMAND | ||||||
|  |             ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} | ||||||
|  |         MAIN_DEPENDENCY | ||||||
|  |             ${SOURCE_FILE} | ||||||
|  |         DEPENDS | ||||||
|  |             ${INPUT_FILE} | ||||||
|  |             # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified | ||||||
|  |     ) | ||||||
|  |     set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) | ||||||
|  | endforeach() | ||||||
|  | 
 | ||||||
| set(SHADER_SOURCES ${SHADER_FILES}) | set(SHADER_SOURCES ${SHADER_FILES}) | ||||||
| list(APPEND SHADER_SOURCES ${GLSL_INCLUDES}) | list(APPEND SHADER_SOURCES ${GLSL_INCLUDES}) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										108
									
								
								src/video_core/host_shaders/opengl_fidelityfx_fsr.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/video_core/host_shaders/opengl_fidelityfx_fsr.frag
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,108 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | //!#version 460 core | ||||||
|  | #extension GL_ARB_separate_shader_objects : enable | ||||||
|  | #extension GL_ARB_shading_language_420pack : enable | ||||||
|  | 
 | ||||||
|  | #extension GL_AMD_gpu_shader_half_float : enable | ||||||
|  | #extension GL_NV_gpu_shader5 : enable | ||||||
|  | 
 | ||||||
|  | // FidelityFX Super Resolution Sample | ||||||
|  | // | ||||||
|  | // Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. | ||||||
|  | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | // of this software and associated documentation files(the "Software"), to deal | ||||||
|  | // in the Software without restriction, including without limitation the rights | ||||||
|  | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell | ||||||
|  | // copies of the Software, and to permit persons to whom the Software is | ||||||
|  | // furnished to do so, subject to the following conditions : | ||||||
|  | // The above copyright notice and this permission notice shall be included in | ||||||
|  | // all copies or substantial portions of the Software. | ||||||
|  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE | ||||||
|  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | // THE SOFTWARE. | ||||||
|  | 
 | ||||||
|  | layout (location = 0) uniform uvec4 constants[4]; | ||||||
|  | 
 | ||||||
|  | #define A_GPU 1 | ||||||
|  | #define A_GLSL 1 | ||||||
|  | 
 | ||||||
|  | #ifdef YUZU_USE_FP16 | ||||||
|  |     #define A_HALF | ||||||
|  | #endif | ||||||
|  | #include "ffx_a.h" | ||||||
|  | 
 | ||||||
|  | #ifndef YUZU_USE_FP16 | ||||||
|  |     layout (binding=0) uniform sampler2D InputTexture; | ||||||
|  |     #if USE_EASU | ||||||
|  |         #define FSR_EASU_F 1 | ||||||
|  |         AF4 FsrEasuRF(AF2 p) { AF4 res = textureGather(InputTexture, p, 0); return res; } | ||||||
|  |         AF4 FsrEasuGF(AF2 p) { AF4 res = textureGather(InputTexture, p, 1); return res; } | ||||||
|  |         AF4 FsrEasuBF(AF2 p) { AF4 res = textureGather(InputTexture, p, 2); return res; } | ||||||
|  |     #endif | ||||||
|  |     #if USE_RCAS | ||||||
|  |         #define FSR_RCAS_F | ||||||
|  |         AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(InputTexture, ASU2(p), 0); } | ||||||
|  |         void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} | ||||||
|  |     #endif | ||||||
|  | #else | ||||||
|  |     layout (binding=0) uniform sampler2D InputTexture; | ||||||
|  |     #if USE_EASU | ||||||
|  |         #define FSR_EASU_H 1 | ||||||
|  |         AH4 FsrEasuRH(AF2 p) { AH4 res = AH4(textureGather(InputTexture, p, 0)); return res; } | ||||||
|  |         AH4 FsrEasuGH(AF2 p) { AH4 res = AH4(textureGather(InputTexture, p, 1)); return res; } | ||||||
|  |         AH4 FsrEasuBH(AF2 p) { AH4 res = AH4(textureGather(InputTexture, p, 2)); return res; } | ||||||
|  |     #endif | ||||||
|  |     #if USE_RCAS | ||||||
|  |         #define FSR_RCAS_H | ||||||
|  |         AH4 FsrRcasLoadH(ASW2 p) { return AH4(texelFetch(InputTexture, ASU2(p), 0)); } | ||||||
|  |         void FsrRcasInputH(inout AH1 r,inout AH1 g,inout AH1 b){} | ||||||
|  |     #endif | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include "ffx_fsr1.h" | ||||||
|  | 
 | ||||||
|  | #if USE_RCAS | ||||||
|  |     layout(location = 0) in vec2 frag_texcoord; | ||||||
|  | #endif | ||||||
|  | layout (location = 0) out vec4 frag_color; | ||||||
|  | 
 | ||||||
|  | void CurrFilter(AU2 pos) | ||||||
|  | { | ||||||
|  | #if USE_EASU | ||||||
|  |     #ifndef YUZU_USE_FP16 | ||||||
|  |         AF3 c; | ||||||
|  |         FsrEasuF(c, pos, constants[0], constants[1], constants[2], constants[3]); | ||||||
|  |         frag_color = AF4(c, 1.0); | ||||||
|  |     #else | ||||||
|  |         AH3 c; | ||||||
|  |         FsrEasuH(c, pos, constants[0], constants[1], constants[2], constants[3]); | ||||||
|  |         frag_color = AH4(c, 1.0); | ||||||
|  |     #endif | ||||||
|  | #endif | ||||||
|  | #if USE_RCAS | ||||||
|  |     #ifndef YUZU_USE_FP16 | ||||||
|  |         AF3 c; | ||||||
|  |         FsrRcasF(c.r, c.g, c.b, pos, constants[0]); | ||||||
|  |         frag_color = AF4(c, 1.0); | ||||||
|  |     #else | ||||||
|  |         AH3 c; | ||||||
|  |         FsrRcasH(c.r, c.g, c.b, pos, constants[0]); | ||||||
|  |         frag_color = AH4(c, 1.0); | ||||||
|  |     #endif | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  | #if USE_RCAS | ||||||
|  |     CurrFilter(AU2(frag_texcoord * vec2(textureSize(InputTexture, 0)))); | ||||||
|  | #else | ||||||
|  |     CurrFilter(AU2(gl_FragCoord.xy)); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 core | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | #define USE_EASU 1 | ||||||
|  | 
 | ||||||
|  | #include "opengl_fidelityfx_fsr.frag" | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | 
 | ||||||
|  | #version 460 core | ||||||
|  | #extension GL_GOOGLE_include_directive : enable | ||||||
|  | 
 | ||||||
|  | #define USE_RCAS 1 | ||||||
|  | 
 | ||||||
|  | #include "opengl_fidelityfx_fsr.frag" | ||||||
							
								
								
									
										101
									
								
								src/video_core/renderer_opengl/gl_fsr.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/video_core/renderer_opengl/gl_fsr.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,101 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #include "common/settings.h" | ||||||
|  | #include "video_core/fsr.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_fsr.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_shader_util.h" | ||||||
|  | 
 | ||||||
|  | namespace OpenGL { | ||||||
|  | using namespace FSR; | ||||||
|  | 
 | ||||||
|  | using FsrConstants = std::array<u32, 4 * 4>; | ||||||
|  | 
 | ||||||
|  | FSR::FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, | ||||||
|  |          std::string_view fsr_rcas_source) | ||||||
|  |     : fsr_vertex{CreateProgram(fsr_vertex_source, GL_VERTEX_SHADER)}, | ||||||
|  |       fsr_easu_frag{CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER)}, | ||||||
|  |       fsr_rcas_frag{CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER)} { | ||||||
|  |     glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f); | ||||||
|  |     glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FSR::~FSR() = default; | ||||||
|  | 
 | ||||||
|  | void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, | ||||||
|  |                u32 input_image_width, u32 input_image_height, | ||||||
|  |                const Common::Rectangle<int>& crop_rect) { | ||||||
|  | 
 | ||||||
|  |     const auto output_image_width = screen.GetWidth(); | ||||||
|  |     const auto output_image_height = screen.GetHeight(); | ||||||
|  | 
 | ||||||
|  |     if (fsr_intermediate_tex.handle) { | ||||||
|  |         GLint fsr_tex_width, fsr_tex_height; | ||||||
|  |         glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_WIDTH, | ||||||
|  |                                      &fsr_tex_width); | ||||||
|  |         glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_HEIGHT, | ||||||
|  |                                      &fsr_tex_height); | ||||||
|  |         if (static_cast<u32>(fsr_tex_width) != output_image_width || | ||||||
|  |             static_cast<u32>(fsr_tex_height) != output_image_height) { | ||||||
|  |             fsr_intermediate_tex.Release(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (!fsr_intermediate_tex.handle) { | ||||||
|  |         fsr_intermediate_tex.Create(GL_TEXTURE_2D); | ||||||
|  |         glTextureStorage2D(fsr_intermediate_tex.handle, 1, GL_RGB16F, output_image_width, | ||||||
|  |                            output_image_height); | ||||||
|  |         glNamedFramebufferTexture(fsr_framebuffer.handle, GL_COLOR_ATTACHMENT0, | ||||||
|  |                                   fsr_intermediate_tex.handle, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     GLint old_draw_fb; | ||||||
|  |     glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); | ||||||
|  | 
 | ||||||
|  |     glFrontFace(GL_CW); | ||||||
|  |     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fsr_framebuffer.handle); | ||||||
|  |     glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width), | ||||||
|  |                        static_cast<GLfloat>(output_image_height)); | ||||||
|  | 
 | ||||||
|  |     FsrConstants constants; | ||||||
|  |     FsrEasuConOffset( | ||||||
|  |         constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12, | ||||||
|  | 
 | ||||||
|  |         static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()), | ||||||
|  |         static_cast<f32>(input_image_width), static_cast<f32>(input_image_height), | ||||||
|  |         static_cast<f32>(output_image_width), static_cast<f32>(output_image_height), | ||||||
|  |         static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top)); | ||||||
|  | 
 | ||||||
|  |     glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); | ||||||
|  | 
 | ||||||
|  |     program_manager.BindPresentPrograms(fsr_vertex.handle, fsr_easu_frag.handle); | ||||||
|  |     glDrawArrays(GL_TRIANGLES, 0, 3); | ||||||
|  | 
 | ||||||
|  |     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); | ||||||
|  |     glBindTextureUnit(0, fsr_intermediate_tex.handle); | ||||||
|  | 
 | ||||||
|  |     const float sharpening = | ||||||
|  |         static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; | ||||||
|  | 
 | ||||||
|  |     FsrRcasCon(constants.data(), sharpening); | ||||||
|  |     glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FSR::InitBuffers() { | ||||||
|  |     fsr_framebuffer.Create(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FSR::ReleaseBuffers() { | ||||||
|  |     fsr_framebuffer.Release(); | ||||||
|  |     fsr_intermediate_tex.Release(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const OGLProgram& FSR::GetPresentFragmentProgram() const noexcept { | ||||||
|  |     return fsr_rcas_frag; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FSR::AreBuffersInitialized() const noexcept { | ||||||
|  |     return fsr_framebuffer.handle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace OpenGL
 | ||||||
							
								
								
									
										43
									
								
								src/video_core/renderer_opengl/gl_fsr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/video_core/renderer_opengl/gl_fsr.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | ||||||
|  | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <string_view> | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/math_util.h" | ||||||
|  | #include "video_core/fsr.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||||
|  | 
 | ||||||
|  | namespace OpenGL { | ||||||
|  | 
 | ||||||
|  | class ProgramManager; | ||||||
|  | 
 | ||||||
|  | class FSR { | ||||||
|  | public: | ||||||
|  |     explicit FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, | ||||||
|  |                  std::string_view fsr_rcas_source); | ||||||
|  |     ~FSR(); | ||||||
|  | 
 | ||||||
|  |     void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, | ||||||
|  |               u32 input_image_width, u32 input_image_height, | ||||||
|  |               const Common::Rectangle<int>& crop_rect); | ||||||
|  | 
 | ||||||
|  |     void InitBuffers(); | ||||||
|  | 
 | ||||||
|  |     void ReleaseBuffers(); | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept; | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] bool AreBuffersInitialized() const noexcept; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     OGLFramebuffer fsr_framebuffer; | ||||||
|  |     OGLProgram fsr_vertex; | ||||||
|  |     OGLProgram fsr_easu_frag; | ||||||
|  |     OGLProgram fsr_rcas_frag; | ||||||
|  |     OGLTexture fsr_intermediate_tex; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace OpenGL
 | ||||||
|  | @ -17,8 +17,14 @@ | ||||||
| #include "core/frontend/emu_window.h" | #include "core/frontend/emu_window.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/telemetry_session.h" | #include "core/telemetry_session.h" | ||||||
|  | #include "video_core/host_shaders/ffx_a_h.h" | ||||||
|  | #include "video_core/host_shaders/ffx_fsr1_h.h" | ||||||
|  | #include "video_core/host_shaders/full_screen_triangle_vert.h" | ||||||
| #include "video_core/host_shaders/fxaa_frag.h" | #include "video_core/host_shaders/fxaa_frag.h" | ||||||
| #include "video_core/host_shaders/fxaa_vert.h" | #include "video_core/host_shaders/fxaa_vert.h" | ||||||
|  | #include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h" | ||||||
|  | #include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h" | ||||||
|  | #include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h" | ||||||
| #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" | ||||||
|  | @ -31,6 +37,7 @@ | ||||||
| #include "video_core/host_shaders/smaa_edge_detection_vert.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_frag.h" | ||||||
| #include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" | #include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_fsr.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" | ||||||
|  | @ -268,12 +275,17 @@ void RendererOpenGL::InitOpenGLObjects() { | ||||||
|     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) { |     const auto replace_include = [](std::string& shader_source, std::string_view include_name, | ||||||
|         std::string shader_source{specialized_source}; |                                     std::string_view include_content) { | ||||||
|         constexpr std::string_view include_string = "#include \"opengl_smaa.glsl\""; |         const std::string include_string = fmt::format("#include \"{}\"", include_name); | ||||||
|         const std::size_t pos = shader_source.find(include_string); |         const std::size_t pos = shader_source.find(include_string); | ||||||
|         ASSERT(pos != std::string::npos); |         ASSERT(pos != std::string::npos); | ||||||
|         shader_source.replace(pos, include_string.size(), HostShaders::OPENGL_SMAA_GLSL); |         shader_source.replace(pos, include_string.size(), include_content); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) { | ||||||
|  |         std::string shader_source{specialized_source}; | ||||||
|  |         replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL); | ||||||
|         return CreateProgram(shader_source, stage); |         return CreateProgram(shader_source, stage); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -298,14 +310,32 @@ void RendererOpenGL::InitOpenGLObjects() { | ||||||
|         CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG), |         CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG), | ||||||
|                       GL_FRAGMENT_SHADER); |                       GL_FRAGMENT_SHADER); | ||||||
| 
 | 
 | ||||||
|  |     std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG}; | ||||||
|  |     replace_include(fsr_source, "ffx_a.h", HostShaders::FFX_A_H); | ||||||
|  |     replace_include(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H); | ||||||
|  | 
 | ||||||
|  |     std::string fsr_easu_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG}; | ||||||
|  |     std::string fsr_rcas_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG}; | ||||||
|  |     replace_include(fsr_easu_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source); | ||||||
|  |     replace_include(fsr_rcas_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source); | ||||||
|  | 
 | ||||||
|  |     fsr = std::make_unique<FSR>(HostShaders::FULL_SCREEN_TRIANGLE_VERT, fsr_easu_frag_source, | ||||||
|  |                                 fsr_rcas_frag_source); | ||||||
|  | 
 | ||||||
|     // Generate presentation sampler
 |     // Generate presentation sampler
 | ||||||
|     present_sampler.Create(); |     present_sampler.Create(); | ||||||
|     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
|  |     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||||
|  |     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||||
|  |     glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); | ||||||
| 
 | 
 | ||||||
|     present_sampler_nn.Create(); |     present_sampler_nn.Create(); | ||||||
|     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||||
|     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||||
|  |     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||||
|  |     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||||
|  |     glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); | ||||||
| 
 | 
 | ||||||
|     // Generate VBO handle for drawing
 |     // Generate VBO handle for drawing
 | ||||||
|     vertex_buffer.Create(); |     vertex_buffer.Create(); | ||||||
|  | @ -525,6 +555,31 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
| 
 | 
 | ||||||
|         glBindTextureUnit(0, aa_texture.handle); |         glBindTextureUnit(0, aa_texture.handle); | ||||||
|     } |     } | ||||||
|  |     glDisablei(GL_SCISSOR_TEST, 0); | ||||||
|  | 
 | ||||||
|  |     if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { | ||||||
|  |         if (!fsr->AreBuffersInitialized()) { | ||||||
|  |             fsr->InitBuffers(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         auto crop_rect = framebuffer_crop_rect; | ||||||
|  |         if (crop_rect.GetWidth() == 0) { | ||||||
|  |             crop_rect.right = framebuffer_width; | ||||||
|  |         } | ||||||
|  |         if (crop_rect.GetHeight() == 0) { | ||||||
|  |             crop_rect.bottom = framebuffer_height; | ||||||
|  |         } | ||||||
|  |         crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor); | ||||||
|  |         const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width); | ||||||
|  |         const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height); | ||||||
|  |         glBindSampler(0, present_sampler.handle); | ||||||
|  |         fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect); | ||||||
|  |     } else { | ||||||
|  |         if (fsr->AreBuffersInitialized()) { | ||||||
|  |             fsr->ReleaseBuffers(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     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)); | ||||||
| 
 | 
 | ||||||
|  | @ -540,10 +595,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|         case Settings::ScalingFilter::ScaleForce: |         case Settings::ScalingFilter::ScaleForce: | ||||||
|             return present_scaleforce_fragment.handle; |             return present_scaleforce_fragment.handle; | ||||||
|         case Settings::ScalingFilter::Fsr: |         case Settings::ScalingFilter::Fsr: | ||||||
|             LOG_WARNING( |             return fsr->GetPresentFragmentProgram().handle; | ||||||
|                 Render_OpenGL, |  | ||||||
|                 "FidelityFX Super Resolution is not supported in OpenGL, changing to ScaleForce"); |  | ||||||
|             return present_scaleforce_fragment.handle; |  | ||||||
|         default: |         default: | ||||||
|             return present_bilinear_fragment.handle; |             return present_bilinear_fragment.handle; | ||||||
|         } |         } | ||||||
|  | @ -578,6 +630,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|     f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width); |     f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width); | ||||||
|     f32 scale_v = |     f32 scale_v = | ||||||
|         static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height); |         static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height); | ||||||
|  | 
 | ||||||
|  |     if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) { | ||||||
|         // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
 |         // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
 | ||||||
|         // (e.g. handheld mode) on a 1920x1080 framebuffer.
 |         // (e.g. handheld mode) on a 1920x1080 framebuffer.
 | ||||||
|         if (framebuffer_crop_rect.GetWidth() > 0) { |         if (framebuffer_crop_rect.GetWidth() > 0) { | ||||||
|  | @ -588,6 +642,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|             scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) / |             scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) / | ||||||
|                       static_cast<f32>(screen_info.texture.height); |                       static_cast<f32>(screen_info.texture.height); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|     if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa && |     if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa && | ||||||
|         !screen_info.was_accelerated) { |         !screen_info.was_accelerated) { | ||||||
|         scale_u /= Settings::values.resolution_info.up_factor; |         scale_u /= Settings::values.resolution_info.up_factor; | ||||||
|  | @ -612,7 +667,6 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||||
|     } else { |     } else { | ||||||
|         glDisable(GL_FRAMEBUFFER_SRGB); |         glDisable(GL_FRAMEBUFFER_SRGB); | ||||||
|     } |     } | ||||||
|     glDisablei(GL_SCISSOR_TEST, 0); |  | ||||||
|     glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width), |     glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width), | ||||||
|                        static_cast<GLfloat>(layout.height)); |                        static_cast<GLfloat>(layout.height)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/renderer_opengl/gl_device.h" | #include "video_core/renderer_opengl/gl_device.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_fsr.h" | ||||||
| #include "video_core/renderer_opengl/gl_rasterizer.h" | #include "video_core/renderer_opengl/gl_rasterizer.h" | ||||||
| #include "video_core/renderer_opengl/gl_resource_manager.h" | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||||
| #include "video_core/renderer_opengl/gl_shader_manager.h" | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||||||
|  | @ -141,6 +142,8 @@ private: | ||||||
|     OGLTexture smaa_edges_tex; |     OGLTexture smaa_edges_tex; | ||||||
|     OGLTexture smaa_blend_tex; |     OGLTexture smaa_blend_tex; | ||||||
| 
 | 
 | ||||||
|  |     std::unique_ptr<FSR> fsr; | ||||||
|  | 
 | ||||||
|     /// OpenGL framebuffer data
 |     /// OpenGL framebuffer data
 | ||||||
|     std::vector<u8> gl_framebuffer_data; |     std::vector<u8> gl_framebuffer_data; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
| 
 | 
 | ||||||
| #include <cmath> |  | ||||||
| #include "common/bit_cast.h" |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/div_ceil.h" | #include "common/div_ceil.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
| 
 | 
 | ||||||
|  | #include "video_core/fsr.h" | ||||||
| #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_comp_spv.h" | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_comp_spv.h" | ||||||
| #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h" | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h" | ||||||
| #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h" | #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h" | ||||||
|  | @ -17,146 +16,7 @@ | ||||||
| #include "video_core/vulkan_common/vulkan_device.h" | #include "video_core/vulkan_common/vulkan_device.h" | ||||||
| 
 | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| namespace { | using namespace FSR; | ||||||
| // Reimplementations of the constant generating functions in ffx_fsr1.h
 |  | ||||||
| // GCC generated a lot of warnings when using the official header.
 |  | ||||||
| u32 AU1_AH1_AF1(f32 f) { |  | ||||||
|     static constexpr u32 base[512]{ |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |  | ||||||
|         0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, |  | ||||||
|         0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00, 0x2000, |  | ||||||
|         0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400, 0x4800, 0x4c00, |  | ||||||
|         0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, |  | ||||||
|         0x7bff, 0x7bff, 0x7bff, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, |  | ||||||
|         0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008, |  | ||||||
|         0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400, |  | ||||||
|         0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00, 0xc000, |  | ||||||
|         0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, 0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00, |  | ||||||
|         0xf000, 0xf400, 0xf800, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|         0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, |  | ||||||
|     }; |  | ||||||
|     static constexpr s8 shift[512]{ |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, |  | ||||||
|         0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, |  | ||||||
|         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, |  | ||||||
|         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, |  | ||||||
|         0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, |  | ||||||
|         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, |  | ||||||
|         0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |  | ||||||
|         0x18, 0x18, |  | ||||||
|     }; |  | ||||||
|     const u32 u = Common::BitCast<u32>(f); |  | ||||||
|     const u32 i = u >> 23; |  | ||||||
|     return base[i] + ((u & 0x7fffff) >> shift[i]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 AU1_AH2_AF2(f32 a[2]) { |  | ||||||
|     return AU1_AH1_AF1(a[0]) + (AU1_AH1_AF1(a[1]) << 16); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void FsrEasuCon(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], f32 inputViewportInPixelsX, |  | ||||||
|                 f32 inputViewportInPixelsY, f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, |  | ||||||
|                 f32 outputSizeInPixelsX, f32 outputSizeInPixelsY) { |  | ||||||
|     con0[0] = Common::BitCast<u32>(inputViewportInPixelsX / outputSizeInPixelsX); |  | ||||||
|     con0[1] = Common::BitCast<u32>(inputViewportInPixelsY / outputSizeInPixelsY); |  | ||||||
|     con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f); |  | ||||||
|     con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f); |  | ||||||
|     con1[0] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); |  | ||||||
|     con1[1] = Common::BitCast<u32>(1.0f / inputSizeInPixelsY); |  | ||||||
|     con1[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); |  | ||||||
|     con1[3] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsY); |  | ||||||
|     con2[0] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsX); |  | ||||||
|     con2[1] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY); |  | ||||||
|     con2[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX); |  | ||||||
|     con2[3] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY); |  | ||||||
|     con3[0] = Common::BitCast<u32>(0.0f / inputSizeInPixelsX); |  | ||||||
|     con3[1] = Common::BitCast<u32>(4.0f / inputSizeInPixelsY); |  | ||||||
|     con3[2] = con3[3] = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void FsrEasuConOffset(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], |  | ||||||
|                       f32 inputViewportInPixelsX, f32 inputViewportInPixelsY, |  | ||||||
|                       f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, f32 outputSizeInPixelsX, |  | ||||||
|                       f32 outputSizeInPixelsY, f32 inputOffsetInPixelsX, f32 inputOffsetInPixelsY) { |  | ||||||
|     FsrEasuCon(con0, con1, con2, con3, inputViewportInPixelsX, inputViewportInPixelsY, |  | ||||||
|                inputSizeInPixelsX, inputSizeInPixelsY, outputSizeInPixelsX, outputSizeInPixelsY); |  | ||||||
|     con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f + |  | ||||||
|                                    inputOffsetInPixelsX); |  | ||||||
|     con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f + |  | ||||||
|                                    inputOffsetInPixelsY); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void FsrRcasCon(u32* con, f32 sharpness) { |  | ||||||
|     sharpness = std::exp2f(-sharpness); |  | ||||||
|     f32 hSharp[2]{sharpness, sharpness}; |  | ||||||
|     con[0] = Common::BitCast<u32>(sharpness); |  | ||||||
|     con[1] = AU1_AH2_AF2(hSharp); |  | ||||||
|     con[2] = 0; |  | ||||||
|     con[3] = 0; |  | ||||||
| } |  | ||||||
| } // Anonymous namespace
 |  | ||||||
| 
 | 
 | ||||||
| FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image_count_, | FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image_count_, | ||||||
|          VkExtent2D output_size_) |          VkExtent2D output_size_) | ||||||
|  |  | ||||||
|  | @ -460,7 +460,7 @@ | ||||||
|              </item> |              </item> | ||||||
|              <item> |              <item> | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|                <string>AMD FidelityFX™️ Super Resolution (Vulkan Only)</string> |                <string>AMD FidelityFX™️ Super Resolution</string> | ||||||
|               </property> |               </property> | ||||||
|              </item> |              </item> | ||||||
|             </widget> |             </widget> | ||||||
|  |  | ||||||
|  | @ -983,11 +983,6 @@ void GMainWindow::InitializeWidgets() { | ||||||
|     filter_status_button->setFocusPolicy(Qt::NoFocus); |     filter_status_button->setFocusPolicy(Qt::NoFocus); | ||||||
|     connect(filter_status_button, &QPushButton::clicked, this, |     connect(filter_status_button, &QPushButton::clicked, this, | ||||||
|             &GMainWindow::OnToggleAdaptingFilter); |             &GMainWindow::OnToggleAdaptingFilter); | ||||||
|     auto filter = Settings::values.scaling_filter.GetValue(); |  | ||||||
|     if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && |  | ||||||
|         filter == Settings::ScalingFilter::Fsr) { |  | ||||||
|         Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); |  | ||||||
|     } |  | ||||||
|     UpdateFilterText(); |     UpdateFilterText(); | ||||||
|     filter_status_button->setCheckable(true); |     filter_status_button->setCheckable(true); | ||||||
|     filter_status_button->setChecked(true); |     filter_status_button->setChecked(true); | ||||||
|  | @ -3468,10 +3463,6 @@ void GMainWindow::OnToggleAdaptingFilter() { | ||||||
|     } else { |     } else { | ||||||
|         filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); |         filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); | ||||||
|     } |     } | ||||||
|     if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && |  | ||||||
|         filter == Settings::ScalingFilter::Fsr) { |  | ||||||
|         filter = Settings::ScalingFilter::NearestNeighbor; |  | ||||||
|     } |  | ||||||
|     Settings::values.scaling_filter.SetValue(filter); |     Settings::values.scaling_filter.SetValue(filter); | ||||||
|     filter_status_button->setChecked(true); |     filter_status_button->setChecked(true); | ||||||
|     UpdateFilterText(); |     UpdateFilterText(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 liamwhite
						liamwhite