mirror of https://git.suyu.dev/suyu/suyu
video_core/opengl: Add FSR upscaling filter to the OpenGL renderer
parent
380dcde154
commit
c4a49eb1dd
@ -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
|
@ -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
|
@ -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"
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue