From 00d36110d528991ebeae4d45d28be3dbb206bd9e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 1 Sep 2021 14:25:21 -0700 Subject: [PATCH] Integrate optimized EASU. filament cannot use fp16, so we make the necessary changes for the float version. Note that we are using mediump float, which ends up using 16 bits floats anyways. This provides 78% reduction in execution time (i.e. 4.6x performance improvement). We see the EASU go from 4.2ms to 0.9ms. The quality is slightly impacted. --- RELEASE_NOTES.md | 2 + filament/CMakeLists.txt | 2 + filament/src/materials/fsr/ffx_fsr1_mobile.h | 152 +++++++++++-------- filament/src/materials/fsr/fsr_easu.mat | 12 +- 4 files changed, 101 insertions(+), 67 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0f2d24ea2b..acd6da5238 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,6 +8,8 @@ A new header is inserted each time a *tag* is created. - engine: New night adaptation API on `ColorGrading`. This API can be used to create an effect that that simulates color and brightness shits in human vision in low-light conditions. +- engine: improved performance of AMD FidelityFX FSR1 by 4.6x, it now runs in about 2ms in 4K. + ## v1.12.3 - engine: Support AMD FidelityFX Super Resolution for dynamic resolution scaling diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 45dbd33278..1af9efef6c 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -165,6 +165,7 @@ set(PRIVATE_HDRS src/fsr.h src/materials/fsr/ffx_a.h src/materials/fsr/ffx_fsr1.h + src/materials/fsr/ffx_fsr1_mobile.h src/upcast.h ) @@ -362,6 +363,7 @@ add_custom_command( OUTPUT "${MATERIAL_DIR}/fsr_easu.filamat" DEPENDS src/materials/fsr/ffx_a.h DEPENDS src/materials/fsr/ffx_fsr1.h + DEPENDS src/materials/fsr/ffx_fsr1_mobile.h APPEND ) diff --git a/filament/src/materials/fsr/ffx_fsr1_mobile.h b/filament/src/materials/fsr/ffx_fsr1_mobile.h index 010e152a81..4851cffe50 100644 --- a/filament/src/materials/fsr/ffx_fsr1_mobile.h +++ b/filament/src/materials/fsr/ffx_fsr1_mobile.h @@ -6,13 +6,19 @@ // -- FsrEasuSampleH should be implemented by calling shader, like following: // half3 FsrEasuSampleH(float2 p) { return MyTex.SampleLevel(LinearSampler, p, 0).xyz; } //============================================================================================================================== + +#define rcp(x) (1.0/(x)) +#define rsqrt inversesqrt + +AF3 FsrEasuSampleF(AF2 p); + void FsrEasuL( - out AH3 pix, - AF2 ip, - AF4 con0, - AF4 con1, - AF4 con2, - AF4 con3){ + out AF3 pix, + highp AF2 ip, + highp AF4 con0, + highp AF4 con1, + highp AF4 con2, + highp AF4 con3){ //------------------------------------------------------------------------------------------------------------------------------ // Direction is the '+' diff. // A @@ -20,83 +26,97 @@ void FsrEasuL( // 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; + AF3 sA=FsrEasuSampleF(tc-AF2(0, con1.y)); + AF3 sB=FsrEasuSampleF(tc-AF2(con1.x, 0)); + AF3 sC=FsrEasuSampleF(tc); + AF3 sD=FsrEasuSampleF(tc+AF2(con1.x, 0)); + AF3 sE=FsrEasuSampleF(tc+AF2(0, con1.y)); + AF1 lA=sA.r*AF1_(0.5)+sA.g; + AF1 lB=sB.r*AF1_(0.5)+sB.g; + AF1 lC=sC.r*AF1_(0.5)+sC.g; + AF1 lD=sD.r*AF1_(0.5)+sD.g; + AF1 lE=sE.r*AF1_(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); + AF1 dc=lD-lC; + AF1 cb=lC-lB; + AF1 lenX=max(abs(dc),abs(cb)); + lenX=ARcpF1(lenX); + AF1 dirX=lD-lB; + lenX=ASatF1(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