GLES 3.0 Support on HW Renderer

updated makefiles for:
- android
- ios
- emscripten
- rpi4

tested on emscripten, GLES3 must be explicitly enabled for android and ios

fixed some things in glsm (libretro-common)

colors are not 100% perfect on GLES3 due to it not including the 1555 ABGR color format. GLES3 uses 5551 instead.
This commit is contained in:
BinBashBanana 2022-07-06 18:17:16 -07:00
parent 88929ae90b
commit 3f525d7d67
14 changed files with 195 additions and 34 deletions

View File

@ -1,6 +1,8 @@
DEBUG = 0
FRONTEND_SUPPORTS_RGB565 = 1
HAVE_OPENGL = 0
GLES = 0
GLES3 = 0 # HW renderer now supported on GLES3
HAVE_VULKAN = 0
HAVE_JIT = 0
HAVE_CHD = 1
@ -173,6 +175,8 @@ else ifneq (,$(findstring ios,$(platform)))
endif
ifeq ($(HAVE_OPENGL),1)
GL_LIB := -framework OpenGLES
GLES = 1
GLES3 = 0
endif
CC = cc -arch $(iarch) -isysroot $(IOSSDK)
@ -324,12 +328,18 @@ else ifeq ($(platform), gcw0)
else ifeq ($(platform), emscripten)
TARGET := $(TARGET_NAME)_libretro_$(platform).bc
fpic := -fPIC
SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T
LDFLAGS += $(PTHREAD_FLAGS)
STATIC_LINKING = 1
FLAGS += -DEMSCRIPTEN
FLAGS += -msimd128 -ftree-vectorize
HAVE_OPENGL = 1
GLES = 1
GLES3 = 1
HAVE_LIGHTREC = 0
NEED_THREADING = 0
HAVE_CDROM = 0
THREADED_RECOMPILER = 0
STATIC_LINKING = 1
# Raspberry Pi 4 in 64bit mode
else ifeq ($(platform), rpi4_64)
@ -342,7 +352,7 @@ else ifeq ($(platform), rpi4_64)
LDFLAGS += $(PTHREAD_FLAGS) -ldl -lrt
HAVE_LIGHTREC = 1
FLAGS += -DHAVE_SHM
GLES = 1
GLES3 = 1
GL_LIB := -lGLESv2
HAVE_CDROM = 0

View File

@ -40,11 +40,15 @@ ZLIB_SOURCES_C = \
$(ZLIB_DIR)/zutil.c
ifeq ($(HAVE_OPENGL), 1)
ifeq ($(GLES), 1)
ifeq ($(GLES3), 1)
GLFLAGS := -DHAVE_OPENGLES -DHAVE_OPENGLES3
CFLAGS += $(GLFLAGS)
CXXFLAGS += $(GLFLAGS)
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
else ifeq ($(GLES), 1)
GLFLAGS := -DHAVE_OPENGLES -DHAVE_OPENGLES2
CFLAGS += $(GLFLAGS)
CXXFLAGS += $(GLFLAGS)
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es2.c
else
GLFLAGS := -DHAVE_OPENGL -DCORE

View File

@ -2,6 +2,10 @@ LOCAL_PATH := $(call my-dir)
CORE_DIR := $(LOCAL_PATH)/..
# set these
HAVE_HW = 0
HAVE_OPENGLES3 = 0
DEBUG := 0
FRONTEND_SUPPORTS_RGB565 := 1
NEED_CD := 1
@ -10,6 +14,7 @@ NEED_DEINTERLACER := 1
NEED_THREADING := 1
NEED_TREMOR := 1
GLES := 0
GLES3 := 0
HAVE_OPENGL := 0
HAVE_VULKAN := 0
HAVE_CHD := 1
@ -23,9 +28,12 @@ ifeq ($(TARGET_ARCH),x86)
endif
ifeq ($(HAVE_HW),1)
# gles support will not compile
#GLES := 1
#HAVE_OPENGL := 1
ifeq ($(HAVE_OPENGLES3),1)
HAVE_OPENGL := 1
GLES := 1
GLES3 := 1
GL_LIB := -lGLESv3
endif
ifneq ($(TARGET_ARCH_ABI),armeabi)
HAVE_VULKAN := 1

View File

