diff options
author | Paul Berry <[email protected]> | 2012-12-05 14:37:19 -0800 |
---|---|---|
committer | Paul Berry <[email protected]> | 2012-12-14 10:51:21 -0800 |
commit | ca7e891e8aceaf1adb4c9ae776916fa3636747ee (patch) | |
tree | bbdedc3c50120d9ead8a8bd92f67f611a3a6ab5a /src/glsl/linker.cpp | |
parent | df87722beccf0255d149668ca54a35cabf99a9c4 (diff) |
glsl/linker: Pack between varyings.
This patch implements varying packing between varyings.
Previously, each varying occupied components 0 through N-1 of its
assigned varying slot, so there was no way to pack two varyings into
the same slot. For example, if the varyings were a float, a vec2, a
vec3, and another vec2, they would be stored as follows:
<----slot1----> <----slot2----> <----slot3----> <----slot4----> slots
* * * * * * * * * * * * * * * *
flt x x x <vec2-> x x <--vec3---> x <vec2-> x x varyings
(Each * represents a varying component, and the "x"s represent wasted
space).
This change packs the varyings together to eliminate wasted space
between varyings, like so:
<----slot1----> <----slot2----> <----slot3----> <----slot4----> slots
* * * * * * * * * * * * * * * *
<vec2-> <vec2-> flt <--vec3---> x x x x x x x x varyings
Note that we take advantage of the sort order introduced in previous
patches (vec4's first, then vec2's, then scalars, then vec3's) to
minimize how often a varying is "double parked" (split across varying
slots).
Reviewed-by: Eric Anholt <[email protected]>
v2: Skip varying packing if ctx->Const.DisableVaryingPacking is true.
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r-- | src/glsl/linker.cpp | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 1ae8fad22d0..83d0e871005 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -76,6 +76,8 @@ extern "C" { #include "main/shaderobj.h" } +#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1)) + /** * Visitor that determines whether or not a variable is ever written. */ @@ -1971,7 +1973,7 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, class varying_matches { public: - varying_matches(); + varying_matches(bool disable_varying_packing); ~varying_matches(); void record(ir_variable *producer_var, ir_variable *consumer_var); unsigned assign_locations(); @@ -1979,6 +1981,13 @@ public: private: /** + * If true, this driver disables varying packing, so all varyings need to + * be aligned on slot boundaries, and take up a number of slots equal to + * their number of matrix columns times their array size. + */ + const bool disable_varying_packing; + + /** * Enum representing the order in which varyings are packed within a * packing class. * @@ -2012,6 +2021,7 @@ private: * Packing order for this varying, computed by compute_packing_order(). */ packing_order_enum packing_order; + unsigned num_components; /** * The output variable in the producer stage. @@ -2046,7 +2056,8 @@ private: }; -varying_matches::varying_matches() +varying_matches::varying_matches(bool disable_varying_packing) + : disable_varying_packing(disable_varying_packing) { /* Note: this initial capacity is rather arbitrarily chosen to be large * enough for many cases without wasting an unreasonable amount of space. @@ -2099,6 +2110,16 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) = this->compute_packing_class(producer_var); this->matches[this->num_matches].packing_order = this->compute_packing_order(producer_var); + if (this->disable_varying_packing) { + unsigned slots = producer_var->type->is_array() + ? (producer_var->type->length + * producer_var->type->fields.array->matrix_columns) + : producer_var->type->matrix_columns; + this->matches[this->num_matches].num_components = 4 * slots; + } else { + this->matches[this->num_matches].num_components + = producer_var->type->component_slots(); + } this->matches[this->num_matches].producer_var = producer_var; this->matches[this->num_matches].consumer_var = consumer_var; this->num_matches++; @@ -2122,20 +2143,19 @@ varying_matches::assign_locations() unsigned generic_location = 0; for (unsigned i = 0; i < this->num_matches; i++) { - this->matches[i].generic_location = generic_location; - - ir_variable *producer_var = this->matches[i].producer_var; - - if (producer_var->type->is_array()) { - const unsigned slots = producer_var->type->length - * producer_var->type->fields.array->matrix_columns; + /* Advance to the next slot if this varying has a different packing + * class than the previous one, and we're not already on a slot + * boundary. + */ + if (i > 0 && + this->matches[i - 1].packing_class + != this->matches[i].packing_class) { + generic_location = ALIGN(generic_location, 4); + } - generic_location += 4 * slots; - } else { - const unsigned slots = producer_var->type->matrix_columns; + this->matches[i].generic_location = generic_location; - generic_location += 4 * slots; - } + generic_location += this->matches[i].num_components; } return (generic_location + 3) / 4; @@ -2289,7 +2309,7 @@ assign_varying_locations(struct gl_context *ctx, /* FINISHME: Set dynamically when geometry shader support is added. */ const unsigned producer_base = VERT_RESULT_VAR0; const unsigned consumer_base = FRAG_ATTRIB_VAR0; - varying_matches matches; + varying_matches matches(ctx->Const.DisableVaryingPacking); /* Operate in a total of three passes. * |