Skip to content

Commit

Permalink
Add proper support for upscaling shaders, add Spline36 upscaling
Browse files Browse the repository at this point in the history
Spline36 isn't as amazing as I had hoped heh. And it will need work to
work in GLSL ES. Anyway...

This also renames u_texcoordDelta to u_texelDelta to fit in with u_pixelDelta.
  • Loading branch information
hrydgard committed Oct 22, 2013
1 parent 492fcb2 commit 7d8aed0
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 52 deletions.
2 changes: 2 additions & 0 deletions GPU/Common/PostShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void LoadPostShaderInfo(std::vector<std::string> directories) {
ShaderInfo off;
off.name = "Off";
off.section = "Off";
off.outputResolution = false;
shaderInfo.push_back(off);

for (size_t d = 0; d < directories.size(); d++) {
Expand Down Expand Up @@ -81,6 +82,7 @@ void LoadPostShaderInfo(std::vector<std::string> directories) {
info.fragmentShaderFile = path + "/" + temp;
section.Get("Vertex", &temp, "");
info.vertexShaderFile = path + "/" + temp;
section.Get("OutputResolution", &info.outputResolution, false);
shaderInfo.erase(std::find(shaderInfo.begin(), shaderInfo.end(), info.name), shaderInfo.end());
shaderInfo.push_back(info);
}
Expand Down
3 changes: 3 additions & 0 deletions GPU/Common/PostShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct ShaderInfo {
std::string fragmentShaderFile;
std::string vertexShaderFile;

// Run at output instead of input resolution
bool outputResolution;

// TODO: Add support for all kinds of fun options like mapping the depth buffer,
// SRGB texture reads, multiple shaders chained, etc.

Expand Down
92 changes: 61 additions & 31 deletions GPU/GLES/Framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ void CenterRect(float *x, float *y, float *w, float *h,
}
}

void ClearBuffer() {
static void ClearBuffer() {
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}

void DisableState() {
static void DisableState() {
glstate.blend.disable();
glstate.cullFace.disable();
glstate.depthTest.disable();
Expand Down Expand Up @@ -184,6 +184,7 @@ void FramebufferManager::CompileDraw2DProgram() {
}

if (shaderInfo) {
postShaderAtOutputResolution_ = shaderInfo->outputResolution;
postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), &errorString);
if (!postShaderProgram_) {
// DO NOT turn this into a report, as it will pollute our logs with all kinds of
Expand All @@ -204,9 +205,21 @@ void FramebufferManager::CompileDraw2DProgram() {
SetNumExtraFBOs(1);
float u_delta = 1.0f / PSP_CoreParameter().renderWidth;
float v_delta = 1.0f / PSP_CoreParameter().renderHeight;
int deltaLoc = glsl_uniform_loc(postShaderProgram_, "u_texcoordDelta");
float u_pixel_delta = u_delta;
float v_pixel_delta = v_delta;
if (postShaderAtOutputResolution_) {
float x, y, w, h;
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);
u_pixel_delta = 1.0f / w;
v_pixel_delta = 1.0f / h;
}

int deltaLoc = glsl_uniform_loc(postShaderProgram_, "u_texelDelta");
if (deltaLoc != -1)
glUniform2f(deltaLoc, u_delta, v_delta);
int pixelDeltaLoc = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta");
if (pixelDeltaLoc != -1)
glUniform2f(pixelDeltaLoc, u_pixel_delta, v_pixel_delta);
usePostShader_ = true;
}
} else {
Expand Down Expand Up @@ -370,16 +383,37 @@ void FramebufferManager::DrawPixels(const u8 *framebuf, GEBufferFormat pixelForm
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);

glBindTexture(GL_TEXTURE_2D,drawPixelsTex_);
if (g_Config.iTexFiltering == LINEAR || (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos))
{
if (g_Config.iTexFiltering == LINEAR || (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos)) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,512,272, GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat == GE_FORMAT_8888 ? framebuf : convBuf);

DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, 480.0f / 512.0f);
// This draws directly at the backbuffer so if there's a post shader, we need to apply it here. Should try to unify this path
// with the regular path somehow, but this simple solution works for most of the post shaders (it always runs at output resolution so FXAA may look odd).
if (usePostShader_) {
DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, 480.0f / 512.0f, 1.0f, postShaderProgram_);
} else {
DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, 480.0f / 512.0f);
}
}

