summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/dispatch.h
blob: 7d4379499f8a6456cce22a7f4fd5a63726153400 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * 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/>.
 */

#ifndef LIBPLACEBO_DISPATCH_H_
#define LIBPLACEBO_DISPATCH_H_

#include <libplacebo/shaders.h>
#include <libplacebo/gpu.h>

PL_API_BEGIN

// Thread-safety: Safe
typedef struct pl_dispatch_t *pl_dispatch;

// Creates a new shader dispatch object. This object provides a translation
// layer between generated shaders (pl_shader) and the ra context such that it
// can be used to execute shaders. This dispatch object will also provide
// shader caching (for efficient re-use).
PL_API pl_dispatch pl_dispatch_create(pl_log log, pl_gpu gpu);
PL_API void pl_dispatch_destroy(pl_dispatch *dp);

// Reset/increments the internal counters of the pl_dispatch. This must be
// called whenever the user is going to begin with a new frame, in order to
// perform garbage collection and advance the state of the internal PRNG.
//
// Note that shaders generated by `pl_dispatch` are therefore entirely
// deterministic, as long as the sequence of calls (and inputs to the shader)
// are the same.
PL_API void pl_dispatch_reset_frame(pl_dispatch dp);

// Returns a blank pl_shader object, suitable for recording rendering commands.
// For more information, see the header documentation in `shaders/*.h`.
PL_API pl_shader pl_dispatch_begin(pl_dispatch dp);

// Struct passed to `info_callback`. Only valid until that function returns.
struct pl_dispatch_info {
    // Information about the shader for this shader execution, as well as a
    // 64-bit signature uniquely identifying it.
    pl_shader_info shader;
    uint64_t signature;

    // A list of execution times for this pass, in nanoseconds. May be empty.
    uint64_t samples[256];
    int num_samples;

    // As a convenience, this contains the last, average and peak of the above
    // list of samples. If `num_samples` is 0, these values are also 0.
    uint64_t last;
    uint64_t peak;
    uint64_t average;
};

// Helper function to make a copy of `pl_dispatch_info`, while overriding
// (and dereferencing) whatever was previously stored there.
static inline void pl_dispatch_info_move(struct pl_dispatch_info *dst,
                                         const struct pl_dispatch_info *src)
{
    pl_shader_info_deref(&dst->shader);
    *dst = *src;
    dst->shader = pl_shader_info_ref(src->shader);
}

// Set up a dispatch callback for this `pl_dispatch` object. The given callback
// will be run for every successfully dispatched shader. Call this again with
// `cb == NULL` to disable.
PL_API void pl_dispatch_callback(pl_dispatch dp, void *priv,
                                 void (*cb)(void *priv,
                                 const struct pl_dispatch_info *));

struct pl_dispatch_params {
    // The shader to execute. The pl_dispatch will take over ownership
    // of this shader, and return it back to the internal pool.
    //
    // This shader must have a compatible signature, i.e. inputs
    // `PL_SHADER_SIG_NONE` and outputs `PL_SHADER_SIG_COLOR`.
    pl_shader *shader;

    // The texture to render to. This must have params compatible with the
    // shader, i.e. `target->params.renderable` for fragment shaders and
    // `target->params.storable` for compute shaders.
    //
    // Note: Even when not using compute shaders, users are advised to always
    // set `target->params.storable` if permitted by the `pl_fmt`, since this
    // allows the use of compute shaders instead of full-screen quads, which is
    // faster on some platforms.
    pl_tex target;

    // The target rect to render to. Optional, if left as {0}, then the
    // entire texture will be rendered to.
    pl_rect2d rect;

    // If set, enables and controls the blending for this pass. Optional. When
    // using this with fragment shaders, `target->params.fmt->caps` must
    // include `PL_FMT_CAP_BLENDABLE`.
    const struct pl_blend_params *blend_params;

    // If set, records the execution time of this dispatch into the given
    // timer object. Optional.
    //
    // Note: If this is set, `pl_dispatch` cannot internally measure the
    // execution time of the shader, which means `pl_dispatch_info.samples` may
    // be empty as a result.
    pl_timer timer;
};

#define pl_dispatch_params(...) (&(struct pl_dispatch_params) { __VA_ARGS__ })

// Dispatch a generated shader (via the pl_shader mechanism). Returns whether
// or not the dispatch was successful.
PL_API bool pl_dispatch_finish(pl_dispatch dp, const struct pl_dispatch_params *params);

struct pl_dispatch_compute_params {
    // The shader to execute. This must be a compute shader with the input
    // set to PL_SHADER_SIG_NONE. The output, if it has any, is ignored.
    pl_shader *shader;

