From 575700fbdcdde9c31ee6ccdd0369604b8ee2df91 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 16 Dec 2004 03:07:18 +0000 Subject: [PATCH] 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. --- src/mesa/shader/arbvertparse.c | 7 ++ src/mesa/shader/nvvertexec.c | 18 +++++- src/mesa/shader/nvvertparse.c | 114 ++++++++++++++++++++++++++++++++- src/mesa/shader/nvvertprog.h | 9 ++- src/mesa/shader/program.c | 9 ++- 5 files changed, 149 insertions(+), 8 deletions(-) diff --git a/src/mesa/shader/arbvertparse.c b/src/mesa/shader/arbvertparse.c index fb6a642b647..33086c2f723 100644 --- a/src/mesa/shader/arbvertparse.c +++ b/src/mesa/shader/arbvertparse.c @@ -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; } diff --git a/src/mesa/shader/nvvertexec.c b/src/mesa/shader/nvvertexec.c index 269c4c93d8c..064a7f020b9 100644 --- a/src/mesa/shader/nvvertexec.c +++ b/src/mesa/shader/nvvertexec.c @@ -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; diff --git a/src/mesa/shader/nvvertparse.c b/src/mesa/shader/nvvertparse.c index 7e8e749d8cc..e84cf9d5049 100644 --- a/src/mesa/shader/nvvertparse.c +++ b/src/mesa/shader/nvvertparse.c @@ -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: + * + * ::= + * | ... + * | + * + * ::= "PRINT" + * | "PRINT" "," + * | "PRINT" "," + */ +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, 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; diff --git a/src/mesa/shader/nvvertprog.h b/src/mesa/shader/nvvertprog.h index 820b3e5692b..583b9012079 100644 --- a/src/mesa/shader/nvvertprog.h +++ b/src/mesa/shader/nvvertprog.h @@ -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 */ }; diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index c2f4b146b6c..ca0421181ce 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -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); } -- 2.30.2