Streamline code generation by using a fixed size instruction buffer in
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 3 Nov 2005 03:30:34 +0000 (03:30 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 3 Nov 2005 03:30:34 +0000 (03:30 +0000)
arb_program struct.

src/mesa/shader/arbfragparse.c
src/mesa/shader/arbprogparse.c
src/mesa/shader/arbprogparse.h
src/mesa/shader/arbvertparse.c

index 7b9abec1c948344e715ff15fc4c5585d74892149..75c7b35e400e54477ac4bb4be1e7b47c1cfcb9bb 100644 (file)
@@ -190,6 +190,7 @@ _mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
 {
    GLuint i;
    struct arb_program ap;
+   struct fp_instruction *newInstructions;
    (void) target;
 
    /* set the program target before parsing */
@@ -203,6 +204,18 @@ _mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
    /* Copy the relevant contents of the arb_program struct into the
     * fragment_program struct.
     */
+   /* copy instruction buffer */
+   newInstructions = (struct fp_instruction *)
+      _mesa_malloc(ap.Base.NumInstructions * sizeof(struct fp_instruction));
+   if (!newInstructions) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+      return;
+   }
+   _mesa_memcpy(newInstructions, ap.FPInstructions,
+                ap.Base.NumInstructions * sizeof(struct fp_instruction));
+   if (program->Instructions)
+      _mesa_free(program->Instructions);
+   program->Instructions = newInstructions;
    program->Base.String          = ap.Base.String;
    program->Base.NumInstructions = ap.Base.NumInstructions;
    program->Base.NumTemporaries  = ap.Base.NumTemporaries;
@@ -212,7 +225,6 @@ _mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
    program->NumAluInstructions = ap.NumAluInstructions;
    program->NumTexInstructions = ap.NumTexInstructions;
    program->NumTexIndirections = ap.NumTexIndirections;
-
    program->InputsRead     = ap.InputsRead;
    program->OutputsWritten = ap.OutputsWritten;
    for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
@@ -228,6 +240,4 @@ _mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
 #if DEBUG_FP
    _mesa_debug_fp_inst(ap.Base.NumInstructions, ap.FPInstructions);
 #endif
-
-   program->Instructions   = ap.FPInstructions;
 }
index 4e4f2cdd41f68825265f80e632dd0caedf8fdbdb..7b56b078a11062a38553410a96e355ad65d76f44 100644 (file)
@@ -3594,47 +3594,25 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
    }
 }
 
-#endif
-
-
-/**
- * Grow an array of fragment program instructions.
- */
-static struct fp_instruction *
-realloc_fp_instructions(struct fp_instruction *oldArray, GLuint oldSize)
-{
-   struct fp_instruction *array = (struct fp_instruction *)
-      _mesa_realloc(oldArray,
-                    oldSize * sizeof(struct fp_instruction),
-                    (oldSize + 1) * sizeof(struct fp_instruction));
-   return array;
-}
-
-/**
- * Grow an array of vertex program instructions.
- */
-static struct vp_instruction *
-realloc_vp_instructions(struct vp_instruction *oldArray, GLuint oldSize)
-{
-   struct vp_instruction *array = (struct vp_instruction *)
-      _mesa_realloc(oldArray,
-                    oldSize * sizeof(struct vp_instruction),
-                    (oldSize + 1) * sizeof(struct vp_instruction));
-   return array;
-}
+#endif /* DEBUG_PARSING */
 
 
 /**
  * The main loop for parsing a fragment or vertex program
  *
- * \return GL_TRUE on success, GL_FALSE on error.
+ * \return 1 on error, 0 on success
  */
-static GLboolean
+static GLint
 parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
                   struct arb_program *Program)
 {
+   const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
+      ? ctx->Const.FragmentProgram.MaxInstructions
+      : ctx->Const.VertexProgram.MaxInstructions;
    GLint err = 0;
 
+   ASSERT(MAX_INSTRUCTIONS >= maxInst);
+
    Program->MajorVersion = (GLuint) * inst++;
    Program->MinorVersion = (GLuint) * inst++;
 
@@ -3683,44 +3661,25 @@ parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
             break;
 
          case INSTRUCTION:
+            /* check length */
+            if (Program->Base.NumInstructions + 1 >= maxInst) {
+               const char *msg = "Max instruction count exceeded";
+               _mesa_set_program_error(ctx, Program->Position, msg);
+               _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+               return 1;
+            }
             Program->Position = parse_position (&inst);
-
+            /* parse the current instruction */
             if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-               /* Check instruction count.  END counts as an instruction. */
-               if (Program->Base.NumInstructions + 1
-                   == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
-                  const char *msg = "Max instruction count exceeded";
-                  _mesa_set_program_error(ctx, Program->Position, msg);
-                  _mesa_error(ctx, GL_INVALID_OPERATION, msg);
-               }
-
-               /* grow instruction list */
-               Program->FPInstructions
-                  = realloc_fp_instructions(Program->FPInstructions,
-                                            Program->Base.NumInstructions);
-               /* parse the current instruction */
                err = parse_fp_instruction (ctx, &inst, vc_head, Program,
                       &Program->FPInstructions[Program->Base.NumInstructions]);
             }
             else {
-               /* Check instruction count.  END counts as an instruction. */
-               if (Program->Base.NumInstructions + 1
-                   == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
-                  const char *msg = "Max instruction count exceeded";
-                  _mesa_set_program_error(ctx, Program->Position, msg);
-                  _mesa_error(ctx, GL_INVALID_OPERATION, msg);
-               }
-
-               /* grow instruction list */
-               Program->VPInstructions
-                  = realloc_vp_instructions(Program->VPInstructions,
-                                            Program->Base.NumInstructions);
-               /* parse the current instruction */
                err = parse_vp_instruction (ctx, &inst, vc_head, Program,
                       &Program->VPInstructions[Program->Base.NumInstructions]);
             }
 
