]> git.sesse.net Git - movit/blobdiff - effect.h
Fix a typo in ResizeEffect. Found by virtual → override transition.
[movit] / effect.h
index 6154dacaec1cf0e55cb7d3e734a3ed3c790cc16b..afac5dc91c840ad6f273786498c1233547927343 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,
@@ -217,6 +217,20 @@ public:
        //     and allow dependent effects to change that sampler state.
        virtual bool is_single_texture() const { return false; }
 
+       // If set, this effect should never be bounced to an output, even if a
+       // dependent effect demands texture bounce.
+       //
+       // Note that setting this can invoke undefined behavior, up to and including crashing,
+       // so you should only use it if you have deep understanding of your entire chain
+       // and Movit's processing of it. The most likely use case is if you have an input
+       // that's cheap to compute but not a single texture (e.g. YCbCrInput), and want
+       // to run a ResampleEffect directly from it. Normally, this would require a bounce,
+       // but it's faster not to. (However, also note that in this case, effective texel
+       // subpixel precision will be too optimistic, since chroma is already subsampled.)
+       //
+       // Has no effect if is_single_texture() is set.
+       virtual bool override_disable_bounce() const { return false; }
+
        // If changes_output_size() is true, you must implement this to tell
        // the framework what output size you want. Also, you can set a
        // virtual width/height, which is the size the next effect (if any)
@@ -231,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.
@@ -302,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);
@@ -339,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);
 
@@ -351,16 +403,19 @@ private:
        std::map<std::string, float *> params_vec4;
 
        // Picked out by EffectChain during finalization.
-       std::vector<Uniform<int> > uniforms_sampler2d;
-       std::vector<Uniform<bool> > uniforms_bool;
-       std::vector<Uniform<int> > uniforms_int;
-       std::vector<Uniform<float> > uniforms_float;
-       std::vector<Uniform<float> > uniforms_vec2;
-       std::vector<Uniform<float> > uniforms_vec3;
-       std::vector<Uniform<float> > uniforms_vec4;
-       std::vector<Uniform<float> > uniforms_vec2_array;
-       std::vector<Uniform<float> > uniforms_vec4_array;
-       std::vector<Uniform<Eigen::Matrix3d> > uniforms_mat3;
+       std::vector<Uniform<int>> uniforms_image2d;
+       std::vector<Uniform<int>> uniforms_sampler2d;
+       std::vector<Uniform<bool>> uniforms_bool;
+       std::vector<Uniform<int>> uniforms_int;
+       std::vector<Uniform<float>> uniforms_float;
+       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;
 };