//============================================================================================================================== // An optimized AMD FSR's EASU implementation for Mobiles // Based on https://github.com/GPUOpen-Effects/FidelityFX-FSR/blob/master/ffx-fsr/ffx_fsr1.h // Details can be found: https://atyuwen.github.io/posts/optimizing-fsr/ // Distributed under the MIT License. Copyright (c) 2021 atyuwen. // -- FsrEasuSampleH should be implemented by calling shader, like following: // AH3 FsrEasuSampleH(AF2 p) { return MyTex.SampleLevel(LinearSampler, p, 0).xyz; } //============================================================================================================================== void FsrEasuL( out AH3 pix, AF2 ip, AF4 con0, AF4 con1, AF4 con2, AF4 con3){ //------------------------------------------------------------------------------------------------------------------------------ // Direction is the '+' diff. // A // B C D // E AF2 pp=(ip)*(con0.xy)+(con0.zw); AF2 tc=(pp+AF2_(0.5))*con1.xy; AH3 sA=FsrEasuSampleH(tc-AF2(0, con1.y)); AH3 sB=FsrEasuSampleH(tc-AF2(con1.x, 0)); AH3 sC=FsrEasuSampleH(tc); AH3 sD=FsrEasuSampleH(tc+AF2(con1.x, 0)); AH3 sE=FsrEasuSampleH(tc+AF2(0, con1.y)); AH1 lA=sA.r*AH1_(0.5)+sA.g; AH1 lB=sB.r*AH1_(0.5)+sB.g; AH1 lC=sC.r*AH1_(0.5)+sC.g; AH1 lD=sD.r*AH1_(0.5)+sD.g; AH1 lE=sE.r*AH1_(0.5)+sE.g; // Then takes magnitude from abs average of both sides of 'C'. // Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms. AH1 dc=lD-lC; AH1 cb=lC-lB; AH1 lenX=max(abs(dc),abs(cb)); lenX=ARcpH1(lenX); AH1 dirX=lD-lB; lenX=ASatH1(abs(dirX)*lenX); lenX*=lenX; // Repeat for the y axis. AH1 ec=lE-lC; AH1 ca=lC-lA; AH1 lenY=max(abs(ec),abs(ca)); lenY=ARcpH1(lenY); AH1 dirY=lE-lA; lenY=ASatH1(abs(dirY)*lenY); AH1 len = lenY * lenY + lenX; AH2 dir = AH2(dirX, dirY); //------------------------------------------------------------------------------------------------------------------------------ AH2 dir2=dir*dir; AH1 dirR=dir2.x+dir2.y; if (dirR