1
0
mirror of https://github.com/citra-emu/citra.git synced 2024-12-21 09:40:07 +00:00

video_core: fix texture filters in GLES

anime4k: reset state.texture_units[0].texture_2d before filtering

clang-fmt
This commit is contained in:
BreadFish64 2020-04-04 16:54:49 -05:00 committed by SachinVin
parent 7b82883767
commit 91f52c2fdb
11 changed files with 88 additions and 102 deletions

View File

@ -100,10 +100,8 @@ add_library(video_core STATIC
set(SHADER_FILES
renderer_opengl/texture_filters/anime4k/refine.frag
renderer_opengl/texture_filters/anime4k/refine.vert
renderer_opengl/texture_filters/anime4k/x_gradient.frag
renderer_opengl/texture_filters/anime4k/y_gradient.frag
renderer_opengl/texture_filters/anime4k/y_gradient.vert
renderer_opengl/texture_filters/bicubic/bicubic.frag
renderer_opengl/texture_filters/scale_force/scale_force.frag
renderer_opengl/texture_filters/tex_coord.vert

View File

@ -34,30 +34,14 @@
#include "video_core/renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h"
#include "shaders/refine.frag"
#include "shaders/refine.vert"
#include "shaders/tex_coord.vert"
#include "shaders/x_gradient.frag"
#include "shaders/y_gradient.frag"
#include "shaders/y_gradient.vert"
namespace OpenGL {
Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_factor) {
const OpenGLState cur_state = OpenGLState::GetCurState();
const auto setup_temp_tex = [this](TempTex& texture, GLint internal_format, GLint format) {
texture.fbo.Create();
texture.tex.Create();
state.draw.draw_framebuffer = texture.fbo.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE, texture.tex.handle);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internal_format, 1024 * internal_scale_factor,
1024 * internal_scale_factor, 0, format, GL_HALF_FLOAT, nullptr);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE,
texture.tex.handle, 0);
};
setup_temp_tex(LUMAD, GL_R16F, GL_RED);
setup_temp_tex(XY, GL_RG16F, GL_RG);
vao.Create();
@ -65,17 +49,17 @@ Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_f
samplers[idx].Create();
state.texture_units[idx].sampler = samplers[idx].handle;
glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MIN_FILTER,
idx == 0 ? GL_LINEAR : GL_NEAREST);
idx != 2 ? GL_LINEAR : GL_NEAREST);
glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MAG_FILTER,
idx == 0 ? GL_LINEAR : GL_NEAREST);
idx != 2 ? GL_LINEAR : GL_NEAREST);
glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
state.draw.vertex_array = vao.handle;
gradient_x_program.Create(tex_coord_vert.data(), x_gradient_frag.data());
gradient_y_program.Create(y_gradient_vert.data(), y_gradient_frag.data());
refine_program.Create(refine_vert.data(), refine_frag.data());
gradient_y_program.Create(tex_coord_vert.data(), y_gradient_frag.data());
refine_program.Create(tex_coord_vert.data(), refine_frag.data());
state.draw.shader_program = gradient_y_program.handle;
state.Apply();
@ -84,8 +68,6 @@ Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_f
state.draw.shader_program = refine_program.handle;
state.Apply();
glUniform1i(glGetUniformLocation(refine_program.handle, "LUMAD"), 1);
glUniform1f(glGetUniformLocation(refine_program.handle, "final_scale"),
static_cast<GLfloat>(internal_scale_factor) / scale_factor);
cur_state.Apply();
}
@ -95,20 +77,48 @@ void Anime4kUltrafast::Filter(GLuint src_tex, const Common::Rectangle<u32>& src_
GLuint read_fb_handle, GLuint draw_fb_handle) {
const OpenGLState cur_state = OpenGLState::GetCurState();
// These will have handles from the previous texture that was filtered, reset them to avoid
// binding invalid textures.
state.texture_units[0].texture_2d = 0;
state.texture_units[1].texture_2d = 0;
state.texture_units[2].texture_2d = 0;
const auto setup_temp_tex = [this, &src_rect](GLint internal_format, GLint format) {
TempTex texture;
texture.fbo.Create();
texture.tex.Create();
state.texture_units[0].texture_2d = texture.tex.handle;
state.draw.draw_framebuffer = texture.fbo.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.tex.handle);
if (GL_ARB_texture_storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, internal_format,
src_rect.GetWidth() * internal_scale_factor,
src_rect.GetHeight() * internal_scale_factor);
} else {
glTexImage2D(
GL_TEXTURE_2D, 0, internal_format, src_rect.GetWidth() * internal_scale_factor,
src_rect.GetHeight() * internal_scale_factor, 0, format, GL_HALF_FLOAT, nullptr);
}
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
texture.tex.handle, 0);
return texture;
};
auto XY = setup_temp_tex(GL_RG16F, GL_RG);
auto LUMAD = setup_temp_tex(GL_R16F, GL_RED);
state.viewport = {static_cast<GLint>(src_rect.left * internal_scale_factor),
static_cast<GLint>(src_rect.bottom * internal_scale_factor),
static_cast<GLsizei>(src_rect.GetWidth() * internal_scale_factor),
static_cast<GLsizei>(src_rect.GetHeight() * internal_scale_factor)};
state.texture_units[0].texture_2d = src_tex;
state.texture_units[1].texture_2d = LUMAD.tex.handle;
state.texture_units[2].texture_2d = XY.tex.handle;
state.draw.draw_framebuffer = XY.fbo.handle;
state.draw.shader_program = gradient_x_program.handle;
state.Apply();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_RECTANGLE, LUMAD.tex.handle);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_RECTANGLE, XY.tex.handle);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// gradient y pass

