This commit is contained in:
2026-02-24 11:44:01 -08:00
parent c9839c9be6
commit 1c3c30e6ce
34 changed files with 1629 additions and 1271 deletions

View File

@ -0,0 +1,9 @@
https://gpuopen.com/manuals/fidelityfx_sdk/license/
Copyright © 2024 Advanced Micro Devices, Inc.
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.

View File

@ -0,0 +1,157 @@
#version 450
// AMD FidelityFX Super Resolution 1.0.2 - EASU (Edge Adaptive Spatial Upsampling)
#include "compiled.inc"
uniform sampler2D tex;
uniform vec2 screenSize;
in vec2 texCoord;
out vec4 fragColor;
// Helper functions from AMD ffx_a.h
float APrxLoRcpF1(float a) {
return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a));
}
float AMax3F1(float x, float y, float z) {
return max(x, max(y, z));
}
float AMin3F1(float x, float y, float z) {
return min(x, min(y, z));
}
// Attempt to use textureGather for efficiency when available
#if __VERSION__ >= 400
void FsrEasuTap(
inout vec3 aC,
inout float aW,
vec2 off,
vec2 dir,
vec2 len,
float lob,
float clp,
vec3 c
) {
vec2 v = off * dir;
float d2 = v.x + v.y;
d2 = clamp(d2 * APrxLoRcpF1(max(abs(v.x), abs(v.y))), 0.0, 1.0);
d2 = d2 * d2;
d2 = d2 * len.x + len.y;
float wB = 2.0 / 5.0 * d2 - 1.0;
float wA = lob * d2 - 1.0;
wB *= wB;
wA *= wA;
float w = 25.0 / 16.0 * wA * wB;
w = min(w, clp);
w = max(w, 0.0);
aC += c * w;
aW += w;
}
vec3 FsrEasuF(vec2 ip) {
vec2 inputSize = textureSize(tex, 0);
vec2 inputRcp = 1.0 / inputSize;
// Position in input pixels
vec2 pp = ip * inputSize - 0.5;
vec2 fp = floor(pp);
pp -= fp;
// 12-tap kernel
// b c
// e f g h
// i j k l
// n o
ivec2 sp = ivec2(fp);
vec3 b = texelFetch(tex, sp + ivec2(0, -1), 0).rgb;
vec3 c = texelFetch(tex, sp + ivec2(1, -1), 0).rgb;
vec3 e = texelFetch(tex, sp + ivec2(-1, 0), 0).rgb;
vec3 f = texelFetch(tex, sp + ivec2(0, 0), 0).rgb;
vec3 g = texelFetch(tex, sp + ivec2(1, 0), 0).rgb;
vec3 h = texelFetch(tex, sp + ivec2(2, 0), 0).rgb;
vec3 i = texelFetch(tex, sp + ivec2(-1, 1), 0).rgb;
vec3 j = texelFetch(tex, sp + ivec2(0, 1), 0).rgb;
vec3 k = texelFetch(tex, sp + ivec2(1, 1), 0).rgb;
vec3 l = texelFetch(tex, sp + ivec2(2, 1), 0).rgb;
vec3 n = texelFetch(tex, sp + ivec2(0, 2), 0).rgb;
vec3 o = texelFetch(tex, sp + ivec2(1, 2), 0).rgb;
// Luma for edge detection (using green channel approximation)
float bL = b.g + 0.5 * (b.r + b.b);
float cL = c.g + 0.5 * (c.r + c.b);
float eL = e.g + 0.5 * (e.r + e.b);
float fL = f.g + 0.5 * (f.r + f.b);
float gL = g.g + 0.5 * (g.r + g.b);
float hL = h.g + 0.5 * (h.r + h.b);
float iL = i.g + 0.5 * (i.r + i.b);
float jL = j.g + 0.5 * (j.r + j.b);
float kL = k.g + 0.5 * (k.r + k.b);
float lL = l.g + 0.5 * (l.r + l.b);
float nL = n.g + 0.5 * (n.r + n.b);
float oL = o.g + 0.5 * (o.r + o.b);
// Gradient detection
float dirX = (cL - bL) + (gL - fL) + (kL - jL) + (oL - nL);
float dirY = (eL - iL) + (fL - jL) + (gL - kL) + (hL - lL);
// Normalize direction
float dirR = APrxLoRcpF1(max(abs(dirX), abs(dirY)));
dirX *= dirR;
dirY *= dirR;
// Calculate stretch based on edge direction
float len = length(vec2(dirX, dirY));
len = len * 0.5;
len *= len;
float stretch = (dirX * dirX + dirY * dirY) * APrxLoRcpF1(max(abs(dirX), abs(dirY)));
vec2 len2 = vec2(1.0 + (stretch - 1.0) * len, 1.0 - 0.5 * len);
float lob = 0.5 + (0.25 - 0.04 - 0.5) * len;
float clp = APrxLoRcpF1(lob);
// Accumulate samples
vec3 aC = vec3(0.0);
float aW = 0.0;
vec2 dir = vec2(dirX, dirY);
FsrEasuTap(aC, aW, vec2(0.0, -1.0) - pp, dir, len2, lob, clp, b);
FsrEasuTap(aC, aW, vec2(1.0, -1.0) - pp, dir, len2, lob, clp, c);
FsrEasuTap(aC, aW, vec2(-1.0, 0.0) - pp, dir, len2, lob, clp, e);
FsrEasuTap(aC, aW, vec2(0.0, 0.0) - pp, dir, len2, lob, clp, f);
FsrEasuTap(aC, aW, vec2(1.0, 0.0) - pp, dir, len2, lob, clp, g);
FsrEasuTap(aC, aW, vec2(2.0, 0.0) - pp, dir, len2, lob, clp, h);
FsrEasuTap(aC, aW, vec2(-1.0, 1.0) - pp, dir, len2, lob, clp, i);
FsrEasuTap(aC, aW, vec2(0.0, 1.0) - pp, dir, len2, lob, clp, j);
FsrEasuTap(aC, aW, vec2(1.0, 1.0) - pp, dir, len2, lob, clp, k);
FsrEasuTap(aC, aW, vec2(2.0, 1.0) - pp, dir, len2, lob, clp, l);
FsrEasuTap(aC, aW, vec2(0.0, 2.0) - pp, dir, len2, lob, clp, n);
FsrEasuTap(aC, aW, vec2(1.0, 2.0) - pp, dir, len2, lob, clp, o);
// Normalize
vec3 pix = aC / aW;
// Clamp to neighborhood min/max to prevent ringing
vec3 mn = min(min(min(f, g), j), k);
vec3 mx = max(max(max(f, g), j), k);
pix = clamp(pix, mn, mx);
return pix;
}
#else
// Fallback for older GLSL - simple bilinear
vec3 FsrEasuF(vec2 ip) {
return texture(tex, ip).rgb;
}
#endif
void main() {
vec3 col = FsrEasuF(texCoord);
fragColor = vec4(col, 1.0);
}

View File

@ -0,0 +1,19 @@
{
"contexts": [
{
"name": "fsr1_easu_pass",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "screenSize",
"link": "_screenSize"
}
],
"texture_params": [],
"vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "fsr1_easu_pass.frag.glsl"
}
]
}