[vlc-commits] [Git][videolan/vlc][master] 10 commits: opengl: make placebo conditional on <libplacebo/opengl.h>

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Oct 15 17:03:40 UTC 2022



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
1095115e by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: make placebo conditional on <libplacebo/opengl.h>

I want to start using the pl_opengl integration, so we need to slightly
revise the check to ensure we also have the libplaceo opengl header
available.

It's worth pointing out that these headers eventually become
non-conditional (in libplacebo git master as of writing), but we need to
live with this transitional logic until then.

- - - - -
90d2a076 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: don't leak sampler state on error

This code as-written leaks libplacebo-related objects in the event of a
failure here.

- - - - -
808146d7 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: add glUniformNfv

We have this for glUniform4fv, add the other types so I can use them.

- - - - -
08abc4d1 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: add pl_var.dim_a support

The dithering code can end up using uniform array variables when
plugging pl_gpu information into the shader, so pre-emptively add
support for these.

- - - - -
41f48d78 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: persist pl_shader_obj until shader is freed

This code, as written, is technically undefined behavior. It was fine so
far because we didn't end up using the shader objects in any way that
wasn't baked into the resulting pl_shader_res, but it needs to be fixed
to allow shaders to reference GPU resources which may be used later on.

- - - - -
5b7bdebd by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: change libplacebo var type check to assertion

Simply continuing in this error case without assigning the corresponding
uniform will silently lead to a broken shader / image. Since we rely on
these assumptions, we should assert them so any such bugs are actually
found in a debuggable way.

This is only a theoretical risk since, as the comment points out, we
don't rely on any such variables. But maybe this will unexpectedly
change in the future.

- - - - -
5cc37e20 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: wrap OpenGL context to pl_opengl

This creates a pl_gpu suitable for use by shaders. It's worth noting
that this commit does not hook the resulting pl_gpu into the shaders
yet, because doing so would break the resulting shaders until we add
support for mapping descriptors (in the following commit).

- - - - -
94925cdb by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: add support for libplacebo descriptors

This change will allow us to integrate more advanced libplacebo
features, such as those requiring LUT-based tone-mapping (in recent
versions of libplacebo).

- - - - -
fb3c80f4 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: plug pl_gpu into pl_shader

This commit merely activates the functionality supported by the previous
commits, tying it all together.

- - - - -
207369d9 by Niklas Haas at 2022-10-15T16:06:52+00:00
opengl: stop hard-coding small LUT size

Since we no longer rely on embedding hard-coded arrays into the shader,
we can finally free up this size limitation, thus improving the quality
of dithering massively.

- - - - -


4 changed files:

- configure.ac
- modules/video_output/opengl/gl_api.c
- modules/video_output/opengl/gl_common.h
- modules/video_output/opengl/sampler.c


Changes:

=====================================
configure.ac
=====================================
@@ -3143,6 +3143,7 @@ AS_IF([test "$enable_libplacebo" != "no"], [
     AC_DEFINE([HAVE_LIBPLACEBO], [1], [Define to 1 if libplacebo is enabled.])
     AC_CHECK_HEADER([libplacebo/vulkan.h], [VLC_ADD_PLUGIN([placebo_vk])])
     AC_CHECK_HEADER([libplacebo/opengl.h], [
+        AC_DEFINE([HAVE_LIBPLACEBO_GL], [1], [Define to 1 if <libplacebo/opengl.h> is available.])
         VLC_ADD_PLUGIN([placebo_gl])
         VLC_ADD_PLUGIN([placebo_gles2])
         dnl Minimum version that the OpenGL filter pl_scale is compatible with


=====================================
modules/video_output/opengl/gl_api.c
=====================================
@@ -108,6 +108,9 @@ vlc_gl_api_Init(struct vlc_gl_api *api, vlc_gl_t *gl)
     GET_PROC_ADDR(UniformMatrix3fv);
     GET_PROC_ADDR(UniformMatrix2fv);
     GET_PROC_ADDR(Uniform4fv);
+    GET_PROC_ADDR(Uniform3fv);
+    GET_PROC_ADDR(Uniform2fv);
+    GET_PROC_ADDR(Uniform1fv);
     GET_PROC_ADDR(Uniform4f);
     GET_PROC_ADDR(Uniform3f);
     GET_PROC_ADDR(Uniform2f);


=====================================
modules/video_output/opengl/gl_common.h
=====================================
@@ -90,6 +90,9 @@
 #ifndef GL_TEXTURE_LUMINANCE_SIZE
 # define GL_TEXTURE_LUMINANCE_SIZE 0x8060
 #endif
+#ifndef GL_TEXTURE_WRAP_R
+# define GL_TEXTURE_WRAP_R 0x8072
+#endif
 
 #ifndef GL_CLAMP_TO_EDGE
 # define GL_CLAMP_TO_EDGE 0x812F
@@ -252,6 +255,9 @@ typedef void (APIENTRY *PFNGLREADPIXELSPROC) (GLint, GLint, GLsizei, GLsizei, GL
 #   define PFNGLUNIFORMMATRIX3FVPROC         typeof(glUniformMatrix3fv)*
 #   define PFNGLUNIFORMMATRIX2FVPROC         typeof(glUniformMatrix2fv)*
 #   define PFNGLUNIFORM4FVPROC               typeof(glUniform4fv)*
+#   define PFNGLUNIFORM3FVPROC               typeof(glUniform3fv)*
+#   define PFNGLUNIFORM2FVPROC               typeof(glUniform2fv)*
+#   define PFNGLUNIFORM1FVPROC               typeof(glUniform1fv)*
 #   define PFNGLUNIFORM4FPROC                typeof(glUniform4f)*
 #   define PFNGLUNIFORM3FPROC                typeof(glUniform3f)*
 #   define PFNGLUNIFORM2FPROC                typeof(glUniform2f)*
@@ -356,6 +362,9 @@ typedef struct {
     PFNGLUNIFORMMATRIX3FVPROC        UniformMatrix3fv;
     PFNGLUNIFORMMATRIX2FVPROC        UniformMatrix2fv;
     PFNGLUNIFORM4FVPROC              Uniform4fv;
+    PFNGLUNIFORM3FVPROC              Uniform3fv;
+    PFNGLUNIFORM2FVPROC              Uniform2fv;
+    PFNGLUNIFORM1FVPROC              Uniform1fv;
     PFNGLUNIFORM4FPROC               Uniform4f;
     PFNGLUNIFORM3FPROC               Uniform3f;
     PFNGLUNIFORM2FPROC               Uniform2f;


=====================================
modules/video_output/opengl/sampler.c
=====================================
@@ -28,7 +28,8 @@
 #include <vlc_memstream.h>
 #include <vlc_opengl.h>
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
+#include <libplacebo/opengl.h>
 #include <libplacebo/shaders.h>
 #include <libplacebo/shaders/colorspace.h>
 #include "../libplacebo/utils.h"
@@ -51,16 +52,18 @@ struct vlc_gl_sampler_priv {
         GLint Textures[PICTURE_PLANE_MAX];
         GLint TexSizes[PICTURE_PLANE_MAX]; /* for GL_TEXTURE_RECTANGLE */
         GLint ConvMatrix;
-        GLint *pl_vars; /* for pl_sh_res */
+        GLint *pl_vars, *pl_descs; /* for pl_sh_res */
     } uloc;
 
     bool yuv_color;
     GLfloat conv_matrix[4*4];
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     /* libplacebo context */
     pl_log pl_log;
+    pl_opengl pl_opengl;
     pl_shader pl_sh;
+    pl_shader_obj dither_state, tone_map_state;
     const struct pl_shader_res *pl_sh_res;
 #endif
 
@@ -276,12 +279,17 @@ sampler_base_fetch_locations(struct vlc_gl_sampler *sampler, GLuint program)
         }
     }
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     const struct pl_shader_res *res = priv->pl_sh_res;
     for (int i = 0; res && i < res->num_variables; i++) {
         struct pl_shader_var sv = res->variables[i];
         priv->uloc.pl_vars[i] = vt->GetUniformLocation(program, sv.var.name);
     }
+
+    for (int i = 0; res && i < res->num_descriptors; i++) {
+        struct pl_shader_desc sd = res->descriptors[i];
+        priv->uloc.pl_descs[i] = vt->GetUniformLocation(program, sd.desc.name);
+    }
 #endif
 }
 
@@ -315,7 +323,7 @@ sampler_base_load(struct vlc_gl_sampler *sampler)
                           glfmt->tex_heights[i]);
     }
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     const struct pl_shader_res *res = priv->pl_sh_res;
     for (int i = 0; res && i < res->num_variables; i++) {
         GLint loc = priv->uloc.pl_vars[i];
@@ -325,27 +333,61 @@ sampler_base_load(struct vlc_gl_sampler *sampler)
         struct pl_shader_var sv = res->variables[i];
         struct pl_var var = sv.var;
         // libplacebo doesn't need anything else anyway
-        if (var.type != PL_VAR_FLOAT)
-            continue;
-        if (var.dim_m > 1 && var.dim_m != var.dim_v)
-            continue;
+        assert(var.type == PL_VAR_FLOAT);
+        assert(var.dim_m == 1 || var.dim_m == var.dim_v);
 
         const float *f = sv.data;
         switch (var.dim_m) {
-        case 4: vt->UniformMatrix4fv(loc, 1, GL_FALSE, f); break;
-        case 3: vt->UniformMatrix3fv(loc, 1, GL_FALSE, f); break;
-        case 2: vt->UniformMatrix2fv(loc, 1, GL_FALSE, f); break;
+        case 4: vt->UniformMatrix4fv(loc, var.dim_a, GL_FALSE, f); break;
+        case 3: vt->UniformMatrix3fv(loc, var.dim_a, GL_FALSE, f); break;
+        case 2: vt->UniformMatrix2fv(loc, var.dim_a, GL_FALSE, f); break;
 
         case 1:
             switch (var.dim_v) {
-            case 1: vt->Uniform1f(loc, f[0]); break;
-            case 2: vt->Uniform2f(loc, f[0], f[1]); break;
-            case 3: vt->Uniform3f(loc, f[0], f[1], f[2]); break;
-            case 4: vt->Uniform4f(loc, f[0], f[1], f[2], f[3]); break;
+            case 1: vt->Uniform1fv(loc, var.dim_a, f); break;
+            case 2: vt->Uniform2fv(loc, var.dim_a, f); break;
+            case 3: vt->Uniform3fv(loc, var.dim_a, f); break;
+            case 4: vt->Uniform4fv(loc, var.dim_a, f); break;
             }
             break;
         }
     }
+
+    for (int i = 0; res && i < res->num_descriptors; i++) {
+        GLint loc = priv->uloc.pl_descs[i];
+        if (loc == -1)
+            continue;
+        struct pl_shader_desc sd = res->descriptors[i];
+        assert(sd.desc.type == PL_DESC_SAMPLED_TEX);
+        pl_tex tex = sd.binding.object;
+        int texid = glfmt->tex_count + i; // first free texture unit
+        unsigned gltex, target;
+        gltex = pl_opengl_unwrap(priv->pl_opengl->gpu, tex, &target, NULL, NULL);
+        vt->Uniform1i(loc, texid);
+        vt->ActiveTexture(GL_TEXTURE0 + texid);
+        vt->BindTexture(target, gltex);
+
+        static const GLint wraps[PL_TEX_ADDRESS_MODE_COUNT] = {
+            [PL_TEX_ADDRESS_CLAMP]  = GL_CLAMP_TO_EDGE,
+            [PL_TEX_ADDRESS_REPEAT] = GL_REPEAT,
+            [PL_TEX_ADDRESS_MIRROR] = GL_MIRRORED_REPEAT,
+        };
+
+        static const GLint filters[PL_TEX_SAMPLE_MODE_COUNT] = {
+            [PL_TEX_SAMPLE_NEAREST] = GL_NEAREST,
+            [PL_TEX_SAMPLE_LINEAR]  = GL_LINEAR,
+        };
+
+        GLint filter = filters[sd.binding.sample_mode];
+        GLint wrap = wraps[sd.binding.address_mode];
+        vt->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
+        vt->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+        switch (pl_tex_params_dimension(tex->params)) {
+        case 3: vt->TexParameteri(target, GL_TEXTURE_WRAP_R, wrap); // fall through
+        case 2: vt->TexParameteri(target, GL_TEXTURE_WRAP_T, wrap); // fall through
+        case 1: vt->TexParameteri(target, GL_TEXTURE_WRAP_S, wrap); break;
+        }
+    }
 #endif
 }
 