View File

@ -30,8 +30,6 @@ private:
OGLTexture tex;
OGLFramebuffer fbo;
};
TempTex LUMAD;
TempTex XY;
std::array<OGLSampler, 3> samplers;

View File

@ -1,14 +1,12 @@
//? #version 330
precision mediump float;
in vec2 tex_coord;
in vec2 input_max;
out vec4 frag_color;
uniform sampler2D HOOKED;
uniform sampler2DRect LUMAD;
uniform sampler2DRect LUMAG;
uniform float final_scale;
uniform sampler2D LUMAD;
const float LINE_DETECT_THRESHOLD = 0.4;
const float STRENGTH = 0.6;
@ -21,12 +19,12 @@ struct RGBAL {
};
vec4 getAverage(vec4 cc, vec4 a, vec4 b, vec4 c) {
return cc * (1 - STRENGTH) + ((a + b + c) / 3) * STRENGTH;
return cc * (1.0 - STRENGTH) + ((a + b + c) / 3.0) * STRENGTH;
}
#define GetRGBAL(offset) \
RGBAL(textureOffset(HOOKED, tex_coord, offset), \
texture(LUMAD, clamp((gl_FragCoord.xy + offset) * final_scale, vec2(0.0), input_max)).x)
#define GetRGBAL(x_offset, y_offset) \
RGBAL(textureLodOffset(HOOKED, tex_coord, 0.0, ivec2(x_offset, y_offset)), \
textureLodOffset(LUMAD, tex_coord, 0.0, ivec2(x_offset, y_offset)).x)
float min3v(float a, float b, float c) {
return min(min(a, b), c);
@ -37,23 +35,23 @@ float max3v(float a, float b, float c) {
}
vec4 Compute() {
RGBAL cc = GetRGBAL(ivec2(0));
RGBAL cc = GetRGBAL(0, 0);
if (cc.l > LINE_DETECT_THRESHOLD) {
return cc.c;
}
RGBAL tl = GetRGBAL(ivec2(-1, -1));
RGBAL t = GetRGBAL(ivec2(0, -1));
RGBAL tr = GetRGBAL(ivec2(1, -1));
RGBAL tl = GetRGBAL(-1, -1);
RGBAL t = GetRGBAL(0, -1);
RGBAL tr = GetRGBAL(1, -1);
RGBAL l = GetRGBAL(ivec2(-1, 0));
RGBAL l = GetRGBAL(-1, 0);
RGBAL r = GetRGBAL(ivec2(1, 0));
RGBAL r = GetRGBAL(1, 0);
RGBAL bl = GetRGBAL(ivec2(-1, 1));
RGBAL b = GetRGBAL(ivec2(0, 1));
RGBAL br = GetRGBAL(ivec2(1, 1));
RGBAL bl = GetRGBAL(-1, 1);
RGBAL b = GetRGBAL(0, 1);
RGBAL br = GetRGBAL(1, 1);
// Kernel 0 and 4
float maxDark = max3v(br.l, b.l, bl.l);

View File

@ -1,14 +0,0 @@
//? #version 330
out vec2 tex_coord;
out vec2 input_max;
uniform sampler2D HOOKED;
const vec2 vertices[4] =
vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0));
void main() {
gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
tex_coord = (vertices[gl_VertexID] + 1.0) / 2.0;
input_max = textureSize(HOOKED, 0) * 2.0 - 1.0;
}

