mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
1c81311673
commit
a24df94fed
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue