mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 04:58:05 +02:00
Implement if-conditionals and while loops, added temporary resolve-branches function in linker.
This commit is contained in:
parent
34ae99d604
commit
1aee657b0f
3 changed files with 167 additions and 52 deletions
|
|
@ -122,10 +122,10 @@ new_seq(slang_ir_node *left, slang_ir_node *right)
|
||||||
}
|
}
|
||||||
|
|
||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
new_label(const char *name)
|
new_label(slang_atom labName)
|
||||||
{
|
{
|
||||||
slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
|
slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
|
||||||
n->Target = _mesa_strdup(name);
|
n->Target = (char *) labName; /*_mesa_strdup(name);*/
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,20 +141,20 @@ new_float_literal(float x, float y, float z, float w)
|
||||||
}
|
}
|
||||||
|
|
||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
new_cjump(slang_ir_node *cond, const char *target)
|
new_cjump(slang_atom target)
|
||||||
{
|
{
|
||||||
slang_ir_node *n = new_node(IR_CJUMP, cond, NULL);
|
slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL);
|
||||||
n->Target = _mesa_strdup(target);
|
if (n)
|
||||||
|
n->Target = (char *) target;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
new_jump(const char *target)
|
new_jump(slang_atom target)
|
||||||
{
|
{
|
||||||
slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
|
slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
|
||||||
if (n) {
|
if (n)
|
||||||
n->Target = _mesa_strdup(target);
|
n->Target = (char *) target;
|
||||||
}
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -893,6 +893,16 @@ slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static GLboolean
|
||||||
|
_slang_is_noop(const slang_operation *oper)
|
||||||
|
{
|
||||||
|
if (!oper ||
|
||||||
|
oper->type == slang_oper_void ||
|
||||||
|
(oper->num_children == 1 && oper->children[0].type == slang_oper_void))
|
||||||
|
return GL_TRUE;
|
||||||
|
else
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -922,6 +932,88 @@ slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static slang_ir_node *
|
||||||
|
_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* label "__whileStart"
|
||||||
|
* eval expr (child[0]), updating condcodes
|
||||||
|
* branch if false to "__endWhile"
|
||||||
|
* code body
|
||||||
|
* jump "__whileStart"
|
||||||
|
* label "__endWhile"
|
||||||
|
*/
|
||||||
|
slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startWhile");
|
||||||
|
slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endWhile");
|
||||||
|
slang_ir_node *startLab, *cond, *bra, *body, *jump, *endLab, *tree;
|
||||||
|
|
||||||
|
startLab = new_label(startAtom);
|
||||||
|
cond = slang_assemble_operation(A, &oper->children[0]);
|
||||||
|
tree = new_seq(startLab, cond);
|
||||||
|
|
||||||
|
bra = new_cjump(endAtom);
|
||||||
|
tree = new_seq(tree, bra);
|
||||||
|
|
||||||
|
body = slang_assemble_operation(A, &oper->children[1]);
|
||||||
|
tree = new_seq(tree, body);
|
||||||
|
|
||||||
|
jump = new_jump(startAtom);
|
||||||
|
tree = new_seq(tree, jump);
|
||||||
|
|
||||||
|
endLab = new_label(endAtom);
|
||||||
|
tree = new_seq(tree, endLab);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static slang_ir_node *
|
||||||
|
_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* eval expr (child[0]), updating condcodes
|
||||||
|
* branch if false to _else or _endif
|
||||||
|
* "true" code block
|
||||||
|
* if haveElseClause clause:
|
||||||
|
* jump "__endif"
|
||||||
|
* label "__else"
|
||||||
|
* "false" code block
|
||||||
|
* label "__endif"
|
||||||
|
*/
|
||||||
|
const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
|
||||||
|
slang_ir_node *cond, *bra, *trueBody, *endifLab, *tree;
|
||||||
|
slang_atom elseAtom = slang_atom_pool_gen(A->atoms, "__else");
|
||||||
|
slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif");
|
||||||
|
|
||||||
|
cond = slang_assemble_operation(A, &oper->children[0]);
|
||||||
|
/*assert(cond->Store);*/
|
||||||
|
bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
|
||||||
|
tree = new_seq(cond, bra);
|
||||||
|
|
||||||
|
trueBody = slang_assemble_operation(A, &oper->children[1]);
|
||||||
|
tree = new_seq(tree, trueBody);
|
||||||
|
|
||||||
|
if (haveElseClause) {
|
||||||
|
/* else clause */
|
||||||
|
slang_ir_node *jump, *elseLab, *falseBody;
|
||||||
|
jump = new_jump(endifAtom);
|
||||||
|
tree = new_seq(tree, jump);
|
||||||
|
|
||||||
|
elseLab = new_label(elseAtom);
|
||||||
|
tree = new_seq(tree, elseLab);
|
||||||
|
|
||||||
|
falseBody = slang_assemble_operation(A, &oper->children[2]);
|
||||||
|
tree = new_seq(tree, falseBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
endifLab = new_label(endifAtom);
|
||||||
|
tree = new_seq(tree, endifLab);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
|
slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
|
||||||
{
|
{
|
||||||
|
|
@ -944,25 +1036,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
|
||||||
return slang_assemble_operation(A, &oper->children[0]);
|
return slang_assemble_operation(A, &oper->children[0]);
|
||||||
break;
|
break;
|
||||||
case slang_oper_while:
|
case slang_oper_while:
|
||||||
{
|
return _slang_gen_while(A, oper);
|
||||||
slang_ir_node *tree;
|
|
||||||
slang_ir_node *nStartLabel = new_label("while-start");
|
|
||||||
slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]);
|
|
||||||
slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL);
|
|
||||||
slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]);
|
|
||||||
slang_ir_node *nEndLabel = new_label("while-end");
|
|
||||||
slang_ir_node *nCJump = new_cjump(nNotCond, "while-end");
|
|
||||||
slang_ir_node *nJump = new_jump("while-start");
|
|
||||||
|
|
||||||
tree = new_seq(nStartLabel, nCond);
|
|
||||||
tree = new_seq(tree, nNotCond);
|
|
||||||
tree = new_seq(tree, nBody);
|
|
||||||
tree = new_seq(tree, nEndLabel);
|
|
||||||
tree = new_seq(tree, nCJump);
|
|
||||||
tree = new_seq(tree, nJump);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case slang_oper_equal:
|
case slang_oper_equal:
|
||||||
return new_node(IR_SEQUAL,
|
return new_node(IR_SEQUAL,
|
||||||
slang_assemble_operation(A, &oper->children[0]),
|
slang_assemble_operation(A, &oper->children[0]),
|
||||||
|
|
@ -1145,24 +1219,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case slang_oper_if:
|
case slang_oper_if:
|
||||||
{
|
return _slang_gen_if(A, oper);
|
||||||
slang_ir_node *cond, *bra, *body, *endif, *tree;
|
|
||||||
|
|
||||||
cond = slang_assemble_operation(A, &oper->children[0]);
|
|
||||||
/*assert(cond->Store);*/
|
|
||||||
bra = new_node(IR_CJUMP, NULL, NULL);
|
|
||||||
bra->Target = _mesa_strdup("__endif");
|
|
||||||
|
|
||||||
body = slang_assemble_operation(A, &oper->children[1]);
|
|
||||||
|
|
||||||
endif = new_label("__endif");
|
|
||||||
|
|
||||||
tree = new_seq(cond, bra);
|
|
||||||
tree = new_seq(tree, body);
|
|
||||||
tree = new_seq(tree, endif);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case slang_oper_field:
|
case slang_oper_field:
|
||||||
{
|
{
|
||||||
slang_assembly_typeinfo ti;
|
slang_assembly_typeinfo ti;
|
||||||
|
|
|
||||||
|
|
@ -897,6 +897,12 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
|
||||||
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
|
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
|
||||||
n->Children[1]->Swizzle);
|
n->Children[1]->Swizzle);
|
||||||
inst->Comment = n->Comment;
|
inst->Comment = n->Comment;
|
||||||
|
|
||||||
|
if (inst->Opcode == OPCODE_SGT) {
|
||||||
|
/* update cond codes */
|
||||||
|
inst->CondUpdate = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -951,6 +957,18 @@ emit_cjump(const char *target, struct gl_program *prog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 *
|
static struct prog_instruction *
|
||||||
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
|
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
|
||||||
|
|
@ -1069,15 +1087,11 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
|
||||||
break;
|
break;
|
||||||
case IR_LABEL:
|
case IR_LABEL:
|
||||||
return emit_label(n->Target, prog);
|
return emit_label(n->Target, prog);
|
||||||
case IR_JUMP:
|
|
||||||
#if 0
|
|
||||||
inst = new_instruction(prog, OPCODE_BRA);
|
|
||||||
inst->Comment = _mesa_strdup(n->Target);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case IR_FLOAT:
|
case IR_FLOAT:
|
||||||
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
|
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
|
||||||
break;
|
break;
|
||||||
|
case IR_JUMP:
|
||||||
|
return emit_jump(n->Target, prog);
|
||||||
case IR_CJUMP:
|
case IR_CJUMP:
|
||||||
return emit_cjump(n->Target, prog);
|
return emit_cjump(n->Target, prog);
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,47 @@ link_uniform_vars(struct gl_linked_program *linked, struct gl_program *prog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XXX Temporary
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
slang_resolve_branches(struct gl_program *prog)
|
||||||
|
{
|
||||||
|
struct target {
|
||||||
|
const char *Name;
|
||||||
|
GLuint Pos;
|
||||||
|
};
|
||||||
|
struct target targets[500];
|
||||||
|
GLuint numTargets = 0;
|
||||||
|
GLuint i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < prog->NumInstructions; i++) {
|
||||||
|
struct prog_instruction *inst = prog->Instructions + i;
|
||||||
|
if (inst->Opcode == OPCODE_NOP && inst->Comment) {
|
||||||
|
targets[numTargets].Name = inst->Comment;
|
||||||
|
targets[numTargets].Pos = i;
|
||||||
|
numTargets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < prog->NumInstructions; i++) {
|
||||||
|
struct prog_instruction *inst = prog->Instructions + i;
|
||||||
|
if (inst->Opcode == OPCODE_BRA) {
|
||||||
|
for (j = 0; j < numTargets; j++) {
|
||||||
|
if (!strcmp(inst->Comment, targets[j].Name)) {
|
||||||
|
inst->BranchTarget = targets[j].Pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == numTargets) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shader linker. Currently:
|
* Shader linker. Currently:
|
||||||
*
|
*
|
||||||
|
|
@ -298,6 +339,9 @@ _slang_link2(GLcontext *ctx,
|
||||||
linked->VertexProgram->Base.Parameters = linked->Uniforms;
|
linked->VertexProgram->Base.Parameters = linked->Uniforms;
|
||||||
linked->FragmentProgram->Base.Parameters = linked->Uniforms;
|
linked->FragmentProgram->Base.Parameters = linked->Uniforms;
|
||||||
|
|
||||||
|
slang_resolve_branches(&linked->VertexProgram->Base);
|
||||||
|
slang_resolve_branches(&linked->FragmentProgram->Base);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
printf("************** original fragment program\n");
|
printf("************** original fragment program\n");
|
||||||
_mesa_print_program(&fragProg->Base);
|
_mesa_print_program(&fragProg->Base);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue