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.
This commit is contained in:
Brian Paul 2008-07-18 14:44:01 -06:00
parent a4fd90e325
commit 7218626cf5
7 changed files with 372 additions and 142 deletions

View file

@ -35,6 +35,7 @@
#include "shader/prog_parameter.h"
#include "shader/prog_statevars.h"
#include "shader/slang/slang_ir.h"
#include "shader/slang/slang_emit.h"
#include "shader/slang/slang_builtin.h"
@ -438,8 +439,13 @@ _slang_alloc_statevar(slang_ir_node *n,
pos = lookup_statevar(var, index1, index2, field, &swizzle, paramList);
assert(pos >= 0);
if (pos >= 0) {
n0->Store->Index = pos;
n0->Store->Swizzle = swizzle;
/* XXX should overwrite Store's fields instead of changing pointers
* since there may be a child storage_info pointing to this one.
*/
n0->Store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR,
pos,
n0->Store->Size,
swizzle);
}
return pos;
}

View file

@ -43,6 +43,7 @@
#include "shader/program.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"
#include "shader/prog_print.h"
#include "shader/prog_statevars.h"
#include "slang_typeinfo.h"
#include "slang_codegen.h"
@ -243,7 +244,12 @@ _slang_attach_storage(slang_ir_node *n, slang_variable *var)
}
else {
/* alloc new storage info */
n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5);
n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -7, -5);
#if 0
printf("%s var=%s Store=%p Size=%d\n", __FUNCTION__,
(char*) var->a_name,
(void*) n->Store, n->Store->Size);
#endif
if (n->Var)
n->Var->aux = n->Store;
assert(n->Var->aux);
@ -658,6 +664,9 @@ new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name)
n = new_node0(IR_VAR);
if (n) {
_slang_attach_storage(n, var);
/*
printf("new_var %s store=%p\n", (char*)name, (void*) n->Store);
*/
}
return n;
}
@ -935,6 +944,18 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
* __asm vec4_lrp __retVal, a, y, x;
* }
*
*
* A call to
* r = mix(p1, p2, p3);
*
* Becomes:
*
* mov
* / \
* r vec4_lrp
* / | \
* p3 p2 p1
*
* We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
*/
static slang_operation *
@ -974,10 +995,10 @@ slang_inline_asm_function(slang_assemble_ctx *A,
slang_operation_copy(inlined, &fun->body->children[0]);
if (haveRetValue) {
/* get rid of the __retVal child */
for (i = 0; i < numArgs; i++) {
inlined->num_children--;
for (i = 0; i < inlined->num_children; i++) {
inlined->children[i] = inlined->children[i + 1];
}
inlined->num_children--;
}
/* now do formal->actual substitutions */
@ -1593,13 +1614,13 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
if (info->NumParams == oper->num_children) {
/* Storage for result is not specified.
* Children[0], [1] are the operands.
* Children[0], [1], [2] are the operands.
*/
firstOperand = 0;
}
else {
/* Storage for result (child[0]) is specified.
* Children[1], [2] are the operands.
* Children[1], [2], [3] are the operands.
*/
firstOperand = 1;
}
@ -1634,7 +1655,8 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
n->Store = get_store(n0);
n->Writemask = writemask;
assert(n->Store->File != PROGRAM_UNDEFINED);
assert(n->Store->File != PROGRAM_UNDEFINED ||
n->Store->Parent);
_slang_free(n0);
}
@ -2071,7 +2093,7 @@ _slang_gen_temporary(GLint size)
slang_ir_storage *store;
slang_ir_node *n = NULL;
store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
if (store) {
n = new_node0(IR_VAR_DECL);
if (n) {
@ -2092,17 +2114,15 @@ static slang_ir_node *
_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
{
slang_ir_node *n;
/*assert(!var->declared);*/
var->declared = GL_TRUE;
assert(!is_sampler_type(&var->type));
n = new_node0(IR_VAR_DECL);
if (n) {
_slang_attach_storage(n, var);
#if 0
printf("%s var %p %s store=%p\n",
__FUNCTION__, (void *) var, (char *) var->a_name,
(void *) n->Store);
#endif
assert(var->aux);
assert(n->Store == var->aux);
assert(n->Store);
@ -2110,6 +2130,13 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
n->Store->File = PROGRAM_TEMPORARY;
n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier);
#if 0
printf("%s var %p %s store=%p index=%d size=%d\n",
__FUNCTION__, (void *) var, (char *) var->a_name,
(void *) n->Store, n->Store->Index, n->Store->Size);
#endif
if (var->array_len > 0) {
/* this is an array */
/* round up element size to mult of 4 */
@ -2118,8 +2145,27 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
sz *= var->array_len;
n->Store->Size = sz;
}
A->program->NumTemporaries++;
assert(n->Store->Size > 0);
/* setup default swizzle for storing the variable */
switch (n->Store->Size) {
case 2:
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_NIL, SWIZZLE_NIL);
break;
case 3:
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_Z, SWIZZLE_NIL);
break;
default:
/* Note that float-sized vars may be allocated in any x/y/z/w
* slot, but that won't be determined until code emit time.
*/
n->Store->Swizzle = SWIZZLE_NOOP;
}
A->program->NumTemporaries++; /* an approximation */
}
return n;
}
@ -2400,11 +2446,11 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
static slang_ir_node *
_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
{
/* XXX should rewrite this to use relative/Parent storage */
slang_ir_node *n = new_node1(IR_SWIZZLE, child);
assert(child);
if (n) {
n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -1);
n->Store->Swizzle = swizzle;
n->Store = _slang_new_ir_storage_swz(PROGRAM_UNDEFINED, -1, -1, swizzle);
}
return n;
}
@ -2495,7 +2541,7 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
* Generate IR tree for referencing a field in a struct (or basic vector type)
*/
static slang_ir_node *
_slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
{
slang_typeinfo ti;
@ -2548,7 +2594,8 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
/* oper->a_id is the field name */
slang_ir_node *base, *n;
slang_typeinfo field_ti;
GLint fieldSize, fieldOffset = -1;
GLint fieldSize, fieldOffset = -1, swz;
/* type of field */
slang_typeinfo_construct(&field_ti);
_slang_typeof_operation(A, oper, &field_ti);
@ -2573,20 +2620,27 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
}
n = new_node1(IR_FIELD, base);
if (n) {
n->Field = (char *) oper->a_id;
n->FieldOffset = fieldOffset;
assert(n->FieldOffset >= 0);
n->Store = _slang_new_ir_storage(base->Store->File,
base->Store->Index,
fieldSize);
}
return n;
if (!n)
return NULL;
#if 0
_mesa_problem(NULL, "glsl structs/fields not supported yet");
return NULL;
#endif
/* setup the storage info for this node */
swz = fieldOffset % 4;
n->Field = (char *) oper->a_id;
n->Store = _slang_new_ir_storage_relative(fieldOffset / 4,
fieldSize,
base->Store);
if (fieldSize == 1)
n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
else if (fieldSize == 2)
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_NIL, SWIZZLE_NIL);
else if (fieldSize == 3)
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_Z, SWIZZLE_NIL);
return n;
}
}
@ -2595,7 +2649,7 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
* Gen code for array indexing.
*/
static slang_ir_node *
_slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper)
_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
{
slang_typeinfo array_ti;
@ -2659,21 +2713,24 @@ _slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper)
index = _slang_gen_operation(A, &oper->children[1]);
if (array && index) {
/* bounds check */
if (index->Opcode == IR_FLOAT &&
((int) index->Value[0] < 0 ||
(int) index->Value[0] >= arrayLen)) {
slang_info_log_error(A->log,
GLint constIndex = 0;
if (index->Opcode == IR_FLOAT) {
constIndex = (int) index->Value[0];
if (constIndex < 0 || constIndex >= arrayLen) {
slang_info_log_error(A->log,
"Array index out of bounds (index=%d size=%d)",
(int) index->Value[0], arrayLen);
_slang_free_ir_tree(array);
_slang_free_ir_tree(index);
return NULL;
constIndex, arrayLen);
_slang_free_ir_tree(array);
_slang_free_ir_tree(index);
return NULL;
}
}
elem = new_node2(IR_ELEMENT, array, index);
elem->Store = _slang_new_ir_storage(array->Store->File,
array->Store->Index,
elemSize);
elem->Store = _slang_new_ir_storage_relative(constIndex,
elemSize,
array->Store);
/* XXX try to do some array bounds checking here */
return elem;
}
@ -2912,9 +2969,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
case SLANG_OPER_IF:
return _slang_gen_if(A, oper);
case SLANG_OPER_FIELD:
return _slang_gen_field(A, oper);
return _slang_gen_struct_field(A, oper);
case SLANG_OPER_SUBSCRIPT:
return _slang_gen_subscript(A, oper);
return _slang_gen_array_element(A, oper);
case SLANG_OPER_LITERAL_FLOAT:
/* fall-through */
case SLANG_OPER_LITERAL_INT:
@ -3076,8 +3133,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
assert(index >= 0);
store = _slang_new_ir_storage(PROGRAM_INPUT, index, size);
store->Swizzle = swizzle;
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
assert(index < FRAG_ATTRIB_MAX);
}
else {
@ -3109,8 +3165,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
&swizzle);
GLint size = 4; /* XXX? */
assert(index >= 0);
store = _slang_new_ir_storage(PROGRAM_INPUT, index, size);
store->Swizzle = swizzle;
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
}
if (dbg) printf("ATTRIB ");
}
@ -3119,8 +3174,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
GLint size = 4; /* XXX? */
store = _slang_new_ir_storage(PROGRAM_INPUT, index, size);
store->Swizzle = swizzle;
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
if (dbg) printf("INPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {

View file

@ -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 */
}

View file

@ -40,10 +40,6 @@ extern GLuint
_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
extern slang_ir_storage *
_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
extern GLboolean
_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
struct gl_program *prog, GLboolean withEnd,

View file

@ -51,6 +51,8 @@ static const slang_ir_info IrInfo[] = {
{ IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
{ IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
{ IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
{ IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
/* unary ops */
{ IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
{ IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */
@ -109,6 +111,66 @@ _slang_ir_info(slang_ir_opcode opcode)
}
/**
* Return a new slang_ir_storage object.
*/
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;
st->Parent = NULL;
}
return st;
}
/**
* Return a new slang_ir_storage object.
*/
slang_ir_storage *
_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size,
GLuint swizzle)
{
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;
st->Parent = NULL;
}
return st;
}
/**
* Return a new slang_ir_storage object.
*/
slang_ir_storage *
_slang_new_ir_storage_relative(GLint index, GLint size,
slang_ir_storage *parent)
{
slang_ir_storage *st;
st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
if (st) {
st->File = PROGRAM_UNDEFINED;
st->Index = index;
st->Size = size;
st->Swizzle = SWIZZLE_NOOP;
st->Parent = parent;
}
return st;
}
static const char *
_slang_ir_name(slang_ir_opcode opcode)
{
@ -116,6 +178,7 @@ _slang_ir_name(slang_ir_opcode opcode)
}
#if 0 /* no longer needed with mempool */
/**
* Since many IR nodes might point to the same IR storage info, we need

View file

@ -147,6 +147,11 @@ struct _slang_ir_storage
GLuint Swizzle;
GLint RefCount; /**< Used during IR tree delete */
GLboolean RelAddr;
/** If Parent is non-null, Index is relative to parent.
* The other fields are ignored.
*/
struct _slang_ir_storage *Parent;
};
typedef struct _slang_ir_storage slang_ir_storage;
@ -165,7 +170,6 @@ typedef struct slang_ir_node_
/** special fields depending on Opcode: */
const char *Field; /**< If Opcode == IR_FIELD */
int FieldOffset; /**< If Opcode == IR_FIELD */
GLuint Writemask; /**< If Opcode == IR_MOVE */
GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
@ -193,6 +197,20 @@ extern const slang_ir_info *
_slang_ir_info(slang_ir_opcode opcode);
extern slang_ir_storage *
_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
extern slang_ir_storage *
_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size,
GLuint swizzle);
extern slang_ir_storage *
_slang_new_ir_storage_relative(GLint index, GLint size,
slang_ir_storage *parent);
extern void
_slang_free_ir_tree(slang_ir_node *n);