View File

@ -1,4 +1,6 @@
//? #version 330
precision mediump float;
in vec2 tex_coord;
out vec2 frag_color;
@ -7,7 +9,7 @@ uniform sampler2D tex_input;
const vec3 K = vec3(0.2627, 0.6780, 0.0593);
// TODO: improve handling of alpha channel
#define GetLum(xoffset) dot(K, textureOffset(tex_input, tex_coord, ivec2(xoffset, 0)).rgb)
#define GetLum(xoffset) dot(K, textureLodOffset(tex_input, tex_coord, 0.0, ivec2(xoffset, 0)).rgb)
void main() {
float l = GetLum(-1);

View File

@ -1,16 +1,18 @@
//? #version 330
in vec2 input_max;
precision mediump float;
in vec2 tex_coord;
out float frag_color;
uniform sampler2DRect tex_input;
uniform sampler2D tex_input;
void main() {
vec2 t = texture(tex_input, min(gl_FragCoord.xy + vec2(0.0, 1.0), input_max)).xy;
vec2 c = texture(tex_input, gl_FragCoord.xy).xy;
vec2 b = texture(tex_input, max(gl_FragCoord.xy - vec2(0.0, 1.0), vec2(0.0))).xy;
vec2 t = textureLodOffset(tex_input, tex_coord, 0.0, ivec2(0, 1)).xy;
vec2 c = textureLod(tex_input, tex_coord, 0.0).xy;
vec2 b = textureLodOffset(tex_input, tex_coord, 0.0, ivec2(0, -1)).xy;
vec2 grad = vec2(t.x + 2 * c.x + b.x, b.y - t.y);
vec2 grad = vec2(t.x + 2.0 * c.x + b.x, b.y - t.y);
frag_color = 1 - length(grad);
frag_color = 1.0 - length(grad);
}

View File

@ -1,12 +0,0 @@
//? #version 330
out vec2 input_max;
uniform sampler2D tex_size;
const vec2 vertices[4] =
vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0));
void main() {
gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
input_max = textureSize(tex_size, 0) * 2 - 1;
}

View File

