{ IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
{ IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
{ IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+ { IR_NEG, "IR_NEG", 0/*spec case*/, 4, 1 },
{ IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
{ IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
/* other */
{ IR_LABEL, "IR_LABEL", 0, 0, 0 },
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
{ IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+ { IR_COND, "IR_COND", 0, 0, 0 },
{ IR_CALL, "IR_CALL", 0, 0, 0 },
{ IR_MOVE, "IR_MOVE", 0, 0, 1 },
{ IR_NOT, "IR_NOT", 0, 1, 1 },
{ IR_VAR, "IR_VAR", 0, 0, 0 },
{ IR_VAR_DECL, "IR_VAR_DECL", 0, 0, 0 },
+ { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
+ { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 2 },
{ IR_FLOAT, "IR_FLOAT", 0, 0, 0 },
{ IR_FIELD, "IR_FIELD", 0, 0, 0 },
{ IR_NOP, NULL, OPCODE_NOP, 0, 0 }
"UNIFORM",
"WRITE_ONLY",
"ADDRESS",
+ "SAMPLER",
"UNDEFINED"
};
static char s[100];
sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
st->Index + st->Size - 1);
#endif
- sprintf(s, "%s", files[st->File]);
+ assert(st->File < sizeof(files) / sizeof(files[0]));
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
return s;
}
case slang_spec_samplerCube:
case slang_spec_sampler1DShadow:
case slang_spec_sampler2DShadow:
- abort();
- return 0;
+ return 1; /* special case */
case slang_spec_struct:
return sizeof_struct(spec->_struct);
case slang_spec_array:
}
-
static GLuint
sizeof_type(const slang_fully_specified_type *t)
{
}
+static GLboolean
+is_sampler_type(const slang_fully_specified_type *t)
+{
+ switch (t->specifier.type) {
+ case slang_spec_sampler1D:
+ case slang_spec_sampler2D:
+ case slang_spec_sampler3D:
+ case slang_spec_samplerCube:
+ case slang_spec_sampler1DShadow:
+ case slang_spec_sampler2DShadow:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
#define IND 0
void
slang_print_ir(const slang_ir_node *n, int indent)
case IR_LABEL:
printf("LABEL: %s\n", n->Target);
break;
+ case IR_COND:
+ printf("COND\n");
+ slang_print_ir(n->Children[0], indent + 3);
+ break;
case IR_JUMP:
printf("JUMP %s\n", n->Target);
break;
}
+static GLint
+alloc_sampler(slang_gen_context *gc)
+{
+ GLint sampler = gc->NumSamplers;
+ gc->NumSamplers++;
+ return sampler;
+}
+
+
static GLboolean
is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
{
}
-
-static GLint
-slang_find_input(GLenum target, const char *name, GLint index)
-{
- struct input_info {
- const char *Name;
- GLuint Attrib;
- };
- static const struct input_info vertInputs[] = {
- { "gl_Vertex", VERT_ATTRIB_POS },
- { "gl_Normal", VERT_ATTRIB_NORMAL },
- { "gl_Color", VERT_ATTRIB_COLOR0 },
- { "gl_SecondaryColor", VERT_ATTRIB_COLOR1 },
- { NULL, 0 }
- };
- static const struct input_info fragInputs[] = {
- { NULL, 0 }
- };
- const struct input_info *inputs;
- GLuint i;
-
- if (target == GL_VERTEX_PROGRAM_ARB) {
- inputs = vertInputs;
- }
- else {
- assert(target == GL_FRAGMENT_PROGRAM_ARB);
- inputs = fragInputs;
- }
-
- for (i = 0; inputs[i].Name; i++) {
- if (strcmp(inputs[i].Name, name) == 0) {
- /* found */
- return inputs[i].Attrib;
- }
- }
- return -1;
-}
-
-
-static GLint
-slang_find_output(GLenum target, const char *name, GLint index)
-{
- struct output_info {
- const char *Name;
- GLuint Attrib;
- };
- static const struct output_info vertOutputs[] = {
- { "gl_Position", VERT_RESULT_HPOS },
- { "gl_FrontColor", VERT_RESULT_COL0 },
- { "gl_BackColor", VERT_RESULT_BFC0 },
- { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
- { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
- { "gl_TexCoord", VERT_RESULT_TEX0 }, /* XXX indexed */
- { "gl_FogFragCoord", VERT_RESULT_FOGC },
- { NULL, 0 }
- };
- static const struct output_info fragOutputs[] = {
- { "gl_FragColor", FRAG_RESULT_COLR },
- { NULL, 0 }
- };
- const struct output_info *outputs;
- GLuint i;
-
- if (target == GL_VERTEX_PROGRAM_ARB) {
- outputs = vertOutputs;
- }
- else {
- assert(target == GL_FRAGMENT_PROGRAM_ARB);
- outputs = fragOutputs;
- }
-
- for (i = 0; outputs[i].Name; i++) {
- if (strcmp(outputs[i].Name, name) == 0) {
- /* found */
- return outputs[i].Attrib;
- }
- }
- return -1;
-}
-
-
/**
* Lookup a named constant and allocate storage for the parameter in
* the given parameter list.
};
static const struct state_info state[] = {
{ "gl_ModelViewMatrix", 4, SWIZZLE_NOOP,
- { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 } },
{ "gl_NormalMatrix", 3, SWIZZLE_NOOP,
- { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_INVTRANS } },
+ { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 } },
{ "gl_ProjectionMatrix", 4, SWIZZLE_NOOP,
- { STATE_MATRIX, STATE_PROJECTION, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { STATE_MATRIX, STATE_PROJECTION, 0, 0, 0, 0 } },
{ "gl_ModelViewProjectionMatrix", 4, SWIZZLE_NOOP,
- { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { STATE_MATRIX, STATE_MVP, 0, 0, 0, 0 } },
{ "gl_TextureMatrix", 4, SWIZZLE_NOOP,
- { STATE_MATRIX, STATE_TEXTURE, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { STATE_MATRIX, STATE_TEXTURE, 0, 0, 0, 0 } },
{ NULL, 0, 0, {0, 0, 0, 0, 0, 0} }
};
GLuint i;
static GLint
-slang_alloc_uniform(struct gl_program *prog, const char *name)
+slang_alloc_uniform(struct gl_program *prog, const char *name, GLuint size)
{
- GLint i = _mesa_add_uniform(prog->Parameters, name, 4);
+ GLint i = _mesa_add_uniform(prog->Parameters, name, size);
return i;
}
-static GLint
-slang_alloc_varying(struct gl_program *prog, const char *name)
-{
- GLint i = _mesa_add_varying(prog->Varying, name, 4); /* XXX fix size */
-#if 0
- if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-#ifdef OLD_LINK
- i += VERT_RESULT_VAR0;
- prog->OutputsWritten |= (1 << i);
-#else
- prog->OutputsWritten |= (1 << (i + VERT_RESULT_VAR0));
-#endif
- }
- else {
-#ifdef OLD_LINK
- i += FRAG_ATTRIB_VAR0;
- prog->InputsRead |= (1 << i);
-#else
- prog->InputsRead |= (1 << (i + FRAG_ATTRIB_VAR0));
-#endif
- }
-#endif
- return i;
-}
-
/**
* Allocate temporary storage for an intermediate result (such as for
* 2. Allocate storage for user-declared variables.
* 3. Allocate intermediate/unnamed storage for complex expressions.
* 4. other?
- *
- * If gc or prog is NULL, we may only be able to determine the Store->File
- * but not an Index (register).
*/
void
slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
if (n->Opcode == IR_VAR_DECL) {
/* storage declaration */
assert(n->Var);
- if (n->Store->Index < 0) { /* XXX assert this? */
+ if (is_sampler_type(&n->Var->type)) {
+ /* i.e. "uniform sampler2D tex;" */
+ n->Store->File = PROGRAM_SAMPLER;
+ n->Store->Size = 1; /* never used */
+ n->Store->Index = alloc_sampler(gc);
+ n->Store->Index = slang_alloc_uniform(prog, (char *) n->Var->a_name, 1);
+ printf("********** Alloc sampler uniform %d\n", n->Store->Index);
+ abort(); /* this is a locally-declared sampler */
+ }
+ else if (n->Store->Index < 0) { /* XXX assert this? */
assert(gc);
n->Store->File = PROGRAM_TEMPORARY;
n->Store->Size = sizeof_type(&n->Var->type);
return;
}
- if (n->Opcode == IR_VAR && n->Store->File == PROGRAM_UNDEFINED) {
+ /*
+ assert(!is_sampler_type(&n->Var->type));
+ */
+ assert(n->Opcode == IR_VAR);
+
+ assert(n->Store->File != PROGRAM_UNDEFINED);
+
+ if (n->Opcode == IR_VAR && (n->Store->File == PROGRAM_UNDEFINED
+ || n->Store->Index < 0)) {
/* try to determine the storage for this variable */
GLint i;
assert(n->Var);
+ assert(n->Store->Size > 0);
if (n->Store->Size < 0) {
/* determine var/storage size now */
n->Var->type.qualifier == slang_qual_const);
#endif
- i = slang_find_input(prog->Target, (char *) n->Var->a_name, 0);
- if (i >= 0) {
- n->Store->File = PROGRAM_INPUT;
- n->Store->Index = i;
- assert(n->Store->Size > 0);
- prog->InputsRead |= (1 << i);
- return;
- }
-
- i = slang_find_output(prog->Target, (char *) n->Var->a_name, 0);
- if (i >= 0) {
- n->Store->File = PROGRAM_OUTPUT;
- n->Store->Index = i;
- prog->OutputsWritten |= (1 << i);
- return;
- }
-
i = slang_lookup_statevar((char *) n->Var->a_name, 0, prog->Parameters);
if (i >= 0) {
+ assert(n->Store->File == PROGRAM_STATE_VAR /*||
+ n->Store->File == PROGRAM_UNIFORM*/);
n->Store->File = PROGRAM_STATE_VAR;
n->Store->Index = i;
return;
i = slang_lookup_constant((char *) n->Var->a_name, 0, prog->Parameters);
if (i >= 0) {
+ assert(n->Store->File == PROGRAM_CONSTANT);
n->Store->File = PROGRAM_CONSTANT;
n->Store->Index = i;
return;
}
- /* probably a uniform or varying */
- if (n->Var->type.qualifier == slang_qual_uniform) {
- i = slang_alloc_uniform(prog, (char *) n->Var->a_name);
- if (i >= 0) {
- n->Store->File = PROGRAM_UNIFORM;
- n->Store->Index = i;
- return;
- }
- }
- else if (n->Var->type.qualifier == slang_qual_varying) {
- i = slang_alloc_varying(prog, (char *) n->Var->a_name);
- if (i >= 0) {
-#ifdef OLD_LINK
- if (prog->Target == GL_VERTEX_PROGRAM_ARB)
- n->Store->File = PROGRAM_OUTPUT;
- else
- n->Store->File = PROGRAM_INPUT;
-#else
- n->Store->File = PROGRAM_VARYING;
-#endif
- n->Store->Index = i;
- return;
- }
- }
-
if (n->Store->File == PROGRAM_UNDEFINED && n->Store->Index < 0) {
/* ordinary local var */
assert(n->Store->Size > 0);
emit(gc, n->Children[0], prog);
inst = new_instruction(prog, info->InstOpcode);
- /*slang_resolve_storage(gc, n, prog);*/
if (!n->Store)
slang_alloc_temp_storage(gc, n, info->ResultSize);
}
+static struct prog_instruction *
+emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+ /* Implement as MOV dst, -src; */
+ /* XXX we could look at the previous instruction and in some circumstances
+ * modify it to accomplish the negation.
+ */
+ struct prog_instruction *inst;
+
+ emit(gc, n->Children[0], prog);
+
+ if (!n->Store)
+ slang_alloc_temp_storage(gc, n, n->Children[0]->Store->Size);
+
+ inst = new_instruction(prog, OPCODE_MOV);
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+ n->Children[0]->Swizzle);
+ inst->SrcReg[0].NegateBase = NEGATE_XYZW;
+ inst->Comment = n->Comment;
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_label(const char *target, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_NOP);
+ inst->Comment = _mesa_strdup(target);
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_cjump(const char *target, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_BRA);
+ inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */
+ inst->DstReg.CondSwizzle = SWIZZLE_X;
+ inst->Comment = _mesa_strdup(target);
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_jump(const char *target, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_BRA);
+ inst->DstReg.CondMask = COND_TR; /* always branch */
+ /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
+ inst->Comment = _mesa_strdup(target);
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ if (n->Opcode == IR_TEX) {
+ inst = new_instruction(prog, OPCODE_TEX);
+ }
+ else {
+ assert(n->Opcode == IR_TEXB);
+ inst = new_instruction(prog, OPCODE_TXB);
+ }
+
+ if (!n->Store)
+ slang_alloc_temp_storage(gc, n, 4);
+
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+
+ /* Child[1] is the coord */
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
+ n->Children[1]->Swizzle);
+
+ /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */
+ assert(n->Children[0]->Store);
+ assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
+
+ inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
+ inst->TexSrcTarget = n->Children[0]->Store->Size;
+ inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
+ * link time, using the sampler uniform's value.
+ */
+ return inst;
+}
+
+
static struct prog_instruction *
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
{
case IR_EXP:
case IR_EXP2:
return emit_binop(gc, n, prog);
- break;
case IR_RSQ:
case IR_RCP:
case IR_FLOOR:
case IR_SIN:
case IR_COS:
return emit_unop(gc, n, prog);
- break;
+ case IR_TEX:
+ case IR_TEXB:
+ return emit_tex(gc, n, prog);
+ case IR_NEG:
+ return emit_negation(gc, n, prog);
case IR_LABEL:
- /*printf("LAB: %s\n", n->Target);*/
- break;
- case IR_JUMP:
-#if 0
- inst = new_instruction(prog, OPCODE_BRA);
- inst->Comment = _mesa_strdup(n->Target);
-#endif
- break;
+ return emit_label(n->Target, prog);
case IR_FLOAT:
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
break;
+ case IR_COND:
+ {
+ /* Conditional expression (in if/while/for stmts).
+ * Need to update condition code register.
+ * Next instruction is typically an IR_CJUMP.
+ */
+ /* last child expr instruction: */
+ struct prog_instruction *inst = emit(gc, n->Children[0], prog);
+ if (inst) {
+ /* set inst's CondUpdate flag */
+ inst->CondUpdate = GL_TRUE;
+ return inst; /* XXX or null? */
+ }
+ else {
+ /* This'll happen for things like "if (i) ..." where no code
+ * is normally generated for the expression "i".
+ * Generate a move instruction just to set condition codes.
+ */
+ slang_alloc_temp_storage(gc, n, 1);
+ inst = new_instruction(prog, OPCODE_MOV);
+ inst->CondUpdate = GL_TRUE;
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+ n->Children[0]->Swizzle);
+ free_temporary(gc, n->Store->Index, n->Store->Size);
+ return inst; /* XXX or null? */
+ }
+ }
+ return NULL;
+ case IR_JUMP:
+ return emit_jump(n->Target, prog);
+ case IR_CJUMP:
+ return emit_cjump(n->Target, prog);
default:
printf("emit: ?\n");
abort();