@@ -661,7 +703,7 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
 
     ADDF("uniform %s Textures[%u];\n", glsl_sampler, tex_count);
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     if (priv->pl_sh) {
         pl_shader sh = priv->pl_sh;
         struct pl_color_map_params color_params;
@@ -671,12 +713,10 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
         dst_space.primaries = var_InheritInteger(priv->gl, "target-prim");
         dst_space.transfer = var_InheritInteger(priv->gl, "target-trc");
 
-        pl_shader_obj tone_map_state = NULL;
         pl_shader_color_map(sh, &color_params,
                 vlc_placebo_ColorSpace(fmt),
-                dst_space, &tone_map_state, false);
+                dst_space, &priv->tone_map_state, false);
 
-        pl_shader_obj dither_state = NULL;
         int method = var_InheritInteger(priv->gl, "dither-algo");
         if (method >= 0) {
 
@@ -700,27 +740,39 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
                 out_bits = fb_depth;
             }
 
-            pl_shader_dither(sh, out_bits, &dither_state, &(struct pl_dither_params) {
+            pl_shader_dither(sh, out_bits, &priv->dither_state, &(struct pl_dither_params) {
                 .method   = method,
-                .lut_size = 4, // avoid too large values, since this gets embedded
             });
         }
 
         const struct pl_shader_res *res = priv->pl_sh_res = pl_shader_finalize(sh);
-        pl_shader_obj_destroy(&tone_map_state);
-        pl_shader_obj_destroy(&dither_state);
 
         FREENULL(priv->uloc.pl_vars);
         priv->uloc.pl_vars = calloc(res->num_variables, sizeof(GLint));
         for (int i = 0; i < res->num_variables; i++) {
             struct pl_shader_var sv = res->variables[i];
             const char *glsl_type_name = pl_var_glsl_type_name(sv.var);
-            ADDF("uniform %s %s;\n", glsl_type_name, sv.var.name);
+            ADDF("uniform %s %s", glsl_type_name, sv.var.name);
+            if (sv.var.dim_a > 1) {
+                ADDF("[%d];\n", sv.var.dim_a);
+            } else {
+                ADDF(";\n");
+            }
+        }
+
+        FREENULL(priv->uloc.pl_descs);
+        priv->uloc.pl_descs = calloc(res->num_descriptors, sizeof(GLint));
+        for (int i = 0; i < res->num_descriptors; i++) {
+            struct pl_shader_desc sd = res->descriptors[i];
+            assert(sd.desc.type == PL_DESC_SAMPLED_TEX);
+            pl_tex tex = sd.binding.object;
+            assert(tex->sampler_type == PL_SAMPLER_NORMAL);
+            int dims = pl_tex_params_dimension(tex->params);
+            ADDF("uniform sampler%dD %s;\n", dims, sd.desc.name);
         }
 
         // We can't handle these yet, but nothing we use requires them, either
         assert(res->num_vertex_attribs == 0);
-        assert(res->num_descriptors == 0);
 
         ADD(res->glsl);
     }
