/*
* 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 .
*/
#ifndef LIBPLACEBO_DISPATCH_H_
#define LIBPLACEBO_DISPATCH_H_
#include
#include
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