Experimental PRINT instruction for NV_vertex_program.

Basically, this lets you put a "PRINT 'mesage', register;" statement in a
vertex program to aid in debugging.
This commit is contained in:
Brian Paul
2004-12-16 03:07:18 +00:00
parent c75900e7a2
commit 575700fbdc
5 changed files with 149 additions and 8 deletions

View File

@@ -44,6 +44,10 @@
#include "arbprogparse.h" #include "arbprogparse.h"
/**
* XXX this is probably redundant. We've already got code like this
* in the nvvertparse.c file. Combine/clean-up someday.
*/
static GLvoid static GLvoid
debug_vp_inst(GLint num, struct vp_instruction *vp) debug_vp_inst(GLint num, struct vp_instruction *vp)
{ {
@@ -135,6 +139,9 @@ debug_vp_inst(GLint num, struct vp_instruction *vp)
case VP_OPCODE_SWZ: case VP_OPCODE_SWZ:
fprintf(stderr, "VP_OPCODE_SWZ"); break; fprintf(stderr, "VP_OPCODE_SWZ"); break;
case VP_OPCODE_PRINT:
fprintf(stderr, "VP_OPCODE_PRINT"); break;
case VP_OPCODE_END: case VP_OPCODE_END:
fprintf(stderr, "VP_OPCODE_END"); break; fprintf(stderr, "VP_OPCODE_END"); break;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 6.1 * Version: 6.3
* *
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* *
@@ -249,6 +249,10 @@ get_register_pointer( const struct vp_src_register *source,
case PROGRAM_INPUT: case PROGRAM_INPUT:
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS); ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS);
return state->Inputs[source->Index]; return state->Inputs[source->Index];
case PROGRAM_OUTPUT:
/* This is only needed for the PRINT instruction */
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
return state->Outputs[source->Index];
case PROGRAM_LOCAL_PARAM: case PROGRAM_LOCAL_PARAM:
ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS); ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
return state->Current->Base.LocalParams[source->Index]; return state->Current->Base.LocalParams[source->Index];
@@ -774,7 +778,17 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct vertex_program *program)
store_vector4( &inst->DstReg, state, result ); store_vector4( &inst->DstReg, state, result );
} }
break; break;
case VP_OPCODE_PRINT:
if (inst->SrcReg[0].File) {
GLfloat t[4];
fetch_vector4( &inst->SrcReg[0], state, t );
_mesa_printf("%s%g, %g, %g, %g\n",
(char *) inst->Data, t[0], t[1], t[2], t[3]);
}
else {
_mesa_printf("%s\n", (char *) inst->Data);
}
break;
case VP_OPCODE_END: case VP_OPCODE_END:
ctx->_CurrentProgram = 0; ctx->_CurrentProgram = 0;
return; return;

View File