void FramebufferManager::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, bool flip, float uscale, float vscale, GLSLProgram *program) {
void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, bool flip, float uscale, float vscale, GLSLProgram *program) {
if (texture) {
// We know the texture, we can do a DrawTexture shortcut on nvidia.
#if defined(USING_GLES2) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(IOS)
if (gl_extensions.NV_draw_texture) {
// Fast path for Tegra. TODO: Make this path work on desktop nvidia, seems glew doesn't have a clue.
// Actually, on Desktop we should just use glBlitFramebuffer.
glDrawTextureNV(texture, 0,
x, y, w, h, 0.0f,
0, 0, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height);

This comment has been minimized.

Copy link
@xsacha

xsacha Oct 22, 2013

Collaborator

Error: 'vfb' was not declared in this scope.
For Android and Blackberry.

This comment has been minimized.

Copy link
@hrydgard

hrydgard Oct 22, 2013

Author Owner

Oops, fixing.

This comment has been minimized.

Copy link
@xsacha

xsacha Oct 22, 2013

Collaborator

While you're there, you can probably add BLACKBERRY to the #ifdef as well. I doubt they'll ever get a Tegra.

return;
}
#endif

glBindTexture(GL_TEXTURE_2D, texture);
}

float u2 = uscale;
// Since we're flipping, 0 is down. That's where the scale goes.
float v1 = flip ? 1.0f : 1.0f - vscale;
Expand Down Expand Up @@ -770,7 +804,7 @@ void FramebufferManager::CopyDisplayToOutput() {
}

if (!vfb) {
// Just a pointer to plain memory to draw. Draw it. And make sure to set the viewport...
// Just a pointer to plain memory to draw. Draw it.
DrawPixels(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_);
return;
}
Expand Down Expand Up @@ -806,44 +840,40 @@ void FramebufferManager::CopyDisplayToOutput() {

GLuint colorTexture = fbo_get_color_texture(vfb->fbo);

// Output coordinates
float x, y, w, h;
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);

// TODO ES3: Use glInvalidateFramebuffer to discard depth/stencil data at the end of frame.
// and to discard extraFBOs_ after using them.

if (usePostShader_ && extraFBOs_.size() == 1) {
glBindTexture(GL_TEXTURE_2D, colorTexture);

if (!usePostShader_) {
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, true, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height);
} else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) {
// An additional pass, FXAA to the extra FBO.
fbo_bind_as_render_target(extraFBOs_[0]);
int fbo_w, fbo_h;
fbo_get_dimensions(extraFBOs_[0], &fbo_w, &fbo_h);
glstate.viewport.set(0, 0, fbo_w, fbo_h);
DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, true, 1.0f, 1.0f, postShaderProgram_);
DrawActiveTexture(colorTexture, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, true, 1.0f, 1.0f, postShaderProgram_);

fbo_unbind();

// Use the extra FBO, with applied FXAA, as a texture.
// fbo_bind_color_as_texture(extraFBOs_[0], 0);
colorTexture = fbo_get_color_texture(extraFBOs_[0]);
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, true, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height);
} else {
// Use post-shader, but run shader at output resolution.
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, true, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height, postShaderProgram_);
}

glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates
float x, y, w, h;
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);

#if defined(USING_GLES2) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(IOS)
if (gl_extensions.NV_draw_texture) {
// Fast path for Tegra. TODO: Make this path work on desktop nvidia, seems glew doesn't have a clue.
// Actually, on Desktop we should just use glBlitFramebuffer.
glDrawTextureNV(colorTexture, 0,
x, y, w, h, 0.0f,
0, 0, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height);
return;
}
#endif

