Initial implementation work for CAL, RET, and BRA instructions for fragment

programs.
This commit is contained in:
Brian Paul 2006-11-16 21:28:35 +00:00
parent fa941e4267
commit 3dedeaa055
3 changed files with 60 additions and 1 deletions

View file

@ -198,6 +198,7 @@
#define MAX_PROGRAM_LOCAL_PARAMS 128 /* KW: power of two */
#define MAX_PROGRAM_MATRICES 8
#define MAX_PROGRAM_MATRIX_STACK_DEPTH 4
#define MAX_PROGRAM_CALL_DEPTH 8
/*@}*/
/** For GL_ARB_fragment_shader */

View file

@ -286,7 +286,7 @@ struct prog_instruction
GLuint CondUpdate:1;
/**
* If prog_instruction::cc_update is \c GL_TRUE, this value selects the
* If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
* condition code register that is to be updated.
*
* In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
@ -339,6 +339,11 @@ struct prog_instruction
*/
GLuint TexSrcTarget:3;
/*@}*/
/**
* For BRA and CAL instructions, the location to jump to.
*/
GLuint BranchTarget;
};

View file

@ -57,6 +57,9 @@ struct fp_machine
GLfloat Inputs[MAX_NV_FRAGMENT_PROGRAM_INPUTS][4];
GLfloat Outputs[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS][4];
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
GLuint StackDepth; /**< Index/ptr to top of CallStack[] */
};
@ -697,6 +700,37 @@ execute_program( GLcontext *ctx,
}
}
break;
case OPCODE_BRA: /* conditional branch */
{
/* NOTE: The return is conditional! */
const GLuint swizzle = inst->DstReg.CondSwizzle;
const GLuint condMask = inst->DstReg.CondMask;
if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
/* take branch */
pc = inst->BranchTarget;
}
}
break;
case OPCODE_CAL: /* Call subroutine */
{
/* NOTE: The call is conditional! */
const GLuint swizzle = inst->DstReg.CondSwizzle;
const GLuint condMask = inst->DstReg.CondMask;
if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
}
machine->CallStack[machine->StackDepth++] = pc + 1;
pc = inst->BranchTarget;
}
}
break;
case OPCODE_CMP:
{
GLfloat a[4], b[4], c[4], result[4];
@ -1093,6 +1127,22 @@ execute_program( GLcontext *ctx,
store_vector4( inst, machine, result );
}
break;
case OPCODE_RET: /* return from subroutine */
{
/* NOTE: The return is conditional! */
const GLuint swizzle = inst->DstReg.CondSwizzle;
const GLuint condMask = inst->DstReg.CondMask;
if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
if (machine->StackDepth == 0) {
return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
}
pc = machine->CallStack[--machine->StackDepth];
}
}
break;
case OPCODE_RFL: /* reflection vector */
{
GLfloat axis[4], dir[4], result[4], tmpX, tmpW;
@ -1539,6 +1589,9 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
machine->CondCodes[1] = COND_EQ;
machine->CondCodes[2] = COND_EQ;
machine->CondCodes[3] = COND_EQ;
/* init call stack */
machine->StackDepth = 0;
}