@ -646,18 +646,18 @@ void rglBlendFunc(GLenum sfactor, GLenum dfactor)
* Core in:
* OpenGL : 1.4
*/
void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor)
void rglBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
#ifdef GLSM_DEBUG
log_cb(RETRO_LOG_INFO, "glBlendFuncSeparate.\n");
#endif
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
gl_state.blendfunc_separate.used = true;
gl_state.blendfunc_separate.srcRGB = sfactor;
gl_state.blendfunc_separate.dstRGB = dfactor;
gl_state.blendfunc_separate.srcAlpha = sfactor;
gl_state.blendfunc_separate.dstAlpha = dfactor;
glBlendFunc(sfactor, dfactor);
gl_state.blendfunc_separate.srcRGB = srcRGB;
gl_state.blendfunc_separate.dstRGB = dstRGB;
gl_state.blendfunc_separate.srcAlpha = srcAlpha;
gl_state.blendfunc_separate.dstAlpha = dstAlpha;
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
}
/*
@ -1030,7 +1030,7 @@ void rglBindFragDataLocation(GLuint program, GLuint colorNumber,
#ifdef GLSM_DEBUG
log_cb(RETRO_LOG_INFO, "glBindFragDataLocation.\n");
#endif
#if !defined(HAVE_OPENGLES2)
#if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGLES3)
glBindFragDataLocation(program, colorNumber, name);
#endif
}

View File

@ -31,7 +31,7 @@
RETRO_BEGIN_DECLS
#ifdef HAVE_OPENGLES2
#if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3)
typedef double GLdouble;
typedef double GLclampd;
#endif

View File

@ -1,13 +1,22 @@
#ifndef LIBRETRO_OPTIONS_H__
#define LIBRETRO_OPTIONS_H__
#ifdef HAVE_OPENGLES3
#define MEDNAFEN_CORE_RENDERER "-GLES3"
#else
#define MEDNAFEN_CORE_RENDERER ""
#endif
#define MEDNAFEN_CORE_SETVERSION "0.9.44.1"
#define MEDNAFEN_CORE_NAME_MODULE "psx"
#ifdef HAVE_HW
#define MEDNAFEN_CORE_NAME "Beetle PSX HW"
#define MEDNAFEN_CORE_VERSION MEDNAFEN_CORE_SETVERSION MEDNAFEN_CORE_RENDERER
#else
#define MEDNAFEN_CORE_NAME "Beetle PSX"
#define MEDNAFEN_CORE_VERSION MEDNAFEN_CORE_SETVERSION
#endif
#define MEDNAFEN_CORE_VERSION "0.9.44.1"
#define MEDNAFEN_CORE_EXTENSIONS "exe|cue|toc|ccd|m3u|pbp|chd"
#define MEDNAFEN_CORE_GEOMETRY_BASE_W 320
#define MEDNAFEN_CORE_GEOMETRY_BASE_H 240

View File

@ -61,7 +61,7 @@
#include "libretro.h"
#include "libretro_options.h"
#if 0 || defined(__APPLE__)
#if 0 || defined(__APPLE__) || defined(HAVE_OPENGLES3)
#define NEW_COPY_RECT
static const GLushort indices[6] = {0, 1, 2, 2, 1, 3};
#else
@ -706,7 +706,13 @@ static void DrawBuffer_map__no_bind(DrawBuffer<T> *drawbuffer)
offset_bytes,
buffer_size,
GL_MAP_WRITE_BIT |
GL_MAP_INVALIDATE_RANGE_BIT);
#ifdef EMSCRIPTEN
// in emscripten, glMapBufferRange is only supported when access is MAP_WRITE|INVALIDATE_BUFFER
GL_MAP_INVALIDATE_BUFFER_BIT
#else
GL_MAP_INVALIDATE_RANGE_BIT
#endif
);
assert(m != NULL);
@ -799,6 +805,7 @@ static void DrawBuffer_bind_attributes(DrawBuffer<T> *drawbuffer)
element_size,
(GLvoid*)attr.offset);
break;
#ifndef HAVE_OPENGLES3
case GL_DOUBLE:
glVertexAttribLPointer( index,
attr.components,
@ -806,6 +813,7 @@ static void DrawBuffer_bind_attributes(DrawBuffer<T> *drawbuffer)
element_size,
(GLvoid*)attr.offset);
break;
#endif
}
}
}
@ -885,10 +893,18 @@ static void Framebuffer_init(struct Framebuffer *fb,
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb->id);
#ifdef HAVE_OPENGLES3
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
color_texture->id,
0);
#else
glFramebufferTexture( GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
color_texture->id,
0);
#endif
GLenum col_attach_0 = GL_COLOR_ATTACHMENT0;
@ -983,10 +999,18 @@ static void GlRenderer_draw(GlRenderer *renderer)
/* Bind the out framebuffer */
Framebuffer_init(&_fb, &renderer->fb_out);
#ifdef HAVE_OPENGLES3
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
renderer->fb_out_depth.id,
0);
#else
glFramebufferTexture( GL_DRAW_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
renderer->fb_out_depth.id,
0);
#endif
glClear(GL_DEPTH_BUFFER_BIT);
@ -1117,7 +1141,19 @@ static void GlRenderer_upload_textures(
(GLsizei) dimensions[0],
(GLsizei) dimensions[1],
GL_RGBA,
#ifdef HAVE_OPENGLES3
GL_UNSIGNED_SHORT_5_5_5_1,
// bits are always in the order that they show
// REV indicates the channels are in reversed order
// RGBA
// 16 bit unsigned short: R5 G5 B5 A1
// RRRRRGGGGGBBBBBA
#else
GL_UNSIGNED_SHORT_1_5_5_5_REV,
// ABGR
// 16 bit unsigned short: A1 B5 G5 R5
// ABBBBBGGGGGRRRRR
#endif
(void*)pixel_buffer);
uint16_t x_start = top_left[0];
@ -1152,7 +1188,9 @@ static void GlRenderer_upload_textures(
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
/* Bind the output framebuffer */
Framebuffer _fb;
@ -1161,7 +1199,9 @@ static void GlRenderer_upload_textures(
if (!DRAWBUFFER_IS_EMPTY(renderer->image_load_buffer))
DrawBuffer_draw(renderer->image_load_buffer, GL_TRIANGLE_STRIP);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, renderer->command_polygon_mode);
#endif
glEnable(GL_SCISSOR_TEST);
#ifdef DEBUG
@ -1404,7 +1444,9 @@ static bool GlRenderer_new(GlRenderer *renderer, DrawConfig config)
DrawBuffer_enable_attribute(command_buffer, "dither");
}
#ifndef HAVE_OPENGLES3
GLenum command_draw_mode = wireframe ? GL_LINE : GL_FILL;
#endif
if (command_buffer->program)
{
@ -1445,7 +1487,9 @@ static bool GlRenderer_new(GlRenderer *renderer, DrawConfig config)
renderer->vertex_index_pos = 0;
renderer->command_draw_mode = GL_TRIANGLES;
renderer->semi_transparency_mode = SemiTransparencyMode_Average;
#ifndef HAVE_OPENGLES3
renderer->command_polygon_mode = command_draw_mode;
#endif
renderer->output_buffer = output_buffer;
renderer->image_load_buffer = image_load_buffer;
renderer->config = config;
@ -1917,7 +1961,9 @@ static bool retro_refresh_variables(GlRenderer *renderer)
glUniform1ui(renderer->command_buffer->program->uniforms["dither_scaling"], dither_scaling);
}
#ifndef HAVE_OPENGLES3
renderer->command_polygon_mode = wireframe ? GL_LINE : GL_FILL;
#endif
glLineWidth((GLfloat) upscaling);
@ -2479,7 +2525,9 @@ void rsx_gl_prepare_frame(void)
/* In case we're upscaling we need to increase the line width
* proportionally */
glLineWidth((GLfloat)renderer->internal_upscaling);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, renderer->command_polygon_mode);
#endif
glEnable(GL_SCISSOR_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
@ -2568,7 +2616,9 @@ void rsx_gl_finalize_frame(const void *fb, unsigned width,
bind_libretro_framebuffer(renderer);
glDisable(GL_SCISSOR_TEST);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
@ -2662,7 +2712,9 @@ void rsx_gl_finalize_frame(const void *fb, unsigned width,
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
Framebuffer_init(&_fb, &renderer->fb_texture);
@ -3184,7 +3236,11 @@ void rsx_gl_load_image(
dimensions,
(size_t) VRAM_WIDTH_PIXELS,
GL_RGBA,
#ifdef HAVE_OPENGLES3
GL_UNSIGNED_SHORT_5_5_5_1,
#else
GL_UNSIGNED_SHORT_1_5_5_5_REV,
#endif
vram);
uint16_t x_start = top_left[0];
@ -3216,7 +3272,9 @@ void rsx_gl_load_image(
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
/* Bind the output framebuffer */
Framebuffer_init(&_fb, &renderer->fb_out);
@ -3224,7 +3282,9 @@ void rsx_gl_load_image(
if (!DRAWBUFFER_IS_EMPTY(renderer->image_load_buffer))
DrawBuffer_draw(renderer->image_load_buffer, GL_TRIANGLE_STRIP);
#ifndef HAVE_OPENGLES3
glPolygonMode(GL_FRONT_AND_BACK, renderer->command_polygon_mode);
#endif
glEnable(GL_SCISSOR_TEST);
#ifdef DEBUG
@ -3281,10 +3341,18 @@ void rsx_gl_fill_rect(
Framebuffer _fb;
Framebuffer_init(&_fb, &renderer->fb_out);
#ifdef HAVE_OPENGLES3
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
renderer->fb_out_depth.id,
0);
#else
glFramebufferTexture(GL_DRAW_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
renderer->fb_out_depth.id,
0);
#endif
glClearColor( (float) col[0] / 255.0,
(float) col[1] / 255.0,
@ -3360,10 +3428,18 @@ void rsx_gl_copy_rect(
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
#ifdef HAVE_OPENGLES3
glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
renderer->fb_out.id,
0);
#else
glFramebufferTexture(GL_READ_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
renderer->fb_out.id,
0);
#endif
glReadBuffer(GL_COLOR_ATTACHMENT0);
@ -3371,6 +3447,7 @@ void rsx_gl_copy_rect(
* GL_TEXTURE_2D? Something tells me this is undefined
* behaviour. I could use glReadPixels and glWritePixels instead
* or something like that. */
/* former seems to work just fine on GLES 3.0 */
glBindTexture(GL_TEXTURE_2D, renderer->fb_out.id);
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, new_dst_x, new_dst_y,
new_src_x, new_src_y, new_w, new_h);

View File

@ -16,7 +16,7 @@
#define command_fragment_name_ command_fragment
#endif
static const char * command_fragment_name_ = GLSL(
static const char * command_fragment_name_ = GLSL_FRAGMENT(
uniform sampler2D fb_texture;
// Scaling to apply to the dither pattern
@ -73,7 +73,17 @@ uint rebuild_psx_color(vec4 color) {
uint g = uint(floor(color.g * 31. + 0.5));
uint b = uint(floor(color.b * 31. + 0.5));
)
#ifdef HAVE_OPENGLES3
STRINGIZE(
return (r << 11) | (g << 6) | (b << 1) | a;
)
#else
STRINGIZE(
return (a << 15) | (b << 10) | (g << 5) | r;
)
#endif
STRINGIZE(
}
// Texture color 0x0000 is special in the Playstation GPU, it denotes
@ -84,6 +94,20 @@ bool is_transparent(vec4 texel) {
return rebuild_psx_color(texel) == 0U;
}
// reinterpret 5551 color for GLES (doesn't support 1555 REV)
vec4 reinterpret_color(vec4 color) {
// rebuild as 5551
uint pre_bits = rebuild_psx_color(color);
// interpret as 1555
float a = float((pre_bits & 0x8000U) >> 15) / 31.;
float b = float((pre_bits & 0x7C00U) >> 10) / 31.;
float g = float((pre_bits & 0x3E0U) >> 5) / 31.;
float r = float(pre_bits & 0x1FU) / 31.;
return vec4(r, g, b, a);
}
// PlayStation dithering pattern. The offset is selected based on the
// pixel position in VRAM, by blocks of 4x4 pixels. The value is added
// to the 8bit color components before they're truncated to 5 bits.
@ -157,7 +181,18 @@ vec4 sample_texel(vec2 coords) {
// Look up the real color for the texel in the CLUT
texel = vram_get_pixel(clut_x, clut_y);
}
)
#ifdef HAVE_OPENGLES3
STRINGIZE(
return reinterpret_color(texel);
)
#else
STRINGIZE(
return texel;
)
#endif
STRINGIZE(
}
)
@ -788,7 +823,7 @@ vec4 get_texel_jinc2(out float opacity)
STRINGIZE(
void main() {
vec4 color;
float opacity=1;
float opacity=1.;
if (frag_texture_blend_mode == BLEND_MODE_NO_TEXTURE)
{

View File

@ -7,7 +7,7 @@
#define command_vertex_name_ command_vertex
#endif
static const char * command_vertex_name_ = GLSL(
static const char * command_vertex_name_ = GLSL_VERTEX(
// Vertex shader for rendering GPU draw commands in the framebuffer
in vec4 position;
in uvec3 color;
@ -55,8 +55,8 @@ void main() {
// Convert VRAM coordinates (0;1023, 0;511) into OpenGL coordinates
// (-1;1, -1;1)
float wpos = position.w;
float xpos = (pos.x / 512) - 1.0;
float ypos = (pos.y / 256) - 1.0;
float xpos = (pos.x / 512.) - 1.0;
float ypos = (pos.y / 256.) - 1.0;
// position.z increases as the primitives near the camera so we
// reverse the order to match the common GL convention

View File

@ -1,6 +1,6 @@
#include "shaders_common.h"
static const char *image_load_fragment = GLSL(
static const char *image_load_fragment = GLSL_FRAGMENT(
uniform sampler2D fb_texture;
uniform uint internal_upscaling;
in vec2 frag_fb_coord;
@ -12,6 +12,7 @@ static const char *image_load_fragment = GLSL(
}
void main() {
// GLES 5551 note: color reinterpretation can be done here
frag_color = vram_get_pixel(int(frag_fb_coord.x), int(frag_fb_coord.y));
}
);

View File

@ -1,6 +1,6 @@
#include "shaders_common.h"
static const char *image_load_vertex = GLSL(
static const char *image_load_vertex = GLSL_VERTEX(
// Vertex shader for uploading textures from the VRAM texture buffer
// into the output framebuffer
@ -10,8 +10,8 @@ static const char *image_load_vertex = GLSL(
void main() {
// Convert VRAM position into OpenGL coordinates
float xpos = (float(position.x) / 512) - 1.0;
float ypos = (float(position.y) / 256) - 1.0;
float xpos = (float(position.x) / 512.) - 1.0;
float ypos = (float(position.y) / 256.) - 1.0;
gl_Position.xyzw = vec4(xpos, ypos, 0.0, 1.0);

View File

@ -1,6 +1,6 @@
#include "shaders_common.h"
static const char *output_fragment = GLSL(
static const char *output_fragment = GLSL_FRAGMENT(
// We're sampling from the internal framebuffer texture
uniform sampler2D fb;
// Framebuffer sampling: 0: Normal 16bpp mode, 1: Use 24bpp mode
@ -24,7 +24,17 @@ static const char *output_fragment = GLSL(
uint g = uint(floor(color.g * 31. + 0.5));
uint b = uint(floor(color.b * 31. + 0.5));
)
#ifdef HAVE_OPENGLES3
STRINGIZE(
return (r << 11) | (g << 6) | (b << 1) | a;
)
#else
STRINGIZE(
return (a << 15) | (b << 10) | (g << 5) | r;
)
#endif
STRINGIZE(
}
void main() {
@ -35,6 +45,7 @@ static const char *output_fragment = GLSL(
// texture. The alpha/mask bit is ignored here.
vec2 off = vec2(offset) / vec2(1024., 512.);
// GLES 5551 note: color reinterpretation shouldn't be done here
color = texture(fb, frag_fb_coord + off).rgb;
} else {
// In this mode we have to interpret the framebuffer as containing

View File

@ -1,6 +1,6 @@
#include "shaders_common.h"
static const char *output_vertex = GLSL(
static const char *output_vertex = GLSL_VERTEX(
// Vertex shader for rendering GPU draw commands in the framebuffer
in vec2 position;
in uvec2 fb_coord;
@ -12,8 +12,8 @@ static const char *output_vertex = GLSL(
// Convert the PlayStation framebuffer coordinate into an OpenGL
// texture coordinate
float fb_x_coord = float(fb_coord.x) / 1024;
float fb_y_coord = float(fb_coord.y) / 512;
float fb_x_coord = float(fb_coord.x) / 1024.;
float fb_y_coord = float(fb_coord.y) / 512.;
frag_fb_coord = vec2(fb_x_coord, fb_y_coord);
}

View File

@ -1,7 +1,13 @@
#ifndef _SHADERS_COMMON
#define _SHADERS_COMMON
#define GLSL(src) "#version 330 core\n" #src
#ifdef HAVE_OPENGLES3
#define GLSL_VERTEX(src) "#version 300 es\n" #src
#define GLSL_FRAGMENT(src) "#version 300 es\n#ifdef GL_ES\n#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\n#endif\n" #src
#else
#define GLSL_VERTEX(src) "#version 330 core\n" #src
#define GLSL_FRAGMENT(src) "#version 330 core\n" #src
#endif
#define STRINGIZE(src) #src
#endif