summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-07-22 21:51:32 +0200
committerwm4 <wm4@nowhere>2017-07-22 21:51:32 +0200
commita24df94fedb762c5fb587d3e8a442ae22b5ce053 (patch)
treea9c41e4a63d2e4560d7e70aad6cf46e8ae42aa85
parent1c8131167334183ad24b90cbbf4fd86d3d5406cc (diff)
downloadmpv-a24df94fedb762c5fb587d3e8a442ae22b5ce053.tar.bz2
mpv-a24df94fedb762c5fb587d3e8a442ae22b5ce053.tar.xz
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.
-rw-r--r--video/out/opengl/utils.c65
-rw-r--r--video/out/opengl/utils.h5
-rw-r--r--video/out/opengl/video.c13
3 files changed, 64 insertions, 19 deletions
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);