shaders.h 8.34 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * This file is part of libplacebo.
 *
 * libplacebo is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * libplacebo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdio.h>

#include "common.h"
#include "context.h"
24
#include "gpu.h"
25

26 27 28 29
// This represents an identifier (e.g. name of function, uniform etc.) for
// a shader resource. The generated identifiers are immutable, but only live
// until pl_shader_reset - so make copies when passing to external stuff.
typedef const char * ident_t;
Niklas Haas's avatar
Niklas Haas committed
30

31 32 33 34
enum pl_shader_buf {
    SH_BUF_PRELUDE, // extra #defines etc.
    SH_BUF_HEADER,  // previous passes, helper function definitions, etc.
    SH_BUF_BODY,    // partial contents of the "current" function
35
    SH_BUF_FOOTER,  // will be appended to the end of the current function
36 37 38
    SH_BUF_COUNT,
};

39 40
struct pl_shader {
    struct pl_context *ctx;
41
    struct pl_shader_res res; // for accumulating vertex_attribs etc.
42
    struct xta_ref *tmp;
43
    bool failed;
44
    bool mutable;
45 46
    int output_w;
    int output_h;
47
    struct bstr buffers[SH_BUF_COUNT];
48
    bool is_compute;
49 50
    bool flexible_work_groups;
    int fresh;
Niklas Haas's avatar
Niklas Haas committed
51
};
52

53 54 55 56 57 58 59
// Helper functions for convenience
#define SH_PARAMS(sh) ((sh)->res.params)
#define SH_GPU(sh) (SH_PARAMS(sh).gpu)

// Returns the GLSL description, defaulting to desktop 130.
struct pl_glsl_desc sh_glsl(const struct pl_shader *sh);

60 61 62 63 64
#define SH_FAIL(sh, ...) do {    \
        sh->failed = true;       \
        PL_ERR(sh, __VA_ARGS__); \
    } while (0)

65 66 67
// Attempt enabling compute shaders for this pass, if possible
bool sh_try_compute(struct pl_shader *sh, int bw, int bh, bool flex, size_t mem);

68 69 70 71 72
// Attempt merging a secondary shader into the current shader. Returns NULL if
// merging fails (e.g. incompatible signatures); otherwise returns an identifier
// corresponding to the generated subpass function.
ident_t sh_subpass(struct pl_shader *sh, const struct pl_shader *sub);

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
// Helpers for adding new variables/descriptors/etc. with fresh, unique
// identifier names. These will never conflcit with other identifiers, even
// if the shaders are merged together.
ident_t sh_fresh(struct pl_shader *sh, const char *name);

// Add a new shader var and return its identifier
ident_t sh_var(struct pl_shader *sh, struct pl_shader_var sv);

// Add a new shader desc and return its identifier. This function takes care of
// setting the binding to a fresh bind point according to the namespace
// requirements, so the caller may leave it blank.
ident_t sh_desc(struct pl_shader *sh, struct pl_shader_desc sd);

// Add a new vec2 vertex attribute from a pl_rect2df, or returns NULL on failure.
ident_t sh_attr_vec2(struct pl_shader *sh, const char *name,
                     const struct pl_rect2df *rc);

// Bind a texture under a given transformation and make its attributes
// available as well. If an output pointer for one of the attributes is left
92 93
// as NULL, that attribute will not be added. Returns NULL on failure. `rect`
// is optional, and defaults to the full texture if left as NULL.
94
//
95 96
// Note that for e.g. compute shaders, the vec2 out_pos might be a macro that
// expands to an expensive computation, and should be cached by the user.
97
ident_t sh_bind(struct pl_shader *sh, const struct pl_tex *tex,
98
                const char *name, const struct pl_rect2df *rect,
99 100
                ident_t *out_pos, ident_t *out_size, ident_t *out_pt);

101 102 103 104 105 106 107 108 109 110 111 112 113
// Incrementally build up a buffer by adding new variable elements to the
// buffer, resizing buf.buffer_vars if necessary. Returns whether or not the
// variable could be successfully added (which may fail if you try exceeding
// the size limits of the buffer type). If successful, the layout is stored
// in *out_layout (may be NULL).
bool sh_buf_desc_append(void *tactx, const struct pl_gpu *gpu,
                        struct pl_shader_desc *buf_desc,
                        struct pl_var_layout *out_layout,
                        const struct pl_var new_var);

size_t sh_buf_desc_size(const struct pl_shader_desc *buf_desc);


114
// Underlying function for appending text to a shader
115
void pl_shader_append(struct pl_shader *sh, enum pl_shader_buf buf,
116 117 118
                      const char *fmt, ...)
    PRINTF_ATTRIBUTE(3, 4);

