GLES1 renderer: discard framebuffer

Available only on GLES1, allows to use a "performance hint" to the
GPU to discard the contents of depth and stencil buffers after each
frame. Some hardware might want to reuse them, but Quake 2 doesn't
work that way.
Controlled by gl1_discardfb cvar, default `1`.
This commit is contained in:
Jaime Moreira 2024-07-27 23:18:06 -04:00
parent 03227f1ed6
commit 0596d23e4c
6 changed files with 58 additions and 0 deletions

View file

@ -492,6 +492,10 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
* **gl1_stencilshadow**: If `gl_shadows` is set to `1`, this makes them * **gl1_stencilshadow**: If `gl_shadows` is set to `1`, this makes them
look a bit better (no flickering) by using the stencil buffer. look a bit better (no flickering) by using the stencil buffer.
* **gl1_discardfb**: Only available in ES1. If set to `1` (default),
send a hint to discard framebuffers after finishing a frame. Useful
for GPUs that attempt to reuse them, something Quake 2 doesn't do.
## Graphics (OpenGL 3.2 and OpenGL ES3 only) ## Graphics (OpenGL 3.2 and OpenGL ES3 only)

View file

@ -91,6 +91,7 @@ cvar_t *gl1_particle_square;
cvar_t *gl1_palettedtexture; cvar_t *gl1_palettedtexture;
cvar_t *gl1_pointparameters; cvar_t *gl1_pointparameters;
cvar_t *gl1_multitexture; cvar_t *gl1_multitexture;
cvar_t *gl1_discardfb;
cvar_t *gl_drawbuffer; cvar_t *gl_drawbuffer;
cvar_t *gl_lightmap; cvar_t *gl_lightmap;
@ -1224,6 +1225,9 @@ R_Register(void)
gl1_palettedtexture = ri.Cvar_Get("r_palettedtextures", "0", CVAR_ARCHIVE); gl1_palettedtexture = ri.Cvar_Get("r_palettedtextures", "0", CVAR_ARCHIVE);
gl1_pointparameters = ri.Cvar_Get("gl1_pointparameters", "1", CVAR_ARCHIVE); gl1_pointparameters = ri.Cvar_Get("gl1_pointparameters", "1", CVAR_ARCHIVE);
gl1_multitexture = ri.Cvar_Get("gl1_multitexture", "1", CVAR_ARCHIVE); gl1_multitexture = ri.Cvar_Get("gl1_multitexture", "1", CVAR_ARCHIVE);
#ifdef YQ2_GL1_GLES
gl1_discardfb = ri.Cvar_Get("gl1_discardfb", "1", CVAR_ARCHIVE);
#endif
gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0); gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
r_vsync = ri.Cvar_Get("r_vsync", "1", CVAR_ARCHIVE); r_vsync = ri.Cvar_Get("r_vsync", "1", CVAR_ARCHIVE);
@ -1641,6 +1645,43 @@ RI_Init(void)
// ---- // ----
/* Discard framebuffer: Available only on GLES1, enables the use of a "performance hint"
* to the graphic driver, to get rid of the contents of the depth and stencil buffers.
* Useful for some GPUs that may attempt to keep them and/or write them back to
* external/uniform memory, actions that are useless for Quake 2 rendering path.
* https://registry.khronos.org/OpenGL/extensions/EXT/EXT_discard_framebuffer.txt
*/
gl_config.discardfb = false;
#ifdef YQ2_GL1_GLES
R_Printf(PRINT_ALL, " - Discard framebuffer: ");
if (strstr(gl_config.extensions_string, "GL_EXT_discard_framebuffer"))
{
qglDiscardFramebufferEXT = (void (APIENTRY *)(GLenum, GLsizei, const GLenum *))
RI_GetProcAddress ("glDiscardFramebufferEXT");
}
if (gl1_discardfb->value)
{
if (qglDiscardFramebufferEXT)
{
gl_config.discardfb = true;
R_Printf(PRINT_ALL, "Okay\n");
}
else
{
R_Printf(PRINT_ALL, "Failed\n");
}
}
else
{
R_Printf(PRINT_ALL, "Disabled\n");
}
#endif
// ----
/* Big lightmaps: this used to be fast, but after the implementation of the "GL Buffer", it /* Big lightmaps: this used to be fast, but after the implementation of the "GL Buffer", it
* became too evident that the bigger the texture, the slower the call to glTexSubImage2D() is. * became too evident that the bigger the texture, the slower the call to glTexSubImage2D() is.
* Original logic remains, but it's preferable not to make it visible to the user. * Original logic remains, but it's preferable not to make it visible to the user.

View file

@ -47,6 +47,13 @@ void
RI_EndFrame(void) RI_EndFrame(void)
{ {
R_ApplyGLBuffer(); // to draw buffered 2D text R_ApplyGLBuffer(); // to draw buffered 2D text
#ifdef YQ2_GL1_GLES
if (gl_config.discardfb)
{
static const GLenum attachments[] = { GL_DEPTH_EXT, GL_STENCIL_EXT };
qglDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, 2, attachments);
}
#endif
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }

View file

@ -429,6 +429,7 @@ typedef struct
qboolean palettedtexture; qboolean palettedtexture;
qboolean pointparameters; qboolean pointparameters;
qboolean multitexture; qboolean multitexture;
qboolean discardfb;
// ---- // ----

View file

@ -100,5 +100,7 @@ extern void ( APIENTRY *qglColorTableEXT ) ( GLenum, GLenum, GLsizei, GLenum,
GLenum, const GLvoid * ); GLenum, const GLvoid * );
extern void ( APIENTRY *qglActiveTexture ) ( GLenum texture ); extern void ( APIENTRY *qglActiveTexture ) ( GLenum texture );
extern void ( APIENTRY *qglClientActiveTexture ) ( GLenum texture ); extern void ( APIENTRY *qglClientActiveTexture ) ( GLenum texture );
extern void ( APIENTRY *qglDiscardFramebufferEXT ) ( GLenum target,
GLsizei numAttachments, const GLenum *attachments );
#endif #endif

View file

@ -44,6 +44,8 @@ void (APIENTRY *qglColorTableEXT)(GLenum, GLenum, GLsizei, GLenum, GLenum,
const GLvoid *); const GLvoid *);
void (APIENTRY *qglActiveTexture) (GLenum texture); void (APIENTRY *qglActiveTexture) (GLenum texture);
void (APIENTRY *qglClientActiveTexture) (GLenum texture); void (APIENTRY *qglClientActiveTexture) (GLenum texture);
void (APIENTRY *qglDiscardFramebufferEXT) (GLenum target,
GLsizei numAttachments, const GLenum *attachments);
/* ========================================================================= */ /* ========================================================================= */
@ -54,6 +56,7 @@ void QGL_EXT_Reset ( void )
qglColorTableEXT = NULL; qglColorTableEXT = NULL;
qglActiveTexture = NULL; qglActiveTexture = NULL;
qglClientActiveTexture = NULL; qglClientActiveTexture = NULL;
qglDiscardFramebufferEXT = NULL;
} }
/* ========================================================================= */ /* ========================================================================= */