diff options
author | Eric Anholt <eric@anholt.net> | 2011-08-23 12:13:14 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2011-08-30 12:09:40 -0700 |
commit | 72cfc6f3778d8297e52c254a5861a88eb62e4d67 (patch) | |
tree | 21330b00f032226df2bc2b603db1b7e9f4247009 /src/mesa/drivers/dri/i965/brw_vec4.cpp | |
parent | 7c84b9d303345fa5075dba8c4ea7af449d93b0f8 (diff) | |
download | external_mesa3d-72cfc6f3778d8297e52c254a5861a88eb62e4d67.zip external_mesa3d-72cfc6f3778d8297e52c254a5861a88eb62e4d67.tar.gz external_mesa3d-72cfc6f3778d8297e52c254a5861a88eb62e4d67.tar.bz2 |
i965/vs: Pack live uniform vectors together in the push constant upload.
At some point we need to also move uniform accesses out to pull
constants when there are just too many in use, but we lack tests for
that at the moment.
Fixes glsl-vs-large-uniform-array.
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_vec4.cpp')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index cdbbb55..9d64a40 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -188,4 +188,93 @@ vec4_visitor::split_uniform_registers() } } +void +vec4_visitor::pack_uniform_registers() +{ + bool uniform_used[this->uniforms]; + int new_loc[this->uniforms]; + int new_chan[this->uniforms]; + + memset(uniform_used, 0, sizeof(uniform_used)); + memset(new_loc, 0, sizeof(new_loc)); + memset(new_chan, 0, sizeof(new_chan)); + + /* Find which uniform vectors are actually used by the program. We + * expect unused vector elements when we've moved array access out + * to pull constants, and from some GLSL code generators like wine. + */ + foreach_list(node, &this->instructions) { + vec4_instruction *inst = (vec4_instruction *)node; + + for (int i = 0 ; i < 3; i++) { + if (inst->src[i].file != UNIFORM) + continue; + + uniform_used[inst->src[i].reg] = true; + } + } + + int new_uniform_count = 0; + + /* Now, figure out a packing of the live uniform vectors into our + * push constants. + */ + for (int src = 0; src < uniforms; src++) { + int size = this->uniform_vector_size[src]; + + if (!uniform_used[src]) { + this->uniform_vector_size[src] = 0; + continue; + } + + int dst; + /* Find the lowest place we can slot this uniform in. */ + for (dst = 0; dst < src; dst++) { + if (this->uniform_vector_size[dst] + size <= 4) + break; + } + + if (src == dst) { + new_loc[src] = dst; + new_chan[src] = 0; + } else { + new_loc[src] = dst; + new_chan[src] = this->uniform_vector_size[dst]; + + /* Move the references to the data */ + for (int j = 0; j < size; j++) { + c->prog_data.param[dst * 4 + new_chan[src] + j] = + c->prog_data.param[src * 4 + j]; + } + + this->uniform_vector_size[dst] += size; + this->uniform_vector_size[src] = 0; + } + + new_uniform_count = MAX2(new_uniform_count, dst + 1); + } + + this->uniforms = new_uniform_count; + + /* Now, update the instructions for our repacked uniforms. */ + foreach_list(node, &this->instructions) { + vec4_instruction *inst = (vec4_instruction *)node; + + for (int i = 0 ; i < 3; i++) { + int src = inst->src[i].reg; + + if (inst->src[i].file != UNIFORM) + continue; + + inst->src[i].reg = new_loc[src]; + + int sx = BRW_GET_SWZ(inst->src[i].swizzle, 0) + new_chan[src]; + int sy = BRW_GET_SWZ(inst->src[i].swizzle, 1) + new_chan[src]; + int sz = BRW_GET_SWZ(inst->src[i].swizzle, 2) + new_chan[src]; + int sw = BRW_GET_SWZ(inst->src[i].swizzle, 3) + new_chan[src]; + inst->src[i].swizzle = BRW_SWIZZLE4(sx, sy, sz, sw); + } + } +} + } /* namespace brw */ |