@@ -775,7 +827,7 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
     }
     assert(yuv_space == COLOR_SPACE_UNDEF || color_count == 3);
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     if (priv->pl_sh_res) {
         const struct pl_shader_res *res = priv->pl_sh_res;
         if (res->input != PL_SHADER_SIG_NONE) {
@@ -842,11 +894,20 @@ vlc_gl_sampler_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
     sampler->shader.extensions = NULL;
     sampler->shader.body = NULL;
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     priv->uloc.pl_vars = NULL;
+    priv->uloc.pl_descs = NULL;
     priv->pl_sh_res = NULL;
     priv->pl_log = vlc_placebo_CreateLog(VLC_OBJECT(gl));
+    priv->pl_opengl = pl_opengl_create(priv->pl_log, NULL);
+    if (!priv->pl_opengl)
+    {
+        vlc_gl_sampler_Delete(sampler);
+        return NULL;
+    }
+
     priv->pl_sh = pl_shader_alloc(priv->pl_log, &(struct pl_shader_params) {
+        .gpu = priv->pl_opengl->gpu,
         .glsl = {
 #   ifdef USE_OPENGL_ES2
             .version = 100,
@@ -861,7 +922,7 @@ vlc_gl_sampler_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
     int ret = opengl_fragment_shader_init(sampler, expose_planes);
     if (ret != VLC_SUCCESS)
     {
-        free(sampler);
+        vlc_gl_sampler_Delete(sampler);
         return NULL;
     }
 
@@ -873,9 +934,13 @@ vlc_gl_sampler_Delete(struct vlc_gl_sampler *sampler)
 {
     struct vlc_gl_sampler_priv *priv = PRIV(sampler);
 
-#ifdef HAVE_LIBPLACEBO
+#ifdef HAVE_LIBPLACEBO_GL
     FREENULL(priv->uloc.pl_vars);
+    FREENULL(priv->uloc.pl_descs);
     pl_shader_free(&priv->pl_sh);
+    pl_shader_obj_destroy(&priv->tone_map_state);
+    pl_shader_obj_destroy(&priv->dither_state);
+    pl_opengl_destroy(&priv->pl_opengl);
     pl_log_destroy(&priv->pl_log);
 #endif
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/804f16bc2cc0229064f5719e54e320673060e613...207369d9073a09a6c7fd8ca65b7a605bec364fa2

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/804f16bc2cc0229064f5719e54e320673060e613...207369d9073a09a6c7fd8ca65b7a605bec364fa2
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list