Be more conservative about texture memory usage.

This commit is contained in:
Themaister 2013-07-06 22:10:09 +02:00
parent 911558462a
commit 6b4924c844
5 changed files with 112 additions and 40 deletions

View File

@ -627,8 +627,16 @@ void gl_init_fbo(void *data, unsigned width, unsigned height)
}
#ifndef HAVE_RGL
static void gl_deinit_hw_render(gl_t *gl)
{
if (gl->hw_render_fbo_init)
glDeleteFramebuffers(gl->textures, gl->hw_render_fbo);
if (gl->hw_render_depth_init)
glDeleteRenderbuffers(gl->textures, gl->hw_render_depth);
gl->hw_render_fbo_init = false;
}
bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height)
static bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height)
{
RARCH_LOG("[GL]: Initializing HW render (%u x %u).\n", width, height);
GLint max_fbo_size = 0;
@ -641,7 +649,7 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height)
return false;
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(TEXTURES, gl->hw_render_fbo);
glGenFramebuffers(gl->textures, gl->hw_render_fbo);
bool depth = g_extern.system.hw_render_callback.depth;
bool stencil = g_extern.system.hw_render_callback.stencil;
@ -653,11 +661,11 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height)
if (depth)
{
glGenRenderbuffers(TEXTURES, gl->hw_render_depth);
glGenRenderbuffers(gl->textures, gl->hw_render_depth);
gl->hw_render_depth_init = true;
}
for (unsigned i = 0; i < TEXTURES; i++)
for (unsigned i = 0; i < gl->textures; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, gl->hw_render_fbo[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->texture[i], 0);
@ -1019,8 +1027,8 @@ static void gl_update_input_size(void *data, unsigned width, unsigned height, un
set_texture_coords(gl->tex_coords, xamt, yamt);
}
// We might have used different texture coordinates last frame. Edge case if resolution changes very rapidly.
else if (width != gl->last_width[(gl->tex_index - 1) & TEXTURES_MASK] ||
height != gl->last_height[(gl->tex_index - 1) & TEXTURES_MASK])
else if (width != gl->last_width[(gl->tex_index + gl->textures - 1) % gl->textures] ||
height != gl->last_height[(gl->tex_index + gl->textures - 1) % gl->textures])
{
GLfloat xamt = (GLfloat)width / gl->tex_w;
GLfloat yamt = (GLfloat)height / gl->tex_h;
@ -1077,13 +1085,13 @@ static inline void gl_convert_frame_argb8888_abgr8888(void *data, void *output,
static void gl_init_textures_data(void *data)
{
gl_t *gl = (gl_t*)data;
for (unsigned i = 0; i < TEXTURES; i++)
for (unsigned i = 0; i < gl->textures; i++)
{
gl->last_width[i] = gl->tex_w;
gl->last_height[i] = gl->tex_h;
}
for (unsigned i = 0; i < TEXTURES; i++)
for (unsigned i = 0; i < gl->textures; i++)
{
gl->prev_info[i].tex = gl->texture[0];
gl->prev_info[i].input_size[0] = gl->tex_w;
@ -1110,7 +1118,7 @@ static void gl_init_textures(void *data, const video_info_t *video)
glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->pbo);
glBufferData(GL_TEXTURE_REFERENCE_BUFFER_SCE,
gl->tex_w * gl->tex_h * gl->base_size * TEXTURES, NULL, GL_STREAM_DRAW);
gl->tex_w * gl->tex_h * gl->base_size * gl->textures, NULL, GL_STREAM_DRAW);
#endif
GLenum internal_fmt = gl->internal_fmt;
@ -1141,9 +1149,9 @@ static void gl_init_textures(void *data, const video_info_t *video)
}
#endif
glGenTextures(TEXTURES, gl->texture);
glGenTextures(gl->textures, gl->texture);
for (unsigned i = 0; i < TEXTURES; i++)
for (unsigned i = 0; i < gl->textures; i++)
{
glBindTexture(GL_TEXTURE_2D, gl->texture[i]);
@ -1264,7 +1272,7 @@ static inline void gl_copy_frame(void *data, const void *frame, unsigned width,
static inline void gl_set_prev_texture(void *data, const struct gl_tex_info *tex_info)
{
gl_t *gl = (gl_t*)data;
memmove(gl->prev_info + 1, gl->prev_info, sizeof(*tex_info) * (TEXTURES - 1));
memmove(gl->prev_info + 1, gl->prev_info, sizeof(*tex_info) * (gl->textures - 1));
memcpy(&gl->prev_info[0], tex_info, sizeof(*tex_info));
}
@ -1386,7 +1394,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
if (frame) // Can be NULL for frame dupe / NULL render.
{
gl->tex_index = (gl->tex_index + 1) & TEXTURES_MASK;
gl->tex_index = (gl->tex_index + 1) % gl->textures;
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
#ifdef HAVE_FBO
@ -1555,7 +1563,7 @@ static void gl_free(void *data)
gl_disable_client_arrays(gl);
#endif
glDeleteTextures(TEXTURES, gl->texture);
glDeleteTextures(gl->textures, gl->texture);
#if defined(HAVE_RGUI) || defined(HAVE_RMENU)
if (gl->rgui_texture)
@ -1584,13 +1592,8 @@ static void gl_free(void *data)
#ifdef HAVE_FBO
gl_deinit_fbo(gl);
#ifndef HAVE_RGL
if (gl->hw_render_fbo_init)
glDeleteFramebuffers(TEXTURES, gl->hw_render_fbo);
if (gl->hw_render_depth_init)
glDeleteRenderbuffers(TEXTURES, gl->hw_render_depth);
gl->hw_render_fbo_init = false;
gl_deinit_hw_render(gl);
#endif
#endif
@ -1707,7 +1710,7 @@ static inline void gl_reinit_textures(void *data, const video_info_t *video)
#endif
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(TEXTURES, gl->texture);
glDeleteTextures(gl->textures, gl->texture);
gl_init_textures(gl, video);
gl_init_textures_data(gl);
@ -1836,6 +1839,8 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
return NULL;
}
gl->video_info = *video;
RARCH_LOG("Found GL context: %s\n", gl->ctx_driver->ident);
context_get_video_size_func(&gl->full_x, &gl->full_y);
@ -1887,6 +1892,9 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
struct retro_hw_render_callback *hw_render = &g_extern.system.hw_render_callback;
gl->vertex_ptr = hw_render->bottom_left_origin ? vertexes : vertexes_flipped;
// Better pipelining with GPU due to synchronous glSubTexImage. Multiple async PBOs would be an alternative,
// but still need multiple textures with PREV.
gl->textures = 4;
#ifdef HAVE_FBO
#ifdef HAVE_OPENGLES2
gl->hw_render_use = hw_render->context_type == RETRO_HW_CONTEXT_OPENGLES2;
@ -1894,6 +1902,8 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
gl->hw_render_use = hw_render->context_type == RETRO_HW_CONTEXT_OPENGL ||
g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGL_CORE;
#endif
if (gl->hw_render_use)
gl->textures = 1; // All on GPU, no need to excessively create textures.
#endif
gl->white_color_ptr = white_color;
@ -1910,6 +1920,13 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
return NULL;
}
if (gl->shader)
{
unsigned minimum = gl->shader->get_prev_textures();
gl->textures = max(minimum + 1, gl->textures);
}
RARCH_LOG("GL: Using %u textures.\n", gl->textures);
RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num(gl));
gl->tex_w = RARCH_SCALE_BASE * video->input_scale;
@ -2027,12 +2044,13 @@ static void gl_update_tex_filter_frame(gl_t *gl)
if (!gl_shader_filter_type(gl, 1, &smooth))
smooth = g_settings.video.smooth;
gl->video_info.smooth = smooth;
GLuint new_filt = smooth ? GL_LINEAR : GL_NEAREST;
if (new_filt == gl->tex_filter)
return;
gl->tex_filter = new_filt;
for (unsigned i = 0; i < TEXTURES; i++)
for (unsigned i = 0; i < gl->textures; i++)
{
if (gl->texture[i])
{
@ -2096,6 +2114,33 @@ static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *p
gl_update_tex_filter_frame(gl);
if (gl->shader)
{
unsigned textures = gl->shader->get_prev_textures() + 1;
if (textures > gl->textures) // Have to reinit a bit.
{
#if defined(HAVE_FBO) && !defined(HAVE_RGL)
gl_deinit_hw_render(gl);
#endif
glDeleteTextures(gl->textures, gl->texture);
#if defined(HAVE_PSGL)
glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, 0);
glDeleteBuffers(1, &gl->pbo);
#endif
gl->textures = textures;
RARCH_LOG("GL: Using %u textures.\n", gl->textures);
gl->tex_index = 0;
gl_init_textures(gl, &gl->video_info);
gl_init_textures_data(gl);
#if defined(HAVE_FBO) && !defined(HAVE_RGL)
if (gl->hw_render_use)
gl_init_hw_render(gl, gl->tex_w, gl->tex_h);
#endif
}
}
#ifdef HAVE_FBO
// Set up render to texture again.
gl_init_fbo(gl, gl->tex_w, gl->tex_h);
@ -2362,7 +2407,7 @@ static void gl_get_overlay_interface(void *data, const video_overlay_interface_t
static uintptr_t gl_get_current_framebuffer(void *data)
{
gl_t *gl = (gl_t*)data;
return gl->hw_render_fbo[(gl->tex_index + 1) & TEXTURES_MASK];
return gl->hw_render_fbo[(gl->tex_index + 1) % gl->textures];
}
static retro_proc_address_t gl_get_proc_address(void *data, const char *sym)

View File

@ -137,13 +137,7 @@ struct gl_coords
typedef struct gl_shader_backend gl_shader_backend_t;
#define MAX_SHADERS 16
#if (defined(HAVE_GLSL) || defined(HAVE_CG))
#define TEXTURES 8
#else
#define TEXTURES 1
#endif
#define TEXTURES_MASK (TEXTURES - 1)
#define MAX_TEXTURES 8
typedef struct gl
{
@ -151,9 +145,10 @@ typedef struct gl
const gl_shader_backend_t *shader;
bool vsync;
GLuint texture[TEXTURES];
GLuint texture[MAX_TEXTURES];
unsigned tex_index; // For use with PREV.
struct gl_tex_info prev_info[TEXTURES];
unsigned textures;
struct gl_tex_info prev_info[MAX_TEXTURES];
GLuint tex_filter;
void *empty_buf;
@ -172,8 +167,8 @@ typedef struct gl
int fbo_pass;
bool fbo_inited;
GLuint hw_render_fbo[TEXTURES];
GLuint hw_render_depth[TEXTURES];
GLuint hw_render_fbo[MAX_TEXTURES];
GLuint hw_render_depth[MAX_TEXTURES];
bool hw_render_fbo_init;
bool hw_render_depth_init;
#endif
@ -192,8 +187,8 @@ typedef struct gl
struct rarch_viewport vp;
unsigned vp_out_width;
unsigned vp_out_height;
unsigned last_width[TEXTURES];
unsigned last_height[TEXTURES];
unsigned last_width[MAX_TEXTURES];
unsigned last_height[MAX_TEXTURES];
unsigned tex_w, tex_h;
GLfloat tex_coords[8];
math_matrix mvp, mvp_no_rot;
@ -223,6 +218,7 @@ typedef struct gl
GLfloat font_color_dark[16];
bool egl_images;
video_info_t video_info;
#ifdef HAVE_OVERLAY
// Overlay rendering

View File

@ -102,9 +102,9 @@ struct cg_fbo_params
CGparameter coord;
};
#define MAX_TEXTURES 8
#define MAX_LUT_TEXTURES 8
#define MAX_VARIABLES 64
#define PREV_TEXTURES (TEXTURES - 1)
#define PREV_TEXTURES (MAX_TEXTURES - 1)
struct cg_program
{
@ -142,7 +142,7 @@ static unsigned active_index;
static struct gfx_shader *cg_shader;
static state_tracker_t *state_tracker;
static GLuint lut_textures[MAX_TEXTURES];
static GLuint lut_textures[MAX_LUT_TEXTURES];
static CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
static unsigned cg_attrib_index;
@ -911,6 +911,20 @@ static void gl_cg_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
scale->valid = false;
}
static unsigned gl_cg_get_prev_textures(void)
{
if (!cg_active)
return 0;
unsigned max_prev = 0;
for (unsigned i = 1; i <= cg_shader->passes; i++)
for (unsigned j = 0; j < PREV_TEXTURES; j++)
if (prg[i].prev[j].tex)
max_prev = max(j + 1, max_prev);
return max_prev;
}
void gl_cg_set_compiler_args(const char **argv)
{
cg_arguments = argv;
@ -931,6 +945,7 @@ const gl_shader_backend_t gl_cg_backend = {
gl_cg_shader_scale,
gl_cg_set_coords,
gl_cg_set_mvp,
gl_cg_get_prev_textures,
RARCH_SHADER_CG,
};

View File

@ -50,6 +50,7 @@ struct gl_shader_backend
void (*shader_scale)(unsigned index, struct gfx_fbo_scale *scale);
bool (*set_coords)(const struct gl_coords *coords);
bool (*set_mvp)(const math_matrix *mat);
unsigned (*get_prev_textures)(void);
enum rarch_shader_type type;
};

View File

@ -64,7 +64,7 @@
#define BORDER_FUNC GL_CLAMP_TO_BORDER
#endif
#define PREV_TEXTURES (TEXTURES - 1)
#define PREV_TEXTURES (MAX_TEXTURES - 1)
static struct gfx_shader *glsl_shader;
static bool glsl_core;
@ -1188,6 +1188,20 @@ static void gl_glsl_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
scale->valid = false;
}
static unsigned gl_glsl_get_prev_textures(void)
{
if (!glsl_enable)
return 0;
unsigned max_prev = 0;
for (unsigned i = 1; i <= glsl_shader->passes; i++)
for (unsigned j = 0; j < PREV_TEXTURES; j++)
if (gl_uniforms[i].prev[j].texture >= 0)
max_prev = max(j + 1, max_prev);
return max_prev;
}
void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*))
{
glsl_get_proc_address = proc;
@ -1210,6 +1224,7 @@ const gl_shader_backend_t gl_glsl_backend = {
gl_glsl_shader_scale,
gl_glsl_set_coords,
gl_glsl_set_mvp,
gl_glsl_get_prev_textures,
RARCH_SHADER_GLSL,
};