1#version 460 core 2#extension GL_ARB_separate_shader_objects : enable 3#extension GL_ARB_shading_language_420pack : enable 4 5// ================================================================================================= 6// RCAS FINAL PASS 7// Ported from AMD FSR 1 / RCAS reference. 8// ================================================================================================= 9 10#include "render/shaders/common/render_color_conversion_common.h" 11#include "render/shaders/common/render_post_process_structs_common.h" 12 13#include "common/bloom_common.h" 14 15//#define Lsr_RCAS_PASSTHROUGH_ALPHA 16//#define Lsr_RCAS_DENOISE 17 18layout(set = 0, binding = 0) uniform texture2D RCAS_InputTex; 19layout(set = 0, binding = 1, rgba16f) uniform writeonly image2D RCAS_OutputImg; // final sharpened 20layout(set = 0, binding = 2) uniform sampler uSampler; 21 22 23layout(push_constant, std430) uniform uPostProcessPushConstant 24{ 25 LocalPostProcessPushConstantStruct uPc; 26}; 27 28vec2 DisplaySize() { return uPc.viewportSizeInvSize.xy; } 29vec2 InvDisplaySize(){ return uPc.viewportSizeInvSize.zw; } 30 31// uPc.factor = (exposure, pre_exposure, sharpness, 0) 32// Sharpness : 0 = max, 1 = -1 stop, 2 = -2 stops 33float Exposure() { return uPc.factor.x; } 34float PreExposure() { return uPc.factor.y; } 35 36vec3 PrepareRgb (vec3 c){ return max(c * Exposure() * PreExposure(), vec3(0.0)); } 37vec3 UnprepareRgb(vec3 c){ return max(c / Exposure(), vec3(0.0)); } 38 39 40#define Saturate(x) clamp((x), 0.0, 1.0) 41#define Max3(a,b,c) max(max((a),(b)),(c)) 42#define Min3(a,b,c) min(min((a),(b)),(c)) 43#define IsGreaterThanZero(x) step(0.0, (x)) 44#define ApproximateReciprocalMedium(x) (1.0 / (x)) 45#define ApproximateReciprocalSquareRoot(x) inversesqrt(x) 46#define Fract(x) fract(x) 47 48 49uvec4 RCASConfig() 50{ 51 float linearSharp = exp2(-uPc.factor.z); 52 uvec4 con; 53 54 con.x = floatBitsToUint(linearSharp); 55 56 con.y = packHalf2x16(vec2(linearSharp)); 57 58 con.z = 0u; 59 con.w = 0u; 60 return con; 61} 62 63vec4 LsrRcasLoadF(ivec2 p) 64{ 65 vec2 uv = (vec2(p) + 0.5) * InvDisplaySize(); 66 vec4 c = texture(sampler2D(RCAS_InputTex, uSampler), uv); 67 68 c.rgb = PrepareRgb(c.rgb); 69 return c; 70} 71 72#define Lsr_RCAS_LIMIT (0.25 - (1.0/16.0)) 73 74void LsrRcasF(out float pixR, out float pixG, out float pixB, 75#ifdef Lsr_RCAS_PASSTHROUGH_ALPHA 76 out float pixA, 77#endif 78 uvec2 ip, uvec4 con) 79{ 80 // neighbourhood fetch ----------------------------------------------------------------- 81 ivec2 sp = ivec2(ip); 82 vec3 b = LsrRcasLoadF(sp + ivec2( 0,-1)).rgb; 83 vec3 d = LsrRcasLoadF(sp + ivec2(-1, 0)).rgb; 84#ifdef Lsr_RCAS_PASSTHROUGH_ALPHA 85 vec4 ee = LsrRcasLoadF(sp); 86 vec3 e = ee.rgb; pixA = ee.a; 87#else 88 vec3 e = LsrRcasLoadF(sp).rgb; 89#endif 90 vec3 f = LsrRcasLoadF(sp + ivec2( 1, 0)).rgb; 91 vec3 h = LsrRcasLoadF(sp + ivec2( 0, 1)).rgb; 92 93 94 // luma*2 and noise figure -------------------------------------------------------------- 95 float bL = dot(b, vec3(0.5,1.0,0.5)); 96 float dL = dot(d, vec3(0.5,1.0,0.5)); 97 float eL = dot(e, vec3(0.5,1.0,0.5)); 98 float fL = dot(f, vec3(0.5,1.0,0.5)); 99 float hL = dot(h, vec3(0.5,1.0,0.5)); 100 101 float nz = 0.25*(bL+dL+fL+hL) - eL; 102 nz = Saturate(abs(nz) * ApproximateReciprocalMedium( 103 Max3(Max3(bL,dL,eL), fL, hL) - Min3(Min3(bL,dL,eL), fL, hL))); 104 nz = -0.5* nz + 1.0; 105 106 // min/max ring ------------------------------------------------------------------------ 107 vec3 mn4 = vec3( min(min(b.x,d.x), min(f.x,h.x)), 108 min(min(b.y,d.y), min(f.y,h.y)), 109 min(min(b.z,d.z), min(f.z,h.z)) ); 110 vec3 mx4 = vec3( max(max(b.x,d.x), max(f.x,h.x)), 111 max(max(b.y,d.y), max(f.y,h.y)), 112 max(max(b.z,d.z), max(f.z,h.z)) ); 113 114 vec2 peakC = vec2(1.0, -4.0); 115 116 vec3 hitMin = mn4 / (4.0*mx4); 117 vec3 hitMax = (peakC.x - mx4) / (peakC.x + peakC.y + 4.0*mn4); 118 vec3 lobe = max(-hitMin, hitMax); 119 float l = max(-Lsr_RCAS_LIMIT, min(max(max(lobe.x,lobe.y), lobe.z), 0.0)); 120 121 float sharp = uintBitsToFloat(con.x); // linear sharpness stored in con.x 122#ifdef Lsr_RCAS_DENOISE 123 l *= nz; 124#endif 125 l *= sharp; 126 127 float rcpL = ApproximateReciprocalMedium(4.0*l + 1.0); 128 vec3 outC = (l*b + l*d + l*h + l*f + e) * rcpL; 129 130 pixR = outC.r; 131 pixG = outC.g; 132 pixB = outC.b; 133} 134 135struct RCASOutputs { vec3 fUpscaledColor; }; 136 137void CurrFilter(uvec2 ip, inout RCASOutputs outR) 138{ 139 float r,g,b; 140 LsrRcasF(r,g,b,ip, RCASConfig()); 141 outR.fUpscaledColor = UnprepareRgb(vec3(r,g,b)); 142} 143 144#define cTgs 16 145 146 147layout(local_size_x = cTgs, local_size_y = cTgs, local_size_z = 1) in; 148void main() 149{ 150 uvec2 gid = gl_GlobalInvocationID.xy; 151 if (any(greaterThanEqual(gid, uvec2(DisplaySize())))) return; 152 153 RCASOutputs o; CurrFilter(gid, o); 154 imageStore(RCAS_OutputImg, ivec2(gid), vec4(o.fUpscaledColor, 1.0)); 155} 156