summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_emit.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-01-13 14:49:52 -0700
committerBrian <brian@yutani.localnet.net>2007-01-13 14:49:52 -0700
commit691ed5e54b0dc305c9a117a6a9804435041a86f0 (patch)
treef43dcd52cfd382c4d1f0c3c90fb28140d55e44dc /src/mesa/shader/slang/slang_emit.c
parent5daa99d2a40fa12d51043c4e326bf62f66ef727d (diff)
Rework code related to temp register allocation, both for user variables
and expression temporarires. Much better register utilization now. Lots of other fixes. The OpenGL GLSL "orange book" brick shader demo works now.
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r--src/mesa/shader/slang/slang_emit.c206
1 files changed, 99 insertions, 107 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2670134025..81f8565502 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -34,6 +34,7 @@
#include "program.h"
#include "prog_instruction.h"
#include "prog_parameter.h"
+#include "prog_print.h"
#include "slang_emit.h"
@@ -83,6 +84,7 @@ static slang_ir_info IrInfo[] = {
{ IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
/* other */
{ IR_SEQ, "IR_SEQ", 0, 0, 0 },
+ { IR_SCOPE, "IR_SCOPE", 0, 0, 0 },
{ IR_LABEL, "IR_LABEL", 0, 0, 0 },
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
{ IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
@@ -227,6 +229,11 @@ slang_print_ir(const slang_ir_node *n, int indent)
slang_print_ir(n->Children[0], indent + IND);
slang_print_ir(n->Children[1], indent + IND);
break;
+ case IR_SCOPE:
+ printf("NEW SCOPE\n");
+ assert(!n->Children[1]);
+ slang_print_ir(n->Children[0], indent + 3);
+ break;
case IR_MOVE:
printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
slang_print_ir(n->Children[0], indent+3);
@@ -279,71 +286,36 @@ slang_print_ir(const slang_ir_node *n, int indent)
}
-GLint
-_slang_alloc_temporary(slang_gen_context *gc, GLint size)
-{
- const GLuint sz4 = (size + 3) / 4;
- GLuint i, j;
- ASSERT(size > 0); /* number of floats */
-
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
- GLuint found = 0;
- for (j = 0; j < sz4; j++) {
- if (!gc->TempUsed[i + j]) {
- found++;
- }
- }
- if (found == sz4) {
- /* found block of size/4 free regs */
- for (j = 0; j < sz4; j++)
- gc->TempUsed[i + j] = GL_TRUE;
- return i;
- }
- }
- return -1;
-}
-
-
-
-static GLboolean
-is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
-{
- if (st->File == PROGRAM_TEMPORARY && gc->TempUsed[st->Index])
- return gc->TempUsed[st->Index];
- else
- return GL_FALSE;
-}
-
-
-void
-_slang_free_temporary(slang_gen_context *gc, GLuint r, GLint size)
-{
- const GLuint sz4 = (size + 3) / 4;
- GLuint i;
- for (i = 0; i < sz4; i++) {
- if (gc->TempUsed[r + i])
- gc->TempUsed[r + i] = GL_FALSE;
- }
-}
-
-
/**
* Allocate temporary storage for an intermediate result (such as for
* a multiply or add, etc.
*/
static void
-slang_alloc_temp_storage(slang_gen_context *gc, slang_ir_node *n, GLint size)
+alloc_temp_storage(slang_var_table *vt, slang_ir_node *n, GLint size)
{
GLint indx;
assert(!n->Var);
assert(!n->Store);
assert(size > 0);
- printf("Allocate binop temp:\n");
- indx = _slang_alloc_temporary(gc, size);
+ indx = _slang_alloc_temp(vt, size);
n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, indx, size);
}
+static void
+free_temp_storage(slang_var_table *vt, slang_ir_node *n)
+{
+ if (n->Store->File == PROGRAM_TEMPORARY && n->Store->Index >= 0) {
+ if (_slang_is_temp(vt, n->Store->Index)) {
+ _slang_free_temp(vt, n->Store->Index, n->Store->Size);
+ /* XXX free(store)? */
+ n->Store->Index = -1;
+ n->Store->Size = -1;
+ }
+ }
+}
+
+
static slang_ir_storage *
alloc_constant(const GLfloat v[], GLuint size, struct gl_program *prog)
{
@@ -445,14 +417,14 @@ new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
static struct prog_instruction *
-emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog);
+emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog);
/**
* Generate code for a simple binary-op instruction.
*/
static struct prog_instruction *
-emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+emit_binop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
const slang_ir_info *info = slang_find_ir_info(n->Opcode);
@@ -460,25 +432,32 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
assert(info->InstOpcode != OPCODE_NOP);
- emit(gc, n->Children[0], prog);
- emit(gc, n->Children[1], prog);
+ /* gen code for children */
+ emit(vt, n->Children[0], prog);
+ emit(vt, n->Children[1], prog);
+
+ /* gen this instruction */
inst = new_instruction(prog, info->InstOpcode);
- /* alloc temp storage for the result: */
- if (!n->Store || n->Store->File == PROGRAM_UNDEFINED) {
- slang_alloc_temp_storage(gc, n, info->ResultSize);
- }
- 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);
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
n->Children[1]->Swizzle);
+ free_temp_storage(vt, n->Children[0]);
+ free_temp_storage(vt, n->Children[1]);
+
+ if (!n->Store) {
+ alloc_temp_storage(vt, n, info->ResultSize);
+ }
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+
inst->Comment = n->Comment;
+ /*_mesa_print_instruction(inst);*/
return inst;
}
static struct prog_instruction *
-emit_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+emit_unop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
const slang_ir_info *info = slang_find_ir_info(n->Opcode);
@@ -486,26 +465,28 @@ emit_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
assert(info->NumParams == 1);
- emit(gc, n->Children[0], prog);
+ /* gen code for child */
+ emit(vt, n->Children[0], prog);
+ /* gen this instruction */
inst = new_instruction(prog, info->InstOpcode);
-
- if (!n->Store)
- slang_alloc_temp_storage(gc, n, info->ResultSize);
-
- 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_temp_storage(vt, n->Children[0]);
- inst->Comment = n->Comment;
+ if (!n->Store) {
+ alloc_temp_storage(vt, n, info->ResultSize);
+ }
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ inst->Comment = n->Comment;
+ /*_mesa_print_instruction(inst);*/
return inst;
}
static struct prog_instruction *
-emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+emit_negation(slang_var_table *vt, 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
@@ -513,10 +494,10 @@ emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
*/
struct prog_instruction *inst;
- emit(gc, n->Children[0], prog);
+ emit(vt, n->Children[0], prog);
if (!n->Store)
- slang_alloc_temp_storage(gc, n, n->Children[0]->Store->Size);
+ alloc_temp_storage(vt, n, n->Children[0]->Store->Size);
inst = new_instruction(prog, OPCODE_MOV);
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -563,7 +544,7 @@ emit_jump(const char *target, struct gl_program *prog)
static struct prog_instruction *
-emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+emit_tex(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
if (n->Opcode == IR_TEX) {
@@ -578,7 +559,7 @@ emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
}
if (!n->Store)
- slang_alloc_temp_storage(gc, n, 4);
+ alloc_temp_storage(vt, n, 4);
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -600,7 +581,7 @@ emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
static struct prog_instruction *
-emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
if (!n)
@@ -610,34 +591,54 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_SEQ:
assert(n->Children[0]);
assert(n->Children[1]);
- emit(gc, n->Children[0], prog);
- inst = emit(gc, n->Children[1], prog);
+ emit(vt, n->Children[0], prog);
+ inst = emit(vt, n->Children[1], prog);
n->Store = n->Children[1]->Store;
return inst;
- break;
+
+ case IR_SCOPE:
+ /* new variable scope */
+ vt = _slang_push_var_table(vt);
+ inst = emit(vt, n->Children[0], prog);
+ vt = _slang_pop_var_table(vt);
+ return inst;
+
case IR_VAR_DECL:
+ /* Variable declaration - allocate a register for it */
+ assert(n->Store);
+ assert(n->Store->File != PROGRAM_UNDEFINED);
+ assert(n->Store->Size > 0);
+ if (n->Var->isTemp)
+ n->Store->Index = _slang_alloc_temp(vt, n->Store->Size);
+ else
+ n->Store->Index = _slang_alloc_var(vt, n->Store->Size);
+ break;
+
case IR_VAR:
- /* Storage should have already been resolved/allocated */
+ /* Reference to a variable
+ * Storage should have already been resolved/allocated.
+ */
assert(n->Store);
assert(n->Store->File != PROGRAM_UNDEFINED);
assert(n->Store->Index >= 0);
assert(n->Store->Size > 0);
break;
+
case IR_MOVE:
/* rhs */
assert(n->Children[1]);
- inst = emit(gc, n->Children[1], prog);
+ inst = emit(vt, n->Children[1], prog);
/* lhs */
- emit(gc, n->Children[0], prog);
+ emit(vt, n->Children[0], prog);
#if 1
- if (inst && is_temporary(gc, n->Children[1]->Store)) {
+ if (inst && _slang_is_temp(vt, n->Children[1]->Store->Index)) {
/* Peephole optimization:
* Just modify the RHS to put its result into the dest of this
* MOVE operation. Then, this MOVE is a no-op.
*/
- _slang_free_temporary(gc, n->Children[1]->Store->Index,
- n->Children[1]->Store->Size);
+ _slang_free_temp(vt, n->Children[1]->Store->Index,
+ n->Children[1]->Store->Size);
*n->Children[1]->Store = *n->Children[0]->Store;
/* fixup the prev (RHS) instruction */
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
@@ -673,9 +674,9 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
n->Children[1]->Swizzle);
}
/* XXX is this test correct? */
- if (n->Children[1]->Store->File == PROGRAM_TEMPORARY) {
- _slang_free_temporary(gc, n->Children[1]->Store->Index,
- n->Children[1]->Store->Size);
+ if (_slang_is_temp(vt, n->Children[1]->Store->Index)) {
+ _slang_free_temp(vt, n->Children[1]->Store->Index,
+ n->Children[1]->Store->Size);
}
/*inst->Comment = _mesa_strdup("IR_MOVE");*/
n->Store = n->Children[0]->Store; /*XXX new */
@@ -697,7 +698,7 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_POW:
case IR_EXP:
case IR_EXP2:
- return emit_binop(gc, n, prog);
+ return emit_binop(vt, n, prog);
case IR_RSQ:
case IR_RCP:
case IR_FLOOR:
@@ -707,13 +708,13 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_COS:
case IR_DDX:
case IR_DDY:
- return emit_unop(gc, n, prog);
+ return emit_unop(vt, n, prog);
case IR_TEX:
case IR_TEXB:
case IR_TEXP:
- return emit_tex(gc, n, prog);
+ return emit_tex(vt, n, prog);
case IR_NEG:
- return emit_negation(gc, n, prog);
+ return emit_negation(vt, n, prog);
case IR_LABEL:
return emit_label(n->Target, prog);
case IR_FLOAT:
@@ -726,7 +727,7 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
* Next instruction is typically an IR_CJUMP.
*/
/* last child expr instruction: */
- struct prog_instruction *inst = emit(gc, n->Children[0], prog);
+ struct prog_instruction *inst = emit(vt, n->Children[0], prog);
if (inst) {
/* set inst's CondUpdate flag */
inst->CondUpdate = GL_TRUE;
@@ -737,13 +738,13 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
* is normally generated for the expression "i".
* Generate a move instruction just to set condition codes.
*/
- slang_alloc_temp_storage(gc, n, 1);
+ alloc_temp_storage(vt, 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);
- _slang_free_temporary(gc, n->Store->Index, n->Store->Size);
+ _slang_free_temp(vt, n->Store->Index, n->Store->Size);
return inst; /* XXX or null? */
}
}
@@ -760,23 +761,14 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
}
-slang_gen_context *
-_slang_new_codegen_context(void)
-{
- slang_gen_context *gc = (slang_gen_context *) _mesa_calloc(sizeof(*gc));
- return gc;
-}
-
-
-
GLboolean
-_slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
+_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
struct gl_program *prog, GLboolean withEnd)
{
GLboolean success;
- if (emit(gc, n, prog)) {
- /* finish up by addeing the END opcode to program */
+ if (emit(vt, n, prog)) {
+ /* finish up by adding the END opcode to program */
if (withEnd) {
struct prog_instruction *inst;
inst = new_instruction(prog, OPCODE_END);
@@ -788,8 +780,8 @@ _slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
success = GL_FALSE;
}
-#if 0
printf("*********** End generate code (%u inst):\n", prog->NumInstructions);
+#if 0
_mesa_print_program(prog);
_mesa_print_program_parameters(ctx,prog);
#endif