mesa: glsl: various writemask/swizzle improvements and clean-ups

This commit is contained in:
Brian Paul 2008-07-18 19:46:19 -06:00
parent 7218626cf5
commit 72e57b52f0
5 changed files with 81 additions and 70 deletions

View file

@ -348,7 +348,7 @@ _mesa_add_varying(struct gl_program_parameter_list *paramList,
return i;
}
else {
assert(size == 4);
/*assert(size == 4);*/
i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name,
size, GL_NONE, NULL, NULL);
return i;

View file

@ -313,7 +313,7 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
const char *
_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
{
static const char swz[] = "xyzw01?!";
static const char swz[] = "xyzw01!?"; /* See SWIZZLE_x definitions */
static char s[20];
GLuint i = 0;

View file

@ -1409,6 +1409,27 @@ slang_find_asm_info(const char *name)
}
/**
* Return the default swizzle mask for accessing a variable of the
* given size (in floats). If size = 1, comp is used to identify
* which component [0..3] of the register holds the variable.
*/
static GLuint
_slang_var_swizzle(GLint size, GLint comp)
{
switch (size) {
case 1:
return MAKE_SWIZZLE4(comp, comp, comp, comp);
case 2:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
case 3:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
default:
return SWIZZLE_XYZW;
}
}
/**
* Some write-masked assignments are simple, but others are hard.
* Simple example:
@ -3063,6 +3084,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
int dbg = 0;
const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
if (texIndex != -1) {
/* This is a texture sampler variable...
@ -3076,8 +3098,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
}
else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
/* Uniform variable */
const GLint size = _slang_sizeof_type_specifier(&var->type.specifier)
* MAX2(var->array_len, 1);
const GLint totalSize = size * MAX2(var->array_len, 1);
const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
if (prog) {
/* user-defined uniform */
if (datatype == GL_NONE) {
@ -3106,8 +3128,10 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
}
else {
GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
size, datatype);
store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size);
totalSize, datatype);
store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
totalSize, swizzle);
printf("GLOBAL USER UNIFORM %s size %d\n", varName, totalSize);
}
}
else {
@ -3115,33 +3139,40 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
/* We know it's a uniform, but don't allocate storage unless
* it's really used.
*/
store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size);
store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
totalSize, swizzle);
}
if (dbg) printf("UNIFORM (sz %d) ", size);
if (dbg) printf("UNIFORM (sz %d) ", totalSize);
}
else if (var->type.qualifier == SLANG_QUAL_VARYING) {
const GLint size = 4; /* XXX fix */
if (prog) {
/* user-defined varying */
GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size);
store = _slang_new_ir_storage(PROGRAM_VARYING, varyingLoc, size);
GLuint swizzle = _slang_var_swizzle(size, 0);
store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
size, swizzle);
}
else {
/* pre-defined varying, like gl_Color or gl_TexCoord */
if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
/* fragment program input */
GLuint swizzle;
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
assert(index >= 0);
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
assert(index < FRAG_ATTRIB_MAX);
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
size, swizzle);
}
else {
/* vertex program output */
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
GLuint swizzle = _slang_var_swizzle(size, 0);
assert(index >= 0);
assert(type == SLANG_UNIT_VERTEX_BUILTIN);
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
assert(index < VERT_RESULT_MAX);
assert(type == SLANG_UNIT_VERTEX_BUILTIN);
store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
size, swizzle);
}
if (dbg) printf("V/F ");
}
@ -3150,7 +3181,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
if (prog) {
/* user-defined vertex attribute */
const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
const GLint attr = -1; /* unknown */
GLint index = _mesa_add_attribute(prog->Attributes, varName,
size, attr);
@ -3163,7 +3193,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLuint swizzle;
GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB,
&swizzle);
GLint size = 4; /* XXX? */
assert(index >= 0);
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
}
@ -3173,27 +3202,24 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
GLint size = 4; /* XXX? */
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
if (dbg) printf("INPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
if (type == SLANG_UNIT_VERTEX_BUILTIN) {
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
GLint size = 4; /* XXX? */
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
}
else {
GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
GLint size = 4; /* XXX? */
GLint specialSize = 4; /* treat all fragment outputs as float[4] */
assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
}
if (dbg) printf("OUTPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
/* pre-defined global constant, like gl_MaxLights */
const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
if (dbg) printf("CONST ");
}

View file

@ -171,21 +171,33 @@ free_temp_storage(slang_var_table *vt, slang_ir_node *n)
/**
* Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
* Ex: fix_swizzle("zyNN") -> "zyyy"
* XXX should put in the default component for the position...
* Remove any SWIZZLE_NIL terms from given swizzle mask.
* For a swizzle like .z??? generate .zzzz (replicate single component).
* Else, for .wx?? generate .wxzw (insert default component for the position).
*/
static GLuint
fix_swizzle(GLuint swizzle)
{
GLuint swz[4], i;
for (i = 0; i < 4; i++) {
swz[i] = GET_SWZ(swizzle, i);
if (swz[i] == SWIZZLE_NIL) {
swz[i] = swz[i - 1];
}
GLuint c0 = GET_SWZ(swizzle, 0),
c1 = GET_SWZ(swizzle, 1),
c2 = GET_SWZ(swizzle, 2),
c3 = GET_SWZ(swizzle, 3);
if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
/* smear first component across all positions */
c1 = c2 = c3 = c0;
}
return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
else {
/* insert default swizzle components */
if (c0 == SWIZZLE_NIL)
c0 = SWIZZLE_X;
if (c1 == SWIZZLE_NIL)
c1 = SWIZZLE_Y;
if (c2 == SWIZZLE_NIL)
c2 = SWIZZLE_Z;
if (c3 == SWIZZLE_NIL)
c3 = SWIZZLE_W;
}
return MAKE_SWIZZLE4(c0, c1, c2, c3);
}
@ -216,6 +228,7 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
assert(size >= 1);
assert(size <= 4);
if (size == 1) {
GLuint comp = GET_SWZ(swizzle, 0);
assert(comp < 4);
@ -233,13 +246,6 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
static void
storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
{
static const GLuint defaultSwizzle[4] = {
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
};
const GLint size = st->Size;
const GLboolean relAddr = st->RelAddr;
GLint index = st->Index;
GLuint swizzle = st->Swizzle;
@ -250,7 +256,6 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
index += st->Index;
swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
}
swizzle = fix_swizzle(swizzle);
assert(st->File >= 0);
assert(st->File < PROGRAM_UNDEFINED);
@ -259,20 +264,14 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
assert(index >= 0);
src->Index = index;
assert(size >= 1);
assert(size <= 4);
swizzle = fix_swizzle(swizzle);
assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
src->Swizzle = swizzle;
src->RelAddr = relAddr;
if (swizzle != SWIZZLE_NOOP)
src->Swizzle = swizzle;
else
src->Swizzle = defaultSwizzle[size - 1]; /*XXX really need this?*/
assert(GET_SWZ(src->Swizzle, 0) <= 3);
assert(GET_SWZ(src->Swizzle, 1) <= 3);
assert(GET_SWZ(src->Swizzle, 2) <= 3);
assert(GET_SWZ(src->Swizzle, 3) <= 3);
}
@ -582,8 +581,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
/* result storage */
if (!n->Store) {
GLint size = n->Children[0]->Store
? n->Children[0]->Store->Size : info->ResultSize;
GLint size = info->ResultSize;
if (!alloc_temp_storage(emitInfo, n, size))
return NULL;
#if 0000 /* this should work, but doesn't yet */
@ -591,6 +589,8 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
n->Writemask = WRITEMASK_XY;
else if (size == 3)
n->Writemask = WRITEMASK_XYZ;
else if (size == 1)
n->Writemask = WRITEMASK_X << GET_SWZ(n->Store->Swizzle,0);
#endif
}
@ -1045,10 +1045,9 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
assert(n->Children[0]->Store->Index >= 0);
/* use tighter writemask when possible */
#if 0000 /* XXX enable this after more testing... */
if (n->Writemask == WRITEMASK_XYZW)
n->Writemask = inst->DstReg.WriteMask;
#endif
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
return inst;
}

View file

@ -239,20 +239,6 @@ _slang_free_ir_tree(slang_ir_node *n)
static const char *
swizzle_string(GLuint swizzle)
{
static char s[6];
GLuint i;
s[0] = '.';
for (i = 1; i < 5; i++) {
s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
}
s[i] = 0;
return s;
}
static const char *
writemask_string(GLuint writemask)
{
@ -410,7 +396,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
case IR_VAR:
printf("VAR %s%s at %s store %p\n",
(n->Var ? (char *) n->Var->a_name : "TEMP"),
swizzle_string(n->Store->Swizzle),
_mesa_swizzle_string(n->Store->Swizzle, 0, 0),
storage_string(n->Store), (void*) n->Store);
break;
case IR_VAR_DECL:
@ -437,7 +423,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
break;
case IR_SWIZZLE:
printf("SWIZZLE %s of (store %p) \n",
swizzle_string(n->Store->Swizzle), (void*) n->Store);
_mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
_slang_print_ir_tree(n->Children[0], indent + 3);
break;
default: