X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.h;h=09b9aedc85ac78aa405b5c37042f5a56fa6feaf5;hp=038fb1c875e282616db5d2193ea02ade2cfad958;hb=fb1f4f2008f97c71248c0554d93e8d7c11347a8b;hpb=5278bd9c038dd9f2d56b4de52c904426dfe0b6fe diff --git a/effect_chain.h b/effect_chain.h index 038fb1c..09b9aed 100644 --- a/effect_chain.h +++ b/effect_chain.h @@ -112,6 +112,12 @@ enum FramebufferTransformation { SQUARE_ROOT_FRAMEBUFFER_TRANSFORMATION, }; +// Whether a link is into another phase or not; see Node::incoming_link_type. +enum NodeLinkType { + IN_ANOTHER_PHASE, + IN_SAME_PHASE +}; + // A node in the graph; basically an effect and some associated information. class Node { public: @@ -143,16 +149,29 @@ private: // sampler state here. int bound_sampler_num; + // For each node in incoming_links, whether it comes from another phase + // or not. This is required because in some rather obscure cases, + // it is possible to have an input twice in the same phase; both by + // itself and as a bounced input. + // + // TODO: It is possible that we might even need to bounce multiple + // times and thus disambiguate also between different external phases, + // but we'll deal with that when we need to care about it, if ever. + std::vector incoming_link_type; + // Used during the building of the effect chain. Colorspace output_color_space; GammaCurve output_gamma_curve; AlphaType output_alpha_type; - bool needs_mipmaps; // Directly or indirectly. + Effect::MipmapRequirements needs_mipmaps; // Directly or indirectly. // Set if this effect, and all effects consuming output from this node // (in the same phase) have one_to_one_sampling() set. bool one_to_one_sampling; + // Same, for strong_one_to_one_sampling(). + bool strong_one_to_one_sampling; + friend class EffectChain; }; @@ -166,8 +185,6 @@ struct Phase { // which is which, because they contain the same data. std::set attribute_indexes; - bool input_needs_mipmaps; - // Inputs are only inputs from other phases (ie., those that come from RTT); // input textures are counted as part of . std::vector inputs; @@ -181,6 +198,7 @@ struct Phase { // Whether this phase is compiled as a compute shader, ie., the last effect is // marked as one. bool is_compute_shader; + Node *compute_shader_node; // If , which image unit the output buffer is bound to. // This is used as source for a Uniform below. @@ -188,17 +206,19 @@ struct Phase { // These are used in transforming from unnormalized to normalized coordinates // in compute shaders. + int uniform_output_size[2]; Point2D inv_output_size, output_texcoord_adjust; // Identifier used to create unique variables in GLSL. // Unique per-phase to increase cacheability of compiled shaders. - std::map effect_ids; + std::map, std::string> effect_ids; // Uniforms for this phase; combined from all the effects. std::vector> uniforms_image2d; std::vector> uniforms_sampler2d; std::vector> uniforms_bool; std::vector> uniforms_int; + std::vector> uniforms_ivec2; std::vector> uniforms_float; std::vector> uniforms_vec2; std::vector> uniforms_vec3; @@ -389,6 +409,27 @@ public: // the current viewport. void render_to_fbo(GLuint fbo, unsigned width, unsigned height); + // Render the effect chain to the given set of textures. This is equivalent + // to render_to_fbo() with a freshly created FBO bound to the given textures, + // except that it is more efficient if the last phase contains a compute shader. + // Thus, prefer this to render_to_fbo() where possible. + // + // Only one destination texture is supported. This restriction will be lifted + // in the future. + // + // All destination textures must be exactly of size x , + // and must either come from the same ResourcePool the effect uses, or outlive + // the EffectChain (otherwise, we could be allocating FBOs that end up being + // stale). Textures must also have valid state; in particular, they must either + // be mipmap complete or have a non-mipmapped minification mode. + // + // width and height can not be zero. + struct DestinationTexture { + GLuint texnum; + GLenum format; + }; + void render_to_texture(const std::vector &destinations, unsigned width, unsigned height); + Effect *last_added_effect() { if (nodes.empty()) { return nullptr; @@ -457,9 +498,19 @@ private: // as the last effect. Also pushes all phases in order onto . Phase *construct_phase(Node *output, std::map *completed_effects); + // Do the actual rendering of the chain. If is not (GLuint)-1, + // renders to that FBO. If is non-empty, render to that set + // of textures (last phase, save for the dummy phase, must be a compute shader), + // with x/y ignored. Having both set is an error. + void render(GLuint dest_fbo, const std::vector &destinations, + unsigned x, unsigned y, unsigned width, unsigned height); + // Execute one phase, ie. set up all inputs, effects and outputs, and render the quad. - void execute_phase(Phase *phase, bool render_to_texture, - std::map *output_textures, + // If is empty, uses whatever output is current (and the phase must not be + // a compute shader). + void execute_phase(Phase *phase, + const std::map &output_textures, + const std::vector &destinations, std::set *generated_mipmaps); // Set up uniforms for one phase. The program must already be bound. @@ -539,6 +590,12 @@ private: bool finalized; GLuint vbo; // Contains vertex and texture coordinate data. + // Whether the last effect (which will then be in a phase all by itself) + // is a dummy effect that is only added because the last phase uses a compute + // shader, which cannot output directly to the backbuffer. This means that + // the phase can be skipped if we are _not_ rendering to the backbuffer. + bool has_dummy_effect = false; + ResourcePool *resource_pool; bool owns_resource_pool;