[client] egl: add ffx_cas post process filter

This commit is contained in:
Geoffrey McRae 2021-08-09 22:42:51 +10:00
parent 9b1d03fcfe
commit 92de467edc
9 changed files with 3499 additions and 12 deletions

View file

@ -52,6 +52,8 @@ build_shaders(
shader/splash_bg.frag
shader/splash_logo.vert
shader/splash_logo.frag
shader/basic.vert
shader/ffx_cas.frag
)
make_defines(

View file

@ -38,6 +38,9 @@
#include "desktop_rgb.frag.h"
#include "desktop_rgb.def.h"
#include "basic.vert.h"
#include "ffx_cas.frag.h"
struct DesktopShader
{
EGL_Shader * shader;
@ -75,6 +78,10 @@ struct EGL_Desktop
bool useDMA;
LG_RendererFormat format;
EGL_Shader * ffxCAS;
bool enableCAS;
PostProcessHandle ffxCASHandle;
};
// forwards
@ -106,6 +113,12 @@ static bool egl_initDesktopShader(
return true;
}
static void setupFilters(EGL_Desktop * desktop)
{
desktop->ffxCASHandle =
egl_textureAddFilter(desktop->texture, desktop->ffxCAS, 1.0f, false);
}
bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display,
bool useDMA, int maxRects)
{
@ -156,6 +169,13 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display,
(*desktop)->scaleAlgo = option_get_int("egl", "scale" );
(*desktop)->useDMA = useDMA;
egl_shaderInit(&(*desktop)->ffxCAS);
egl_shaderCompile((*desktop)->ffxCAS,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size);
setupFilters(*desktop);
return true;
}
@ -190,6 +210,7 @@ void egl_desktopFree(EGL_Desktop ** desktop)
egl_shaderFree (&(*desktop)->shader.shader);
egl_desktopRectsFree(&(*desktop)->mesh );
countedBufferRelease(&(*desktop)->matrix );
egl_shaderFree(&(*desktop)->ffxCAS);
free(*desktop);
*desktop = NULL;
@ -232,6 +253,14 @@ void egl_desktopConfigUI(EGL_Desktop * desktop)
}
igSliderInt("##nvgain", &desktop->nvGain, 0, desktop->nvMax, format, 0);
igPopItemWidth();
bool cas = desktop->enableCAS;
igCheckbox("AMD FidelityFX CAS", &cas);
if (cas != desktop->enableCAS)
{
desktop->enableCAS = cas;
egl_textureEnableFilter(desktop->ffxCASHandle, cas);
}
}
bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
@ -299,6 +328,8 @@ bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dm
return false;
}
setupFilters(desktop);
if (!egl_desktopSetup(desktop, desktop->format))
return false;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
#version 300 es
precision mediump float;
in vec2 iFragCoord;
out vec4 fragColor;
uniform sampler2D iChannel0;
uniform uvec2 uInRes[8];
uniform uvec2 uOutRes;
// the following are not available until verion 400 or later
// so we implement our own versions of them
uint bitfieldExtract(uint val, int off, int size)
{
uint mask = uint((1 << size) - 1);
return uint(val >> off) & mask;
}
uint bitfieldInsert(uint a, uint b, int c, int d)
{
uint mask = ~(0xffffffffu << d) << c;
mask = ~mask;
a &= mask;
return a | (b << c);
}
#define A_GPU 1
#define A_GLSL 1
#include "ffx_a.h"
vec3 imageLoad(ivec2 point)
{
return texelFetch(iChannel0, point, 0).rgb;
}
AF3 CasLoad(ASU2 p)
{
return imageLoad(p).rgb;
}
void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {}
#include "ffx_cas.h"
void main()
{
uvec2 point = uvec2(iFragCoord * vec2(uInRes[0].xy));
vec4 color;
vec2 inputResolution = vec2(uInRes[0]);
vec2 outputResolution = vec2(uOutRes);
float sharpnessTuning = 1.0f;
uvec4 const0;
uvec4 const1;
CasSetup(const0, const1, sharpnessTuning,
inputResolution.x, inputResolution.y,
outputResolution.x, outputResolution.y);
CasFilter(
fragColor.r, fragColor.g, fragColor.b,
point,
const0, const1,
true);
}

