• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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