summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorNicolai Hähnle <nhaehnle@gmail.com>2009-07-23 21:38:28 +0200
committerNicolai Hähnle <nhaehnle@gmail.com>2009-07-27 20:32:06 +0200
commit8bcb6ef786dc41049b56e6efeca0f5788cfefe5a (patch)
treef9ee8b1b20dd80390351e22b67989d2b0933596d /src/mesa/drivers
parentc5cb9a337881229f1db462632fa1d64e2677f316 (diff)
r300/compiler: Lay groundwork for better error handling
Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog.h2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c22
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c12
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c37
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog.h2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c23
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.c50
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.h9
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c18
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h2
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog_common.c4
-rw-r--r--src/mesa/drivers/dri/r300/r300_vertprog.c4
12 files changed, 113 insertions, 72 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h
index 21507bd8e0..2d094c3618 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h
@@ -40,7 +40,7 @@
#include "radeon_program.h"
-extern GLboolean r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
+extern void r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
extern void r300FragmentProgramDump(struct rX00_fragment_program_code *c);
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
index 672b36532c..f2472d6ce1 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
@@ -51,7 +51,7 @@
struct r300_fragment_program_code *code = &c->code->code.r300
#define error(fmt, args...) do { \
- fprintf(stderr, "%s::%s(): " fmt "\n", \
+ rc_error(&c->Base, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
} while(0)
@@ -91,7 +91,7 @@ static void use_temporary(struct r300_fragment_program_code *code, GLuint index)
}
-static GLuint translate_rgb_opcode(GLuint opcode)
+static GLuint translate_rgb_opcode(struct r300_fragment_program_compiler * c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R300_ALU_OUTC_CMP;
@@ -110,7 +110,7 @@ static GLuint translate_rgb_opcode(GLuint opcode)
}
}
-static GLuint translate_alpha_opcode(GLuint opcode)
+static GLuint translate_alpha_opcode(struct r300_fragment_program_compiler * c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R300_ALU_OUTA_CMP;
@@ -148,8 +148,8 @@ static GLboolean emit_alu(void* data, struct radeon_pair_instruction* inst)
int j;
code->node[code->cur_node].alu_end++;
- code->alu.inst[ip].inst0 = translate_rgb_opcode(inst->RGB.Opcode);
- code->alu.inst[ip].inst2 = translate_alpha_opcode(inst->Alpha.Opcode);
+ code->alu.inst[ip].inst0 = translate_rgb_opcode(c, inst->RGB.Opcode);
+ code->alu.inst[ip].inst2 = translate_alpha_opcode(c, inst->Alpha.Opcode);
for(j = 0; j < 3; ++j) {
GLuint src = inst->RGB.Src[j].Index | (inst->RGB.Src[j].Constant << 5);
@@ -326,7 +326,7 @@ static const struct radeon_pair_handler pair_handler = {
* Final compilation step: Turn the intermediate radeon_program into
* machine-readable instructions.
*/
-GLboolean r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
+void r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
{
struct r300_fragment_program_code *code = &compiler->code->code.r300;
@@ -334,12 +334,10 @@ GLboolean r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *
code->node[0].alu_end = -1;
code->node[0].tex_end = -1;
- if (!radeonPairProgram(&compiler->Base, &pair_handler, compiler))
- return GL_FALSE;
-
- if (!finish_node(compiler))
- return GL_FALSE;
+ radeonPairProgram(&compiler->Base, &pair_handler, compiler);
+ if (compiler->Base.Error)
+ return;
- return GL_TRUE;
+ finish_node(compiler);
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
index 30fedb4211..dae77a575c 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -235,10 +235,8 @@ static void rewrite_depth_out(struct gl_program *prog)
}
}
-GLboolean r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
+void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
{
- GLboolean success = GL_FALSE;
-
if (c->Base.Debug) {
fflush(stdout);
_mesa_printf("Fragment Program: Initial program:\n");
@@ -300,18 +298,16 @@ GLboolean r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c
rc_mesa_to_rc_program(&c->Base, c->program);
if (c->is_r500) {
- success = r500BuildFragmentProgramHwCode(c);
+ r500BuildFragmentProgramHwCode(c);
} else {
- success = r300BuildFragmentProgramHwCode(c);
+ r300BuildFragmentProgramHwCode(c);
}
- if (!success || c->Base.Debug) {
+ if (c->Base.Debug) {
if (c->is_r500) {
r500FragmentProgramDump(c->code);
} else {
r300FragmentProgramDump(c->code);
}
}
-
- return success;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
index a0e081fe6f..9edff6b039 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -384,22 +384,25 @@ static void t_inputs_outputs(struct r300_vertex_program_code *vp, struct gl_prog
}
}
-static GLboolean translate_vertex_program(struct r300_vertex_program_compiler * compiler)
+static void translate_vertex_program(struct r300_vertex_program_compiler * compiler)
{
struct prog_instruction *vpi = compiler->program->Instructions;
- GLuint *inst;
compiler->code->pos_end = 0; /* Not supported yet */
compiler->code->length = 0;
t_inputs_outputs(compiler->code, compiler->program);
- for (inst = compiler->code->body.d; vpi->Opcode != OPCODE_END;
- vpi++, inst += 4) {
+ for (; vpi->Opcode != OPCODE_END; vpi++) {
+ GLuint *inst = compiler->code->body.d + compiler->code->length;
+
/* Skip instructions writing to non-existing destination */
- if (!valid_dst(compiler->code, &vpi->DstReg)) {
- inst -= 4;
+ if (!valid_dst(compiler->code, &vpi->DstReg))
continue;
+
+ if (compiler->code->length >= VSF_MAX_FRAGMENT_LENGTH) {
+ rc_error(&compiler->Base, "Vertex program has too many instructions\n");
+ return;
}
switch (vpi->Opcode) {
@@ -424,17 +427,15 @@ static GLboolean translate_vertex_program(struct r300_vertex_program_compiler *
case OPCODE_SGE: ei_vector2(compiler->code, VE_SET_GREATER_THAN_EQUAL, vpi, inst); break;
case OPCODE_SLT: ei_vector2(compiler->code, VE_SET_LESS_THAN, vpi, inst); break;
default:
- fprintf(stderr, "Unknown opcode %i\n", vpi->Opcode);
- return GL_FALSE;
+ rc_error(&compiler->Base, "Unknown opcode %i\n", vpi->Opcode);
+ return;
}
- }
- compiler->code->length = (inst - compiler->code->body.d);
- if (compiler->code->length >= VSF_MAX_FRAGMENT_LENGTH) {
- return GL_FALSE;
- }
+ compiler->code->length += 4;
- return GL_TRUE;
+ if (compiler->Base.Error)
+ return;
+ }
}
struct temporary_allocation {
@@ -768,10 +769,8 @@ static GLboolean swizzleIsNative(GLuint opcode, struct prog_src_register reg)
-GLboolean r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
+void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
{
- GLboolean success;
-
if (compiler->state.WPosAttr != FRAG_ATTRIB_MAX) {
pos_as_texcoord(compiler->program, compiler->state.WPosAttr - FRAG_ATTRIB_TEX0);
}
@@ -832,10 +831,8 @@ GLboolean r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compi
assert(compiler->program->NumInstructions);
- success = translate_vertex_program(compiler);
+ translate_vertex_program(compiler);
compiler->code->InputsRead = compiler->program->InputsRead;
compiler->code->OutputsWritten = compiler->program->OutputsWritten;
-
- return success;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h
index a1ffde1e83..e405267bb3 100644
--- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h
@@ -39,7 +39,7 @@
#include "radeon_compiler.h"
#include "radeon_nqssadce.h"
-extern GLboolean r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
+extern void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
extern void r500FragmentProgramDump(struct rX00_fragment_program_code *c);
diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
index f8a1dc5fbe..5b0b306b9c 100644
--- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
@@ -55,7 +55,7 @@
struct r500_fragment_program_code *code = &c->code->code.r500
#define error(fmt, args...) do { \
- fprintf(stderr, "%s::%s(): " fmt "\n", \
+ rc_error(&c->Base, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
} while(0)
@@ -87,7 +87,7 @@ static GLboolean emit_const(void *data, GLuint file, GLuint idx, GLuint *hwindex
return GL_TRUE;
}
-static GLuint translate_rgb_op(GLuint opcode)
+static GLuint translate_rgb_op(struct r300_fragment_program_compiler *c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R500_ALU_RGBA_OP_CMP;
@@ -108,7 +108,7 @@ static GLuint translate_rgb_op(GLuint opcode)
}
}
-static GLuint translate_alpha_op(GLuint opcode)
+static GLuint translate_alpha_op(struct r300_fragment_program_compiler *c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R500_ALPHA_OP_CMP;
@@ -191,8 +191,8 @@ static GLboolean emit_paired(void *data, struct radeon_pair_instruction *inst)
int ip = ++code->inst_end;
- code->inst[ip].inst5 = translate_rgb_op(inst->RGB.Opcode);
- code->inst[ip].inst4 = translate_alpha_op(inst->Alpha.Opcode);
+ code->inst[ip].inst5 = translate_rgb_op(c, inst->RGB.Opcode);
+ code->inst[ip].inst4 = translate_alpha_op(c, inst->Alpha.Opcode);
if (inst->RGB.OutputWriteMask || inst->Alpha.OutputWriteMask || inst->Alpha.DepthWriteMask)
code->inst[ip].inst0 = R500_INST_TYPE_OUT;
@@ -301,7 +301,7 @@ static const struct radeon_pair_handler pair_handler = {
.MaxHwTemps = 128
};
-GLboolean r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
+void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
{
struct r500_fragment_program_code *code = &compiler->code->code.r500;
@@ -310,20 +310,19 @@ GLboolean r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *
code->inst_offset = 0;
code->inst_end = -1;
- if (!radeonPairProgram(&compiler->Base, &pair_handler, compiler))
- return GL_FALSE;
+ radeonPairProgram(&compiler->Base, &pair_handler, compiler);
+ if (compiler->Base.Error)
+ return;
if ((code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
/* This may happen when dead-code elimination is disabled or
* when most of the fragment program logic is leading to a KIL */
if (code->inst_end >= 511) {
- error("Introducing fake OUT: Too many instructions");
- return GL_FALSE;
+ rc_error(&compiler->Base, "Introducing fake OUT: Too many instructions");
+ return;
}
int ip = ++code->inst_end;
code->inst[ip].inst0 = R500_INST_TYPE_OUT | R500_INST_TEX_SEM_WAIT;
}
-
- return GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
index 17c9b17682..7b8322c201 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
@@ -22,6 +22,8 @@
#include "radeon_compiler.h"
+#include <stdarg.h>
+
void rc_init(struct radeon_compiler * c)
{
@@ -36,4 +38,52 @@ void rc_init(struct radeon_compiler * c)
void rc_destroy(struct radeon_compiler * c)
{
memory_pool_destroy(&c->Pool);
+ free(c->ErrorMsg);
+}
+
+void rc_debug(struct radeon_compiler * c, const char * fmt, ...)
+{
+ va_list ap;
+
+ if (!c->Debug)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void rc_error(struct radeon_compiler * c, const char * fmt, ...)
+{
+ va_list ap;
+
+ c->Error = GL_TRUE;
+
+ if (!c->ErrorMsg) {
+ /* Only remember the first error */
+ char buf[1024];
+ int written;
+
+ va_start(ap, fmt);
+ written = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ if (written < sizeof(buf)) {
+ c->ErrorMsg = strdup(buf);
+ } else {
+ c->ErrorMsg = malloc(written + 1);
+
+ va_start(ap, fmt);
+ vsnprintf(c->ErrorMsg, written + 1, fmt, ap);
+ va_end(ap);
+ }
+ }
+
+ if (c->Debug) {
+ fprintf(stderr, "r300compiler error: ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
index b98b1c9e6b..f0ed78a11f 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
@@ -51,11 +51,16 @@ struct radeon_compiler {
struct memory_pool Pool;
struct rc_program Program;
GLboolean Debug;
+ GLboolean Error;
+ char * ErrorMsg;
};
void rc_init(struct radeon_compiler * c);
void rc_destroy(struct radeon_compiler * c);
+void rc_debug(struct radeon_compiler * c, const char * fmt, ...);
+void rc_error(struct radeon_compiler * c, const char * fmt, ...);
+
struct r300_fragment_program_compiler {
struct radeon_compiler Base;
struct rX00_fragment_program_code *code;
@@ -64,7 +69,7 @@ struct r300_fragment_program_compiler {
GLboolean is_r500;
};
-GLboolean r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c);
+void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c);
struct r300_vertex_program_compiler {
@@ -74,6 +79,6 @@ struct r300_vertex_program_compiler {
struct gl_program *program;
};
-GLboolean r3xx_compile_vertex_program(struct r300_vertex_program_compiler* c);
+void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* c);
#endif /* RADEON_COMPILER_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
index ffc218b5ec..ca63b90696 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
@@ -40,9 +40,8 @@
#include "shader/prog_print.h"
#define error(fmt, args...) do { \
- fprintf(stderr, "r300 driver problem: %s::%s(): " fmt "\n", \
+ rc_error(s->Compiler, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
- s->Error = GL_TRUE; \
} while(0)
struct pair_state_instruction {
@@ -121,7 +120,6 @@ struct pair_register_translation {
struct pair_state {
struct radeon_compiler * Compiler;
const struct radeon_pair_handler *Handler;
- GLboolean Error;
GLboolean Verbose;
void *UserData;
@@ -583,7 +581,7 @@ static void emit_all_tex(struct pair_state *s)
_mesa_printf(" BEGIN_TEX\n");
if (s->Handler->BeginTexBlock)
- s->Error = s->Error || !s->Handler->BeginTexBlock(s->UserData);
+ s->Compiler->Error = s->Compiler->Error || !s->Handler->BeginTexBlock(s->UserData);
for(pairinst = readytex; pairinst; pairinst = pairinst->NextReady) {
struct prog_instruction *inst = &pairinst->Instruction;
@@ -616,7 +614,7 @@ static void emit_all_tex(struct pair_state *s)
rpti.SrcIndex = inst->SrcReg[0].Index;
rpti.SrcSwizzle = inst->SrcReg[0].Swizzle;
- s->Error = s->Error || !s->Handler->EmitTex(s->UserData, &rpti);
+ s->Compiler->Error = s->Compiler->Error || !s->Handler->EmitTex(s->UserData, &rpti);
}
if (s->Compiler->Debug)
@@ -642,7 +640,7 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
index = get_hw_reg(s, src.File, src.Index);
} else {
constant = 1;
- s->Error |= !s->Handler->EmitConst(s->UserData, src.File, src.Index, &index);
+ s->Compiler->Error |= !s->Handler->EmitConst(s->UserData, src.File, src.Index, &index);
}
for(i = 0; i < 3; ++i) {
@@ -869,11 +867,11 @@ static void emit_alu(struct pair_state *s)
if (s->Compiler->Debug)
radeonPrintPairInstruction(&pair);
- s->Error = s->Error || !s->Handler->EmitPaired(s->UserData, &pair);
+ s->Compiler->Error = s->Compiler->Error || !s->Handler->EmitPaired(s->UserData, &pair);
}
-GLboolean radeonPairProgram(
+void radeonPairProgram(
struct radeon_compiler * compiler,
const struct radeon_pair_handler* handler, void *userdata)
{
@@ -891,7 +889,7 @@ GLboolean radeonPairProgram(
scan_instructions(&s);
allocate_input_registers(&s);
- while(!s.Error &&
+ while(!s.Compiler->Error &&
(s.ReadyTEX || s.ReadyRGB || s.ReadyAlpha || s.ReadyFullALU)) {
if (s.ReadyTEX)
emit_all_tex(&s);
@@ -902,8 +900,6 @@ GLboolean radeonPairProgram(
if (s.Compiler->Debug)
_mesa_printf(" END\n");
-
- return !s.Error;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
index 3992082662..46196fb1c8 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
@@ -141,7 +141,7 @@ struct radeon_pair_handler {
GLuint MaxHwTemps;
};
-GLboolean radeonPairProgram(
+void radeonPairProgram(
struct radeon_compiler * compiler,
const struct radeon_pair_handler*, void *userdata);
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
index 27aec64575..0ce57e834b 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_common.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
@@ -99,8 +99,8 @@ static void translate_fragment_program(GLcontext *ctx, struct r300_fragment_prog
compiler.program = _mesa_clone_program(ctx, &cont->Base.Base);
compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) ? GL_TRUE : GL_FALSE;
- if (!r3xx_compile_fragment_program(&compiler))
- fp->error = GL_TRUE;
+ r3xx_compile_fragment_program(&compiler);
+ fp->error = compiler.Base.Error;
fp->InputsRead = compiler.Base.Program.InputsRead;
fp->Base = compiler.program;
diff --git a/src/mesa/drivers/dri/r300/r300_vertprog.c b/src/mesa/drivers/dri/r300/r300_vertprog.c
index dfb2a9e3d8..91d9d8ae94 100644
--- a/src/mesa/drivers/dri/r300/r300_vertprog.c
+++ b/src/mesa/drivers/dri/r300/r300_vertprog.c
@@ -125,8 +125,8 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
_mesa_insert_mvp_code(ctx, (struct gl_vertex_program *)compiler.program);
}
- if (!r3xx_compile_vertex_program(&compiler))
- vp->error = GL_TRUE;
+ r3xx_compile_vertex_program(&compiler);
+ vp->error = compiler.Base.Error;
rc_destroy(&compiler.Base);