119 120 121
#define GLSLP(...) pl_shader_append(sh, SH_BUF_PRELUDE, __VA_ARGS__)
#define GLSLH(...) pl_shader_append(sh, SH_BUF_HEADER, __VA_ARGS__)
#define GLSL(...)  pl_shader_append(sh, SH_BUF_BODY, __VA_ARGS__)
122
#define GLSLF(...) pl_shader_append(sh, SH_BUF_FOOTER, __VA_ARGS__)
123

124 125 126 127
// Requires that the share is mutable, has an output signature compatible
// with the given input signature, as well as an output size compatible with
// the given size requirements. Errors and returns false otherwise.
bool sh_require(struct pl_shader *sh, enum pl_shader_sig insig, int w, int h);
128 129 130 131 132

// Shader resources

enum pl_shader_obj_type {
    PL_SHADER_OBJ_INVALID = 0,
133
    PL_SHADER_OBJ_PEAK_DETECT,
134
    PL_SHADER_OBJ_SAMPLER,
135
    PL_SHADER_OBJ_DITHER,
136
    PL_SHADER_OBJ_3DLUT,
137
    PL_SHADER_OBJ_LUT,
138
    PL_SHADER_OBJ_AV1_GRAIN,
139 140 141 142
};

struct pl_shader_obj {
    enum pl_shader_obj_type type;
143 144
    const struct pl_gpu *gpu;
    void (*uninit)(const struct pl_gpu *gpu, void *priv);
145
    void *priv;
146 147
};

148 149 150
// Returns (*ptr)->priv, or NULL on failure
void *sh_require_obj(struct pl_shader *sh, struct pl_shader_obj **ptr,
                     enum pl_shader_obj_type type, size_t priv_size,
151
                     void (*uninit)(const struct pl_gpu *gpu, void *priv));
152 153 154

#define SH_OBJ(sh, ptr, type, t, uninit) \
    ((t*) sh_require_obj(sh, ptr, type, sizeof(t), uninit))
155 156

// Initializes a PRNG. The resulting string will directly evaluate to a
157 158 159 160
// pseudorandom, uniformly distributed float from [0.0,1.0]. Since this
// algorithm works by mutating a state variable, if the user wants to use the
// resulting PRNG inside a subfunction, they must add an extra `inout float %s`
// with the name of `state` to the signature. (Optional)
161 162 163
//
// If `temporal` is set, the PRNG will vary across frames.
ident_t sh_prng(struct pl_shader *sh, bool temporal, ident_t *state);
164 165 166 167

enum sh_lut_method {
    SH_LUT_AUTO = 0, // pick whatever makes the most sense
    SH_LUT_TEXTURE,  // upload as texture
168
    SH_LUT_UNIFORM,  // uniform array
169 170 171 172 173 174
    SH_LUT_LITERAL,  // constant / literal array in shader source (fallback)

    // this is never picked by SH_DATA_AUTO
    SH_LUT_LINEAR,   // upload as linearly-sampleable texture
};

175 176
// Makes a table of float vecs values available as a shader variable, using an
// a given method (falling back if needed). The resulting identifier can be
177 178
// sampled directly as %s(pos), where pos is a vector with the right number of
// dimensions. `pos` must be an integer vector within the bounds of the array,
179 180
// unless the method is `SH_LUT_LINEAR`, in which case it's a float vector that
// gets interpolated and clamped as needed. Returns NULL on error.
181 182 183 184 185 186 187 188 189 190
//
// This function also acts as `sh_require_obj`, and uses the `buf`, `tex`
// and `text` fields of the resulting `obj`. (The other fields may be used by
// the caller)
//
// The `fill` function will be called with a zero-initialized buffer whenever
// the data needs to be computed, which happens whenever the size is changed,
// the shader object is invalidated, or `update` is set to true.
ident_t sh_lut(struct pl_shader *sh, struct pl_shader_obj **obj,
               enum sh_lut_method method, int width, int height, int depth,
191
               int components, bool update, void *priv,
192
               void (*fill)(void *priv, float *data, int w, int h, int d));
193 194 195 196 197

// Returns a GLSL-version appropriate "bvec"-like type. For GLSL 130+, this
// returns bvecN. For GLSL 120, this returns vecN instead. The intended use of
// this function is with mix(), which only accepts bvec in GLSL 130+.
const char *sh_bvec(const struct pl_shader *sh, int dims);
198 199 200 201

// Returns the appropriate `texture`-equivalent function for the shader and
// given texture.
const char *sh_tex_fn(const struct pl_shader *sh, const struct pl_tex *tex);