-            /* increment Program->Base.NumInstructions */
+            /* increment instuction count */
             Program->Base.NumInstructions++;
             break;
 
@@ -3739,8 +3698,6 @@ parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
    /* Finally, tag on an OPCODE_END instruction */
    if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
       const GLuint numInst = Program->Base.NumInstructions;
-      Program->FPInstructions
-         = realloc_fp_instructions(Program->FPInstructions, numInst);
       _mesa_init_fp_instruction(Program->FPInstructions + numInst);
       Program->FPInstructions[numInst].Opcode = FP_OPCODE_END;
       /* YYY Wrong Position in program, whatever, at least not random -> crash
@@ -3750,8 +3707,6 @@ parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
    }
    else {
       const GLuint numInst = Program->Base.NumInstructions;
-      Program->VPInstructions
-         = realloc_vp_instructions(Program->VPInstructions, numInst);
       _mesa_init_vp_instruction(Program->VPInstructions + numInst);
       Program->VPInstructions[numInst].Opcode = VP_OPCODE_END;
       /* YYY Wrong Position in program, whatever, at least not random -> crash
@@ -4017,9 +3972,6 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
 
    program->UsesKill = 0;
 
-   program->FPInstructions = NULL;
-   program->VPInstructions = NULL;
-
    vc_head = NULL;
    err = GL_FALSE;
 
index 947c22e767bc568cf17ad6e36ccce675648df86a..59f8e3b22ed829055fa48f44732563965b23f3ae 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
 #include "nvvertprog.h"
 #include "nvfragprog.h"
 
+
+#define MAX_INSTRUCTIONS 256
+
+
 /**
  * This is basically a union of the vertex_program and fragment_program
  * structs that we can use to parse the program into
  *
- * XXX: this should go into mtypes.h?
+ * XXX we can probably get rid of this entirely someday.
  */
 struct arb_program
 {
    struct program Base;
    struct program_parameter_list *Parameters; 
-   GLuint InputsRead;
-   GLuint OutputsWritten;
+   GLbitfield InputsRead;
+   GLbitfield OutputsWritten;
 
    GLuint Position;       /* Just used for error reporting while parsing */
    GLuint MajorVersion;
    GLuint MinorVersion;
 
    /* ARB_vertex_program specifics */ 
-   struct vp_instruction *VPInstructions;
+   struct vp_instruction VPInstructions[MAX_INSTRUCTIONS];
 
    /* Options currently recognized by the parser */
    /* ARB_fp */
@@ -60,8 +64,8 @@ struct arb_program
    GLboolean HintPositionInvariant;
 
    /* ARB_fragment_program specifics */
-   struct fp_instruction *FPInstructions;
-   GLuint TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; 
+   struct fp_instruction FPInstructions[MAX_INSTRUCTIONS];
+   GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; 
    GLuint NumAluInstructions; 
    GLuint NumTexInstructions;
    GLuint NumTexIndirections;
index 5d1ad3de2e71964593d93ca60572f851f93034a4..2fbfa5fe9e27f58f09836eaf99cf4ed98c2934ce 100644 (file)
@@ -169,6 +169,7 @@ _mesa_parse_arb_vertex_program(GLcontext * ctx, GLenum target,
 {
    struct arb_program ap;
    (void) target;
+   struct vp_instruction *newInstructions;
 
    /* set the program target before parsing */
    ap.Base.Target = GL_VERTEX_PROGRAM_ARB;
@@ -181,13 +182,24 @@ _mesa_parse_arb_vertex_program(GLcontext * ctx, GLenum target,
    /* Copy the relevant contents of the arb_program struct into the 
     * vertex_program struct.
     */
+   /* copy instruction buffer */
+   newInstructions = (struct vp_instruction *)
+      _mesa_malloc(ap.Base.NumInstructions * sizeof(struct vp_instruction));
+   if (!newInstructions) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+      return;
+   }
+   _mesa_memcpy(newInstructions, ap.VPInstructions,
+                ap.Base.NumInstructions * sizeof(struct vp_instruction));
+   if (program->Instructions)
+      _mesa_free(program->Instructions);
+   program->Instructions = newInstructions;
    program->Base.String          = ap.Base.String;
    program->Base.NumInstructions = ap.Base.NumInstructions;
    program->Base.NumTemporaries  = ap.Base.NumTemporaries;
    program->Base.NumParameters   = ap.Base.NumParameters;
    program->Base.NumAttributes   = ap.Base.NumAttributes;
    program->Base.NumAddressRegs  = ap.Base.NumAddressRegs;
-
    program->IsPositionInvariant = ap.HintPositionInvariant;
    program->InputsRead     = ap.InputsRead;
    program->OutputsWritten = ap.OutputsWritten;
@@ -198,10 +210,7 @@ _mesa_parse_arb_vertex_program(GLcontext * ctx, GLenum target,
    }
    program->Parameters     = ap.Parameters; 
 
-   program->Instructions   = ap.VPInstructions;
-
 #if DEBUG_VP
    _mesa_debug_vp_inst(ap.Base.NumInstructions, ap.VPInstructions);
 #endif
-
 }