Experimental PRINT instruction for NV_vertex_program.
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Dec 2004 03:07:18 +0000 (03:07 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Dec 2004 03:07:18 +0000 (03:07 +0000)
Basically, this lets you put a "PRINT 'mesage', register;" statement in a
vertex program to aid in debugging.

src/mesa/shader/arbvertparse.c
src/mesa/shader/nvvertexec.c
src/mesa/shader/nvvertparse.c
src/mesa/shader/nvvertprog.h
src/mesa/shader/program.c

index fb6a642..33086c2 100644 (file)
 #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;
       }
index 269c4c9..064a7f0 100644 (file)
@@ -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;
index 7e8e749..e84cf9d 100644 (file)
@@ -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;
index 820b3e5..583b901 100644 (file)
@@ -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 */
 };
 
 
index c2f4b14..ca04211 100644 (file)
@@ -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);
    }