View file

@ -1,6 +1,7 @@
#include "main/imports.h"
#include "shader/prog_instruction.h"
#include "shader/program.h"
#include "shader/prog_print.h"
#include "slang_compile.h"
#include "slang_compile_variable.h"
#include "slang_mem.h"
@ -247,14 +248,25 @@ _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
if (store->Size == 1) {
const GLuint comp = i % 4;
store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n",
store->Size, store->Index, "xyzw"[comp], t->Level);
}
else if (store->Size == 2) {
store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_NIL, SWIZZLE_NIL);
}
else if (store->Size == 3) {
store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
SWIZZLE_Z, SWIZZLE_NIL);
}
else {
store->Swizzle = SWIZZLE_NOOP;
if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
store->Size, store->Index, t->Level);
}
if (dbg)
printf("Alloc var sz %d at %d.%s (level %d)\n",
store->Size, store->Index,
_mesa_swizzle_string(store->Swizzle, 0, 0),
t->Level);
return GL_TRUE;
}
@ -279,6 +291,7 @@ _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
store->Size, store->Index, "xyzw"[comp], t->Level);
}
else {
/* XXX improve swizzled for size=2/3, use for writemask... */
store->Swizzle = SWIZZLE_NOOP;
if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
store->Size, store->Index, t->Level);