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:
@@ -44,6 +44,10 @@
|
||||
#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
|
||||
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:
|
||||
fprintf(stderr, "VP_OPCODE_SWZ"); break;
|
||||
|
||||
case VP_OPCODE_PRINT:
|
||||
fprintf(stderr, "VP_OPCODE_PRINT"); break;
|
||||
|
||||
case VP_OPCODE_END:
|
||||
fprintf(stderr, "VP_OPCODE_END"); break;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.1
|
||||
* Version: 6.3
|
||||
*
|
||||
* 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:
|
||||
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS);
|
||||
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:
|
||||
ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
|
||||
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 );
|
||||
}
|
||||
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:
|
||||
ctx->_CurrentProgram = 0;
|
||||
return;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.1
|
||||
* Version: 6.3
|
||||
*
|
||||
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
|
||||
*
|
||||
@@ -299,6 +299,8 @@ static const char *Opcodes[] = {
|
||||
"ABS", "END",
|
||||
/* GL_ARB_vertex_program */
|
||||
"FLR", "FRC", "EX2", "LG2", "POW", "XPD", "SWZ",
|
||||
/* Mesa-specific */
|
||||
"PRINT",
|
||||
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
|
||||
Parse_OptionSequence(struct parse_state *parseState,
|
||||
struct vp_instruction program[])
|
||||
@@ -1051,6 +1145,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
|
||||
inst->SrcReg[1].File = (enum register_file) -1;
|
||||
inst->SrcReg[2].File = (enum register_file) -1;
|
||||
inst->DstReg.File = (enum register_file) -1;
|
||||
inst->Data = NULL;
|
||||
|
||||
if (Parse_String(parseState, "MOV")) {
|
||||
if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_MOV))
|
||||
@@ -1136,6 +1231,10 @@ Parse_InstructionSequence(struct parse_state *parseState,
|
||||
if (!Parse_AddressInstruction(parseState, inst))
|
||||
RETURN_ERROR;
|
||||
}
|
||||
else if (Parse_String(parseState, "PRINT")) {
|
||||
if (!Parse_PrintInstruction(parseState, inst))
|
||||
RETURN_ERROR;
|
||||
}
|
||||
else if (Parse_String(parseState, "END")) {
|
||||
if (!Parse_EndInstruction(parseState, inst))
|
||||
RETURN_ERROR;
|
||||
@@ -1303,7 +1402,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
|
||||
program->IsPositionInvariant = parseState.isPositionInvariant;
|
||||
program->IsNVProgram = GL_TRUE;
|
||||
|
||||
#ifdef DEBUG_foo
|
||||
#ifdef DEBUG
|
||||
_mesa_printf("--- glLoadProgramNV result ---\n");
|
||||
_mesa_print_nv_vertex_program(program);
|
||||
_mesa_printf("------------------------------\n");
|
||||
@@ -1457,6 +1556,17 @@ _mesa_print_nv_vertex_instruction(const struct vp_instruction *inst)
|
||||
PrintSrcReg(&inst->SrcReg[0]);
|
||||
_mesa_printf(";\n");
|
||||
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:
|
||||
_mesa_printf("END\n");
|
||||
break;
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* 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
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -66,7 +66,9 @@ enum vp_opcode
|
||||
VP_OPCODE_LG2,
|
||||
VP_OPCODE_POW,
|
||||
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
|
||||
GLint StringPos;
|
||||
#endif
|
||||
void *Data; /* some arbitrary data, only used for PRINT instruction now */
|
||||
};
|
||||
|
||||
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "nvfragparse.h"
|
||||
#include "nvfragprog.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 ||
|
||||
prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
|
||||
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);
|
||||
}
|
||||
if (vprog->Parameters)
|
||||
_mesa_free_parameter_list(vprog->Parameters);
|
||||
}
|
||||
|
Reference in New Issue
Block a user