start implementing conditions, branching

This commit is contained in:
Brian
2007-02-22 14:43:41 -07:00
parent 2eeaae6cbc
commit 11b9ef9454
2 changed files with 123 additions and 2 deletions
+122 -2
View File
@@ -39,6 +39,8 @@
#include "math/m_matrix.h"
static const GLboolean DEBUG_VERT = GL_FALSE;
static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
@@ -67,6 +69,12 @@ _mesa_init_vp_per_vertex_registers(GLcontext *ctx, struct vp_machine *machine)
ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0);
}
}
/* init condition codes */
machine->CondCodes[0] = COND_EQ;
machine->CondCodes[1] = COND_EQ;
machine->CondCodes[2] = COND_EQ;
machine->CondCodes[3] = COND_EQ;
}
@@ -333,6 +341,65 @@ fetch_vector1( GLcontext *ctx,
}
/**
* Test value against zero and return GT, LT, EQ or UN if NaN.
*/
static INLINE GLuint
generate_cc( float value )
{
if (value != value)
return COND_UN; /* NaN */
if (value > 0.0F)
return COND_GT;
if (value < 0.0F)
return COND_LT;
return COND_EQ;
}
/**
* Test if the ccMaskRule is satisfied by the given condition code.
* Used to mask destination writes according to the current condition code.
*/
static INLINE GLboolean
test_cc(GLuint condCode, GLuint ccMaskRule)
{
switch (ccMaskRule) {
case COND_EQ: return (condCode == COND_EQ);
case COND_NE: return (condCode != COND_EQ);
case COND_LT: return (condCode == COND_LT);
case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);
case COND_LE: return (condCode == COND_LT || condCode == COND_EQ);
case COND_GT: return (condCode == COND_GT);
case COND_TR: return GL_TRUE;
case COND_FL: return GL_FALSE;
default: return GL_TRUE;
}
}
/**
* Evaluate the 4 condition codes against a predicate and return GL_TRUE
* or GL_FALSE to indicate result.
*/
static INLINE GLboolean
eval_condition(const struct vp_machine *machine,
const struct prog_instruction *inst)
{
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)) {
return GL_TRUE;
}
else {
return GL_FALSE;
}
}
/**
* Store 4 floats into a register.
*/
@@ -342,12 +409,16 @@ store_vector4( const struct prog_instruction *inst,
const GLfloat value[4] )
{
const struct prog_dst_register *dest = &(inst->DstReg);
GLuint writeMask = dest->WriteMask;
GLfloat *dst;
switch (dest->File) {
case PROGRAM_OUTPUT:
ASSERT(dest->Index < VERT_RESULT_MAX);
dst = machine->Outputs[dest->Index];
break;
case PROGRAM_TEMPORARY:
ASSERT(dest->Index < MAX_PROGRAM_TEMPS);
dst = machine->Temporaries[dest->Index];
break;
case PROGRAM_ENV_PARAM:
@@ -355,6 +426,7 @@ store_vector4( const struct prog_instruction *inst,
{
/* a slight hack */
GET_CURRENT_CONTEXT(ctx);
ASSERT(dest->Index < MAX_PROGRAM_ENV_PARAMS);
dst = ctx->VertexProgram.Parameters[dest->Index];
}
break;
@@ -372,6 +444,17 @@ store_vector4( const struct prog_instruction *inst,
dst[2] = value[2];
if (dest->WriteMask & WRITEMASK_W)
dst[3] = value[3];
if (inst->CondUpdate) {
if (writeMask & WRITEMASK_X)
machine->CondCodes[0] = generate_cc(value[0]);
if (writeMask & WRITEMASK_Y)
machine->CondCodes[1] = generate_cc(value[1]);
if (writeMask & WRITEMASK_Z)
machine->CondCodes[2] = generate_cc(value[2]);
if (writeMask & WRITEMASK_W)
machine->CondCodes[3] = generate_cc(value[3]);
}
}
@@ -400,7 +483,8 @@ _mesa_exec_vertex_program(GLcontext *ctx,
struct vp_machine *machine,
const struct gl_vertex_program *program)
{
const struct prog_instruction *inst;
const GLuint maxInst = program->Base.NumInstructions;
GLuint pc;
ctx->_CurrentProgram = GL_VERTEX_PROGRAM_ARB; /* or NV, doesn't matter */
@@ -416,7 +500,8 @@ _mesa_exec_vertex_program(GLcontext *ctx,
ctx->VertexProgram.Current->Base.OutputsWritten |= VERT_BIT_POS;
}
for (inst = program->Base.Instructions; ; inst++) {
for (pc = 0; pc < maxInst; pc++) {
const struct prog_instruction *inst = program->Base.Instructions + pc;
if (ctx->VertexProgram.CallbackEnabled &&
ctx->VertexProgram.Callback) {
@@ -637,6 +722,22 @@ _mesa_exec_vertex_program(GLcontext *ctx,
store_vector4( inst, machine, sge );
}
break;
case OPCODE_SGT: /* set on greater */
{
GLfloat a[4], b[4], result[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
result[0] = (a[0] > b[0]) ? 1.0F : 0.0F;
result[1] = (a[1] > b[1]) ? 1.0F : 0.0F;
result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
store_vector4( inst, machine, result );
if (DEBUG_VERT) {
printf("SGT %g %g %g %g\n",
result[0], result[1], result[2], result[3]);
}
}
break;
case OPCODE_MAD:
{
GLfloat t[4], u[4], v[4], sum[4];
@@ -740,6 +841,25 @@ _mesa_exec_vertex_program(GLcontext *ctx,
store_vector4( inst, machine, t );
}
break;
case OPCODE_IF:
if (eval_condition(machine, inst)) {
/* do if-clause (just continue execution) */
}
else {
/* go to the instruction after ELSE or ENDIF */
assert(inst->BranchTarget >= 0);
pc = inst->BranchTarget - 1;
}
break;
case OPCODE_ELSE:
/* goto ENDIF */
assert(inst->BranchTarget >= 0);
pc = inst->BranchTarget - 1;
break;
case OPCODE_ENDIF:
/* nothing */
break;
case OPCODE_EX2: /* GL_ARB_vertex_program */
{
GLfloat t[4];
+1
View File
@@ -39,6 +39,7 @@ struct vp_machine
GLfloat Inputs[VERT_ATTRIB_MAX][4];
GLuint InputsSize[VERT_ATTRIB_MAX];
GLfloat Outputs[VERT_RESULT_MAX][4];
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
GLint AddressReg[MAX_VERTEX_PROGRAM_ADDRESS_REGS][4];
};