Skip to content

Commit

Permalink
PlatformCore: Change shader order
Browse files Browse the repository at this point in the history
Move xBRZ shader to the end of the shader stack, making it
an output shader. This necessitated changes to the rendering loop and
an addition of another shader uniform.
  • Loading branch information
GranMinigun committed Oct 29, 2023
1 parent d25f9f4 commit 7c9cf6a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct OGLVideoDevice : VideoDevice {
void UpdateTextures();
void CreateShaderPrograms();
void ReleaseShaderPrograms();
void UpdateShaderUniforms();

auto CompileShader(
GLenum type,
Expand Down
127 changes: 67 additions & 60 deletions src/platform/core/src/device/ogl_video_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ OGLVideoDevice::~OGLVideoDevice() {
glDeleteVertexArrays(1, &quad_vao);
glDeleteBuffers(1, &quad_vbo);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(4, texture);
glDeleteTextures(3, texture);
}

void OGLVideoDevice::Initialize() {
Expand All @@ -59,7 +59,7 @@ void OGLVideoDevice::Initialize() {

// Create three textures and a framebuffer for postprocessing.
glGenFramebuffers(1, &fbo);
glGenTextures(4, texture);
glGenTextures(3, texture);

glEnable(GL_FRAMEBUFFER_SRGB);

Expand Down Expand Up @@ -106,20 +106,6 @@ void OGLVideoDevice::CreateShaderPrograms() {

ReleaseShaderPrograms();

// xBRZ freescale upsampling filter (two passes)
if(video.filter == Video::Filter::xBRZ) {
auto [success0, program0] = CompileProgram(xbrz0_vert, xbrz0_frag);
auto [success1, program1] = CompileProgram(xbrz1_vert, xbrz1_frag);

if(success0 && success1) {
programs.push_back(program0);
programs.push_back(program1);
} else {
if(success0) glDeleteProgram(program0);
if(success1) glDeleteProgram(program1);
}
}

// Color correction pass
switch(video.color) {
case Video::Color::higan: {
Expand Down Expand Up @@ -147,29 +133,56 @@ void OGLVideoDevice::CreateShaderPrograms() {
}

// Output pass (final)
auto [success, program] = CompileProgram(output_vert, output_frag);
if(success) {
programs.push_back(program);
switch (video.filter) {
// xBRZ freescale upsampling filter (two passes)
case Video::Filter::xBRZ: {
auto [success0, program0] = CompileProgram(xbrz0_vert, xbrz0_frag);
auto [success1, program1] = CompileProgram(xbrz1_vert, xbrz1_frag);

if(success0 && success1) {
programs.push_back(program0);
programs.push_back(program1);
} else {
if(success0) glDeleteProgram(program0);
if(success1) glDeleteProgram(program1);
}
break;
}
// Plain linear/nearest output.
default: {
auto [success, program] = CompileProgram(output_vert, output_frag);
if(success) {
programs.push_back(program);
}
break;
}
}

UpdateShaderUniforms();
}

void OGLVideoDevice::UpdateShaderUniforms() {
// Set constant shader uniforms.
for(auto program : programs) {
for(const auto program : programs) {
glUseProgram(program);

auto screen_map = glGetUniformLocation(program, "u_screen_map");
const auto screen_map = glGetUniformLocation(program, "u_screen_map");
if(screen_map != -1) {
glUniform1i(screen_map, 0);
}

auto history_map = glGetUniformLocation(program, "u_history_map");
const auto history_map = glGetUniformLocation(program, "u_history_map");
if(history_map != -1) {
glUniform1i(history_map, 1);
}

auto source_map = glGetUniformLocation(program, "u_source_map");
if(source_map != -1) {
glUniform1i(source_map, 2);
const auto info_map = glGetUniformLocation(program, "u_info_map");
if(info_map != -1) {
glUniform1i(info_map, 2);
}

const auto output_size = glGetUniformLocation(program, "u_output_size");
glUniform2f(output_size, view_width, view_height);
}
}

Expand Down Expand Up @@ -233,65 +246,59 @@ void OGLVideoDevice::SetViewport(int x, int y, int width, int height) {
view_y = y;
view_width = width;
view_height = height;

UpdateShaderUniforms();
}

void OGLVideoDevice::SetDefaultFBO(GLuint fbo) {
default_fbo = fbo;
}

void OGLVideoDevice::Draw(u32* buffer) {
int target = 0;
// Bind LCD history map
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture[2]);

// Update and bind LCD screen texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexSubImage2D(
GL_TEXTURE_2D, 0, 0, 0, 240, 160, GL_BGRA, GL_UNSIGNED_BYTE, buffer
);

// Bind LCD history map
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture[2]);

// Bind LCD source map
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture[3]);

auto program_count = programs.size();

glViewport(0, 0, 240, 160);
glBindVertexArray(quad_vao);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

if(program_count <= 2) {
target = 2;
}
for(auto pass_iter = programs.begin(); pass_iter != programs.end(); ++pass_iter) {
glUseProgram(*pass_iter);

for(int i = 0; i < program_count; i++) {
glUseProgram(programs[i]);
if (pass_iter != programs.begin()) {
// Swap input and output textures.
std::swap(texture[0], texture[1]);
}
if (pass_iter == std::prev(programs.end())) {
if (config->video.filter == Video::Filter::xBRZ) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
} else {
glBindTexture(GL_TEXTURE_2D, texture[0]);
}
glActiveTexture(GL_TEXTURE1);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 240, 160);

if(i == program_count - 1) {
glViewport(view_x, view_y, view_width, view_height);
glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
glViewport(view_x, view_y, view_width, view_height);
} else {
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[target], 0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
}

glDrawArrays(GL_TRIANGLES, 0, 6);

// Output of the current pass is the input for the next pass.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[target]);

if(i == program_count - 3) {
/* The next pass is the next-to-last pass, before we render to screen.
* Render that pass into a separate texture, so that it can be
* used in the next frame to calculate LCD ghosting.
*/
target = 2;
} else {
target ^= 1;
}
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/platform/core/src/device/shader/common.glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,18 @@ constexpr auto common_vert = R"(
v_uv = uv;
gl_Position = vec4(position, 0.0, 1.0);
}
)";
)";

constexpr auto common_vert_flip = R"(
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 uv;
out vec2 v_uv;
void main() {
v_uv = vec2(uv.x, 1.0 - uv.y);
gl_Position = vec4(position, 0.0, 1.0);
}
)";
6 changes: 3 additions & 3 deletions src/platform/core/src/device/shader/output.glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include "device/shader/common.glsl.hpp"

constexpr auto output_vert = common_vert;
constexpr auto output_vert = common_vert_flip;

constexpr auto output_frag = R"(
#version 330 core
Expand All @@ -21,6 +21,6 @@ constexpr auto output_frag = R"(
uniform sampler2D u_screen_map;
void main() {
frag_color = texture(u_screen_map, vec2(v_uv.x, 1.0 - v_uv.y));
frag_color = texture(u_screen_map, v_uv);
}
)";
)";
43 changes: 13 additions & 30 deletions src/platform/core/src/device/shader/xbrz.glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ constexpr auto xbrz0_frag = R"(
in vec2 v_uv;
uniform sampler2D u_source_map;
uniform sampler2D u_screen_map;
#define u_source_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
#define u_screen_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
#define BLEND_NONE 0
#define BLEND_NORMAL 1
Expand Down Expand Up @@ -98,7 +98,7 @@ constexpr auto xbrz0_frag = R"(
#define eq(a,b) (a == b)
#define neq(a,b) (a != b)
#define P(x,y) texture(u_source_map, coord + u_source_size.zw * vec2(x, y)).rgb
#define P(x,y) texture(u_screen_map, coord + u_screen_size.zw * vec2(x, y)).rgb
void main() {
//---------------------------------------
Expand All @@ -108,8 +108,8 @@ void main() {
// x|G|H|I|x
// -|x|x|x|-
vec2 pos = fract(v_uv * u_source_size.xy) - vec2(0.5, 0.5);
vec2 coord = v_uv - pos * u_source_size.zw;
vec2 pos = fract(v_uv * u_screen_size.xy) - vec2(0.5, 0.5);
vec2 coord = v_uv - pos * u_screen_size.zw;
vec3 A = P(-1,-1);
vec3 B = P( 0,-1);
Expand Down Expand Up @@ -268,35 +268,18 @@ frag_color /= 255.0;
}
)";

constexpr auto xbrz1_vert = R"(
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 uv;
out vec2 v_uv;
out vec4 u_screen_size;
uniform sampler2D u_screen_map;
void main() {
v_uv = uv;
u_screen_size.xy = textureSize(u_screen_map, 0);
u_screen_size.zw = 1.0 / textureSize(u_screen_map, 0);
gl_Position = vec4(position, 0.0, 1.0);
}
)";
constexpr auto xbrz1_vert = common_vert_flip;

constexpr auto xbrz1_frag = R"(
#version 330 core
layout(location = 0) out vec4 frag_color;
in vec2 v_uv;
in vec4 u_screen_size;
uniform sampler2D u_screen_map; // info texture
uniform sampler2D u_source_map; // LCD texture
uniform sampler2D u_info_map; // info texture
uniform sampler2D u_screen_map; // LCD texture
uniform vec2 u_output_size;
#define u_source_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
Expand Down Expand Up @@ -342,15 +325,15 @@ constexpr auto xbrz1_frag = R"(
#define eq(a,b) (a == b)
#define neq(a,b) (a != b)
#define P(x,y) texture(u_source_map, coord + u_source_size.zw * vec2(x, y)).rgb
#define P(x,y) texture(u_screen_map, coord + u_source_size.zw * vec2(x, y)).rgb
void main() {
//---------------------------------------
// Input Pixel Mapping: -|B|-
// D|E|F
// -|H|-
vec2 scale = u_screen_size.xy * u_source_size.zw;
vec2 scale = u_output_size.xy * u_source_size.zw;
vec2 pos = fract(v_uv * u_source_size.xy) - vec2(0.5, 0.5);
vec2 coord = v_uv - pos * u_source_size.zw;
Expand All @@ -360,7 +343,7 @@ constexpr auto xbrz1_frag = R"(
vec3 F = P( 1, 0);
vec3 H = P( 0, 1);
vec4 info = floor(texture(u_screen_map, coord) * 255.0 + 0.5);
vec4 info = floor(texture(u_info_map, coord) * 255.0 + 0.5);
// info Mapping: x|y|
// w|z|
Expand Down Expand Up @@ -448,4 +431,4 @@ constexpr auto xbrz1_frag = R"(
frag_color = vec4(res, 1.0);
}
)";
)";

0 comments on commit 7c9cf6a

Please sign in to comment.