Skip to content

Commit

Permalink
backend/gl: reuse buffer and vertex array objects
Browse files Browse the repository at this point in the history
Mainly to workaround a mesa performance regression that causes object
deallocations to be quadratic. But it's also just good to not have so
many object allocations/deallocations.

Signed-off-by: Yuxuan Shui <[email protected]>
  • Loading branch information
yshui committed Jun 21, 2024
1 parent 6fc23c3 commit 5ec2c87
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 47 deletions.
49 changes: 30 additions & 19 deletions src/backend/gl/blur.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,15 +360,10 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_,
// we never actually use that capability anywhere.
assert(source->y_inverted);

GLuint vao[2];
glGenVertexArrays(2, vao);
GLuint bo[4];
glGenBuffers(4, bo);

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBindVertexArray(vao[0]);
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
glBindVertexArray(gd->vertex_array_objects[0]);
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[1]);
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * nrects * 16, coord, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6,
indices, GL_STREAM_DRAW);
Expand All @@ -378,9 +373,9 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_,
glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_FLOAT, GL_FALSE,
sizeof(GLfloat) * 4, (void *)(sizeof(GLfloat) * 2));

glBindVertexArray(vao[1]);
glBindBuffer(GL_ARRAY_BUFFER, bo[2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[3]);
glBindVertexArray(gd->vertex_array_objects[1]);
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[3]);
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord_resized) * nrects_resized * 16,
coord_resized, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
Expand All @@ -396,25 +391,41 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_,

auto target_fbo = gl_bind_image_to_fbo(gd, (image_handle)target);
if (bctx->method == BLUR_METHOD_DUAL_KAWASE) {
ret = gl_dual_kawase_blur(args->opacity, bctx, args->source_mask, vao,
vao_nelems, source, gd->samplers[GL_SAMPLER_BLUR],
target_fbo, gd->default_mask_texture);
ret = gl_dual_kawase_blur(args->opacity, bctx, args->source_mask,
gd->vertex_array_objects, vao_nelems, source,
gd->samplers[GL_SAMPLER_BLUR], target_fbo,
gd->default_mask_texture);
} else {
ret = gl_kernel_blur(args->opacity, bctx, args->source_mask, vao,
vao_nelems, source, gd->samplers[GL_SAMPLER_BLUR],
target_fbo, gd->default_mask_texture);
ret = gl_kernel_blur(args->opacity, bctx, args->source_mask,
gd->vertex_array_objects, vao_nelems, source,
gd->samplers[GL_SAMPLER_BLUR], target_fbo,
gd->default_mask_texture);
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);

// Invalidate buffer data
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[1]);
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * nrects * 16, NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6, NULL,
GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[3]);
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord_resized) * nrects_resized * 16,
NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(long)sizeof(*indices_resized) * nrects_resized * 6, NULL,
GL_STREAM_DRAW);

// Cleanup vertex array states
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(4, bo);
glBindVertexArray(0);
glDeleteVertexArrays(2, vao);
glUseProgram(0);

free(indices);
Expand Down
62 changes: 34 additions & 28 deletions src/backend/gl/gl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,9 @@ static GLuint gl_average_texture_color(struct gl_data *gd, struct gl_texture *im
glUniform2f(UNIFORM_TEXSIZE_LOC, (GLfloat)img->width, (GLfloat)img->height);

// Prepare vertex attributes
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint bo[2];
glGenBuffers(2, bo);
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
glBindVertexArray(gd->vertex_array_objects[0]);
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[1]);
glEnableVertexAttribArray(vert_coord_loc);
glEnableVertexAttribArray(vert_in_texcoord_loc);
glVertexAttribPointer(vert_coord_loc, 2, GL_INT, GL_FALSE, sizeof(GLint) * 4, NULL);
Expand All @@ -316,11 +312,15 @@ static GLuint gl_average_texture_color(struct gl_data *gd, struct gl_texture *im
// Cleanup vertex attributes
glDisableVertexAttribArray(vert_coord_loc);
glDisableVertexAttribArray(vert_in_texcoord_loc);

// Invalidate buffer data
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * 16, NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * 6, NULL, GL_STREAM_DRAW);

// Cleanup buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(2, bo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);

