Streamline code generation by using a fixed size instruction buffer in
arb_program struct.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.3
|
||||
* Version: 6.5
|
||||
*
|
||||
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
||||
*
|
||||
@@ -31,25 +31,29 @@
|
||||
#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;
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user