summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang/slang_emit.c
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-07-29 17:15:08 -0600
committerBrian Paul <[email protected]>2008-07-29 17:15:08 -0600
commit38a62ede6c68f292615ff8eaac749e12652dbdb9 (patch)
tree58fdb14a2544525d5ba415329af3e56e0b7662e3 /src/mesa/shader/slang/slang_emit.c
parent378017417a7a0b7b8e25b6e859e9dcb92ef24ea9 (diff)
mesa: rework array/struct addressing code.
The slang_ir_storage type now has a pointer to parent storage to represent storage of an array element within an array, or a field within a struct. This fixes some problems related to addressing of fields/elements in non- trivial cases. More work to follow.
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r--src/mesa/shader/slang/slang_emit.c240
1 files changed, 160 insertions, 80 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index c997c11a7de..ec8ed0b4e88 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -126,21 +126,6 @@ _slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
}
-slang_ir_storage *
-_slang_new_ir_storage(enum register_file file, GLint index, GLint size)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = SWIZZLE_NOOP;
- }
- return st;
-}
-
-
/**
* Allocate temporary storage for an intermediate result (such as for
* a multiply or add, etc.
@@ -184,6 +169,27 @@ 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...
+ */
+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];
+ }
+ }
+ return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+}
+
+
+
/**
* Convert IR storage to an instruction dst register.
*/
@@ -191,14 +197,27 @@ static void
storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
GLuint writemask)
{
- assert(st->Index >= 0);
- dst->File = st->File;
- dst->Index = st->Index;
+ const GLint size = st->Size;
+ GLint index = st->Index;
+ GLuint swizzle = st->Swizzle;
+
+ /* if this is storage relative to some parent storage, walk up the tree */
+ while (st->Parent) {
+ st = st->Parent;
+ index += st->Index;
+ swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+ }
+
assert(st->File != PROGRAM_UNDEFINED);
- assert(st->Size >= 1);
- assert(st->Size <= 4);
- if (st->Size == 1) {
- GLuint comp = GET_SWZ(st->Swizzle, 0);
+ dst->File = st->File;
+
+ assert(index >= 0);
+ dst->Index = index;
+
+ assert(size >= 1);
+ assert(size <= 4);
+ if (size == 1) {
+ GLuint comp = GET_SWZ(swizzle, 0);
assert(comp < 4);
dst->WriteMask = WRITEMASK_X << comp;
}
@@ -220,17 +239,35 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
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;
+
+ /* if this is storage relative to some parent storage, walk up the tree */
+ while (st->Parent) {
+ st = st->Parent;
+ index += st->Index;
+ swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+ }
+ swizzle = fix_swizzle(swizzle);
+
assert(st->File >= 0);
assert(st->File < PROGRAM_UNDEFINED);
- assert(st->Size >= 1);
- assert(st->Size <= 4);
src->File = st->File;
- src->Index = st->Index;
- src->RelAddr = st->RelAddr;
- if (st->Swizzle != SWIZZLE_NOOP)
- src->Swizzle = st->Swizzle;
+
+ assert(index >= 0);
+ src->Index = index;
+
+ assert(size >= 1);
+ assert(size <= 4);
+
+ src->RelAddr = relAddr;
+
+ if (swizzle != SWIZZLE_NOOP)
+ src->Swizzle = swizzle;
else
- src->Swizzle = defaultSwizzle[st->Size - 1]; /*XXX really need this?*/
+ src->Swizzle = defaultSwizzle[size - 1]; /*XXX really need this?*/
assert(GET_SWZ(src->Swizzle, 0) <= 3);
assert(GET_SWZ(src->Swizzle, 1) <= 3);
@@ -549,6 +586,12 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
? n->Children[0]->Store->Size : info->ResultSize;
if (!alloc_temp_storage(emitInfo, n, size))
return NULL;
+#if 0000 /* this should work, but doesn't yet */
+ if (size == 2)
+ n->Writemask = WRITEMASK_XY;
+ else if (size == 3)
+ n->Writemask = WRITEMASK_XYZ;
+#endif
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -957,6 +1000,8 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
{
struct prog_instruction *inst;
+ assert(n->Opcode == IR_MOVE);
+
/* lhs */
emit(emitInfo, n->Children[0]);
if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
@@ -995,8 +1040,15 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
if (n->Children[1]->Opcode != IR_SWIZZLE)
_slang_free_temp(emitInfo->vt, n->Children[1]->Store);
*n->Children[1]->Store = *n->Children[0]->Store;
+
/* fixup the previous instruction (which stored the RHS result) */
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;
}
@@ -1408,25 +1460,6 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
}
-
-/**
- * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
- * Ex: fix_swizzle("zyNN") -> "zyyy"
- */
-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];
- }
- }
- return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
-}
-
-
/**
* Return the number of components actually named by the swizzle.
* Recall that swizzles may have undefined/don't-care values.
@@ -1451,15 +1484,6 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
inst = emit(emitInfo, n->Children[0]);
-#ifdef DEBUG
- {
- GLuint s = n->Children[0]->Store->Swizzle;
- assert(GET_SWZ(s, 0) != SWIZZLE_NIL);
- assert(GET_SWZ(s, 1) != SWIZZLE_NIL);
- assert(GET_SWZ(s, 2) != SWIZZLE_NIL);
- assert(GET_SWZ(s, 3) != SWIZZLE_NIL);
- }
-#endif
/* For debug: n->Var = n->Children[0]->Var; */
/* "pull-up" the child's storage info, applying our swizzle info */
@@ -1475,6 +1499,16 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
/* apply this swizzle to child's swizzle to get composed swizzle */
swizzle = fix_swizzle(n->Store->Swizzle); /* remove the don't care terms */
+
+#ifdef DEBUG
+ {
+ assert(GET_SWZ(swizzle, 0) != SWIZZLE_NIL);
+ assert(GET_SWZ(swizzle, 1) != SWIZZLE_NIL);
+ assert(GET_SWZ(swizzle, 2) != SWIZZLE_NIL);
+ assert(GET_SWZ(swizzle, 3) != SWIZZLE_NIL);
+ }
+#endif
+
n->Store->Swizzle = _slang_swizzle_swizzle(n->Children[0]->Store->Swizzle,
swizzle);
@@ -1489,33 +1523,77 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
static struct prog_instruction *
emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
{
+ slang_ir_storage *root;
+
+ assert(n->Opcode == IR_ELEMENT);
assert(n->Store);
- assert(n->Store->File != PROGRAM_UNDEFINED);
+ assert(n->Store->File == PROGRAM_UNDEFINED);
+ assert(n->Store->Parent);
assert(n->Store->Size > 0);
- if (n->Store->File == PROGRAM_STATE_VAR) {
- n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);
+ root = n->Store;
+ while (root->Parent)
+ root = root->Parent;
+
+ if (root->File == PROGRAM_STATE_VAR) {
+ GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);
+ assert(n->Store->Index == index);
return NULL;
}
if (n->Children[1]->Opcode == IR_FLOAT) {
- /* Constant index */
+ /* Constant array index */
+#if 0 /* just debug code */
const GLint arrayAddr = n->Children[0]->Store->Index;
const GLint index = (GLint) n->Children[1]->Value[0];
- n->Store->Index = arrayAddr + index;
+ assert(index == n->Store->Index);
+ assert(arrayAddr == parent->Index);
+ assert(n->Children[0]->Store == parent);
+ assert(n->Children[0]->Store->Index == parent->Index);
+#endif
+
+ GLint index = n->Store->Index;
+
+ slang_ir_storage *p = n->Store;
+ index = 0;
+ while (p->Parent) {
+ int sz = (p->Size + 3) / 4;
+ /*printf("element [%d] of size %d (%d)\n", p->Index, p->Size, sz);*/
+ index += sz * p->Index;
+ p = p->Parent;
+ }
+ index += p->Index;
+
+ assert(root->File != PROGRAM_UNDEFINED);
+
+ /* resolve new absolute storage location */
+ assert(n->Store);
+ n->Store->File = root->File;
+ n->Store->Index = index;
+ n->Store->Parent = NULL;
}
else {
- /* Variable index*/
+ /* Variable array index */
struct prog_instruction *inst;
+
+ /* do codegen for array */
+ emit(emitInfo, n->Children[0]);
+
+ /* do codegen for array index expression */
+ emit(emitInfo, n->Children[1]);
+
inst = new_instruction(emitInfo, OPCODE_ARL);
+
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store);
+
inst->DstReg.File = PROGRAM_ADDRESS;
+ inst->DstReg.Index = 0; /* always address register [0] */
inst->Comment = _mesa_strdup("ARL ADDR");
+
n->Store->RelAddr = GL_TRUE;
- n->Store->Index = inst->DstReg.Index;/*index of the array*/
- inst->DstReg.Index = 0; /*addr index is always 0*/
}
+
return NULL; /* no instruction */
}
@@ -1526,25 +1604,27 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
static struct prog_instruction *
emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
{
- if (n->Store->File == PROGRAM_STATE_VAR) {
- n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);
- if (n->Store->Index < 0) {
+ slang_ir_storage *root = n->Store;
+
+ assert(n->Opcode == IR_FIELD);
+
+ while (root->Parent)
+ root = root->Parent;
+
+ /* If this is the field of a state var, allocate constant/uniform
+ * storage for it now if we haven't already.
+ * Note that we allocate storage (uniform/constant slots) for state
+ * variables here rather than at declaration time so we only allocate
+ * space for the ones that we actually use!
+ */
+ if (root->File == PROGRAM_STATE_VAR) {
+ root->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);
+ if (root->Index < 0) {
slang_info_log_error(emitInfo->log, "Error parsing state variable");
return NULL;
}
}
- else {
- GLint offset = n->FieldOffset / 4;
- assert(n->Children[0]->Store->Index >= 0);
- n->Store->Index = n->Children[0]->Store->Index + offset;
- if (n->Store->Size == 1) {
- GLint swz = n->FieldOffset % 4;
- n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
- }
- else {
- n->Store->Swizzle = SWIZZLE_XYZW;
- }
- }
+
return NULL; /* no instruction */
}