// Cleanup shaders
glUseProgram(0);
Expand Down Expand Up @@ -384,10 +384,11 @@ static const struct gl_vertex_attribs_definition gl_blit_vertex_attribs = {
* @param nuniforms number of uniforms for `shader`
* @param uniforms uniforms for `shader`
*/
static void gl_blit_inner(GLuint target_fbo, int nrects, GLfloat *coord, GLuint *indices,
const struct gl_vertex_attribs_definition *vert_attribs,
const struct gl_shader *shader, int nuniforms,
struct gl_uniform_value *uniforms) {
static void
gl_blit_inner(struct gl_data *gd, GLuint target_fbo, int nrects, GLfloat *coord,
GLuint *indices, const struct gl_vertex_attribs_definition *vert_attribs,
const struct gl_shader *shader, int nuniforms,
struct gl_uniform_value *uniforms) {
// FIXME(yshui) breaks when `mask` and `img` doesn't have the same y_inverted
// value. but we don't ever hit this problem because all of our
// images and masks are y_inverted.
Expand Down Expand Up @@ -431,14 +432,10 @@ static void gl_blit_inner(GLuint target_fbo, int nrects, GLfloat *coord, GLuint
// log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n",
// x, y, width, height, dx, dy, ptex->width, ptex->height, z);

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindVertexArray(gd->vertex_array_objects[0]);

GLuint bo[2];
glGenBuffers(2, bo);
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
glBindBuffer(GL_ARRAY_BUFFER, gd->buffer_objects[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->buffer_objects[1]);
glBufferData(GL_ARRAY_BUFFER, vert_attribs->stride * nrects * 4, coord, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6,
indices, GL_STREAM_DRAW);
Expand All @@ -454,8 +451,15 @@ static void gl_blit_inner(GLuint target_fbo, int nrects, GLfloat *coord, GLuint

glDisableVertexAttribArray(vert_coord_loc);
glDisableVertexAttribArray(vert_in_texcoord_loc);

// Invalidate buffer data
glBufferData(GL_ARRAY_BUFFER, vert_attribs->stride * nrects * 4, NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6, NULL,
GL_STREAM_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);

// Cleanup
for (GLuint i = GL_TEXTURE1; i < texture_unit; i++) {
Expand All @@ -466,10 +470,6 @@ static void gl_blit_inner(GLuint target_fbo, int nrects, GLfloat *coord, GLuint
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(2, bo);

glUseProgram(0);

gl_check_err();
Expand Down Expand Up @@ -636,7 +636,7 @@ bool gl_blit(backend_t *base, ivec2 origin, image_handle target_,
// X pixmap is in premultiplied alpha, so we might just as well use it too.
// Thanks to derhass for help.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
gl_blit_inner(fbo, nrects, coord, indices, &gl_blit_vertex_attribs, shader,
gl_blit_inner(gd, fbo, nrects, coord, indices, &gl_blit_vertex_attribs, shader,
NUMBER_OF_UNIFORMS, uniforms);

free(indices);
Expand Down Expand Up @@ -696,7 +696,7 @@ static bool gl_copy_area_draw(struct gl_data *gd, ivec2 origin,
};
auto fbo = gl_bind_image_to_fbo(gd, target_handle);
glBlendFunc(GL_ONE, GL_ZERO);
gl_blit_inner(fbo, nrects, coord, indices, &gl_blit_vertex_attribs, shader,
gl_blit_inner(gd, fbo, nrects, coord, indices, &gl_blit_vertex_attribs, shader,
ARR_SIZE(uniforms), uniforms);
free(indices);
free(coord);
Expand Down Expand Up @@ -881,6 +881,9 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
glGenQueries(2, gd->frame_timing);
gd->current_frame_timing = 0;

glGenBuffers(4, gd->buffer_objects);
glGenVertexArrays(2, gd->vertex_array_objects);

// Initialize GL data structure
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
Expand Down Expand Up @@ -1039,6 +1042,9 @@ void gl_deinit(struct gl_data *gd) {

glDeleteFramebuffers(1, &gd->temp_fbo);

glDeleteBuffers(4, gd->buffer_objects);
glDeleteVertexArrays(2, gd->vertex_array_objects);

glDeleteQueries(2, gd->frame_timing);

gl_check_err();
Expand Down Expand Up @@ -1134,7 +1140,7 @@ bool gl_apply_alpha(backend_t *base, image_handle target, double alpha, const re
[UNIFORM_COLOR_LOC] = {.type = GL_FLOAT_VEC4, .f4 = {0, 0, 0, 0}},
};
gl_mask_rects_to_coords_simple(nrects, rect, coord, indices);
gl_blit_inner(gd->temp_fbo, nrects, coord, indices, &vertex_attribs,
gl_blit_inner(gd, gd->temp_fbo, nrects, coord, indices, &vertex_attribs,
&gd->fill_shader, ARR_SIZE(uniforms), uniforms);
free(indices);
free(coord);
Expand Down
2 changes: 2 additions & 0 deletions src/backend/gl/gl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ struct gl_data {
struct gl_shader copy_area_prog;
struct gl_shader copy_area_with_dither_prog;
GLuint samplers[GL_MAX_SAMPLERS];
GLuint buffer_objects[4];
GLuint vertex_array_objects[2];

bool dithered_present;

Expand Down

0 comments on commit 5ec2c87

Please sign in to comment.