mirror of https://github.com/mpv-player/mpv
vo_opengl: refactor tex_upload to ra_buf_pool
Also refactors the usage of tex_upload to make ra_tex_upload_pbo a RA-internal thing again. ra_buf_pool has the main advantage of being dynamically sized depending on buf_poll, so for OpenGL we'll end up only using one buffer (when not persistently mapping) - while for vulkan we'll use as many as necessary, which depends on the swapchain depth anyway.
This commit is contained in:
parent
371000108a
commit
09c501a40e
|
@ -54,7 +54,6 @@ struct mpgl_osd_part {
|
|||
enum sub_bitmap_format format;
|
||||
int change_id;
|
||||
struct ra_tex *texture;
|
||||
struct tex_upload pbo;
|
||||
int w, h;
|
||||
int num_subparts;
|
||||
int prev_num_subparts;
|
||||
|
@ -71,7 +70,6 @@ struct mpgl_osd {
|
|||
const struct ra_format *fmt_table[SUBBITMAP_COUNT];
|
||||
bool formats[SUBBITMAP_COUNT];
|
||||
bool change_flag; // for reporting to API user only
|
||||
bool want_pbo;
|
||||
// temporary
|
||||
int stereo_mode;
|
||||
struct mp_osd_res osd_res;
|
||||
|
@ -79,7 +77,7 @@ struct mpgl_osd {
|
|||
};
|
||||
|
||||
struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
|
||||
struct osd_state *osd, bool want_pbo)
|
||||
struct osd_state *osd)
|
||||
{
|
||||
struct mpgl_osd *ctx = talloc_ptrtype(NULL, ctx);
|
||||
*ctx = (struct mpgl_osd) {
|
||||
|
@ -88,7 +86,6 @@ struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
|
|||
.ra = ra,
|
||||
.change_flag = true,
|
||||
.scratch = talloc_zero_size(ctx, 1),
|
||||
.want_pbo = want_pbo,
|
||||
};
|
||||
|
||||
ctx->fmt_table[SUBBITMAP_LIBASS] = ra_find_unorm_format(ra, 1, 1);
|
||||
|
@ -111,7 +108,6 @@ void mpgl_osd_destroy(struct mpgl_osd *ctx)
|
|||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct mpgl_osd_part *p = ctx->parts[n];
|
||||
ra_tex_free(ctx->ra, &p->texture);
|
||||
tex_upload_uninit(ctx->ra, &p->pbo);
|
||||
}
|
||||
talloc_free(ctx);
|
||||
}
|
||||
|
@ -180,7 +176,7 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
|
|||
.stride = imgs->packed->stride[0],
|
||||
};
|
||||
|
||||
ok = tex_upload(ra, &osd->pbo, ctx->want_pbo, ¶ms);
|
||||
ok = ra->fns->tex_upload(ra, ¶ms);
|
||||
|
||||
done:
|
||||
return ok;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "sub/osd.h"
|
||||
|
||||
struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log,
|
||||
struct osd_state *osd, bool want_pbo);
|
||||
struct osd_state *osd);
|
||||
void mpgl_osd_destroy(struct mpgl_osd *ctx);
|
||||
|
||||
void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts,
|
||||
|
|
|
@ -30,6 +30,11 @@ struct ra {
|
|||
// formats should have a lower index. (E.g. GLES3 should put rg8 before la.)
|
||||
struct ra_format **formats;
|
||||
int num_formats;
|
||||
|
||||
// Accelerate texture uploads via an extra PBO even when
|
||||
// RA_CAP_DIRECT_UPLOAD is supported. This is basically only relevant for
|
||||
// OpenGL. Set by the RA user.
|
||||
bool use_pbo;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -15,6 +15,7 @@ struct ra_gl {
|
|||
|
||||
// For ra_tex.priv
|
||||
struct ra_tex_gl {
|
||||
struct ra_buf_pool pbo; // for ra.use_pbo
|
||||
bool own_objects;
|
||||
GLenum target;
|
||||
GLuint texture; // 0 if no texture data associated
|
||||
|
@ -218,6 +219,8 @@ static void gl_tex_destroy(struct ra *ra, struct ra_tex *tex)
|
|||
GL *gl = ra_gl_get(ra);
|
||||
struct ra_tex_gl *tex_gl = tex->priv;
|
||||
|
||||
ra_buf_pool_uninit(ra, &tex_gl->pbo);
|
||||
|
||||
if (tex_gl->own_objects) {
|
||||
if (tex_gl->fbo)
|
||||
gl->DeleteFramebuffers(1, &tex_gl->fbo);
|
||||
|
@ -435,6 +438,9 @@ static bool gl_tex_upload(struct ra *ra,
|
|||
assert(tex->params.host_mutable);
|
||||
assert(!params->buf || !params->src);
|
||||
|
||||
if (ra->use_pbo && !params->buf)
|
||||
return ra_tex_upload_pbo(ra, &tex_gl->pbo, params);
|
||||
|
||||
const void *src = params->src;
|
||||
if (buf) {
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->buffer);
|
||||
|
|
|
@ -39,6 +39,91 @@ void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo)
|
|||
gl_transform_ortho(t, 0, fbo.tex->params.w, 0, fbo.tex->params.h * y_dir);
|
||||
}
|
||||
|
||||
void ra_buf_pool_uninit(struct ra *ra, struct ra_buf_pool *pool)
|
||||
{
|
||||
for (int i = 0; i < pool->num_buffers; i++)
|
||||
ra_buf_free(ra, &pool->buffers[i]);
|
||||
|
||||
talloc_free(pool->buffers);
|
||||
*pool = (struct ra_buf_pool){0};
|
||||
}
|
||||
|
||||
static bool ra_buf_params_compatible(const struct ra_buf_params *new,
|
||||
const struct ra_buf_params *old)
|
||||
{
|
||||
return new->type == old->type &&
|
||||
new->size <= old->size &&
|
||||
new->host_mapped == old->host_mapped &&
|
||||
new->host_mutable == old->host_mutable;
|
||||
}
|
||||
|
||||
static bool ra_buf_pool_grow(struct ra *ra, struct ra_buf_pool *pool)
|
||||
{
|
||||
struct ra_buf *buf = ra_buf_create(ra, &pool->current_params);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
MP_TARRAY_INSERT_AT(NULL, pool->buffers, pool->num_buffers, pool->index, buf);
|
||||
MP_VERBOSE(ra, "Resized buffer pool to size %d\n", pool->num_buffers);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ra_buf *ra_buf_pool_get(struct ra *ra, struct ra_buf_pool *pool,
|
||||
const struct ra_buf_params *params)
|
||||
{
|
||||
assert(!params->initial_data);
|
||||
|
||||
if (!ra_buf_params_compatible(params, &pool->current_params)) {
|
||||
ra_buf_pool_uninit(ra, pool);
|
||||
pool->current_params = *params;
|
||||
}
|
||||
|
||||
// Make sure we have at least one buffer available
|
||||
if (!pool->buffers && !ra_buf_pool_grow(ra, pool))
|
||||
return NULL;
|
||||
|
||||
// Make sure the next buffer is available for use
|
||||
if (!ra->fns->buf_poll(ra, pool->buffers[pool->index]) &&
|
||||
!ra_buf_pool_grow(ra, pool))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ra_buf *buf = pool->buffers[pool->index++];
|
||||
pool->index %= pool->num_buffers;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool ra_tex_upload_pbo(struct ra *ra, struct ra_buf_pool *pbo,
|
||||
const struct ra_tex_upload_params *params)
|
||||
{
|
||||
if (params->buf)
|
||||
return ra->fns->tex_upload(ra, params);
|
||||
|
||||
struct ra_tex *tex = params->tex;
|
||||
size_t row_size = tex->params.dimensions == 2 ? params->stride :
|
||||
tex->params.w * tex->params.format->pixel_size;
|
||||
|
||||
struct ra_buf_params bufparams = {
|
||||
.type = RA_BUF_TYPE_TEX_UPLOAD,
|
||||
.size = row_size * tex->params.h * tex->params.d,
|
||||
.host_mutable = true,
|
||||
};
|
||||
|
||||
struct ra_buf *buf = ra_buf_pool_get(ra, pbo, &bufparams);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
ra->fns->buf_update(ra, buf, 0, params->src, bufparams.size);
|
||||
|
||||
struct ra_tex_upload_params newparams = *params;
|
||||
newparams.buf = buf;
|
||||
newparams.src = NULL;
|
||||
|
||||
return ra->fns->tex_upload(ra, &newparams);
|
||||
}
|
||||
|
||||
// Create a texture and a FBO using the texture as color attachments.
|
||||
// fmt: texture internal format
|
||||
// If the parameters are the same as the previous call, do not touch it.
|
||||
|
@ -120,63 +205,6 @@ void fbotex_uninit(struct fbotex *fbo)
|
|||
}
|
||||
}
|
||||
|
||||
bool tex_upload(struct ra *ra, struct tex_upload *pbo, bool want_pbo,
|
||||
const struct ra_tex_upload_params *params)
|
||||
{
|
||||
if (!(ra->caps & RA_CAP_DIRECT_UPLOAD))
|
||||
want_pbo = true;
|
||||
|
||||
if (!want_pbo || params->buf)
|
||||
return ra->fns->tex_upload(ra, params);
|
||||
|
||||
struct ra_tex *tex = params->tex;
|
||||
size_t row_size = tex->params.dimensions == 2 ? params->stride :
|
||||
tex->params.w * tex->params.format->pixel_size;
|
||||
size_t needed_size = row_size * tex->params.h * tex->params.d;
|
||||
|
||||
if (needed_size > pbo->buffer_size)
|
||||
tex_upload_uninit(ra, pbo);
|
||||
|
||||
if (!pbo->buffers[0]) {
|
||||
struct ra_buf_params bufparams = {
|
||||
.type = RA_BUF_TYPE_TEX_UPLOAD,
|
||||
.size = needed_size,
|
||||
.host_mutable = true,
|
||||
};
|
||||
|
||||
pbo->buffer_size = bufparams.size;
|
||||
for (int i = 0; i < NUM_PBO_BUFFERS; i++) {
|
||||
pbo->buffers[i] = ra_buf_create(ra, &bufparams);
|
||||
if (!pbo->buffers[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct ra_buf *buf = pbo->buffers[pbo->index++];
|
||||
pbo->index %= NUM_PBO_BUFFERS;
|
||||
|
||||
if (!ra->fns->buf_poll(ra, buf)) {
|
||||
MP_WARN(ra, "Texture upload buffer was not free to use! Try "
|
||||
"increasing NUM_PBO_BUFFERS.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ra->fns->buf_update(ra, buf, 0, params->src, needed_size);
|
||||
|
||||
struct ra_tex_upload_params newparams = *params;
|
||||
newparams.buf = buf;
|
||||
newparams.src = NULL;
|
||||
|
||||
return ra->fns->tex_upload(ra, &newparams);
|
||||
}
|
||||
|
||||
void tex_upload_uninit(struct ra *ra, struct tex_upload *pbo)
|
||||
{
|
||||
for (int i = 0; i < NUM_PBO_BUFFERS; i++)
|
||||
ra_buf_free(ra, &pbo->buffers[i]);
|
||||
*pbo = (struct tex_upload){0};
|
||||
}
|
||||
|
||||
struct timer_pool {
|
||||
struct ra *ra;
|
||||
ra_timer *timer;
|
||||
|
|
|
@ -69,6 +69,25 @@ struct fbodst {
|
|||
|
||||
void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo);
|
||||
|
||||
// A pool of buffers, which can grow as needed
|
||||
struct ra_buf_pool {
|
||||
struct ra_buf_params current_params;
|
||||
struct ra_buf **buffers;
|
||||
int num_buffers;
|
||||
int index;
|
||||
};
|
||||
|
||||
void ra_buf_pool_uninit(struct ra *ra, struct ra_buf_pool *pool);
|
||||
|
||||
// Note: params->initial_data is *not* supported
|
||||
struct ra_buf *ra_buf_pool_get(struct ra *ra, struct ra_buf_pool *pool,
|
||||
const struct ra_buf_params *params);
|
||||
|
||||
// Helper that wraps ra_tex_upload using texture upload buffers to ensure that
|
||||
// params->buf is always set. This is intended for RA-internal usage.
|
||||
bool ra_tex_upload_pbo(struct ra *ra, struct ra_buf_pool *pbo,
|
||||
const struct ra_tex_upload_params *params);
|
||||
|
||||
struct fbotex {
|
||||
struct ra *ra;
|
||||
struct ra_tex *tex;
|
||||
|
@ -83,21 +102,6 @@ bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log,
|
|||
#define FBOTEX_FUZZY_H 2
|
||||
#define FBOTEX_FUZZY (FBOTEX_FUZZY_W | FBOTEX_FUZZY_H)
|
||||
|
||||
#define NUM_PBO_BUFFERS 3
|
||||
|
||||
// A wrapper around tex_upload that uses PBOs internally if requested or
|
||||
// required
|
||||
struct tex_upload {
|
||||
size_t buffer_size;
|
||||
struct ra_buf *buffers[NUM_PBO_BUFFERS];
|
||||
int index;
|
||||
};
|
||||
|
||||
bool tex_upload(struct ra *ra, struct tex_upload *pbo, bool want_pbo,
|
||||
const struct ra_tex_upload_params *params);
|
||||
|
||||
void tex_upload_uninit(struct ra *ra, struct tex_upload *pbo);
|
||||
|
||||
// A wrapper around ra_timer that does result pooling, averaging etc.
|
||||
struct timer_pool;
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@ static const struct ra_renderpass_input vertex_vao[] = {
|
|||
|
||||
struct texplane {
|
||||
struct ra_tex *tex;
|
||||
struct tex_upload pbo;
|
||||
int w, h;
|
||||
bool flipped;
|
||||
};
|
||||
|
@ -494,7 +493,7 @@ static void reinit_osd(struct gl_video *p)
|
|||
mpgl_osd_destroy(p->osd);
|
||||
p->osd = NULL;
|
||||
if (p->osd_state)
|
||||
p->osd = mpgl_osd_init(p->ra, p->log, p->osd_state, p->opts.pbo);
|
||||
p->osd = mpgl_osd_init(p->ra, p->log, p->osd_state);
|
||||
}
|
||||
|
||||
static void uninit_rendering(struct gl_video *p)
|
||||
|
@ -987,7 +986,6 @@ static void uninit_video(struct gl_video *p)
|
|||
for (int n = 0; n < p->plane_count; n++) {
|
||||
struct texplane *plane = &vimg->planes[n];
|
||||
ra_tex_free(p->ra, &plane->tex);
|
||||
tex_upload_uninit(p->ra, &plane->pbo);
|
||||
}
|
||||
*vimg = (struct video_image){0};
|
||||
|
||||
|
@ -3291,7 +3289,7 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
|
|||
MP_VERBOSE(p, "DR enabled: %s\n", p->using_dr_path ? "yes" : "no");
|
||||
}
|
||||
|
||||
if (!tex_upload(p->ra, &plane->pbo, p->opts.pbo, ¶ms)) {
|
||||
if (!p->ra->fns->tex_upload(p->ra, ¶ms)) {
|
||||
timer_pool_stop(p->upload_timer);
|
||||
goto error;
|
||||
}
|
||||
|
@ -3300,7 +3298,9 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
|
|||
mapped->mpi = mp_image_new_ref(mpi);
|
||||
}
|
||||
timer_pool_stop(p->upload_timer);
|
||||
const char *mode = p->using_dr_path ? "DR" : p->opts.pbo ? "PBO" : "naive";
|
||||
|
||||
bool using_pbo = p->ra->use_pbo || !(p->ra->caps & RA_CAP_DIRECT_UPLOAD);
|
||||
const char *mode = p->using_dr_path ? "DR" : using_pbo ? "PBO" : "naive";
|
||||
pass_describe(p, "upload frame (%s)", mode);
|
||||
pass_record(p, timer_pool_measure(p->upload_timer));
|
||||
|
||||
|
@ -3639,6 +3639,7 @@ static void reinit_from_options(struct gl_video *p)
|
|||
check_gl_features(p);
|
||||
uninit_rendering(p);
|
||||
gl_sc_set_cache_dir(p->sc, p->opts.shader_cache_dir);
|
||||
p->ra->use_pbo = p->opts.pbo;
|
||||
gl_video_setup_hooks(p);
|
||||
reinit_osd(p);
|
||||
|
||||
|
|
Loading…
Reference in New Issue