    // The number of work groups to dispatch in each dimension. If this is left
    // as [0} and `width/height` are both set, the number of work groups will
    // be inferred from the shader's `compute_group_sizes`.
    int dispatch_size[3];

    // If set, simulate vertex attributes (similar to `pl_dispatch_finish`)
    // according to the given dimensions. The first two components of the
    // thread's global ID will be interpreted as the X and Y locations.
    //
    // Optional, ignored if either component is left as 0.
    int width, height;

    // If set, records the execution time of this dispatch into the given
    // timer object. Optional.
    //
    // Note: If this is set, `pl_dispatch` cannot internally measure the
    // execution time of the shader, which means `pl_dispatch_info.samples` may
    // be empty as a result.
    pl_timer timer;
};

#define pl_dispatch_compute_params(...) (&(struct pl_dispatch_compute_params) { __VA_ARGS__ })

// A variant of `pl_dispatch_finish`, this one only dispatches a compute shader
// while ignoring its output (if it has one). It's only useful for shaders
// which have otherwise observable side effects (such as updating state
// objects).
PL_API bool pl_dispatch_compute(pl_dispatch dp, const struct pl_dispatch_compute_params *params);

enum pl_vertex_coords {
    PL_COORDS_ABSOLUTE,     // Absolute/integer `target` coordinates
    PL_COORDS_RELATIVE,     // Relative `target` coordinates in range [0, 1]
    PL_COORDS_NORMALIZED,   // GL-normalized coordinates in range  [-1, 1]
};

struct pl_dispatch_vertex_params {
    // The shader to execute. This must be a raster shader with the input set
    // to `PL_SHADER_SIG_NONE` and the output set to `PL_SHADER_SIG_COLOR`.
    //
    // Additionally, the shader must not have any attached vertex attributes.
    pl_shader *shader;

    // The texture to render to. Requires `target->params.renderable`.
    pl_tex target;

    // The target rect to clip the rendering to. (Optional)
    pl_rect2d scissors;

    // If set, enables and controls the blending for this pass. Optional. When
    // enabled, `target->params.fmt->caps` must include `PL_FMT_CAP_BLENDABLE`.
    const struct pl_blend_params *blend_params;

    // The description of the vertex format, including offsets.
    //
    // Note: `location` is ignored and can safely be left unset.
    const struct pl_vertex_attrib *vertex_attribs;
    int num_vertex_attribs;
    size_t vertex_stride;

    // The index of the vertex position in `vertex_attribs`, as well as the
    // interpretation of its contents.
    int vertex_position_idx;
    enum pl_vertex_coords vertex_coords;
    bool vertex_flipped; // flip all vertex y coordinates

    // Type and number of vertices to render.
    enum pl_prim_type vertex_type;
    int vertex_count;

    // Vertex data. See `pl_pass_run_params.vertex_data`.
    const void *vertex_data;
    pl_buf vertex_buf;
    size_t buf_offset;

    // Index data. See `pl_pass_run_params.index_data`. Optional.
    const void *index_data;
    enum pl_index_format index_fmt;
    pl_buf index_buf;
    size_t index_offset;

    // If set, records the execution time of this dispatch into the given
    // timer object. Optional.
    //
    // Note: If this is set, `pl_dispatch` cannot internally measure the
    // execution time of the shader, which means `pl_dispatch_info.samples` may
    // be empty as a result.
    pl_timer timer;
};

#define pl_dispatch_vertex_params(...) (&(struct pl_dispatch_vertex_params) { __VA_ARGS__ })

// Dispatch a generated shader using custom vertices, rather than using a quad
// generated by the dispatch. This allows the use of e.g. custom fragment
// shaders for things like rendering custom UI elements, or possibly doing
// advanced things like sampling from a cube map or spherical video.
PL_API bool pl_dispatch_vertex(pl_dispatch dp, const struct pl_dispatch_vertex_params *params);

// Cancel an active shader without submitting anything. Useful, for example,
// if the shader was instead merged into a different shader.
PL_API void pl_dispatch_abort(pl_dispatch dp, pl_shader *sh);

// Deprecated in favor of `pl_cache_save/pl_cache_load` on the `pl_cache`
// associated with the `pl_gpu` this dispatch is using.
PL_DEPRECATED PL_API size_t pl_dispatch_save(pl_dispatch dp, uint8_t *out_cache);
PL_DEPRECATED PL_API void pl_dispatch_load(pl_dispatch dp, const uint8_t *cache);

PL_API_END

#endif // LIBPLACEBO_DISPATCH_H