@ -1,4 +1,6 @@
//? #version 330
precision mediump float;
in vec2 tex_coord;
out vec4 frag_color;
@ -18,7 +20,7 @@ vec4 cubic(float v) {
vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
vec2 texSize = textureSize(sampler, 0);
vec2 texSize = vec2(textureSize(sampler, 0));
vec2 invTexSize = 1.0 / texSize;
texCoords = texCoords * texSize - 0.5;

View File

@ -1,4 +1,6 @@
//? #version 330
precision mediump float;
in vec2 tex_coord;
in vec2 source_size;
in vec2 output_size;
@ -6,7 +8,7 @@ in vec2 output_size;
out vec4 frag_color;
uniform sampler2D tex;
uniform float scale;
uniform lowp float scale;
const int BLEND_NONE = 0;
const int BLEND_NORMAL = 1;
@ -42,12 +44,12 @@ float GetLeftRatio(vec2 center, vec2 origin, vec2 direction) {
return smoothstep(-sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, v);
}
vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5);
vec2 coord = tex_coord - pos / source_size;
#define P(x, y) textureOffset(tex, coord, ivec2(x, y))
void main() {
vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5);
vec2 coord = tex_coord - pos / source_size;
//---------------------------------------
// Input Pixel Mapping: -|x|x|x|-
// x|A|B|C|x
@ -142,15 +144,15 @@ void main() {
(IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) &&
IsPixEqual(F, C) && !IsPixEqual(E, I))));
vec2 origin = vec2(0.0, 1.0 / sqrt(2.0));
ivec2 direction = ivec2(1, -1);
vec2 direction = vec2(1.0, -1.0);
if (doLineBlend) {
bool haveShallowLine =
(STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && E != G && D != G;
bool haveSteepLine =
(STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && E != C && B != C;
origin = haveShallowLine ? vec2(0.0, 0.25) : vec2(0.0, 0.5);
direction.x += haveShallowLine ? 1 : 0;
direction.y -= haveSteepLine ? 1 : 0;
direction.x += haveShallowLine ? 1.0 : 0.0;
direction.y -= haveSteepLine ? 1.0 : 0.0;
}
vec4 blendPix = mix(H, F, step(ColorDist(E, F), ColorDist(E, H)));
res = mix(res, blendPix, GetLeftRatio(pos, origin, direction));
@ -169,15 +171,15 @@ void main() {
(IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) &&
IsPixEqual(H, I) && !IsPixEqual(E, G))));
vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0);
ivec2 direction = ivec2(1, 1);
vec2 direction = vec2(1.0, 1.0);
if (doLineBlend) {
bool haveShallowLine =
(STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && E != A && B != A;
bool haveSteepLine =
(STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && E != I && F != I;
origin = haveShallowLine ? vec2(-0.25, 0.0) : vec2(-0.5, 0.0);
direction.y += haveShallowLine ? 1 : 0;
direction.x += haveSteepLine ? 1 : 0;
direction.y += haveShallowLine ? 1.0 : 0.0;
direction.x += haveSteepLine ? 1.0 : 0.0;
}
origin = origin;
direction = direction;
@ -198,15 +200,15 @@ void main() {
(IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) &&
IsPixEqual(B, A) && !IsPixEqual(E, C))));
vec2 origin = vec2(1.0 / sqrt(2.0), 0.0);
ivec2 direction = ivec2(-1, -1);
vec2 direction = vec2(-1.0, -1.0);
if (doLineBlend) {
bool haveShallowLine =
(STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && E != I && H != I;
bool haveSteepLine =
(STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && E != A && D != A;
origin = haveShallowLine ? vec2(0.25, 0.0) : vec2(0.5, 0.0);
direction.y -= haveShallowLine ? 1 : 0;
direction.x -= haveSteepLine ? 1 : 0;
direction.y -= haveShallowLine ? 1.0 : 0.0;
direction.x -= haveSteepLine ? 1.0 : 0.0;
}
vec4 blendPix = mix(F, B, step(ColorDist(E, B), ColorDist(E, F)));
res = mix(res, blendPix, GetLeftRatio(pos, origin, direction));
@ -225,15 +227,15 @@ void main() {
(IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) &&
IsPixEqual(D, G) && !IsPixEqual(E, A))));
vec2 origin = vec2(0.0, -1.0 / sqrt(2.0));
ivec2 direction = ivec2(-1, 1);
vec2 direction = vec2(-1.0, 1.0);
if (doLineBlend) {
bool haveShallowLine =
(STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && E != C && F != C;
bool haveSteepLine =
(STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && E != G && H != G;
origin = haveShallowLine ? vec2(0.0, -0.25) : vec2(0.0, -0.5);
direction.x -= haveShallowLine ? 1 : 0;
direction.y += haveSteepLine ? 1 : 0;
direction.x -= haveShallowLine ? 1.0 : 0.0;
direction.y += haveSteepLine ? 1.0 : 0.0;
}
vec4 blendPix = mix(D, B, step(ColorDist(E, B), ColorDist(E, D)));
res = mix(res, blendPix, GetLeftRatio(pos, origin, direction));

View File

@ -4,7 +4,7 @@ out vec2 source_size;
out vec2 output_size;
uniform sampler2D tex;
uniform float scale;
uniform lowp float scale;
const vec2 vertices[4] =
vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0));
@ -12,6 +12,6 @@ const vec2 vertices[4] =
void main() {
gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
tex_coord = (vertices[gl_VertexID] + 1.0) / 2.0;
source_size = textureSize(tex, 0);
source_size = vec2(textureSize(tex, 0));
output_size = source_size * scale;
}