shaders.h 7.7 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 24
/*
 * 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 "bstr/bstr.h"

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

27 28
#include <libplacebo/shaders.h>

29 30 31 32
// 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
33

34 35 36 37 38 39 40
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
    SH_BUF_COUNT,
};

41 42 43
struct pl_shader {
    // Read-only fields
    struct pl_context *ctx;
44
    const struct pl_gpu *gpu;
45 46

    // Internal state
47
    struct ta_ref *tmp;
48
    bool mutable;
49 50
    int output_w;
    int output_h;
51
    struct pl_shader_res res; // for accumulating vertex_attribs etc.
52
    struct bstr buffers[SH_BUF_COUNT];
53
    bool is_compute;
54
    bool flexible_work_groups;
55
    uint8_t ident;
56
    uint8_t index;
57
    int fresh;
Niklas Haas's avatar
Niklas Haas committed
58
};
59

60 61 62 63 64 65 66 67
// Like `pl_shader_alloc`, but also has an extra `uint8_t ident` which can be
// used to namespace shaders in order to allow safely merging together multiple
// shaders using `sh_subpass`. This is not exposed publicly since there's no
// reasonable public API for `sh_subpass`.
struct pl_shader *pl_shader_alloc_ex(struct pl_context *ctx,
                                     const struct pl_gpu *gpu,
                                     uint8_t index, uint8_t ident);

68 69 70
// 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);

71 72 73 74 75
// 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);

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
// 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
95 96
// 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.
97
//
98 99
// 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.
100
ident_t sh_bind(struct pl_shader *sh, const struct pl_tex *tex,
101
                const char *name, const struct pl_rect2df *rect,
102 103 104
                ident_t *out_pos, ident_t *out_size, ident_t *out_pt);

// Underlying function for appending text to a shader
105
void pl_shader_append(struct pl_shader *sh, enum pl_shader_buf buf,
106 107 108
                      const char *fmt, ...)
    PRINTF_ATTRIBUTE(3, 4);

109 110 111
#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__)
112

113 114 115 116
// 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);
117 118 119 120 121

// Shader resources

enum pl_shader_obj_type {
    PL_SHADER_OBJ_INVALID = 0,
122
    PL_SHADER_OBJ_PEAK_DETECT,
123
    PL_SHADER_OBJ_SAMPLER,
124
    PL_SHADER_OBJ_SAMPLER_SEP,
125
    PL_SHADER_OBJ_DITHER,
126
    PL_SHADER_OBJ_3DLUT,
127
    PL_SHADER_OBJ_LUT,
128 129 130 131
};

struct pl_shader_obj {
    enum pl_shader_obj_type type;
132 133
    const struct pl_gpu *gpu;
    void (*uninit)(const struct pl_gpu *gpu, void *priv);
134
    void *priv;
135 136
};

137 138 139
// 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,
140
                     void (*uninit)(const struct pl_gpu *gpu, void *priv));
141 142 143

#define SH_OBJ(sh, ptr, type, t, uninit) \
    ((t*) sh_require_obj(sh, ptr, type, sizeof(t), uninit))
144 145

// Initializes a PRNG. The resulting string will directly evaluate to a
146 147 148 149
// 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)
150 151 152
//
// If `temporal` is set, the PRNG will vary across frames.
ident_t sh_prng(struct pl_shader *sh, bool temporal, ident_t *state);
153 154 155 156

enum sh_lut_method {
    SH_LUT_AUTO = 0, // pick whatever makes the most sense
    SH_LUT_TEXTURE,  // upload as texture
157
    SH_LUT_UNIFORM,  // uniform array
158 159 160 161 162 163
    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
};

164 165
// 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
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
// 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,
// unless the method is `SH_LUT_LINEAR` or `SH_LUT_TEXTURE` in which case it's
// a float vector that gets interpolated and clamped as needed. Returns NULL on
// error.
//
// 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,
181
               int components, bool update, void *priv,
182
               void (*fill)(void *priv, float *data, int w, int h, int d));
183 184 185 186 187

// 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);