From a24df94fedb762c5fb587d3e8a442ae22b5ce053 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Jul 2017 21:51:32 +0200 Subject: vo_opengl: add mechanism to create/cache VAO on the fly This removes VAO handling from video.c. Instead the shader cache will create the VAO as needed. The consequence is that this creates a VAO per shader, which might be a bit wasteful, but doesn't matter anyway. --- video/out/opengl/utils.c | 65 +++++++++++++++++++++++++++++++++++++++++------- video/out/opengl/utils.h | 5 ++++ video/out/opengl/video.c | 13 +++------- 3 files changed, 64 insertions(+), 19 deletions(-) (limited to 'video') diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index d3066d3ccb..79fe19bdd6 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -467,6 +467,7 @@ struct sc_entry { bstr frag; bstr vert; struct gl_timer *timer; + struct gl_vao vao; }; struct gl_shader_cache { @@ -482,14 +483,19 @@ struct gl_shader_cache { bstr header_text; bstr text; int next_texture_unit; - struct gl_vao *vao; + struct gl_vao *vao; // deprecated struct sc_entry *entries; int num_entries; + struct sc_entry *current_shader; // set by gl_sc_generate() + struct sc_uniform *uniforms; int num_uniforms; + const struct gl_vao_entry *vertex_entries; + size_t vertex_size; + // For checking that the user is calling gl_sc_reset() properly. bool needs_reset; @@ -541,6 +547,9 @@ void gl_sc_reset(struct gl_shader_cache *sc) talloc_free(sc->uniforms[n].name); sc->num_uniforms = 0; sc->next_texture_unit = 1; // not 0, as 0 is "free for use" + sc->vertex_entries = NULL; + sc->vertex_size = 0; + sc->current_shader = NULL; sc->needs_reset = false; } @@ -555,6 +564,7 @@ static void sc_flush_cache(struct gl_shader_cache *sc) talloc_free(e->frag.start); talloc_free(e->uniforms); gl_timer_free(e->timer); + gl_vao_uninit(&e->vao); } sc->num_entries = 0; } @@ -754,11 +764,23 @@ void gl_sc_uniform_mat3(struct gl_shader_cache *sc, char *name, // The vertex shader is setup such that the elements are available as fragment // shader variables using the names in the vao entries, which "position" being // set to gl_Position. +// Deprecated. void gl_sc_set_vao(struct gl_shader_cache *sc, struct gl_vao *vao) { sc->vao = vao; } +// Tell the shader generator (and later gl_sc_draw_data()) about the vertex +// data layout and attribute names. The entries array is terminated with a {0} +// entry. The array memory must remain valid indefinitely (for now). +void gl_sc_set_vertex_format(struct gl_shader_cache *sc, + const struct gl_vao_entry *entries, + size_t vertex_size) +{ + sc->vertex_entries = entries; + sc->vertex_size = vertex_size; +} + static const char *vao_glsl_type(const struct gl_vao_entry *e) { // pretty dumb... too dumb, but works for us @@ -899,9 +921,9 @@ static GLuint compile_program(struct gl_shader_cache *sc, const char *vertex, GLuint prog = gl->CreateProgram(); compile_attach_shader(sc, prog, GL_VERTEX_SHADER, vertex); compile_attach_shader(sc, prog, GL_FRAGMENT_SHADER, frag); - for (int n = 0; sc->vao->entries[n].name; n++) { + for (int n = 0; sc->vertex_entries[n].name; n++) { char vname[80]; - snprintf(vname, sizeof(vname), "vertex_%s", sc->vao->entries[n].name); + snprintf(vname, sizeof(vname), "vertex_%s", sc->vertex_entries[n].name); gl->BindAttribLocation(prog, n, vname); } link_shader(sc, prog); @@ -940,9 +962,9 @@ static GLuint load_program(struct gl_shader_cache *sc, const char *vertex, av_sha_update(sha, frag, strlen(frag) + 1); // In theory, the array could change order, breaking old binaries. - for (int n = 0; sc->vao->entries[n].name; n++) { - av_sha_update(sha, sc->vao->entries[n].name, - strlen(sc->vao->entries[n].name) + 1); + for (int n = 0; sc->vertex_entries[n].name; n++) { + av_sha_update(sha, sc->vertex_entries[n].name, + strlen(sc->vertex_entries[n].name) + 1); } uint8_t hash[256 / 8]; @@ -1030,7 +1052,16 @@ struct mp_pass_perf gl_sc_generate(struct gl_shader_cache *sc) // and before starting a new one. assert(!sc->needs_reset); - assert(sc->vao); + if (sc->vertex_entries) { + assert(!sc->vao); + } else { + // gl_sc_set_vertex_format() must always be called - except in the + // compat code path, where sc->vao must be set. + assert(sc->vao); + assert(sc->vao->entries); + sc->vertex_entries = sc->vao->entries; + sc->vertex_size = sc->vao->stride; + } for (int n = 0; n < MP_ARRAY_SIZE(sc->tmp); n++) sc->tmp[n].len = 0; @@ -1058,8 +1089,8 @@ struct mp_pass_perf gl_sc_generate(struct gl_shader_cache *sc) bstr *vert_body = &sc->tmp[2]; ADD(vert_body, "void main() {\n"); bstr *frag_vaos = &sc->tmp[3]; - for (int n = 0; sc->vao->entries[n].name; n++) { - const struct gl_vao_entry *e = &sc->vao->entries[n]; + for (int n = 0; sc->vertex_entries[n].name; n++) { + const struct gl_vao_entry *e = &sc->vertex_entries[n]; const char *glsl_type = vao_glsl_type(e); if (strcmp(e->name, "position") == 0) { // setting raster pos. requires setting gl_Position magic variable @@ -1144,6 +1175,8 @@ struct mp_pass_perf gl_sc_generate(struct gl_shader_cache *sc) }; MP_TARRAY_APPEND(sc, entry->uniforms, entry->num_uniforms, un); } + assert(!entry->vao.vao); + gl_vao_init(&entry->vao, gl, sc->vertex_size, sc->vertex_entries); } gl->UseProgram(entry->gl_shader); @@ -1157,10 +1190,24 @@ struct mp_pass_perf gl_sc_generate(struct gl_shader_cache *sc) gl_timer_start(entry->timer); sc->needs_reset = true; + sc->current_shader = entry; return gl_timer_measure(entry->timer); } +// Draw the vertex data (as described by the gl_vao_entry entries) in ptr +// to the screen. num is the number of vertexes. prim is usually GL_TRIANGLES. +// gl_sc_generate() must have been called before this. Some additional setup +// might be needed (like setting the viewport). +void gl_sc_draw_data(struct gl_shader_cache *sc, GLenum prim, void *ptr, + size_t num) +{ + assert(ptr); + assert(sc->current_shader); + + gl_vao_draw_data(&sc->current_shader->vao, prim, ptr, num); +} + // Maximum number of simultaneous query objects to keep around. Reducing this // number might cause rendering to block until the result of a previous query is // available diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h index 191565dd93..7a5606871f 100644 --- a/video/out/opengl/utils.h +++ b/video/out/opengl/utils.h @@ -166,8 +166,13 @@ void gl_sc_uniform_mat2(struct gl_shader_cache *sc, char *name, void gl_sc_uniform_mat3(struct gl_shader_cache *sc, char *name, bool transpose, GLfloat *v); void gl_sc_set_vao(struct gl_shader_cache *sc, struct gl_vao *vao); +void gl_sc_set_vertex_format(struct gl_shader_cache *sc, + const struct gl_vao_entry *entries, + size_t vertex_size); void gl_sc_enable_extension(struct gl_shader_cache *sc, char *name); struct mp_pass_perf gl_sc_generate(struct gl_shader_cache *sc); +void gl_sc_draw_data(struct gl_shader_cache *sc, GLenum prim, void *ptr, + size_t num); void gl_sc_reset(struct gl_shader_cache *sc); struct mpv_global; void gl_sc_set_cache_dir(struct gl_shader_cache *sc, struct mpv_global *global, diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 4b2c8ecc56..17433b4647 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -189,8 +189,6 @@ struct gl_video { struct gl_shader_cache *sc; - struct gl_vao vao; - struct osd_state *osd_state; struct mpgl_osd *osd; double osd_pts; @@ -1102,7 +1100,7 @@ static void render_pass_quad(struct gl_video *p, int vp_w, int vp_h, } p->gl->Viewport(0, 0, vp_w, abs(vp_h)); - gl_vao_draw_data(&p->vao, GL_TRIANGLE_STRIP, va, 4); + gl_sc_draw_data(p->sc, GL_TRIANGLE_STRIP, va, 4); debug_check_gl(p, "after rendering"); } @@ -1112,6 +1110,7 @@ static void finish_pass_direct(struct gl_video *p, GLint fbo, int vp_w, int vp_h { GL *gl = p->gl; pass_prepare_src_tex(p); + gl_sc_set_vertex_format(p->sc, vertex_vao, sizeof(struct vertex)); pass_record(p, gl_sc_generate(p->sc)); gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); render_pass_quad(p, vp_w, vp_h, dst); @@ -2443,8 +2442,8 @@ static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts, pass_record(p, gl_sc_generate(p->sc)); mpgl_osd_draw_part(p->osd, vp_w, vp_h, n); gl_sc_reset(p->sc); + gl_sc_set_vao(p->sc, NULL); } - gl_sc_set_vao(p->sc, &p->vao); } static float chroma_realign(int size, int pixel) @@ -2852,8 +2851,6 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) } if (has_frame) { - gl_sc_set_vao(p->sc, &p->vao); - bool interpolate = p->opts.interpolation && frame->display_synced && (p->frames_drawn || !frame->still); if (interpolate) { @@ -3302,8 +3299,6 @@ static void init_gl(struct gl_video *p) gl->Disable(GL_DITHER); - gl_vao_init(&p->vao, gl, sizeof(struct vertex), vertex_vao); - gl_video_set_gl_state(p); // Test whether we can use 10 bit. @@ -3328,8 +3323,6 @@ void gl_video_uninit(struct gl_video *p) gl_sc_destroy(p->sc); - gl_vao_uninit(&p->vao); - gl->DeleteTextures(1, &p->lut_3d_texture); gl_timer_free(p->upload_timer); -- cgit v1.2.3