]> git.sesse.net Git - movit/blobdiff - effect.h
Add support for compute shaders.
[movit] / effect.h
index ebbb6726104051caaba9b4e58df21279682dc1f3..073780f172bdbc929db64238c1705221264691c4 100644 (file)
--- a/effect.h
+++ b/effect.h
@@ -138,7 +138,7 @@ public:
                // Keeps the type of alpha (premultiplied, postmultiplied, blank)
                // unchanged from input to output. Usually appropriate if you
                // process all color channels in a linear fashion, do not change
-               // alpha, and do not produce any new pixels thare have alpha != 1.0.
+               // alpha, and do not produce any new pixels that have alpha != 1.0.
                //
                // Does not make sense for inputs.
                DONT_CARE_ALPHA_TYPE,
@@ -245,6 +245,45 @@ public:
                assert(false);
        }
 
+       // Whether this effect uses a compute shader instead of a regular fragment shader.
+       // Compute shaders are more flexible in that they can have multiple outputs
+       // for each invocation and also communicate between instances (by using shared
+       // memory within each group), but are not universally supported. The typical
+       // pattern would be to check movit_compute_shaders_supported and rewrite the
+       // graph to use a compute shader effect instead of a regular effect if it is
+       // available, in order to get better performance. Since compute shaders can reuse
+       // loads (again typically through shared memory), using needs_texture_bounce()
+       // is usually not needed, although it is allowed; the best candidates for compute
+       // shaders are typically those that sample many times from their input
+       // but can reuse those loads across neighboring instances.
+       //
+       // Compute shaders commonly work with unnormalized texture coordinates
+       // (where coordinates are integers [0..W) and [0..H)), whereas the rest
+       // of Movit, including any inputs you may want to sample from, works
+       // with normalized coordinates ([0..1)). Movit gives you uniforms
+       // PREFIX(inv_output_size) and PREFIX(output_texcoord_adjust) that you
+       // can use to transform unnormalized to normalized, as well as a macro
+       // NORMALIZE_TEXTURE_COORDS(vec2) that does it for you.
+       //
+       // Since compute shaders have flexible output, it is difficult to chain other
+       // effects after them in the same phase, and thus, they will always be last.
+       // (This limitation may be lifted for the special case of one-to-one effects
+       // in the future.) Furthermore, they cannot write to the framebuffer, just to
+       // textures, so Movit may have to insert an extra phase just to do the output
+       // from a texture to the screen in some cases. However, this is transparent
+       // to both the effect and the user.
+       virtual bool is_compute_shader() const { return false; }
+
+       // For a compute shader (see the previous member function), what dimensions
+       // it should be invoked over. Called every frame, before uniforms are set
+       // (so you are allowed to update uniforms based from this call).
+       virtual void get_compute_dimensions(unsigned output_width, unsigned output_height,
+                                           unsigned *x, unsigned *y, unsigned *z) const {
+               *x = output_width;
+               *y = output_height;
+               *z = 1;
+       }
+
        // Tells the effect the resolution of each of its input.
        // This will be called every frame, and always before get_output_size(),
        // so you can change your output size based on the input if so desired.
@@ -316,11 +355,8 @@ protected:
        //
        // Neither of these take ownership of the pointer.
 
-       // int is special since GLSL pre-1.30 doesn't have integer uniforms.
-       // Thus, ints that you register will _not_ be converted to GLSL uniforms.
+       // These correspond directly to int/float/vec2/vec3/vec4 in GLSL.
        void register_int(const std::string &key, int *value);
-
-       // These correspond directly to float/vec2/vec3/vec4 in GLSL.
        void register_float(const std::string &key, float *value);
        void register_vec2(const std::string &key, float *values);
        void register_vec3(const std::string &key, float *values);
@@ -353,7 +389,9 @@ protected:
        void register_uniform_vec2(const std::string &key, const float *values);
        void register_uniform_vec3(const std::string &key, const float *values);
        void register_uniform_vec4(const std::string &key, const float *values);
+       void register_uniform_float_array(const std::string &key, const float *values, size_t num_values);
        void register_uniform_vec2_array(const std::string &key, const float *values, size_t num_values);
+       void register_uniform_vec3_array(const std::string &key, const float *values, size_t num_values);
        void register_uniform_vec4_array(const std::string &key, const float *values, size_t num_values);
        void register_uniform_mat3(const std::string &key, const Eigen::Matrix3d *matrix);
 
@@ -365,6 +403,7 @@ private:
        std::map<std::string, float *> params_vec4;
 
        // Picked out by EffectChain during finalization.
+       std::vector<Uniform<int> > uniforms_image2d;
        std::vector<Uniform<int> > uniforms_sampler2d;
        std::vector<Uniform<bool> > uniforms_bool;
        std::vector<Uniform<int> > uniforms_int;
@@ -372,7 +411,9 @@ private:
        std::vector<Uniform<float> > uniforms_vec2;
        std::vector<Uniform<float> > uniforms_vec3;
        std::vector<Uniform<float> > uniforms_vec4;
+       std::vector<Uniform<float> > uniforms_float_array;
        std::vector<Uniform<float> > uniforms_vec2_array;
+       std::vector<Uniform<float> > uniforms_vec3_array;
        std::vector<Uniform<float> > uniforms_vec4_array;
        std::vector<Uniform<Eigen::Matrix3d> > uniforms_mat3;
        friend class EffectChain;