LCOV - code coverage report
Current view: top level - src/include/libplacebo/shaders - custom.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 5 40.0 %
Date: 2025-03-29 09:04:10 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 3 33.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of libplacebo.
       3                 :            :  *
       4                 :            :  * libplacebo is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU Lesser General Public
       6                 :            :  * License as published by the Free Software Foundation; either
       7                 :            :  * version 2.1 of the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * libplacebo is distributed in the hope that it will be useful,
      10                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :  * GNU Lesser General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Lesser General Public
      15                 :            :  * License along with libplacebo.  If not, see <http://www.gnu.org/licenses/>.
      16                 :            :  */
      17                 :            : 
      18                 :            : #ifndef LIBPLACEBO_SHADERS_CUSTOM_H_
      19                 :            : #define LIBPLACEBO_SHADERS_CUSTOM_H_
      20                 :            : 
      21                 :            : #include <stdlib.h>
      22                 :            : 
      23                 :            : // Functions for writing custom shaders and hooking them into the `pl_renderer`
      24                 :            : // pipeline, as well as compatibility functions for parsing shaders in mpv
      25                 :            : // format.
      26                 :            : 
      27                 :            : #include <libplacebo/shaders.h>
      28                 :            : #include <libplacebo/dispatch.h>
      29                 :            : #include <libplacebo/colorspace.h>
      30                 :            : 
      31                 :            : PL_API_BEGIN
      32                 :            : 
      33                 :            : // Parameters describing custom shader text to be embedded into a `pl_shader`
      34                 :            : // object. All of the strings are optional and can be left as NULL, but without
      35                 :            : // a `body` in particular, the shader will do nothing useful on its own.
      36                 :            : struct pl_custom_shader {
      37                 :            :     // The prelude contains text such as extra #defines, #extension pragmas,
      38                 :            :     // or other parts of the shader that must be placed at the very
      39                 :            :     // beginning (before input layout declarations etc.)
      40                 :            :     //
      41                 :            :     // Note: #extension pragmas do not need to be emitted to enable support for
      42                 :            :     // resource types already attached to the shader (e.g. SSBOs), compute
      43                 :            :     // shaders, or GPU capabilities known to libplacebo (e.g. subgroups).
      44                 :            :     const char *prelude;
      45                 :            : 
      46                 :            :     // The header contains text such as helper function definitions, extra
      47                 :            :     // uniforms, shared memory variables or buffer descriptions.
      48                 :            :     const char *header;
      49                 :            : 
      50                 :            :     // A friendly name for the shader. (Optional)
      51                 :            :     const char *description;
      52                 :            : 
      53                 :            :     // The "primary" GLSL code. This will be effectively appended to the "main"
      54                 :            :     // function. It lives in an environment given by the `input` signature, and
      55                 :            :     // is expected to return results in a way given by the `output` signature.
      56                 :            :     //
      57                 :            :     // Note: In the case of PL_SHADER_SIG_COLOR, the output `vec4 color` is
      58                 :            :     // allocated by `pl_shader_custom`, the user merely needs to assign to it.
      59                 :            :     //
      60                 :            :     // Note: For ease of development it can be useful to have the main logic
      61                 :            :     // live inside a helper function defined as part of `header`, and specify
      62                 :            :     // the `body` as a single line that simply calls the helper function.
      63                 :            :     const char *body;
      64                 :            :     enum pl_shader_sig input;
      65                 :            :     enum pl_shader_sig output;
      66                 :            : 
      67                 :            :     // Extra descriptors, variables and vertex attributes to attach to the
      68                 :            :     // resulting `pl_shader_res`.
      69                 :            :     //
      70                 :            :     // Note: The names inside these will possibly be replaced by fresh
      71                 :            :     // identifiers internally, so users should avoid looking for exact string
      72                 :            :     // matches for the given names inside the `pl_shader_res`.
      73                 :            :     const struct pl_shader_desc *descriptors;
      74                 :            :     int num_descriptors;
      75                 :            :     const struct pl_shader_var *variables;
      76                 :            :     int num_variables;
      77                 :            :     const struct pl_shader_va *vertex_attribs;
      78                 :            :     int num_vertex_attribs;
      79                 :            :     const struct pl_shader_const *constants;
      80                 :            :     int num_constants;
      81                 :            : 
      82                 :            :     // If true, this shader must be a compute shader. The desired workgroup
      83                 :            :     // size and shared memory usage can be optionally specified, or 0 if no
      84                 :            :     // specific work group size or shared memory size restrictions apply.
      85                 :            :     //
      86                 :            :     // See also: `pl_shader_res.compute_group_size`
      87                 :            :     bool compute;
      88                 :            :     size_t compute_shmem;
      89                 :            :     int compute_group_size[2];
      90                 :            : 
      91                 :            :     // Fixes the output size requirements of the shader to exact dimensions.
      92                 :            :     // Optional, if left as 0, means the shader can be dispatched at any size.
      93                 :            :     int output_w;
      94                 :            :     int output_h;
      95                 :            : };
      96                 :            : 
      97                 :            : // Append custom shader code, including extra descriptors and variables, to an
      98                 :            : // existing `pl_shader` object. Returns whether successful. This function may
      99                 :            : // fail in the event that e.g. the custom shader requires compute shaders on
     100                 :            : // an unsupported GPU, or exceeds the GPU's shared memory capabilities.
     101                 :            : PL_API bool pl_shader_custom(pl_shader sh, const struct pl_custom_shader *params);
     102                 :            : 
     103                 :            : // Which "rendering stages" are available for user shader hooking purposes.
     104                 :            : // Except where otherwise noted, all stages are "non-resizable", i.e. the
     105                 :            : // shaders already have specific output size requirements.
     106                 :            : enum pl_hook_stage {
     107                 :            :     // Hook stages for the untouched planes, as made available by the source.
     108                 :            :     // These are all resizable, i.e. there are no specific output stage
     109                 :            :     // requirements.
     110                 :            :     PL_HOOK_RGB_INPUT       = 1 << 0,
     111                 :            :     PL_HOOK_LUMA_INPUT      = 1 << 1,
     112                 :            :     PL_HOOK_CHROMA_INPUT    = 1 << 2,
     113                 :            :     PL_HOOK_ALPHA_INPUT     = 1 << 3,
     114                 :            :     PL_HOOK_XYZ_INPUT       = 1 << 4,
     115                 :            : 
     116                 :            :     // Hook stages for the scaled/aligned planes
     117                 :            :     PL_HOOK_CHROMA_SCALED   = 1 << 5,
     118                 :            :     PL_HOOK_ALPHA_SCALED    = 1 << 6,
     119                 :            : 
     120                 :            :     PL_HOOK_NATIVE          = 1 << 7,  // Combined image in its native color space
     121                 :            :     PL_HOOK_RGB             = 1 << 8,  // After conversion to RGB (resizable)
     122                 :            :     PL_HOOK_LINEAR          = 1 << 9,  // After linearization but before scaling
     123                 :            :     PL_HOOK_SIGMOID         = 1 << 10, // After sigmoidization
     124                 :            :     PL_HOOK_PRE_KERNEL      = 1 << 11, // Immediately before the main scaler kernel
     125                 :            :     PL_HOOK_POST_KERNEL     = 1 << 12, // Immediately after the main scaler kernel
     126                 :            :     PL_HOOK_SCALED          = 1 << 13, // After scaling, before color management
     127                 :            :     PL_HOOK_PRE_OUTPUT      = 1 << 14, // After color management, before blending/rotation
     128                 :            :     PL_HOOK_OUTPUT          = 1 << 15, // After blending/rotation, before dithering
     129                 :            : };
     130                 :            : 
     131                 :            : // Returns true if a given hook stage is resizable
     132                 :         19 : static inline bool pl_hook_stage_resizable(enum pl_hook_stage stage) {
     133      [ -  -  + ]:         19 :     switch (stage) {
     134                 :            :     case PL_HOOK_RGB_INPUT:
     135                 :            :     case PL_HOOK_LUMA_INPUT:
     136                 :            :     case PL_HOOK_CHROMA_INPUT:
     137                 :            :     case PL_HOOK_ALPHA_INPUT:
     138                 :            :     case PL_HOOK_XYZ_INPUT:
     139                 :            :     case PL_HOOK_NATIVE:
     140                 :            :     case PL_HOOK_RGB:
     141                 :            :         return true;
     142                 :            : 
     143                 :          0 :     case PL_HOOK_CHROMA_SCALED:
     144                 :            :     case PL_HOOK_ALPHA_SCALED:
     145                 :            :     case PL_HOOK_LINEAR:
     146                 :            :     case PL_HOOK_SIGMOID:
     147                 :            :     case PL_HOOK_PRE_KERNEL:
     148                 :            :     case PL_HOOK_POST_KERNEL:
     149                 :            :     case PL_HOOK_SCALED:
     150                 :            :     case PL_HOOK_PRE_OUTPUT:
     151                 :            :     case PL_HOOK_OUTPUT:
     152                 :          0 :         return false;
     153                 :            :     }
     154                 :            : 
     155                 :          0 :     abort();
     156                 :            : }
     157                 :            : 
     158                 :            : // The different forms of communicating image data between the renderer and
     159                 :            : // the hooks
     160                 :            : enum pl_hook_sig {
     161                 :            :     PL_HOOK_SIG_NONE,   // No data is passed, no data is received/returned
     162                 :            :     PL_HOOK_SIG_COLOR,  // `vec4 color` already pre-sampled in a `pl_shader`
     163                 :            :     PL_HOOK_SIG_TEX,    // `pl_tex` containing the image data
     164                 :            :     PL_HOOK_SIG_COUNT,
     165                 :            : };
     166                 :            : 
     167                 :            : struct pl_hook_params {
     168                 :            :     // GPU objects associated with the `pl_renderer`, which the user may
     169                 :            :     // use for their own purposes.
     170                 :            :     pl_gpu gpu;
     171                 :            :     pl_dispatch dispatch;
     172                 :            : 
     173                 :            :     // Helper function to fetch a new temporary texture, using renderer-backed
     174                 :            :     // storage. This is guaranteed to have sane image usage requirements and a
     175                 :            :     // 16-bit or floating point format. The user does not need to free/destroy
     176                 :            :     // this texture in any way. May return NULL.
     177                 :            :     pl_tex (*get_tex)(void *priv, int width, int height);
     178                 :            :     void *priv;
     179                 :            : 
     180                 :            :     // Which stage triggered the hook to run.
     181                 :            :     enum pl_hook_stage stage;
     182                 :            : 
     183                 :            :     // For `PL_HOOK_SIG_COLOR`, this contains the existing shader object with
     184                 :            :     // the color already pre-sampled into `vec4 color`. The user may modify
     185                 :            :     // this as much as they want, as long as they don't dispatch/finalize/reset
     186                 :            :     // it.
     187                 :            :     //
     188                 :            :     // Note that this shader might have specific output size requirements,
     189                 :            :     // depending on the exact shader stage hooked by the user, and may already
     190                 :            :     // be a compute shader.
     191                 :            :     pl_shader sh;
     192                 :            : 
     193                 :            :     // For `PL_HOOK_SIG_TEX`, this contains the texture that the user should
     194                 :            :     // sample from.
     195                 :            :     //
     196                 :            :     // Note: This texture object is owned by the renderer, and users must not
     197                 :            :     // modify its contents. It will not be touched for the duration of a frame,
     198                 :            :     // but the contents are lost in between frames.
     199                 :            :     pl_tex tex;
     200                 :            : 
     201                 :            :     // The effective current rectangle of the image we're rendering in this
     202                 :            :     // shader, i.e. the effective rect of the content we're interested in,
     203                 :            :     // as a crop of either `sh` or `tex` (depending on the signature).
     204                 :            :     //
     205                 :            :     // Note: This is still set even for `PL_HOOK_SIG_NONE`!
     206                 :            :     pl_rect2df rect;
     207                 :            : 
     208                 :            :     // The current effective colorspace and representation, of either the
     209                 :            :     // pre-sampled color (in `sh`), or the contents of `tex`, respectively.
     210                 :            :     //
     211                 :            :     // Note: This is still set even for `PL_HOOK_SIG_NONE`!
     212                 :            :     struct pl_color_repr repr;
     213                 :            :     struct pl_color_space color;
     214                 :            :     int components;
     215                 :            : 
     216                 :            :     // The representation and colorspace of the original image, for reference.
     217                 :            :     const struct pl_color_repr *orig_repr;
     218                 :            :     const struct pl_color_space *orig_color;
     219                 :            : 
     220                 :            :     // The (cropped) source and destination rectangles of the overall
     221                 :            :     // rendering. These are functionallty equivalent to `image.crop` and
     222                 :            :     // `target.crop`, respectively, but `src_rect` in particular may change as
     223                 :            :     // a result of previous hooks being executed. (e.g. prescalers)
     224                 :            :     pl_rect2df src_rect;
     225                 :            :     pl_rect2d dst_rect;
     226                 :            : };
     227                 :            : 
     228                 :            : struct pl_hook_res {
     229                 :            :     // If true, the hook is assumed to have "failed" or errored in some way,
     230                 :            :     // and all other fields are ignored.
     231                 :            :     bool failed;
     232                 :            : 
     233                 :            :     // What type of output this hook is returning.
     234                 :            :     // Note: If this is `PL_HOOK_SIG_NONE`, all other fields are ignored.
     235                 :            :     enum pl_hook_sig output;
     236                 :            : 
     237                 :            :     // For `PL_HOOK_SIG_COLOR`, this *must* be set to a valid `pl_shader`
     238                 :            :     // object containing the sampled color value (i.e. with an output signature
     239                 :            :     // of `PL_SHADER_SIG_COLOR`), and *should* be allocated from the given
     240                 :            :     // `pl_dispatch` object. Ignored otherwise.
     241                 :            :     pl_shader sh;
     242                 :            : 
     243                 :            :     // For `PL_HOOK_SIG_TEX`, this *must* contain the texture object containing
     244                 :            :     // the result of rendering the hook. This *should* be a texture allocated
     245                 :            :     // using the given `get_tex` callback, to ensure the format and texture
     246                 :            :     // usage flags are compatible with what the renderer expects.
     247                 :            :     pl_tex tex;
     248                 :            : 
     249                 :            :     // For shaders that return some sort of output, this contains the
     250                 :            :     // new/altered versions of the existing "current texture" metadata.
     251                 :            :     struct pl_color_repr repr;
     252                 :            :     struct pl_color_space color;
     253                 :            :     int components;
     254                 :            : 
     255                 :            :     // This contains the new effective rect of the contents. This may be
     256                 :            :     // different from the original `rect` for resizable passes. Ignored for
     257                 :            :     // non-resizable passes.
     258                 :            :     pl_rect2df rect;
     259                 :            : };
     260                 :            : 
     261                 :            : enum pl_hook_par_mode {
     262                 :            :     PL_HOOK_PAR_VARIABLE,   // normal shader variable
     263                 :            :     PL_HOOK_PAR_DYNAMIC,    // dynamic shader variable, e.g. per-frame changing
     264                 :            :     PL_HOOK_PAR_CONSTANT,   // fixed at compile time (e.g. for array sizes),
     265                 :            :                             // must be scalar (non-vector/matrix)
     266                 :            :     PL_HOOK_PAR_DEFINE,     // defined in the preprocessor, must be `int`
     267                 :            :     PL_HOOK_PAR_MODE_COUNT,
     268                 :            : };
     269                 :            : 
     270                 :            : typedef union pl_var_data {
     271                 :            :     int i;
     272                 :            :     unsigned u;
     273                 :            :     float f;
     274                 :            : } pl_var_data;
     275                 :            : 
     276                 :            : struct pl_hook_par {
     277                 :            :     // Name as used in the shader.
     278                 :            :     const char *name;
     279                 :            : 
     280                 :            :     // Type of this shader parameter, and how it's manifested in the shader.
     281                 :            :     enum pl_var_type type;
     282                 :            :     enum pl_hook_par_mode mode;
     283                 :            : 
     284                 :            :     // Human-readable explanation of this parameter. (Optional)
     285                 :            :     const char *description;
     286                 :            : 
     287                 :            :     // Mutable data pointer to current value of variable.
     288                 :            :     pl_var_data *data;
     289                 :            : 
     290                 :            :     // Default/initial value, and lower/upper bounds.
     291                 :            :     pl_var_data initial;
     292                 :            :     pl_var_data minimum;
     293                 :            :     pl_var_data maximum;
     294                 :            : 
     295                 :            :     // Human-readable names for the variants of an integer option. This array
     296                 :            :     // can be indexed directly by integer values, ranging from `minimum.i` to
     297                 :            :     // `maximum.i`. May be NULL, in which case options are unnamed.
     298                 :            :     const char * const *names;
     299                 :            : };
     300                 :            : 
     301                 :            : // Struct describing a hook.
     302                 :            : //
     303                 :            : // Note: Users may freely create their own instances of this struct, there is
     304                 :            : // nothing particularly special about `pl_mpv_user_shader_parse`.
     305                 :            : struct pl_hook {
     306                 :            :     enum pl_hook_stage stages;  // Which stages to hook on
     307                 :            :     enum pl_hook_sig input;     // Which input signature this hook expects
     308                 :            :     void *priv;                 // Arbitrary user context
     309                 :            : 
     310                 :            :     // Custom tunable shader parameters exported by this hook. These may be
     311                 :            :     // updated at any time by the user, to influence the behavior of the hook.
     312                 :            :     // Contents are arbitrary and subject to the method of hook construction.
     313                 :            :     const struct pl_hook_par *parameters;
     314                 :            :     int num_parameters;
     315                 :            : 
     316                 :            :     // Called at the beginning of passes, to reset/initialize the hook. (Optional)
     317                 :            :     void (*reset)(void *priv);
     318                 :            : 
     319                 :            :     // The hook function itself. Called by the renderer at any of the indicated
     320                 :            :     // hook stages. See `pl_hook_res` for more info on the return values.
     321                 :            :     struct pl_hook_res (*hook)(void *priv, const struct pl_hook_params *params);
     322                 :            : 
     323                 :            :     // Unique signature identifying this hook, used to disable misbehaving hooks.
     324                 :            :     // All hooks with the same signature will be disabled, should they fail to
     325                 :            :     // execute during run-time.
     326                 :            :     uint64_t signature;
     327                 :            : };
     328                 :            : 
     329                 :            : // Compatibility layer with `mpv` user shaders. See the mpv man page for more
     330                 :            : // information on the format. Will return `NULL` if the shader fails parsing.
     331                 :            : //
     332                 :            : // The resulting `pl_hook` objects should be destroyed with the corresponding
     333                 :            : // destructor when no longer needed.
     334                 :            : PL_API const struct pl_hook *
     335                 :            : pl_mpv_user_shader_parse(pl_gpu gpu, const char *shader_text, size_t shader_len);
     336                 :            : 
     337                 :            : PL_API void pl_mpv_user_shader_destroy(const struct pl_hook **hook);
     338                 :            : 
     339                 :            : PL_API_END
     340                 :            : 
     341                 :            : #endif // LIBPLACEBO_SHADERS_CUSTOM_H_

Generated by: LCOV version 1.16