r300/compiler: Lay groundwork for better error handling

Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
This commit is contained in:
Nicolai Hähnle 2009-07-23 21:38:28 +02:00
parent c5cb9a3378
commit 8bcb6ef786
12 changed files with 113 additions and 72 deletions

View file

@ -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);

View file

@ -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;
radeonPairProgram(&compiler->Base, &pair_handler, compiler);
if (compiler->Base.Error)
return;
if (!finish_node(compiler))
return GL_FALSE;
return GL_TRUE;
finish_node(compiler);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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);