File diff suppressed because it is too large Load diff

View file

@ -39,6 +39,7 @@ extern const EGL_TextureOps EGL_TextureDMABUF;
typedef struct RenderStep
{
bool enabled;
GLuint fb;
GLuint tex;
EGL_Shader * shader;
@ -300,11 +301,12 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
BindData * bd = (BindData *)this->bindData;
RenderStep * step;
ringbuffer_reset(this->textures);
/* if the postProcessing has not yet been done */
if (!this->postProcessed)
{
ringbuffer_reset(this->textures);
if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK)
return status;
@ -316,8 +318,14 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
ringbuffer_forEach(this->textures, rbBindTexture, bd, true);
bool cleanup = false;
for(ll_reset(this->render); ll_walk(this->render, (void **)&step); )
{
if (!step->enabled)
continue;
cleanup = true;
/* create the framebuffer here as it must be in the same gl context as
* it's usage */
if (!step->fb)
@ -361,26 +369,29 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
}
/* restore the state and the viewport */
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
egl_resetViewport(this->egl);
if (cleanup)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
egl_resetViewport(this->egl);
}
this->postProcessed = true;
}
else
{
/* bind the last texture */
ll_peek_tail(this->render, (void **)&step);
BindInfo * bi = (BindInfo *)ringBuffer_getLastValue(this->textures);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, step->tex);
glBindTexture(GL_TEXTURE_2D, bi->tex);
glBindSampler(0, this->sampler);
}
return EGL_TEX_STATUS_OK;
}
enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
float outputScale)
PostProcessHandle egl_textureAddFilter(EGL_Texture * this, EGL_Shader * shader,
float outputScale, bool enabled)
{
if (!this->render)
{
@ -396,6 +407,7 @@ enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
step->scale = outputScale;
step->uInRes = egl_shaderGetUniform(shader, "uInRes" );
step->uOutRes = egl_shaderGetUniform(shader, "uOutRes");
step->enabled = enabled;
this->scale = outputScale;
@ -404,11 +416,17 @@ enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
{
glDeleteTextures(1, &step->tex);
free(step);
return EGL_TEX_STATUS_ERROR;
return NULL;
}
ll_push(this->render, step);
return EGL_TEX_STATUS_OK;
return (PostProcessHandle)step;
}
void egl_textureEnableFilter(PostProcessHandle * handle, bool enable)
{
RenderStep * step = (RenderStep *)handle;
step->enabled = enable;
}
float egl_textureGetScale(EGL_Texture * this)

View file

@ -170,7 +170,10 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture);
enum EGL_TexStatus egl_textureBind(EGL_Texture * texture);
enum EGL_TexStatus egl_textureAddShader(EGL_Texture * texture,
EGL_Shader * shader, float outputScale);
typedef void * PostProcessHandle;
PostProcessHandle egl_textureAddFilter(EGL_Texture * texture,
EGL_Shader * shader, float outputScale, bool enabled);
void egl_textureEnableFilter(PostProcessHandle * handle, bool enable);
float egl_textureGetScale(EGL_Texture * texture);

View file

@ -33,6 +33,7 @@ int ringbuffer_getLength(const RingBuffer rb);
int ringbuffer_getStart (const RingBuffer rb);
int ringbuffer_getCount (const RingBuffer rb);
void * ringbuffer_getValues(const RingBuffer rb);
void * ringBuffer_getLastValue(const RingBuffer rb);
typedef void (*RingBufferValueFn)(void * value, void * udata);

View file

@ -99,6 +99,18 @@ void * ringbuffer_getValues(const RingBuffer rb)
return rb->values;
}
void * ringBuffer_getLastValue(const RingBuffer rb)
{
if (rb->count == 0)
return NULL;
int index = rb->start + rb->count - 1;
if (index >= rb->length)
index -= rb->length;
return rb->values + index * rb->valueSize;
}
void ringbuffer_setPreOverwriteFn(const RingBuffer rb, RingBufferValueFn fn,
void * udata)
{