glBindTexture(GL_TEXTURE_2D, colorTexture);
DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, true, 480.0f / (float)vfb->width, 272.0f / (float)vfb->height);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
Expand Down Expand Up @@ -990,7 +1020,7 @@ void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFrameb

CompileDraw2DProgram();

DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, flip, upscale, vscale, draw2dprogram_);
DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, flip, upscale, vscale, draw2dprogram_);

glBindTexture(GL_TEXTURE_2D, 0);
fbo_unbind();
Expand Down
5 changes: 4 additions & 1 deletion GPU/GLES/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ class FramebufferManager {
}

void DrawPixels(const u8 *framebuf, GEBufferFormat pixelFormat, int linesize);
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, bool flip = false, float uscale = 1.0f, float vscale = 1.0f, GLSLProgram *program = 0);

// If texture != 0, will bind it.
void DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, bool flip = false, float uscale = 1.0f, float vscale = 1.0f, GLSLProgram *program = 0);

void DestroyAllFBOs();
void DecimateFBOs();
Expand Down Expand Up @@ -202,6 +204,7 @@ class FramebufferManager {
TextureCache *textureCache_;
ShaderManager *shaderManager_;
bool usePostShader_;
bool postShaderAtOutputResolution_;

// Used by antialiasing
std::vector<FBO *> extraFBOs_;
Expand Down
6 changes: 3 additions & 3 deletions assets/shaders/4xhqglsl.vsh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
attribute vec4 a_position;
attribute vec2 a_texcoord0;
uniform mat4 u_viewproj;
uniform vec2 u_texcoordDelta;
uniform vec2 u_texelDelta;

varying vec4 v_texcoord0;
varying vec4 v_texcoord1;
Expand All @@ -15,8 +15,8 @@ float scaleoffset = 0.8;

void main()
{
float x = u_texcoordDelta.x*scaleoffset;
float y = u_texcoordDelta.y*scaleoffset;
float x = u_texelDelta.x*scaleoffset;
float y = u_texelDelta.y*scaleoffset;
vec2 dg1 = vec2( x,y);
vec2 dg2 = vec2(-x,y);
vec2 sd1 = dg1*0.5;
Expand Down
6 changes: 3 additions & 3 deletions assets/shaders/aacolor.vsh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
attribute vec4 a_position;
attribute vec2 a_texcoord0;
uniform mat4 u_viewproj;
uniform vec2 u_texcoordDelta;
uniform vec2 u_texelDelta;

varying vec4 v_texcoord0;
varying vec4 v_texcoord1;
Expand All @@ -19,8 +19,8 @@ float scaleoffset = 0.8;
void main()

{
float x = u_texcoordDelta.x*scaleoffset;
float y = u_texcoordDelta.y*scaleoffset;
float x = u_texelDelta.x*scaleoffset;
float y = u_texelDelta.y*scaleoffset;
gl_Position = u_viewproj * a_position;
v_texcoord0 = a_texcoord0.xyxy;
v_texcoord1 = v_texcoord0;
Expand Down
6 changes: 3 additions & 3 deletions assets/shaders/cartoon.vsh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
attribute vec4 a_position;
attribute vec2 a_texcoord0;
uniform mat4 u_viewproj;
uniform vec2 u_texcoordDelta;
uniform vec2 u_texelDelta;

varying vec4 v_texcoord0;
varying vec4 v_texcoord1;
Expand All @@ -15,8 +15,8 @@ float scaleoffset = 0.8; //edge detection offset

void main()
{
float x = u_texcoordDelta.x*scaleoffset;
float y = u_texcoordDelta.y*scaleoffset;
float x = u_texelDelta.x*scaleoffset;
float y = u_texelDelta.y*scaleoffset;
vec2 dg1 = vec2( x,y);
vec2 dg2 = vec2(-x,y);
vec2 dx = vec2(x,0.0);
Expand Down
5 changes: 5 additions & 0 deletions assets/shaders/defaultshaders.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ Vertex=4xhqglsl.vsh
Name=AA-Color
Fragment=aacolor.fsh
Vertex=aacolor.vsh
[UpscaleSpline36]
Name=Spline36 Upscaler
Fragment=upscale_spline36.fsh
Vertex=upscale_spline36.vsh
OutputResolution=True
12 changes: 6 additions & 6 deletions assets/shaders/fxaa.fsh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ precision mediump int;
uniform sampler2D sampler0;

// The inverse of the texture dimensions along X and Y
uniform vec2 u_texcoordDelta;
uniform vec2 u_texelDelta;
varying vec2 v_texcoord0;

void main() {
Expand All @@ -23,10 +23,10 @@ void main() {
float FXAA_REDUCE_MUL = 1.0/8.0;
float FXAA_REDUCE_MIN = (1.0/128.0);

vec3 rgbNW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, -1.0) * u_texcoordDelta)).xyz;
vec3 rgbNE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, -1.0) * u_texcoordDelta)).xyz;
vec3 rgbSW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, +1.0) * u_texcoordDelta)).xyz;
vec3 rgbSE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, +1.0) * u_texcoordDelta)).xyz;
vec3 rgbNW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, -1.0) * u_texelDelta)).xyz;
vec3 rgbNE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, -1.0) * u_texelDelta)).xyz;
vec3 rgbSW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, +1.0) * u_texelDelta)).xyz;
vec3 rgbSE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, +1.0) * u_texelDelta)).xyz;
vec3 rgbM = texture2D(sampler0, v_texcoord0.xy).xyz;