@@ -1,6 +1,6 @@
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 6.1 * Version: 6.3
* *
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* *
@@ -299,6 +299,8 @@ static const char *Opcodes[] = {
"ABS", "END", "ABS", "END",
/* GL_ARB_vertex_program */ /* GL_ARB_vertex_program */
"FLR", "FRC", "EX2", "LG2", "POW", "XPD", "SWZ", "FLR", "FRC", "EX2", "LG2", "POW", "XPD", "SWZ",
/* Mesa-specific */
"PRINT",
NULL NULL
}; };
@@ -1019,6 +1021,98 @@ Parse_EndInstruction(struct parse_state *parseState, struct vp_instruction *inst
} }
/**
* The PRINT instruction is Mesa-specific and is meant as a debugging aid for
* the vertex program developer.
* The NV_vertex_program extension grammar is modified as follows:
*
* <instruction> ::= <ARL-instruction>
* | ...
* | <PRINT-instruction>
*
* <PRINT-instruction> ::= "PRINT" <string literal>
* | "PRINT" <string literal> "," <srcReg>
* | "PRINT" <string literal> "," <dstReg>
*/
static GLboolean
Parse_PrintInstruction(struct parse_state *parseState, struct vp_instruction *inst)
{
const GLubyte *str;
GLubyte *msg;
GLuint len;
GLubyte token[100];
struct vp_src_register *srcReg = &inst->SrcReg[0];
inst->Opcode = VP_OPCODE_PRINT;
inst->StringPos = parseState->curLine - parseState->start;
/* The first argument is a literal string 'just like this' */
if (!Parse_String(parseState, "'"))
RETURN_ERROR;
str = parseState->pos;
for (len = 0; str[len] != '\''; len++) /* find closing quote */
;
parseState->pos += len + 1;
msg = _mesa_malloc(len + 1);
_mesa_memcpy(msg, str, len);
msg[len] = 0;
inst->Data = msg;
/* comma */
if (Parse_String(parseState, ",")) {
/* The second argument is a register name */
if (!Peek_Token(parseState, token))
RETURN_ERROR;
srcReg->RelAddr = GL_FALSE;
srcReg->Negate = GL_FALSE;
srcReg->Swizzle[0] = 0;
srcReg->Swizzle[1] = 1;
srcReg->Swizzle[2] = 2;
srcReg->Swizzle[3] = 3;
/* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
* or an o[n] output register.
*/
if (token[0] == 'R') {
srcReg->File = PROGRAM_TEMPORARY;
if (!Parse_TempReg(parseState, &srcReg->Index))
RETURN_ERROR;
}
else if (token[0] == 'c') {
srcReg->File = PROGRAM_ENV_PARAM;
if (!Parse_ParamReg(parseState, srcReg))
RETURN_ERROR;
}
else if (token[0] == 'v') {
srcReg->File = PROGRAM_INPUT;
if (!Parse_AttribReg(parseState, &srcReg->Index))
RETURN_ERROR;
}
else if (token[0] == 'o') {
srcReg->File = PROGRAM_OUTPUT;
if (!Parse_OutputReg(parseState, &srcReg->Index))
RETURN_ERROR;
}
else {
RETURN_ERROR2("Bad source register name", token);
}
}
else {
srcReg->File = 0;
}
/* semicolon */
if (!Parse_String(parseState, ";"))
RETURN_ERROR;
return GL_TRUE;
}
static GLboolean static GLboolean
Parse_OptionSequence(struct parse_state *parseState, Parse_OptionSequence(struct parse_state *parseState,
struct vp_instruction program[]) struct vp_instruction program[])
@@ -1051,6 +1145,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
inst->SrcReg[1].File = (enum register_file) -1; inst->SrcReg[1].File = (enum register_file) -1;
inst->SrcReg[2].File = (enum register_file) -1; inst->SrcReg[2].File = (enum register_file) -1;
inst->DstReg.File = (enum register_file) -1; inst->DstReg.File = (enum register_file) -1;
inst->Data = NULL;
if (Parse_String(parseState, "MOV")) { if (Parse_String(parseState, "MOV")) {
if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_MOV)) if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_MOV))
@@ -1136,6 +1231,10 @@ Parse_InstructionSequence(struct parse_state *parseState,
if (!Parse_AddressInstruction(parseState, inst)) if (!Parse_AddressInstruction(parseState, inst))
RETURN_ERROR; RETURN_ERROR;
} }
else if (Parse_String(parseState, "PRINT")) {
if (!Parse_PrintInstruction(parseState, inst))
RETURN_ERROR;
}
else if (Parse_String(parseState, "END")) { else if (Parse_String(parseState, "END")) {
if (!Parse_EndInstruction(parseState, inst)) if (!Parse_EndInstruction(parseState, inst))
RETURN_ERROR; RETURN_ERROR;
@@ -1303,7 +1402,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
program->IsPositionInvariant = parseState.isPositionInvariant; program->IsPositionInvariant = parseState.isPositionInvariant;
program->IsNVProgram = GL_TRUE; program->IsNVProgram = GL_TRUE;
#ifdef DEBUG_foo #ifdef DEBUG
_mesa_printf("--- glLoadProgramNV result ---\n"); _mesa_printf("--- glLoadProgramNV result ---\n");
_mesa_print_nv_vertex_program(program); _mesa_print_nv_vertex_program(program);
_mesa_printf("------------------------------\n"); _mesa_printf("------------------------------\n");
@@ -1457,6 +1556,17 @@ _mesa_print_nv_vertex_instruction(const struct vp_instruction *inst)
PrintSrcReg(&inst->SrcReg[0]); PrintSrcReg(&inst->SrcReg[0]);
_mesa_printf(";\n"); _mesa_printf(";\n");
break; break;
case VP_OPCODE_PRINT:
_mesa_printf("PRINT '%s'", inst->Data);
if (inst->SrcReg[0].File) {
_mesa_printf(", ");
PrintSrcReg(&inst->SrcReg[0]);
_mesa_printf(";\n");
}
else {
_mesa_printf("\n");
}
break;
case VP_OPCODE_END: case VP_OPCODE_END:
_mesa_printf("END\n"); _mesa_printf("END\n");
break; break;

View File

@@ -1,8 +1,8 @@
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 5.1 * Version: 6.3
* *
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -66,7 +66,9 @@ enum vp_opcode
VP_OPCODE_LG2, VP_OPCODE_LG2,
VP_OPCODE_POW, VP_OPCODE_POW,
VP_OPCODE_XPD, VP_OPCODE_XPD,
VP_OPCODE_SWZ VP_OPCODE_SWZ,
/* Special Mesa opcodes */
VP_OPCODE_PRINT
}; };
@@ -101,6 +103,7 @@ struct vp_instruction
#if FEATURE_MESA_program_debug #if FEATURE_MESA_program_debug
GLint StringPos; GLint StringPos;
#endif #endif
void *Data; /* some arbitrary data, only used for PRINT instruction now */
}; };

View File

@@ -39,6 +39,7 @@
#include "nvfragparse.h" #include "nvfragparse.h"
#include "nvfragprog.h" #include "nvfragprog.h"
#include "nvvertparse.h" #include "nvvertparse.h"
#include "nvvertprog.h"
/**********************************************************************/ /**********************************************************************/
@@ -263,8 +264,14 @@ _mesa_delete_program(GLcontext *ctx, struct program *prog)
if (prog->Target == GL_VERTEX_PROGRAM_NV || if (prog->Target == GL_VERTEX_PROGRAM_NV ||
prog->Target == GL_VERTEX_STATE_PROGRAM_NV) { prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
struct vertex_program *vprog = (struct vertex_program *) prog; struct vertex_program *vprog = (struct vertex_program *) prog;
if (vprog->Instructions) if (vprog->Instructions) {
GLuint i;
for (i = 0; i < vprog->Base.NumInstructions; i++) {
if (vprog->Instructions[i].Data)
_mesa_free(vprog->Instructions[i].Data);
}
_mesa_free(vprog->Instructions); _mesa_free(vprog->Instructions);
}
if (vprog->Parameters) if (vprog->Parameters)
_mesa_free_parameter_list(vprog->Parameters); _mesa_free_parameter_list(vprog->Parameters);
} }