mesa: be smarter about allocating vert/frag program constants

Try to re-use constants/literals more often to make best use of the
constant buffer space.

See bug 21354.
This commit is contained in:
Brian Paul 2009-05-06 08:45:55 -06:00
parent 71fb9d62ec
commit 9b678af796

View file

@ -563,6 +563,7 @@ struct var_cache
* we take up with our state tokens or constants. Note that
* this is _not_ the same as the number of param registers
* we eventually use */
GLuint swizzle; /**< swizzle to access this variable */
struct var_cache *next;
};
@ -581,6 +582,7 @@ var_cache_create (struct var_cache **va)
(**va).param_binding_begin = ~0;
(**va).param_binding_length = ~0;
(**va).alias_binding = NULL;
(**va).swizzle = SWIZZLE_XYZW;
(**va).next = NULL;
}
}
@ -872,15 +874,16 @@ parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
* This picks out a constant value from the parsed array. The constant vector is r
* returned in the *values array, which should be of length 4.
*
* \param values - The 4 component vector with the constant value in it
* \param values - return the vector constant values.
* \param size - returns the number elements in valuesOut [1..4]
*/
static GLvoid
parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
GLboolean use)
parse_constant(const GLubyte ** inst, GLfloat *values, GLint *size,
struct arb_program *Program,
GLboolean use)
{
GLuint components, i;
switch (*(*inst)++) {
case CONSTANT_SCALAR:
if (use == GL_TRUE) {
@ -893,7 +896,7 @@ parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Prog
values[1] =
values[2] = values[3] = parse_signed_float (inst, Program);
}
*size = 1;
break;
case CONSTANT_VECTOR:
values[0] = values[1] = values[2] = 0;
@ -902,7 +905,12 @@ parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Prog
for (i = 0; i < components; i++) {
values[i] = parse_signed_float (inst, Program);
}
*size = 4;
break;
default:
_mesa_problem(NULL, "unexpected case in parse_constant()");
values[0] = 0.0F;
*size = 0;
}
}
@ -1816,7 +1824,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
GLint idx;
GLuint err = 0;
gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
GLfloat const_values[4];
GLubyte token = *(*inst)++;
@ -1908,18 +1915,31 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
case PARAM_CONSTANT:
/* parsing something like {1.0, 2.0, 3.0, 4.0} */
parse_constant (inst, const_values, Program, use);
idx = _mesa_add_named_constant(Program->Base.Parameters,
(char *) param_var->name,
const_values, 4);
if (param_var->param_binding_begin == ~0U)
param_var->param_binding_begin = idx;
param_var->param_binding_type = PROGRAM_STATE_VAR;
/* Note: when we reference this parameter in an instruction later,
* we'll check if it's really a constant/immediate and set the
* instruction register type appropriately.
*/
param_var->param_binding_length++;
{
GLfloat const_values[4];
GLint size;
parse_constant(inst, const_values, &size, Program, use);
if (param_var->name[0] == ' ') {
/* this is an unnamed constant */
idx = _mesa_add_unnamed_constant(Program->Base.Parameters,
const_values, size,
&param_var->swizzle);
}
else {
/* named parameter/constant */
idx = _mesa_add_named_constant(Program->Base.Parameters,
(char *) param_var->name,
const_values, size);
}
if (param_var->param_binding_begin == ~0U)
param_var->param_binding_begin = idx;
param_var->param_binding_type = PROGRAM_STATE_VAR;
/* Note: when we reference this parameter in an instruction later,
* we'll check if it's really a constant/immediate and set the
* instruction register type appropriately.
*/
param_var->param_binding_length++;
}
break;
default:
@ -2428,6 +2448,9 @@ parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
return;
}
}
if (len == 1)
swizzle[1] = swizzle[2] = swizzle[3] = swizzle[0];
}
@ -2482,7 +2505,7 @@ static GLuint
parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
struct var_cache **vc_head,
struct arb_program *Program,
gl_register_file * File, GLint * Index,
gl_register_file * File, GLint * Index, GLuint *swizzle,
GLboolean *IsRelOffset )
{
struct var_cache *src;
@ -2491,6 +2514,8 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
*IsRelOffset = 0;
*swizzle = SWIZZLE_XYZW; /* default */
/* And the binding for the src */
switch (*(*inst)++) {
case REGISTER_ATTRIB:
@ -2546,6 +2571,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
}
*Index = src->param_binding_begin + offset;
*swizzle = src->swizzle;
break;
case ARRAY_INDEX_RELATIVE:
@ -2568,6 +2594,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
/* And store it properly */
*Index = src->param_binding_begin + rel_off;
*IsRelOffset = 1;
*swizzle = src->swizzle;
}
break;
}
@ -2579,6 +2606,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
*File = (gl_register_file) src->param_binding_type;
*Index = src->param_binding_begin;
*swizzle = src->swizzle;
break;
}
break;
@ -2647,6 +2675,21 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
}
static GLuint
swizzle_swizzle(GLuint baseSwizzle, const GLubyte swizzle[4])
{
GLuint i, swz, s[4];
for (i = 0; i < 4; i++) {
GLuint c = swizzle[i];
if (c <= SWIZZLE_W)
s[i] = GET_SWZ(baseSwizzle, c);
else
s[i] = c;
}
swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
return swz;
}
/**
* Parse vertex/fragment program vector source register.
*/
@ -2661,12 +2704,14 @@ parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
GLubyte negateMask;
GLubyte swizzle[4];
GLboolean isRelOffset;
GLuint baseSwizzle;
/* Grab the sign */
negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
/* And the src reg */
if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &baseSwizzle,
&isRelOffset))
return 1;
/* finally, the swizzle */
@ -2674,7 +2719,7 @@ parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
reg->File = file;
reg->Index = index;
reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
reg->Swizzle = swizzle_swizzle(baseSwizzle, swizzle);
reg->Negate = negateMask;
reg->RelAddr = isRelOffset;
return 0;
@ -2695,12 +2740,14 @@ parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
GLubyte negateMask;
GLubyte swizzle[4];
GLboolean isRelOffset;
GLuint baseSwizzle;
/* Grab the sign */
negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
/* And the src reg */
if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &baseSwizzle,
&isRelOffset))
return 1;
/* finally, the swizzle */
@ -2708,7 +2755,7 @@ parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
reg->File = file;
reg->Index = index;
reg->Swizzle = (swizzle[0] << 0);
reg->Swizzle = swizzle_swizzle(baseSwizzle, swizzle);
reg->Negate = negateMask;
reg->RelAddr = isRelOffset;
return 0;
@ -3019,8 +3066,10 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
GLubyte negateMask;
gl_register_file file;
GLint index;
GLuint baseSwizzle;
if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index,
&baseSwizzle, &rel))
return 1;
parse_extended_swizzle_mask(inst, swizzle, &negateMask);
fp->SrcReg[0].File = file;
@ -3360,11 +3409,13 @@ parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
GLboolean relAddr;
gl_register_file file;
GLint index;
GLuint baseSwizzle;
if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
return 1;
if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index,
&baseSwizzle, &relAddr))
return 1;
parse_extended_swizzle_mask (inst, swizzle, &negateMask);
vp->SrcReg[0].File = file;