vec3 luma = vec3(0.299, 0.587, 0.114);
Expand All @@ -48,7 +48,7 @@ void main() {
float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);

dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * u_texcoordDelta;
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * u_texelDelta;

vec3 rgbA = (1.0/2.0) * (
texture2D(sampler0, v_texcoord0.xy + dir * (1.0/3.0 - 0.5)).xyz +
Expand Down
10 changes: 5 additions & 5 deletions assets/shaders/natural.vsh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
uniform vec4 u_texcoordDelta;
uniform vec4 u_texelDelta;

attribute vec4 a_position;
attribute vec2 a_texcoord0;
Expand All @@ -13,8 +13,8 @@ void main()
{
gl_Position=u_viewproj * a_position;

v_texcoord0=a_texcoord0.xyxy+vec4(-0.5,-0.5,-1.5,-1.5)*u_texcoordDelta.xyxy;
v_texcoord1=a_texcoord0.xyxy+vec4( 0.5,-0.5, 1.5,-1.5)*u_texcoordDelta.xyxy;
v_texcoord2=a_texcoord0.xyxy+vec4(-0.5, 0.5,-1.5, 1.5)*u_texcoordDelta.xyxy;
v_texcoord3=a_texcoord0.xyxy+vec4( 0.5, 0.5, 1.5, 1.5)*u_texcoordDelta.xyxy;
v_texcoord0=a_texcoord0.xyxy+vec4(-0.5,-0.5,-1.5,-1.5)*u_texelDelta.xyxy;
v_texcoord1=a_texcoord0.xyxy+vec4( 0.5,-0.5, 1.5,-1.5)*u_texelDelta.xyxy;
v_texcoord2=a_texcoord0.xyxy+vec4(-0.5, 0.5,-1.5, 1.5)*u_texelDelta.xyxy;
v_texcoord3=a_texcoord0.xyxy+vec4( 0.5, 0.5, 1.5, 1.5)*u_texelDelta.xyxy;
}
Loading

1 comment on commit 7d8aed0

@danyalzia
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work! That's what I meant when I asked about "viewport" and you did it. Now I can push my improvements to shaders. Hang on.

Please sign in to comment.