ir_to_mesa: Move the STATE_VAR elements of a builtin uniform to a temp (v2).

Like the constant handling and the handling of other uniforms, we add
the whole thing to the Parameters, avoiding messy, incomplete logic
for adding just the elements of a builting uniform that get used.
This means that a driver that relies only on ParameterValues[] for its
parameters will have an increased parameter load, but drivers
generally don't do that (since they have other params they need to
handle, too).

Fixes glsl-fs-statevar-call (testcase for Ember).  Bug #29687.

v2: Continue referencing the STATE_VAR[] file directly when the
uniform will land in STATE_VAR[] formatted exactly as we'd put into a
temporary.  When there's array dereferencing, we don't copy-propagate
in Mesa IR (not knowing where the array is in register space), so
smarts here are required or we'll massively increase the temp count.
This commit is contained in:
Eric Anholt 2010-09-01 16:06:32 -07:00
parent 956f049fd2
commit 6c0ba32fd1
1 changed files with 326 additions and 345 deletions

View File

@ -577,6 +577,239 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
return NULL;
}
struct statevar_element {
const char *field;
int tokens[STATE_LENGTH];
int swizzle;
bool array_indexed;
};
static struct statevar_element gl_DepthRange_elements[] = {
{"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
{"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
{"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
};
static struct statevar_element gl_ClipPlane_elements[] = {
{NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
};
static struct statevar_element gl_Point_elements[] = {
{"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
{"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
{"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
{"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
{"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
{"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
{"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
};
static struct statevar_element gl_FrontMaterial_elements[] = {
{"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
{"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
{"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
};
static struct statevar_element gl_BackMaterial_elements[] = {
{"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
{"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
{"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
};
static struct statevar_element gl_LightSource_elements[] = {
{"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
{"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
{"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
{"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW},
{"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
{"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
{"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
{"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
{"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
{"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
};
static struct statevar_element gl_LightModel_elements[] = {
{"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
};
static struct statevar_element gl_FrontLightModelProduct_elements[] = {
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
};
static struct statevar_element gl_BackLightModelProduct_elements[] = {
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
};
static struct statevar_element gl_FrontLightProduct_elements[] = {
{"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
};
static struct statevar_element gl_BackLightProduct_elements[] = {
{"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
};
static struct statevar_element gl_TextureEnvColor_elements[] = {
{NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
};
static struct statevar_element gl_EyePlaneS_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
};
static struct statevar_element gl_EyePlaneT_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
};
static struct statevar_element gl_EyePlaneR_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
};
static struct statevar_element gl_EyePlaneQ_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
};
static struct statevar_element gl_ObjectPlaneS_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
};
static struct statevar_element gl_ObjectPlaneT_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
};
static struct statevar_element gl_ObjectPlaneR_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
};
static struct statevar_element gl_ObjectPlaneQ_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
};
static struct statevar_element gl_Fog_elements[] = {
{"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
{"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
{"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
{"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
{"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
};
#define MATRIX(name, statevar, modifier) \
static struct statevar_element name ## _elements[] = { \
{ NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
{ NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
{ NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
{ NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \
}
MATRIX(gl_ModelViewMatrix,
STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
MATRIX(gl_ModelViewMatrixInverse,
STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
MATRIX(gl_ModelViewMatrixTranspose,
STATE_MODELVIEW_MATRIX, 0);
MATRIX(gl_ModelViewMatrixInverseTranspose,
STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
MATRIX(gl_ProjectionMatrix,
STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
MATRIX(gl_ProjectionMatrixInverse,
STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
MATRIX(gl_ProjectionMatrixTranspose,
STATE_PROJECTION_MATRIX, 0);
MATRIX(gl_ProjectionMatrixInverseTranspose,
STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
MATRIX(gl_ModelViewProjectionMatrix,
STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
MATRIX(gl_ModelViewProjectionMatrixInverse,
STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
MATRIX(gl_ModelViewProjectionMatrixTranspose,
STATE_MVP_MATRIX, 0);
MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
MATRIX(gl_TextureMatrix,
STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
MATRIX(gl_TextureMatrixInverse,
STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
MATRIX(gl_TextureMatrixTranspose,
STATE_TEXTURE_MATRIX, 0);
MATRIX(gl_TextureMatrixInverseTranspose,
STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
static struct statevar_element gl_NormalMatrix_elements[] = {
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
SWIZZLE_XYZW },
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
SWIZZLE_XYZW },
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
SWIZZLE_XYZW },
};
#undef MATRIX
#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
static const struct statevar {
const char *name;
struct statevar_element *elements;
unsigned int num_elements;
} statevars[] = {
STATEVAR(gl_DepthRange),
STATEVAR(gl_ClipPlane),
STATEVAR(gl_Point),
STATEVAR(gl_FrontMaterial),
STATEVAR(gl_BackMaterial),
STATEVAR(gl_LightSource),
STATEVAR(gl_LightModel),
STATEVAR(gl_FrontLightModelProduct),
STATEVAR(gl_BackLightModelProduct),
STATEVAR(gl_FrontLightProduct),
STATEVAR(gl_BackLightProduct),
STATEVAR(gl_TextureEnvColor),
STATEVAR(gl_EyePlaneS),
STATEVAR(gl_EyePlaneT),
STATEVAR(gl_EyePlaneR),
STATEVAR(gl_EyePlaneQ),
STATEVAR(gl_ObjectPlaneS),
STATEVAR(gl_ObjectPlaneT),
STATEVAR(gl_ObjectPlaneR),
STATEVAR(gl_ObjectPlaneQ),
STATEVAR(gl_Fog),
STATEVAR(gl_ModelViewMatrix),
STATEVAR(gl_ModelViewMatrixInverse),
STATEVAR(gl_ModelViewMatrixTranspose),
STATEVAR(gl_ModelViewMatrixInverseTranspose),
STATEVAR(gl_ProjectionMatrix),
STATEVAR(gl_ProjectionMatrixInverse),
STATEVAR(gl_ProjectionMatrixTranspose),
STATEVAR(gl_ProjectionMatrixInverseTranspose),
STATEVAR(gl_ModelViewProjectionMatrix),
STATEVAR(gl_ModelViewProjectionMatrixInverse),
STATEVAR(gl_ModelViewProjectionMatrixTranspose),
STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
STATEVAR(gl_TextureMatrix),
STATEVAR(gl_TextureMatrixInverse),
STATEVAR(gl_TextureMatrixTranspose),
STATEVAR(gl_TextureMatrixInverseTranspose),
STATEVAR(gl_NormalMatrix),
};
void
ir_to_mesa_visitor::visit(ir_variable *ir)
{
@ -586,6 +819,99 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
fp->OriginUpperLeft = ir->origin_upper_left;
fp->PixelCenterInteger = ir->pixel_center_integer;
}
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
unsigned int i;
for (i = 0; i < Elements(statevars); i++) {
if (strcmp(ir->name, statevars[i].name) == 0)
break;
}
if (i == Elements(statevars)) {
fail_link(this->shader_program,
"Failed to find builtin uniform `%s'\n", ir->name);
return;
}
const struct statevar *statevar = &statevars[i];
int array_count;
if (ir->type->is_array()) {
array_count = ir->type->length;
} else {
array_count = 1;
}
/* Check if this statevar's setup in the STATE file exactly
* matches how we'll want to reference it as a
* struct/array/whatever. If not, then we need to move it into
* temporary storage and hope that it'll get copy-propagated
* out.
*/
for (i = 0; i < statevar->num_elements; i++) {
if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
break;
}
}
struct variable_storage *storage;
ir_to_mesa_dst_reg dst;
if (i == statevar->num_elements) {
/* We'll set the index later. */
storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
this->variables.push_tail(storage);
dst = ir_to_mesa_undef_dst;
} else {
storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
this->next_temp);
this->variables.push_tail(storage);
this->next_temp += type_size(ir->type);
dst = ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
storage->index,
NULL));
}
for (int a = 0; a < array_count; a++) {
for (unsigned int i = 0; i < statevar->num_elements; i++) {
struct statevar_element *element = &statevar->elements[i];
int tokens[STATE_LENGTH];
memcpy(tokens, element->tokens, sizeof(element->tokens));
if (ir->type->is_array()) {
tokens[1] = a;
}
int index = _mesa_add_state_reference(this->prog->Parameters,
(gl_state_index *)tokens);
if (storage->file == PROGRAM_STATE_VAR) {
if (storage->index == -1) {
storage->index = index;
} else {
assert(index == (storage->index +
a * statevar->num_elements + i));
}
} else {
ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
src.swizzle = element->swizzle;
ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
/* even a float takes up a whole vec4 reg in a struct/array. */
dst.index++;
}
}
}
if (storage->file == PROGRAM_TEMPORARY &&
dst.index != storage->index + type_size(ir->type)) {
fail_link(this->shader_program,
"failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
ir->name, dst.index - storage->index,
type_size(ir->type));
}
}
}
void
@ -1057,289 +1383,6 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
this->result = src_reg;
}
static const struct {
const char *name;
const char *field;
int tokens[STATE_LENGTH];
int swizzle;
bool array_indexed;
} statevars[] = {
{"gl_DepthRange", "near",
{STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX, false},
{"gl_DepthRange", "far",
{STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY, false},
{"gl_DepthRange", "diff",
{STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ, false},
{"gl_ClipPlane", NULL,
{STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true}
,
{"gl_Point", "size",
{STATE_POINT_SIZE}, SWIZZLE_XXXX, false},
{"gl_Point", "sizeMin",
{STATE_POINT_SIZE}, SWIZZLE_YYYY, false},
{"gl_Point", "sizeMax",
{STATE_POINT_SIZE}, SWIZZLE_ZZZZ, false},
{"gl_Point", "fadeThresholdSize",
{STATE_POINT_SIZE}, SWIZZLE_WWWW, false},
{"gl_Point", "distanceConstantAttenuation",
{STATE_POINT_ATTENUATION}, SWIZZLE_XXXX, false},
{"gl_Point", "distanceLinearAttenuation",
{STATE_POINT_ATTENUATION}, SWIZZLE_YYYY, false},
{"gl_Point", "distanceQuadraticAttenuation",
{STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ, false},
{"gl_FrontMaterial", "emission",
{STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW, false},
{"gl_FrontMaterial", "ambient",
{STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW, false},
{"gl_FrontMaterial", "diffuse",
{STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, false},
{"gl_FrontMaterial", "specular",
{STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW, false},
{"gl_FrontMaterial", "shininess",
{STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX, false},
{"gl_BackMaterial", "emission",
{STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW, false},
{"gl_BackMaterial", "ambient",
{STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW, false},
{"gl_BackMaterial", "diffuse",
{STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, false},
{"gl_BackMaterial", "specular",
{STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW, false},
{"gl_BackMaterial", "shininess",
{STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX, false},
{"gl_LightSource", "ambient",
{STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
{"gl_LightSource", "diffuse",
{STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
{"gl_LightSource", "specular",
{STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
{"gl_LightSource", "position",
{STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW, true},
{"gl_LightSource", "halfVector",
{STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW, true},
{"gl_LightSource", "spotDirection",
{STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW, true},
{"gl_LightSource", "spotCosCutoff",
{STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW, true},
{"gl_LightSource", "spotCutoff",
{STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX, true},
{"gl_LightSource", "spotExponent",
{STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW, true},
{"gl_LightSource", "constantAttenuation",
{STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX, true},
{"gl_LightSource", "linearAttenuation",
{STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY, true},
{"gl_LightSource", "quadraticAttenuation",
{STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true},
{"gl_LightModel", "ambient",
{STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false},
{"gl_FrontLightModelProduct", "sceneColor",
{STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW, false},
{"gl_BackLightModelProduct", "sceneColor",
{STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW, false},
{"gl_FrontLightProduct", "ambient",
{STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
{"gl_FrontLightProduct", "diffuse",
{STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
{"gl_FrontLightProduct", "specular",
{STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
{"gl_BackLightProduct", "ambient",
{STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW, true},
{"gl_BackLightProduct", "diffuse",
{STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
{"gl_BackLightProduct", "specular",
{STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true},
{"gl_TextureEnvColor", NULL,
{STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true},
{"gl_EyePlaneS", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW, true},
{"gl_EyePlaneT", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW, true},
{"gl_EyePlaneR", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW, true},
{"gl_EyePlaneQ", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW, true},
{"gl_ObjectPlaneS", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW, true},
{"gl_ObjectPlaneT", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW, true},
{"gl_ObjectPlaneR", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW, true},
{"gl_ObjectPlaneQ", NULL,
{STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true},
{"gl_Fog", "color",
{STATE_FOG_COLOR}, SWIZZLE_XYZW, false},
{"gl_Fog", "density",
{STATE_FOG_PARAMS}, SWIZZLE_XXXX, false},
{"gl_Fog", "start",
{STATE_FOG_PARAMS}, SWIZZLE_YYYY, false},
{"gl_Fog", "end",
{STATE_FOG_PARAMS}, SWIZZLE_ZZZZ, false},
{"gl_Fog", "scale",
{STATE_FOG_PARAMS}, SWIZZLE_WWWW, false},
};
static ir_to_mesa_src_reg
get_builtin_uniform_reg(struct gl_program *prog,
const char *name, int array_index, const char *field)
{
unsigned int i;
ir_to_mesa_src_reg src_reg;
int tokens[STATE_LENGTH];
for (i = 0; i < Elements(statevars); i++) {
if (strcmp(statevars[i].name, name) != 0)
continue;
if (!field && statevars[i].field) {
assert(!"FINISHME: whole-structure state var dereference");
}
if (field && (!statevars[i].field || strcmp(statevars[i].field, field) != 0))
continue;
break;
}
if (i == Elements(statevars)) {
printf("builtin uniform %s%s%s not found\n",
name,
field ? "." : "",
field ? field : "");
abort();
}
memcpy(&tokens, statevars[i].tokens, sizeof(tokens));
if (statevars[i].array_indexed)
tokens[1] = array_index;
src_reg.file = PROGRAM_STATE_VAR;
src_reg.index = _mesa_add_state_reference(prog->Parameters,
(gl_state_index *)tokens);
src_reg.swizzle = statevars[i].swizzle;
src_reg.negate = 0;
src_reg.reladdr = false;
return src_reg;
}
static int
add_matrix_ref(struct gl_program *prog, int *tokens)
{
int base_pos = -1;
int i;
/* Add a ref for each column. It looks like the reason we do
* it this way is that _mesa_add_state_reference doesn't work
* for things that aren't vec4s, so the tokens[2]/tokens[3]
* range has to be equal.
*/
for (i = 0; i < 4; i++) {
tokens[2] = i;
tokens[3] = i;
int pos = _mesa_add_state_reference(prog->Parameters,
(gl_state_index *)tokens);
if (base_pos == -1)
base_pos = pos;
else
assert(base_pos + i == pos);
}
return base_pos;
}
static variable_storage *
get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
ir_rvalue *array_index)
{
/*
* NOTE: The ARB_vertex_program extension specified that matrices get
* loaded in registers in row-major order. With GLSL, we want column-
* major order. So, we need to transpose all matrices here...
*/
static const struct {
const char *name;
int matrix;
int modifier;
} matrices[] = {
{ "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
{ "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
{ "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
{ "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
{ "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
{ "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
{ "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
{ "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
{ "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
{ "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
{ "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
{ "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
{ "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
{ "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
{ "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
{ "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
{ "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
};
unsigned int i;
variable_storage *entry;
/* C++ gets angry when we try to use an int as a gl_state_index, so we use
* ints for gl_state_index. Make sure they're compatible.
*/
assert(sizeof(gl_state_index) == sizeof(int));
for (i = 0; i < Elements(matrices); i++) {
if (strcmp(var->name, matrices[i].name) == 0) {
int tokens[STATE_LENGTH];
int base_pos = -1;
tokens[0] = matrices[i].matrix;
tokens[4] = matrices[i].modifier;
if (matrices[i].matrix == STATE_TEXTURE_MATRIX) {
ir_constant *index = array_index->constant_expression_value();
if (index) {
tokens[1] = index->value.i[0];
base_pos = add_matrix_ref(prog, tokens);
} else {
for (i = 0; i < var->type->length; i++) {
tokens[1] = i;
int pos = add_matrix_ref(prog, tokens);
if (base_pos == -1)
base_pos = pos;
else
assert(base_pos + (int)i * 4 == pos);
}
}
} else {
tokens[1] = 0; /* unused array index */
base_pos = add_matrix_ref(prog, tokens);
}
entry = new(mem_ctx) variable_storage(var,
PROGRAM_STATE_VAR,
base_pos);
return entry;
}
}
return NULL;
}
void
ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
{
@ -1348,11 +1391,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
if (!entry) {
switch (ir->var->mode) {
case ir_var_uniform:
entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var,
NULL);
if (entry)
break;
entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
ir->var->location);
this->variables.push_tail(entry);
@ -1411,58 +1449,12 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
void
ir_to_mesa_visitor::visit(ir_dereference_array *ir)
{
ir_variable *var = ir->variable_referenced();
ir_constant *index;
ir_to_mesa_src_reg src_reg;
ir_dereference_variable *deref_var = ir->array->as_dereference_variable();
int element_size = type_size(ir->type);
index = ir->array_index->constant_expression_value();
if (deref_var && strncmp(deref_var->var->name,
"gl_TextureMatrix",
strlen("gl_TextureMatrix")) == 0) {
variable_storage *entry;
entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var,
ir->array_index);
assert(entry);
ir_to_mesa_src_reg src_reg(entry->file, entry->index, ir->type);
if (index) {
src_reg.reladdr = NULL;
} else {
ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type);
ir->array_index->accept(this);
ir_to_mesa_emit_op2(ir, OPCODE_MUL,
ir_to_mesa_dst_reg_from_src(index_reg),
this->result, src_reg_for_float(element_size));
src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
}
this->result = src_reg;
return;
}
if (var &&
strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform &&
!var->type->is_matrix()) {
ir_dereference_record *record = NULL;
if (ir->array->ir_type == ir_type_dereference_record)
record = (ir_dereference_record *)ir->array;
assert(index || !"FINISHME: variable-indexed builtin uniform access");
this->result = get_builtin_uniform_reg(prog,
var->name,
index->value.i[0],
record ? record->field : NULL);
}
ir->array->accept(this);
src_reg = this->result;
@ -1507,17 +1499,6 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir)
unsigned int i;
const glsl_type *struct_type = ir->record->type;
int offset = 0;
ir_variable *var = ir->record->variable_referenced();
if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform) {
assert(var);
this->result = get_builtin_uniform_reg(prog,
var->name,
0,
ir->field);
return;
}
ir->record->accept(this);