summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-08-05 22:29:48 +0200
committerNiklas Haas <git@haasn.xyz>2017-08-07 12:46:30 +0200
commit9581fbe56926c75e52bc015fa6146b7f11f3d6a3 (patch)
tree252ff1098cd07bc5ae56770eecf0a3c0549435a5 /video
parent207458c7a9b682185a82ee23910c1327a70d276b (diff)
downloadmpv-9581fbe56926c75e52bc015fa6146b7f11f3d6a3.tar.bz2
mpv-9581fbe56926c75e52bc015fa6146b7f11f3d6a3.tar.xz
vo_opengl: generalize ra_buf to support other buffer objects
This allows us to integrate PBOs and SSBOs into the same abstraction, with the potential to easily add UBOs if the need arises.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/ra.c12
-rw-r--r--video/out/opengl/ra.h55
-rw-r--r--video/out/opengl/ra_gl.c107
-rw-r--r--video/out/opengl/ra_gl.h6
-rw-r--r--video/out/opengl/shader_cache.c17
-rw-r--r--video/out/opengl/shader_cache.h2
-rw-r--r--video/out/opengl/video.c94
7 files changed, 182 insertions, 111 deletions
diff --git a/video/out/opengl/ra.c b/video/out/opengl/ra.c
index e67dd6ebdf..31f585fdf9 100644
--- a/video/out/opengl/ra.c
+++ b/video/out/opengl/ra.c
@@ -16,6 +16,18 @@ void ra_tex_free(struct ra *ra, struct ra_tex **tex)
*tex = NULL;
}
+struct ra_buf *ra_buf_create(struct ra *ra, const struct ra_buf_params *params)
+{
+ return ra->fns->buf_create(ra, params);
+}
+
+void ra_buf_free(struct ra *ra, struct ra_buf **buf)
+{
+ if (*buf)
+ ra->fns->buf_destroy(ra, *buf);
+ *buf = NULL;
+}
+
static size_t vartype_size(enum ra_vartype type)
{
switch (type) {
diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h
index c60d75d47c..e93061eb61 100644
--- a/video/out/opengl/ra.h
+++ b/video/out/opengl/ra.h
@@ -37,6 +37,7 @@ enum {
RA_CAP_BLIT = 1 << 2, // supports ra_fns.blit
RA_CAP_COMPUTE = 1 << 3, // supports compute shaders
RA_CAP_PBO = 1 << 4, // supports ra.use_pbo
+ RA_CAP_BUF_RW = 1 << 5, // supports RA_VARTYPE_BUF_RW
RA_CAP_NESTED_ARRAY = 1 << 5,
};
@@ -107,13 +108,31 @@ struct ra_tex {
void *priv;
};
-// A persistent mapping, which can be used for texture upload.
-struct ra_mapped_buffer {
- // All fields are read-only after creation. The data is read/write, but
- // requires explicit fence usage.
+// Buffer type hint. Setting this may result in more or less efficient
+// operation, although it shouldn't technically prohibit anything
+enum ra_buf_type {
+ RA_BUF_TYPE_INVALID,
+ RA_BUF_TYPE_TEX_UPLOAD, // texture upload buffer (pixel buffer object)
+ RA_BUF_TYPE_SHADER_STORAGE // shader buffer, used for RA_VARTYPE_BUF_RW
+};
+
+struct ra_buf_params {
+ enum ra_buf_type type;
+ size_t size;
+ // Creates a read-writable persistent mapping (ra_buf.data)
+ bool host_mapped;
+ // If non-NULL, the buffer will be created with these contents. Otherwise,
+ // the initial data is undefined.
+ void *initial_data;
+};
+
+// A generic buffer, which can be used for many purposes (texture upload,
+// storage buffer, uniform buffer, etc.)
+struct ra_buf {
+ // All fields are read-only after creation.
+ struct ra_buf_params params;
+ void *data; // for persistently mapped buffers, points to the first byte
void *priv;
- void *data; // pointer to first usable byte
- size_t size; // total size of the mapping, starting at data
};
// Type of a shader uniform variable, or a vertex attribute. In all cases,
@@ -127,7 +146,7 @@ enum ra_vartype {
RA_VARTYPE_IMG_W, // C: ra_tex*, GLSL: various image types
// write-only (W) image for compute shaders
RA_VARTYPE_BYTE_UNORM, // C: uint8_t, GLSL: int, vec* (vertex data only)
- RA_VARTYPE_SSBO, // a hack for GL
+ RA_VARTYPE_BUF_RW, // C: ra_buf*, GLSL: buffer block
};
// Represents a uniform, texture input parameter, and similar things.
@@ -140,7 +159,7 @@ struct ra_renderpass_input {
// Vertex data: byte offset of the attribute into the vertex struct
// RA_VARTYPE_TEX: texture unit
// RA_VARTYPE_IMG_W: image unit
- // RA_VARTYPE_SSBO: whatever?
+ // RA_VARTYPE_BUF_* buffer binding point
// Other uniforms: unused
int binding;
};
@@ -304,20 +323,23 @@ struct ra_fns {
void (*tex_upload)(struct ra *ra, struct ra_tex *tex,
const void *src, ptrdiff_t stride,
struct mp_rect *region, uint64_t flags,
- struct ra_mapped_buffer *buf);
+ struct ra_buf *buf);
- // Create a persistently mapped buffer for tex_upload.
- // Optional, can be NULL or return NULL if unavailable.
- struct ra_mapped_buffer *(*create_mapped_buffer)(struct ra *ra, size_t size);
+ // Create a buffer. This can be used as a persistently mapped buffer,
+ // a uniform buffer, a shader storage buffer or possibly others.
+ // Not all usage types must be supported; may return NULL if unavailable.
+ struct ra_buf *(*buf_create)(struct ra *ra,
+ const struct ra_buf_params *params);
- void (*destroy_mapped_buffer)(struct ra *ra, struct ra_mapped_buffer *buf);
+ void (*buf_destroy)(struct ra *ra, struct ra_buf *buf);
// Essentially a fence: once the GPU uses the mapping for read-access (e.g.
// by starting a texture upload), the host must not write to the mapped
// data until an internal object has been signalled. This call returns
// whether it was signalled yet. If true, write accesses are allowed again.
- // Optional, only available if flush_mapping is.
- bool (*poll_mapped_buffer)(struct ra *ra, struct ra_mapped_buffer *buf);
+ // Optional, may be NULL if unavailable. This is only usable for buffers
+ // which have been persistently mapped.
+ bool (*poll_mapped_buffer)(struct ra *ra, struct ra_buf *buf);
// Clear the dst with the given color (rgba) and within the given scissor.
// dst must have dst->params.render_dst==true. Content outside of the
@@ -374,6 +396,9 @@ struct ra_fns {
struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params);
void ra_tex_free(struct ra *ra, struct ra_tex **tex);
+struct ra_buf *ra_buf_create(struct ra *ra, const struct ra_buf_params *params);
+void ra_buf_free(struct ra *ra, struct ra_buf **buf);
+
const struct ra_format *ra_find_unorm_format(struct ra *ra,
int bytes_per_component,
int n_components);
diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c
index 4c99fe0f59..3966afcebb 100644
--- a/video/out/opengl/ra_gl.c
+++ b/video/out/opengl/ra_gl.c
@@ -30,6 +30,8 @@ int ra_init_gl(struct ra *ra, GL *gl)
ra->caps |= RA_CAP_PBO;
if (gl->mpgl_caps & MPGL_CAP_NESTED_ARRAY)
ra->caps |= RA_CAP_NESTED_ARRAY;
+ if (gl->mpgl_caps & MPGL_CAP_SSBO)
+ ra->caps |= RA_CAP_BUF_RW;
ra->glsl_version = gl->glsl_version;
ra->glsl_es = gl->es > 0;
@@ -329,16 +331,16 @@ GL *ra_gl_get(struct ra *ra)
static void gl_tex_upload(struct ra *ra, struct ra_tex *tex,
const void *src, ptrdiff_t stride,
struct mp_rect *rc, uint64_t flags,
- struct ra_mapped_buffer *buf)
+ struct ra_buf *buf)
{
GL *gl = ra_gl_get(ra);
struct ra_tex_gl *tex_gl = tex->priv;
- struct ra_mapped_buffer_gl *buf_gl = NULL;
+ struct ra_buf_gl *buf_gl = NULL;
struct mp_rect full = {0, 0, tex->params.w, tex->params.h};
if (buf) {
buf_gl = buf->priv;
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
+ gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->buffer);
src = (void *)((uintptr_t)src - (uintptr_t)buf->data);
}
@@ -380,57 +382,87 @@ static void gl_tex_upload(struct ra *ra, struct ra_tex *tex,
}
}
-static void gl_destroy_mapped_buffer(struct ra *ra, struct ra_mapped_buffer *buf)
+static void gl_buf_destroy(struct ra *ra, struct ra_buf *buf)
{
+ if (!buf)
+ return;
+
GL *gl = ra_gl_get(ra);
- struct ra_mapped_buffer_gl *buf_gl = buf->priv;
+ struct ra_buf_gl *buf_gl = buf->priv;
gl->DeleteSync(buf_gl->fence);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
- if (buf->data)
- gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- gl->DeleteBuffers(1, &buf_gl->pbo);
+ if (buf->data) {
+ // The target type used here doesn't matter at all to OpenGL
+ gl->BindBuffer(GL_ARRAY_BUFFER, buf_gl->buffer);
+ gl->UnmapBuffer(GL_ARRAY_BUFFER);
+ gl->BindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ gl->DeleteBuffers(1, &buf_gl->buffer);
talloc_free(buf_gl);
talloc_free(buf);
}
-static struct ra_mapped_buffer *gl_create_mapped_buffer(struct ra *ra,
- size_t size)
+static struct ra_buf *gl_buf_create(struct ra *ra,
+ const struct ra_buf_params *params)
{
GL *gl = ra_gl_get(ra);
- if (gl->version < 440)
+ if (params->host_mapped && gl->version < 440)
return NULL;
- struct ra_mapped_buffer *buf = talloc_zero(NULL, struct ra_mapped_buffer);
- buf->size = size;
+ struct ra_buf *buf = talloc_zero(NULL, struct ra_buf);
+ buf->params = *params;
+ buf->params.initial_data = NULL;
- struct ra_mapped_buffer_gl *buf_gl = buf->priv =
- talloc_zero(NULL, struct ra_mapped_buffer_gl);
+ struct ra_buf_gl *buf_gl = buf->priv = talloc_zero(NULL, struct ra_buf_gl);
+ gl->GenBuffers(1, &buf_gl->buffer);
- unsigned flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
- GL_MAP_COHERENT_BIT;
+ GLenum target;
+ switch (params->type) {
+ case RA_BUF_TYPE_TEX_UPLOAD: target = GL_PIXEL_UNPACK_BUFFER; break;
+ case RA_BUF_TYPE_SHADER_STORAGE: target = GL_SHADER_STORAGE_BUFFER; break;
+ default: abort();
+ };
- gl->GenBuffers(1, &buf_gl->pbo);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, buf_gl->pbo);
- gl->BufferStorage(GL_PIXEL_UNPACK_BUFFER, size, NULL, flags | GL_CLIENT_STORAGE_BIT);
- buf->data = gl->MapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buf->size, flags);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- if (!buf->data) {
- gl_check_error(gl, ra->log, "mapping buffer");
- gl_destroy_mapped_buffer(ra, buf);
- return NULL;
+ gl->BindBuffer(target, buf_gl->buffer);
+
+ if (params->host_mapped) {
+ unsigned flags = GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT |
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+
+ unsigned storflags = flags;
+ if (params->type == RA_BUF_TYPE_TEX_UPLOAD)
+ storflags |= GL_CLIENT_STORAGE_BIT;
+
+ gl->BufferStorage(target, params->size, params->initial_data, storflags);
+ buf->data = gl->MapBufferRange(target, 0, params->size, flags);
+ if (!buf->data) {
+ gl_check_error(gl, ra->log, "mapping buffer");
+ gl_buf_destroy(ra, buf);
+ buf = NULL;
+ }
+ } else {
+ GLenum hint;
+ switch (params->type) {
+ case RA_BUF_TYPE_TEX_UPLOAD: hint = GL_STREAM_DRAW; break;
+ case RA_BUF_TYPE_SHADER_STORAGE: hint = GL_STREAM_COPY; break;
+ default: abort();
+ }
+
+ gl->BufferData(target, params->size, params->initial_data, hint);
}
+ gl->BindBuffer(target, 0);
return buf;
}
-static bool gl_poll_mapped_buffer(struct ra *ra, struct ra_mapped_buffer *buf)
+static bool gl_poll_mapped_buffer(struct ra *ra, struct ra_buf *buf)
{
+ assert(buf->data);
+
GL *gl = ra_gl_get(ra);
- struct ra_mapped_buffer_gl *buf_gl = buf->priv;
+ struct ra_buf_gl *buf_gl = buf->priv;
if (buf_gl->fence) {
GLenum res = gl->ClientWaitSync(buf_gl->fence, 0, 0); // non-blocking
@@ -743,9 +775,11 @@ static void update_uniform(struct ra *ra, struct ra_renderpass *pass,
}
break;
}
- case RA_VARTYPE_SSBO: {
- gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding,
- *(int *)val->data);
+ case RA_VARTYPE_BUF_RW: {
+ struct ra_buf *buf = *(struct ra_buf **)val->data;
+ struct ra_buf_gl *buf_gl = buf->priv;
+ gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding, buf_gl->buffer);
+ gl->MemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
break;
}
default:
@@ -775,11 +809,10 @@ static void disable_binding(struct ra *ra, struct ra_renderpass *pass,
}
break;
}
- case RA_VARTYPE_SSBO: {
+ case RA_VARTYPE_BUF_RW:
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, input->binding, 0);
break;
}
- }
}
static void gl_renderpass_run(struct ra *ra,
@@ -915,8 +948,8 @@ static struct ra_fns ra_fns_gl = {
.tex_create = gl_tex_create,
.tex_destroy = gl_tex_destroy,
.tex_upload = gl_tex_upload,
- .create_mapped_buffer = gl_create_mapped_buffer,
- .destroy_mapped_buffer = gl_destroy_mapped_buffer,
+ .buf_create = gl_buf_create,
+ .buf_destroy = gl_buf_destroy,
.poll_mapped_buffer = gl_poll_mapped_buffer,
.clear = gl_clear,
.blit = gl_blit,
diff --git a/video/out/opengl/ra_gl.h b/video/out/opengl/ra_gl.h
index 0d3828c978..6270daba92 100644
--- a/video/out/opengl/ra_gl.h
+++ b/video/out/opengl/ra_gl.h
@@ -22,9 +22,9 @@ struct ra_tex_gl {
struct gl_pbo_upload pbo;
};
-// For ra_mapped_buffer.priv
-struct ra_mapped_buffer_gl {
- GLuint pbo;
+// For ra_buf.priv
+struct ra_buf_gl {
+ GLuint buffer;
GLsync fence;
};
diff --git a/video/out/opengl/shader_cache.c b/video/out/opengl/shader_cache.c
index 68d9d4cab2..050d01d36d 100644
--- a/video/out/opengl/shader_cache.c
+++ b/video/out/opengl/shader_cache.c
@@ -22,15 +22,16 @@
union uniform_val {
float f[9]; // RA_VARTYPE_FLOAT
- int i[4]; // RA_VARTYPE_INT, RA_VARTYPE_SSBO
+ int i[4]; // RA_VARTYPE_INT
struct ra_tex *tex; // RA_VARTYPE_TEX, RA_VARTYPE_IMG_*
+ struct ra_buf *buf; // RA_VARTYPE_BUF_*
};
struct sc_uniform {
struct ra_renderpass_input input;
const char *glsl_type;
union uniform_val v;
- char *ssbo_format;
+ char *buffer_format;
};
struct sc_cached_uniform {
@@ -264,20 +265,20 @@ void gl_sc_uniform_image2D_wo(struct gl_shader_cache *sc, const char *name,
u->v.tex = tex;
}
-void gl_sc_ssbo(struct gl_shader_cache *sc, char *name, int gl_ssbo,
+void gl_sc_ssbo(struct gl_shader_cache *sc, char *name, struct ra_buf *buf,
char *format, ...)
{
gl_sc_enable_extension(sc, "GL_ARB_shader_storage_buffer_object");
struct sc_uniform *u = find_uniform(sc, name);
- u->input.type = RA_VARTYPE_SSBO;
+ u->input.type = RA_VARTYPE_BUF_RW;
u->glsl_type = "";
u->input.binding = sc->next_buffer_binding++;
- u->v.i[0] = gl_ssbo;
+ u->v.buf = buf;
va_list ap;
va_start(ap, format);
- u->ssbo_format = ta_vasprintf(sc, format, ap);
+ u->buffer_format = ta_vasprintf(sc, format, ap);
va_end(ap);
}
@@ -516,9 +517,9 @@ static void add_uniforms(struct gl_shader_cache *sc, bstr *dst)
case RA_VARTYPE_IMG_W:
ADD(dst, "uniform %s %s;\n", u->glsl_type, u->input.name);
break;
- case RA_VARTYPE_SSBO:
+ case RA_VARTYPE_BUF_RW:
ADD(dst, "layout(std430, binding=%d) buffer %s { %s };\n",
- u->input.binding, u->input.name, u->ssbo_format);
+ u->input.binding, u->input.name, u->buffer_format);
break;
default: abort();
}
diff --git a/video/out/opengl/shader_cache.h b/video/out/opengl/shader_cache.h
index c4fcefc391..d5d512d779 100644
--- a/video/out/opengl/shader_cache.h
+++ b/video/out/opengl/shader_cache.h
@@ -26,7 +26,7 @@ void gl_sc_uniform_texture(struct gl_shader_cache *sc, char *name,
struct ra_tex *tex);
void gl_sc_uniform_image2D_wo(struct gl_shader_cache *sc, const char *name,
struct ra_tex *tex);
-void gl_sc_ssbo(struct gl_shader_cache *sc, char *name, int gl_ssbo,
+void gl_sc_ssbo(struct gl_shader_cache *sc, char *name, struct ra_buf *buf,
char *format, ...) PRINTF_ATTRIBUTE(4, 5);
void gl_sc_uniform_f(struct gl_shader_cache *sc, char *name, float f);
void gl_sc_uniform_i(struct gl_shader_cache *sc, char *name, int f);
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 8c90a11376..c044e62664 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -169,7 +169,7 @@ struct pass_info {
#define PASS_INFO_MAX (SHADER_MAX_PASSES + 32)
struct dr_buffer {
- struct ra_mapped_buffer *buffer;
+ struct ra_buf *buf;
// The mpi reference will keep the data from being recycled (or from other
// references gaining write access) while the GPU is accessing the buffer.
struct mp_image *mpi;
@@ -230,7 +230,7 @@ struct gl_video {
struct fbotex output_fbo;
struct fbosurface surfaces[FBOSURFACES_MAX];
struct fbotex vdpau_deinterleave_fbo[2];
- GLuint hdr_peak_ssbo;
+ struct ra_buf *hdr_peak_ssbo;
// user pass descriptions and textures
struct tex_hook tex_hooks[SHADER_MAX_PASSES];
@@ -933,9 +933,9 @@ static struct dr_buffer *gl_find_dr_buffer(struct gl_video *p, uint8_t *ptr)
{
for (int i = 0; i < p->num_dr_buffers; i++) {
struct dr_buffer *buffer = &p->dr_buffers[i];
- uint8_t *buf = buffer->buffer->data;
- size_t size = buffer->buffer->size;
- if (ptr >= buf && ptr < buf + size)
+ uint8_t *bufptr = buffer->buf->data;
+ size_t size = buffer->buf->params.size;
+ if (ptr >= bufptr && ptr < bufptr + size)
return buffer;
}
@@ -950,7 +950,7 @@ again:;
if (!buffer->mpi)
continue;
- bool res = p->ra->fns->poll_mapped_buffer(p->ra, buffer->buffer);
+ bool res = p->ra->fns->poll_mapped_buffer(p->ra, buffer->buf);
if (res || force) {
// Unreferencing the image could cause gl_video_dr_free_buffer()
// to be called by the talloc destructor (if it was the last
@@ -2388,7 +2388,7 @@ static void pass_scale_main(struct gl_video *p)
// by previous passes (i.e. linear scaling)
static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool osd)
{
- GL *gl = p->gl;
+ struct ra *ra = p->ra;
// Figure out the target color space from the options, or auto-guess if
// none were set
@@ -2450,31 +2450,35 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool
}
bool detect_peak = p->opts.compute_hdr_peak && mp_trc_is_hdr(src.gamma);
- if (detect_peak) {
- pass_describe(p, "detect HDR peak");
- pass_is_compute(p, 8, 8); // 8x8 is good for performance
+ if (detect_peak && !p->hdr_peak_ssbo) {
+ struct {
+ unsigned int sig_peak_raw;
+ unsigned int index;
+ unsigned int frame_max[PEAK_DETECT_FRAMES+1];
+ } peak_ssbo = {0};
+
+ // Prefill with safe values
+ int safe = MP_REF_WHITE * mp_trc_nom_peak(p->image_params.color.gamma);
+ peak_ssbo.sig_peak_raw = PEAK_DETECT_FRAMES * safe;
+ for (int i = 0; i < PEAK_DETECT_FRAMES+1; i++)
+ peak_ssbo.frame_max[i] = safe;
+
+ struct ra_buf_params params = {
+ .type = RA_BUF_TYPE_SHADER_STORAGE,
+ .size = sizeof(peak_ssbo),
+ .initial_data = &peak_ssbo,
+ };
+ p->hdr_peak_ssbo = ra_buf_create(ra, &params);
if (!p->hdr_peak_ssbo) {
- struct {
- GLuint sig_peak_raw;
- GLuint index;
- GLuint frame_max[PEAK_DETECT_FRAMES+1];
- } peak_ssbo = {0};
-
- // Prefill with safe values
- int safe = MP_REF_WHITE * mp_trc_nom_peak(p->image_params.color.gamma);
- peak_ssbo.sig_peak_raw = PEAK_DETECT_FRAMES * safe;
- for (int i = 0; i < PEAK_DETECT_FRAMES+1; i++)
- peak_ssbo.frame_max[i] = safe;
-
- gl->GenBuffers(1, &p->hdr_peak_ssbo);
- gl->BindBuffer(GL_SHADER_STORAGE_BUFFER, p->hdr_peak_ssbo);
- gl->BufferData(GL_SHADER_STORAGE_BUFFER, sizeof(peak_ssbo),
- &peak_ssbo, GL_STREAM_COPY);
- gl->BindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+ MP_WARN(p, "Failed to create HDR peak detection SSBO, disabling.\n");
+ detect_peak = (p->opts.compute_hdr_peak = false);
}
+ }
- gl->MemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
+ if (detect_peak) {
+ pass_describe(p, "detect HDR peak");
+ pass_is_compute(p, 8, 8); // 8x8 is good for performance
gl_sc_ssbo(p->sc, "PeakDetect", p->hdr_peak_ssbo,
"uint sig_peak_raw;"
"uint index;"
@@ -3304,7 +3308,7 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
p->ra->fns->tex_upload(p->ra, plane->tex, mpi->planes[n],
mpi->stride[n], NULL, 0,
- mapped ? mapped->buffer : NULL);
+ mapped ? mapped->buf : NULL);
if (mapped && !mapped->mpi)
mapped->mpi = mp_image_new_ref(mpi);
@@ -3377,7 +3381,7 @@ static void check_gl_features(struct gl_video *p)
bool have_mglsl = ra->glsl_version >= 130; // modern GLSL
bool have_texrg = gl->mpgl_caps & MPGL_CAP_TEX_RG;
bool have_compute = ra->caps & RA_CAP_COMPUTE;
- bool have_ssbo = gl->mpgl_caps & MPGL_CAP_SSBO;
+ bool have_ssbo = ra->caps & RA_CAP_BUF_RW;
const char *auto_fbo_fmts[] = {"rgba16", "rgba16f", "rgb10_a2", "rgba8", 0};
const char *user_fbo_fmts[] = {p->opts.fbo_format, 0};
@@ -3516,7 +3520,7 @@ void gl_video_uninit(struct gl_video *p)
gl_sc_destroy(p->sc);
ra_tex_free(p->ra, &p->lut_3d_texture);
- gl->DeleteBuffers(1, &p->hdr_peak_ssbo);
+ ra_buf_free(p->ra, &p->hdr_peak_ssbo);
timer_pool_destroy(p->upload_timer);
timer_pool_destroy(p->blit_timer);
@@ -3802,33 +3806,29 @@ void gl_video_set_hwdec(struct gl_video *p, struct gl_hwdec *hwdec)
void *gl_video_dr_alloc_buffer(struct gl_video *p, size_t size)
{
- if (!p->ra->fns->create_mapped_buffer)
- return NULL;
-
- MP_TARRAY_GROW(p, p->dr_buffers, p->num_dr_buffers);
- int index = p->num_dr_buffers++;
- struct dr_buffer *buffer = &p->dr_buffers[index];
-
- *buffer = (struct dr_buffer){
- .buffer = p->ra->fns->create_mapped_buffer(p->ra, size),
+ struct ra_buf_params params = {
+ .type = RA_BUF_TYPE_TEX_UPLOAD,
+ .host_mapped = true,
+ .size = size,
};
- if (!buffer->buffer) {
- MP_TARRAY_REMOVE_AT(p->dr_buffers, p->num_dr_buffers, index);
+ struct ra_buf *buf = ra_buf_create(p->ra, &params);
+ if (!buf)
return NULL;
- }
- return buffer->buffer->data;
+ MP_TARRAY_GROW(p, p->dr_buffers, p->num_dr_buffers);
+ p->dr_buffers[p->num_dr_buffers++] = (struct dr_buffer){ .buf = buf };
+
+ return buf->data;
};
void gl_video_dr_free_buffer(struct gl_video *p, void *ptr)
{
for (int n = 0; n < p->num_dr_buffers; n++) {
struct dr_buffer *buffer = &p->dr_buffers[n];
- if (buffer->buffer->data == ptr) {
+ if (buffer->buf->data == ptr) {
assert(!buffer->mpi); // can't be freed while it has a ref
- p->ra->fns->destroy_mapped_buffer(p->ra, buffer->buffer);
-
+ ra_buf_free(p->ra, &buffer->buf);
MP_TARRAY_REMOVE_AT(p->dr_buffers, p->num_dr_buffers, n);
return;
}