mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-01-10 14:23:57 +00:00
[client] egl: add ffx_cas post process filter
This commit is contained in:
parent
9b1d03fcfe
commit
92de467edc
9 changed files with 3499 additions and 12 deletions
|
@ -52,6 +52,8 @@ build_shaders(
|
||||||
shader/splash_bg.frag
|
shader/splash_bg.frag
|
||||||
shader/splash_logo.vert
|
shader/splash_logo.vert
|
||||||
shader/splash_logo.frag
|
shader/splash_logo.frag
|
||||||
|
shader/basic.vert
|
||||||
|
shader/ffx_cas.frag
|
||||||
)
|
)
|
||||||
|
|
||||||
make_defines(
|
make_defines(
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#include "desktop_rgb.frag.h"
|
#include "desktop_rgb.frag.h"
|
||||||
#include "desktop_rgb.def.h"
|
#include "desktop_rgb.def.h"
|
||||||
|
|
||||||
|
#include "basic.vert.h"
|
||||||
|
#include "ffx_cas.frag.h"
|
||||||
|
|
||||||
struct DesktopShader
|
struct DesktopShader
|
||||||
{
|
{
|
||||||
EGL_Shader * shader;
|
EGL_Shader * shader;
|
||||||
|
@ -75,6 +78,10 @@ struct EGL_Desktop
|
||||||
|
|
||||||
bool useDMA;
|
bool useDMA;
|
||||||
LG_RendererFormat format;
|
LG_RendererFormat format;
|
||||||
|
|
||||||
|
EGL_Shader * ffxCAS;
|
||||||
|
bool enableCAS;
|
||||||
|
PostProcessHandle ffxCASHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
// forwards
|
// forwards
|
||||||
|
@ -106,6 +113,12 @@ static bool egl_initDesktopShader(
|
||||||
return true;
|
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 egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display,
|
||||||
bool useDMA, int maxRects)
|
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)->scaleAlgo = option_get_int("egl", "scale" );
|
||||||
(*desktop)->useDMA = useDMA;
|
(*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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +210,7 @@ void egl_desktopFree(EGL_Desktop ** desktop)
|
||||||
egl_shaderFree (&(*desktop)->shader.shader);
|
egl_shaderFree (&(*desktop)->shader.shader);
|
||||||
egl_desktopRectsFree(&(*desktop)->mesh );
|
egl_desktopRectsFree(&(*desktop)->mesh );
|
||||||
countedBufferRelease(&(*desktop)->matrix );
|
countedBufferRelease(&(*desktop)->matrix );
|
||||||
|
egl_shaderFree(&(*desktop)->ffxCAS);
|
||||||
|
|
||||||
free(*desktop);
|
free(*desktop);
|
||||||
*desktop = NULL;
|
*desktop = NULL;
|
||||||
|
@ -232,6 +253,14 @@ void egl_desktopConfigUI(EGL_Desktop * desktop)
|
||||||
}
|
}
|
||||||
igSliderInt("##nvgain", &desktop->nvGain, 0, desktop->nvMax, format, 0);
|
igSliderInt("##nvgain", &desktop->nvGain, 0, desktop->nvMax, format, 0);
|
||||||
igPopItemWidth();
|
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)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupFilters(desktop);
|
||||||
|
|
||||||
if (!egl_desktopSetup(desktop, desktop->format))
|
if (!egl_desktopSetup(desktop, desktop->format))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
1907
client/renderers/EGL/shader/ffx_a.h
Normal file
1907
client/renderers/EGL/shader/ffx_a.h
Normal file
File diff suppressed because it is too large
Load diff
68
client/renderers/EGL/shader/ffx_cas.frag
Normal file
68
client/renderers/EGL/shader/ffx_cas.frag
Normal 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);
|
||||||
|
}
|
1445
client/renderers/EGL/shader/ffx_cas.h
Normal file
1445
client/renderers/EGL/shader/ffx_cas.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -39,6 +39,7 @@ extern const EGL_TextureOps EGL_TextureDMABUF;
|
||||||
|
|
||||||
typedef struct RenderStep
|
typedef struct RenderStep
|
||||||
{
|
{
|
||||||
|
bool enabled;
|
||||||
GLuint fb;
|
GLuint fb;
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
EGL_Shader * shader;
|
EGL_Shader * shader;
|
||||||
|
@ -300,11 +301,12 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||||
|
|
||||||
BindData * bd = (BindData *)this->bindData;
|
BindData * bd = (BindData *)this->bindData;
|
||||||
RenderStep * step;
|
RenderStep * step;
|
||||||
ringbuffer_reset(this->textures);
|
|
||||||
|
|
||||||
/* if the postProcessing has not yet been done */
|
/* if the postProcessing has not yet been done */
|
||||||
if (!this->postProcessed)
|
if (!this->postProcessed)
|
||||||
{
|
{
|
||||||
|
ringbuffer_reset(this->textures);
|
||||||
|
|
||||||
if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK)
|
if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -316,8 +318,14 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||||
|
|
||||||
ringbuffer_forEach(this->textures, rbBindTexture, bd, true);
|
ringbuffer_forEach(this->textures, rbBindTexture, bd, true);
|
||||||
|
|
||||||
|
bool cleanup = false;
|
||||||
for(ll_reset(this->render); ll_walk(this->render, (void **)&step); )
|
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
|
/* create the framebuffer here as it must be in the same gl context as
|
||||||
* it's usage */
|
* it's usage */
|
||||||
if (!step->fb)
|
if (!step->fb)
|
||||||
|
@ -361,26 +369,29 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore the state and the viewport */
|
/* restore the state and the viewport */
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
if (cleanup)
|
||||||
glUseProgram(0);
|
{
|
||||||
egl_resetViewport(this->egl);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glUseProgram(0);
|
||||||
|
egl_resetViewport(this->egl);
|
||||||
|
}
|
||||||
|
|
||||||
this->postProcessed = true;
|
this->postProcessed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* bind the last texture */
|
/* bind the last texture */
|
||||||
ll_peek_tail(this->render, (void **)&step);
|
BindInfo * bi = (BindInfo *)ringBuffer_getLastValue(this->textures);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, step->tex);
|
glBindTexture(GL_TEXTURE_2D, bi->tex);
|
||||||
glBindSampler(0, this->sampler);
|
glBindSampler(0, this->sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EGL_TEX_STATUS_OK;
|
return EGL_TEX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
|
PostProcessHandle egl_textureAddFilter(EGL_Texture * this, EGL_Shader * shader,
|
||||||
float outputScale)
|
float outputScale, bool enabled)
|
||||||
{
|
{
|
||||||
if (!this->render)
|
if (!this->render)
|
||||||
{
|
{
|
||||||
|
@ -396,6 +407,7 @@ enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
|
||||||
step->scale = outputScale;
|
step->scale = outputScale;
|
||||||
step->uInRes = egl_shaderGetUniform(shader, "uInRes" );
|
step->uInRes = egl_shaderGetUniform(shader, "uInRes" );
|
||||||
step->uOutRes = egl_shaderGetUniform(shader, "uOutRes");
|
step->uOutRes = egl_shaderGetUniform(shader, "uOutRes");
|
||||||
|
step->enabled = enabled;
|
||||||
|
|
||||||
this->scale = outputScale;
|
this->scale = outputScale;
|
||||||
|
|
||||||
|
@ -404,11 +416,17 @@ enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader,
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &step->tex);
|
glDeleteTextures(1, &step->tex);
|
||||||
free(step);
|
free(step);
|
||||||
return EGL_TEX_STATUS_ERROR;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ll_push(this->render, step);
|
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)
|
float egl_textureGetScale(EGL_Texture * this)
|
||||||
|
|
|
@ -170,7 +170,10 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture);
|
||||||
|
|
||||||
enum EGL_TexStatus egl_textureBind(EGL_Texture * texture);
|
enum EGL_TexStatus egl_textureBind(EGL_Texture * texture);
|
||||||
|
|
||||||
enum EGL_TexStatus egl_textureAddShader(EGL_Texture * texture,
|
typedef void * PostProcessHandle;
|
||||||
EGL_Shader * shader, float outputScale);
|
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);
|
float egl_textureGetScale(EGL_Texture * texture);
|
||||||
|
|
|
@ -33,6 +33,7 @@ int ringbuffer_getLength(const RingBuffer rb);
|
||||||
int ringbuffer_getStart (const RingBuffer rb);
|
int ringbuffer_getStart (const RingBuffer rb);
|
||||||
int ringbuffer_getCount (const RingBuffer rb);
|
int ringbuffer_getCount (const RingBuffer rb);
|
||||||
void * ringbuffer_getValues(const RingBuffer rb);
|
void * ringbuffer_getValues(const RingBuffer rb);
|
||||||
|
void * ringBuffer_getLastValue(const RingBuffer rb);
|
||||||
|
|
||||||
typedef void (*RingBufferValueFn)(void * value, void * udata);
|
typedef void (*RingBufferValueFn)(void * value, void * udata);
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,18 @@ void * ringbuffer_getValues(const RingBuffer rb)
|
||||||
return rb->values;
|
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 ringbuffer_setPreOverwriteFn(const RingBuffer rb, RingBufferValueFn fn,
|
||||||
void * udata)
|
void * udata)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue