Skip to content

Commit 7c9cf6a

Browse files
committed
PlatformCore: Change shader order
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.
1 parent d25f9f4 commit 7c9cf6a

File tree

5 files changed

+99
-94
lines changed

5 files changed

+99
-94
lines changed

src/platform/core/include/platform/device/ogl_video_device.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct OGLVideoDevice : VideoDevice {
3030
void UpdateTextures();
3131
void CreateShaderPrograms();
3232
void ReleaseShaderPrograms();
33+
void UpdateShaderUniforms();
3334

3435
auto CompileShader(
3536
GLenum type,

src/platform/core/src/device/ogl_video_device.cpp

Lines changed: 67 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ OGLVideoDevice::~OGLVideoDevice() {
4040
glDeleteVertexArrays(1, &quad_vao);
4141
glDeleteBuffers(1, &quad_vbo);
4242
glDeleteFramebuffers(1, &fbo);
43-
glDeleteTextures(4, texture);
43+
glDeleteTextures(3, texture);
4444
}
4545

4646
void OGLVideoDevice::Initialize() {
@@ -59,7 +59,7 @@ void OGLVideoDevice::Initialize() {
5959

6060
// Create three textures and a framebuffer for postprocessing.
6161
glGenFramebuffers(1, &fbo);
62-
glGenTextures(4, texture);
62+
glGenTextures(3, texture);
6363

6464
glEnable(GL_FRAMEBUFFER_SRGB);
6565

@@ -106,20 +106,6 @@ void OGLVideoDevice::CreateShaderPrograms() {
106106

107107
ReleaseShaderPrograms();
108108

109-
// xBRZ freescale upsampling filter (two passes)
110-
if(video.filter == Video::Filter::xBRZ) {
111-
auto [success0, program0] = CompileProgram(xbrz0_vert, xbrz0_frag);
112-
auto [success1, program1] = CompileProgram(xbrz1_vert, xbrz1_frag);
113-
114-
if(success0 && success1) {
115-
programs.push_back(program0);
116-
programs.push_back(program1);
117-
} else {
118-
if(success0) glDeleteProgram(program0);
119-
if(success1) glDeleteProgram(program1);
120-
}
121-
}
122-
123109
// Color correction pass
124110
switch(video.color) {
125111
case Video::Color::higan: {
@@ -147,29 +133,56 @@ void OGLVideoDevice::CreateShaderPrograms() {
147133
}
148134

149135
// Output pass (final)
150-
auto [success, program] = CompileProgram(output_vert, output_frag);
151-
if(success) {
152-
programs.push_back(program);
136+
switch (video.filter) {
137+
// xBRZ freescale upsampling filter (two passes)
138+
case Video::Filter::xBRZ: {
139+
auto [success0, program0] = CompileProgram(xbrz0_vert, xbrz0_frag);
140+
auto [success1, program1] = CompileProgram(xbrz1_vert, xbrz1_frag);
141+
142+
if(success0 && success1) {
143+
programs.push_back(program0);
144+
programs.push_back(program1);
145+
} else {
146+
if(success0) glDeleteProgram(program0);
147+
if(success1) glDeleteProgram(program1);
148+
}
149+
break;
150+
}
151+
// Plain linear/nearest output.
152+
default: {
153+
auto [success, program] = CompileProgram(output_vert, output_frag);
154+
if(success) {
155+
programs.push_back(program);
156+
}
157+
break;
158+
}
153159
}
154160

161+
UpdateShaderUniforms();
162+
}
163+
164+
void OGLVideoDevice::UpdateShaderUniforms() {
155165
// Set constant shader uniforms.
156-
for(auto program : programs) {
166+
for(const auto program : programs) {
157167
glUseProgram(program);
158168

159-
auto screen_map = glGetUniformLocation(program, "u_screen_map");
169+
const auto screen_map = glGetUniformLocation(program, "u_screen_map");
160170
if(screen_map != -1) {
161171
glUniform1i(screen_map, 0);
162172
}
163173

164-
auto history_map = glGetUniformLocation(program, "u_history_map");
174+
const auto history_map = glGetUniformLocation(program, "u_history_map");
165175
if(history_map != -1) {
166176
glUniform1i(history_map, 1);
167177
}
168178

169-
auto source_map = glGetUniformLocation(program, "u_source_map");
170-
if(source_map != -1) {
171-
glUniform1i(source_map, 2);
179+
const auto info_map = glGetUniformLocation(program, "u_info_map");
180+
if(info_map != -1) {
181+
glUniform1i(info_map, 2);
172182
}
183+
184+
const auto output_size = glGetUniformLocation(program, "u_output_size");
185+
glUniform2f(output_size, view_width, view_height);
173186
}
174187
}
175188

@@ -233,65 +246,59 @@ void OGLVideoDevice::SetViewport(int x, int y, int width, int height) {
233246
view_y = y;
234247
view_width = width;
235248
view_height = height;
249+
250+
UpdateShaderUniforms();
236251
}
237252

238253
void OGLVideoDevice::SetDefaultFBO(GLuint fbo) {
239254
default_fbo = fbo;
240255
}
241256

242257
void OGLVideoDevice::Draw(u32* buffer) {
243-
int target = 0;
258+
// Bind LCD history map
259+
glActiveTexture(GL_TEXTURE1);
260+
glBindTexture(GL_TEXTURE_2D, texture[2]);
244261

245262
// Update and bind LCD screen texture
246263
glActiveTexture(GL_TEXTURE0);
247-
glBindTexture(GL_TEXTURE_2D, texture[3]);
264+
glBindTexture(GL_TEXTURE_2D, texture[0]);
248265
glTexSubImage2D(
249266
GL_TEXTURE_2D, 0, 0, 0, 240, 160, GL_BGRA, GL_UNSIGNED_BYTE, buffer
250267
);
251268

252-
// Bind LCD history map
253-
glActiveTexture(GL_TEXTURE1);
254-
glBindTexture(GL_TEXTURE_2D, texture[2]);
255-
256-
// Bind LCD source map
257-
glActiveTexture(GL_TEXTURE2);
258-
glBindTexture(GL_TEXTURE_2D, texture[3]);
259-
260-
auto program_count = programs.size();
261-
262269
glViewport(0, 0, 240, 160);
263270
glBindVertexArray(quad_vao);
271+
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
264272

265-
if(program_count <= 2) {
266-
target = 2;
267-
}
273+
for(auto pass_iter = programs.begin(); pass_iter != programs.end(); ++pass_iter) {
274+
glUseProgram(*pass_iter);
268275

269-
for(int i = 0; i < program_count; i++) {
270-
glUseProgram(programs[i]);
276+
if (pass_iter != programs.begin()) {
277+
// Swap input and output textures.
278+
std::swap(texture[0], texture[1]);
279+
}
280+
if (pass_iter == std::prev(programs.end())) {
281+
if (config->video.filter == Video::Filter::xBRZ) {
282+
glActiveTexture(GL_TEXTURE2);
283+
glBindTexture(GL_TEXTURE_2D, texture[0]);
284+
glActiveTexture(GL_TEXTURE0);
285+
glBindTexture(GL_TEXTURE_2D, texture[1]);
286+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
287+
} else {
288+
glBindTexture(GL_TEXTURE_2D, texture[0]);
289+
}
290+
glActiveTexture(GL_TEXTURE1);
291+
glReadBuffer(GL_COLOR_ATTACHMENT0);
292+
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 240, 160);
271293

272-
if(i == program_count - 1) {
273-
glViewport(view_x, view_y, view_width, view_height);
274294
glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
295+
glViewport(view_x, view_y, view_width, view_height);
275296
} else {
276-
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
277-
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[target], 0);
297+
glBindTexture(GL_TEXTURE_2D, texture[0]);
298+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
278299
}
279300

280301
glDrawArrays(GL_TRIANGLES, 0, 6);
281-
282-
// Output of the current pass is the input for the next pass.
283-
glActiveTexture(GL_TEXTURE0);
284-
glBindTexture(GL_TEXTURE_2D, texture[target]);
285-
286-
if(i == program_count - 3) {
287-
/* The next pass is the next-to-last pass, before we render to screen.
288-
* Render that pass into a separate texture, so that it can be
289-
* used in the next frame to calculate LCD ghosting.
290-
*/
291-
target = 2;
292-
} else {
293-
target ^= 1;
294-
}
295302
}
296303
}
297304

src/platform/core/src/device/shader/common.glsl.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,18 @@ constexpr auto common_vert = R"(
1919
v_uv = uv;
2020
gl_Position = vec4(position, 0.0, 1.0);
2121
}
22-
)";
22+
)";
23+
24+
constexpr auto common_vert_flip = R"(
25+
#version 330 core
26+
27+
layout(location = 0) in vec2 position;
28+
layout(location = 1) in vec2 uv;
29+
30+
out vec2 v_uv;
31+
32+
void main() {
33+
v_uv = vec2(uv.x, 1.0 - uv.y);
34+
gl_Position = vec4(position, 0.0, 1.0);
35+
}
36+
)";

src/platform/core/src/device/shader/output.glsl.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

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

12-
constexpr auto output_vert = common_vert;
12+
constexpr auto output_vert = common_vert_flip;
1313

1414
constexpr auto output_frag = R"(
1515
#version 330 core
@@ -21,6 +21,6 @@ constexpr auto output_frag = R"(
2121
uniform sampler2D u_screen_map;
2222
2323
void main() {
24-
frag_color = texture(u_screen_map, vec2(v_uv.x, 1.0 - v_uv.y));
24+
frag_color = texture(u_screen_map, v_uv);
2525
}
26-
)";
26+
)";

src/platform/core/src/device/shader/xbrz.glsl.hpp

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ constexpr auto xbrz0_frag = R"(
5252
5353
in vec2 v_uv;
5454
55-
uniform sampler2D u_source_map;
55+
uniform sampler2D u_screen_map;
5656
57-
#define u_source_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
57+
#define u_screen_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
5858
5959
#define BLEND_NONE 0
6060
#define BLEND_NORMAL 1
@@ -98,7 +98,7 @@ constexpr auto xbrz0_frag = R"(
9898
#define eq(a,b) (a == b)
9999
#define neq(a,b) (a != b)
100100
101-
#define P(x,y) texture(u_source_map, coord + u_source_size.zw * vec2(x, y)).rgb
101+
#define P(x,y) texture(u_screen_map, coord + u_screen_size.zw * vec2(x, y)).rgb
102102
103103
void main() {
104104
//---------------------------------------
@@ -108,8 +108,8 @@ void main() {
108108
// x|G|H|I|x
109109
// -|x|x|x|-
110110
111-
vec2 pos = fract(v_uv * u_source_size.xy) - vec2(0.5, 0.5);
112-
vec2 coord = v_uv - pos * u_source_size.zw;
111+
vec2 pos = fract(v_uv * u_screen_size.xy) - vec2(0.5, 0.5);
112+
vec2 coord = v_uv - pos * u_screen_size.zw;
113113
114114
vec3 A = P(-1,-1);
115115
vec3 B = P( 0,-1);
@@ -268,35 +268,18 @@ frag_color /= 255.0;
268268
}
269269
)";
270270

271-
constexpr auto xbrz1_vert = R"(
272-
#version 330 core
273-
274-
layout(location = 0) in vec2 position;
275-
layout(location = 1) in vec2 uv;
276-
277-
out vec2 v_uv;
278-
out vec4 u_screen_size;
279-
280-
uniform sampler2D u_screen_map;
281-
282-
void main() {
283-
v_uv = uv;
284-
u_screen_size.xy = textureSize(u_screen_map, 0);
285-
u_screen_size.zw = 1.0 / textureSize(u_screen_map, 0);
286-
gl_Position = vec4(position, 0.0, 1.0);
287-
}
288-
)";
271+
constexpr auto xbrz1_vert = common_vert_flip;
289272

290273
constexpr auto xbrz1_frag = R"(
291274
#version 330 core
292275
293276
layout(location = 0) out vec4 frag_color;
294277
295278
in vec2 v_uv;
296-
in vec4 u_screen_size;
297279
298-
uniform sampler2D u_screen_map; // info texture
299-
uniform sampler2D u_source_map; // LCD texture
280+
uniform sampler2D u_info_map; // info texture
281+
uniform sampler2D u_screen_map; // LCD texture
282+
uniform vec2 u_output_size;
300283
301284
#define u_source_size vec4(240.0, 160.0, 1.0/240.0, 1.0/160.0)
302285
@@ -342,15 +325,15 @@ constexpr auto xbrz1_frag = R"(
342325
#define eq(a,b) (a == b)
343326
#define neq(a,b) (a != b)
344327
345-
#define P(x,y) texture(u_source_map, coord + u_source_size.zw * vec2(x, y)).rgb
328+
#define P(x,y) texture(u_screen_map, coord + u_source_size.zw * vec2(x, y)).rgb
346329
347330
void main() {
348331
//---------------------------------------
349332
// Input Pixel Mapping: -|B|-
350333
// D|E|F
351334
// -|H|-
352335
353-
vec2 scale = u_screen_size.xy * u_source_size.zw;
336+
vec2 scale = u_output_size.xy * u_source_size.zw;
354337
vec2 pos = fract(v_uv * u_source_size.xy) - vec2(0.5, 0.5);
355338
vec2 coord = v_uv - pos * u_source_size.zw;
356339
@@ -360,7 +343,7 @@ constexpr auto xbrz1_frag = R"(
360343
vec3 F = P( 1, 0);
361344
vec3 H = P( 0, 1);
362345
363-
vec4 info = floor(texture(u_screen_map, coord) * 255.0 + 0.5);
346+
vec4 info = floor(texture(u_info_map, coord) * 255.0 + 0.5);
364347
365348
// info Mapping: x|y|
366349
// w|z|
@@ -448,4 +431,4 @@ constexpr auto xbrz1_frag = R"(
448431
449432
frag_color = vec4(res, 1.0);
450433
}
451-
)";
434+
)";

0 commit comments

Comments
 (0)