From c3ac2709967299481928dee175a124bf8a72fecd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 21 Jan 2007 16:45:40 +1100 Subject: nouveau: start converting shaders into a tree format again.. No branching stuff implemented yet. Works enough for gears, probably other stuff broken. --- src/mesa/drivers/dri/nouveau/nouveau_shader.c | 6 +- src/mesa/drivers/dri/nouveau/nouveau_shader.h | 60 +++- src/mesa/drivers/dri/nouveau/nouveau_shader_0.c | 375 +++++++++++++++--------- src/mesa/drivers/dri/nouveau/nouveau_shader_2.c | 45 ++- 4 files changed, 315 insertions(+), 171 deletions(-) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/src/mesa/drivers/dri/nouveau/nouveau_shader.c index e4db115362..f911347d62 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.c @@ -563,12 +563,12 @@ nvsDumpInstruction(nvsInstruction * inst, int slot, int lvl) } void -nvsDumpFragmentList(nvsFragmentList *f, int lvl) +nvsDumpFragmentList(nvsFragmentHeader *f, int lvl) { while (f) { - switch (f->fragment->type) { + switch (f->type) { case NVS_INSTRUCTION: - nvsDumpInstruction((nvsInstruction*)f->fragment, 0, lvl); + nvsDumpInstruction((nvsInstruction*)f, 0, lvl); break; default: fprintf(stderr, "%s: Only NVS_INSTRUCTION fragments can be in" diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index 1a971e56bf..a3ab027142 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -12,19 +12,18 @@ typedef struct _nvsFunc nvsFunc; #define NVS_MAX_ADDRESS 2 #define NVS_MAX_INSNS 4096 -typedef struct { +typedef struct _nvs_fragment_header { + struct _nvs_fragment_header *parent; + struct _nvs_fragment_header *prev; + struct _nvs_fragment_header *next; enum { NVS_INSTRUCTION, + NVS_BRANCH, + NVS_LOOP, + NVS_SUBROUTINE } type; - int position; } nvsFragmentHeader; -typedef struct _nvs_fragment_list { - struct _nvs_fragment_list *prev; - struct _nvs_fragment_list *next; - nvsFragmentHeader *fragment; -} nvsFragmentList; - typedef struct _nouveauShader { union { struct gl_vertex_program vp; @@ -59,8 +58,7 @@ typedef struct _nouveauShader { /* Pass-private data */ void *pass_rec; - nvsFragmentList *list_head; - nvsFragmentList *list_tail; + nvsFragmentHeader *program_tree; } nouveauShader, *nvsPtr; typedef enum { @@ -186,7 +184,8 @@ typedef enum { NVS_TEX_TARGET_UNKNOWN = 0 } nvsTexTarget; -typedef struct { +/* Arith/TEX instructions */ +typedef struct nvs_instruction { nvsFragmentHeader header; nvsOpcode op; @@ -207,6 +206,43 @@ typedef struct { int cond_update; } nvsInstruction; +/* BRA, CAL, IF */ +typedef struct nvs_branch { + nvsFragmentHeader header; + + nvsOpcode op; + + nvsCond cond; + nvsSwzComp cond_swizzle[4]; + int cond_test; + + nvsFragmentHeader *target_head; + nvsFragmentHeader *target_tail; + nvsFragmentHeader *else_head; + nvsFragmentHeader *else_tail; +} nvsBranch; + +/* LOOP+ENDLOOP */ +typedef struct { + nvsFragmentHeader header; + + int count; + int initial; + int increment; + + nvsFragmentHeader *insn_head; + nvsFragmentHeader *insn_tail; +} nvsLoop; + +/* label+following instructions */ +typedef struct nvs_subroutine { + nvsFragmentHeader header; + + char * label; + nvsFragmentHeader *insn_head; + nvsFragmentHeader *insn_tail; +} nvsSubroutine; + #define SMASK_X (1<<0) #define SMASK_Y (1<<1) #define SMASK_Z (1<<2) @@ -353,7 +389,7 @@ nvsSwizzle(nvsRegister reg, nvsSwzComp x, nvsSwzComp y, extern GLboolean nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs); extern void nvsDisasmHWShader(nvsPtr); -extern void nvsDumpFragmentList(nvsFragmentList *f, int lvl); +extern void nvsDumpFragmentList(nvsFragmentHeader *f, int lvl); extern nouveauShader *nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c index 34475cad03..503eae36b7 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c @@ -40,6 +40,7 @@ #include "nouveau_context.h" #include "nouveau_shader.h" +#include "nouveau_msg.h" static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = { NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, @@ -134,21 +135,63 @@ struct pass0_rec { #define W NVS_SWZ_W static void -pass0_append_fragment(nouveauShader *nvs, nvsFragmentHeader *fragment) +pass0_append_fragment(nvsFragmentHeader *parent, + nvsFragmentHeader *fragment, + int pos) { - nvsFragmentList *list = calloc(1, sizeof(nvsFragmentList)); - if (!list) - return; - - list->fragment = fragment; - list->prev = nvs->list_tail; - if ( nvs->list_tail) - nvs->list_tail->next = list; - if (!nvs->list_head) - nvs->list_head = list; - nvs->list_tail = list; - - nvs->inst_count++; + nvsFragmentHeader **head, **tail; + assert(parent && fragment); + + switch (parent->type) { + case NVS_BRANCH: + if (pos == 0) { + head = &((nvsBranch *)parent)->target_head; + tail = &((nvsBranch *)parent)->target_tail; + } else { + head = &((nvsBranch *)parent)->else_head; + tail = &((nvsBranch *)parent)->else_tail; + } + break; + case NVS_LOOP: + head = &((nvsLoop *)parent)->insn_head; + tail = &((nvsLoop *)parent)->insn_tail; + break; + case NVS_SUBROUTINE: + head = &((nvsSubroutine *)parent)->insn_head; + tail = &((nvsSubroutine *)parent)->insn_tail; + break; + default: + assert(0); + break; + } + + fragment->parent = parent; + fragment->prev = *tail; + fragment->next = NULL; + if (!(*head)) + *head = fragment; + else + (*tail)->next = fragment; + *tail = fragment; + +} + +static nvsSubroutine * +pass0_create_subroutine(nouveauShader *nvs, const char *label) +{ + nvsSubroutine *sub; + + sub = CALLOC_STRUCT(nvs_subroutine); + if (sub) { + sub->header.type = NVS_SUBROUTINE; + sub->label = strdup(label); + if (!nvs->program_tree) + nvs->program_tree = &sub->header; + else + pass0_append_fragment(nvs->program_tree, &sub->header, 0); + } + + return sub; } static void @@ -312,41 +355,40 @@ pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) } static nvsInstruction * -pass0_emit(nouveauShader *nvs, nvsOpcode op, nvsRegister dst, - unsigned int mask, int saturate, +pass0_emit(nouveauShader *nvs, nvsFragmentHeader *parent, int fpos, + nvsOpcode op, nvsRegister dst, + unsigned int mask, int saturate, nvsRegister src0, nvsRegister src1, nvsRegister src2) { - struct pass0_rec *rec = nvs->pass_rec; - nvsInstruction *sif = NULL; - - /* Seems mesa doesn't explicitly 0 this.. */ - if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) - saturate = 0; - - sif = calloc(1, sizeof(nvsInstruction)); - if (sif) { - sif->header.type = NVS_INSTRUCTION; - sif->header.position = rec->nvs_ipos++; - sif->op = op; - sif->saturate = saturate; - sif->dest = dst; - sif->mask = mask; - sif->src[0] = src0; - sif->src[1] = src1; - sif->src[2] = src2; - sif->cond = COND_TR; - sif->cond_reg = 0; - sif->cond_test = 0; - sif->cond_update = 0; - pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP); - pass0_append_fragment(nvs, (nvsFragmentHeader *)sif); - } - - return sif; + nvsInstruction *sif; + + sif = CALLOC_STRUCT(nvs_instruction); + if (!sif) + return NULL; + + /* Seems mesa doesn't explicitly 0 this.. */ + if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) + saturate = 0; + + sif->op = op; + sif->saturate = saturate; + sif->dest = dst; + sif->mask = mask; + sif->src[0] = src0; + sif->src[1] = src1; + sif->src[2] = src2; + sif->cond = COND_TR; + sif->cond_reg = 0; + sif->cond_test = 0; + sif->cond_update= 0; + pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP); + pass0_append_fragment(parent, &sif->header, fpos); + + return sif; } static void -pass0_fixup_swizzle(nvsPtr nvs, +pass0_fixup_swizzle(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, struct prog_src_register *src, unsigned int sm1, unsigned int sm2) @@ -376,7 +418,7 @@ pass0_fixup_swizzle(nvsPtr nvs, */ pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); pass0_make_src_reg(nvs, &sr, src); - pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); } else { if (fixup_1) @@ -391,10 +433,10 @@ pass0_fixup_swizzle(nvsPtr nvs, /* Any combination with SWIZZLE_ONE */ pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id); pass0_make_swizzle(sm2const.swizzle, sm2); - pass0_emit(nvs, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); } else { /* SWIZZLE_ZERO || arbitrary negate */ - pass0_emit(nvs, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); } src->File = PROGRAM_TEMPORARY; @@ -404,7 +446,8 @@ pass0_fixup_swizzle(nvsPtr nvs, #define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3)) static void -pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) +pass0_check_sources(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, + struct prog_instruction *inst) { unsigned int insrc = -1, constsrc = -1; int i; @@ -444,7 +487,7 @@ pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) */ if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && sm_1 != MAKE_SWIZZLE4(2,2,2,2)) || sm_2 != MAKE_SWIZZLE4(1,1,1,1)) { - pass0_fixup_swizzle(nvs, src, sm_1, sm_2); + pass0_fixup_swizzle(nvs, parent, fpos, src, sm_1, sm_2); /* The source is definitely in a temp now, so don't bother checking * for multiple ATTRIB/CONST regs. */ @@ -473,7 +516,7 @@ pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) if (do_mov) { pass0_make_src_reg(nvs, &sr, src); pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); src->File = PROGRAM_TEMPORARY; @@ -484,7 +527,9 @@ pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) } static GLboolean -pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) +pass0_emulate_instruction(nouveauShader *nvs, + nvsFragmentHeader *parent, int fpos, + struct prog_instruction *inst) { nvsFunc *shader = nvs->func; nvsRegister src[3], dest, temp; @@ -504,10 +549,10 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) switch (inst->Opcode) { case OPCODE_ABS: if (shader->caps & SCAP_SRC_ABS) - pass0_emit(nvs, NVS_OP_MOV, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dest, mask, sat, nvsAbs(src[0]), nvr_unused, nvr_unused); else - pass0_emit(nvs, NVS_OP_MAX, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_MAX, dest, mask, sat, src[0], nvsNegate(src[0]), nvr_unused); break; case OPCODE_KIL: @@ -516,12 +561,12 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) */ /* MOVC0 temp, src */ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - nvsinst = pass0_emit(nvs, NVS_OP_MOV, temp, SMASK_ALL, 0, + nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_MOV, temp, SMASK_ALL, 0, src[0], nvr_unused, nvr_unused); nvsinst->cond_update = 1; nvsinst->cond_reg = 0; /* KIL_NV (LT0.xyzw) temp */ - nvsinst = pass0_emit(nvs, NVS_OP_KIL, nvr_unused, 0, 0, + nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_KIL, nvr_unused, 0, 0, nvr_unused, nvr_unused, nvr_unused); nvsinst->cond = COND_LT; nvsinst->cond_reg = 0; @@ -532,9 +577,9 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) break; case OPCODE_LRP: pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MAD, temp, mask, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, temp, mask, 0, nvsNegate(src[0]), src[2], src[2]); - pass0_emit(nvs, NVS_OP_MAD, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dest, mask, sat, src[0], src[1], temp); break; case OPCODE_POW: @@ -542,17 +587,17 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) shader->SupportsOpcode(shader, NVS_OP_EX2)) { pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); /* LG2 temp.x, src0.c */ - pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_LG2, temp, SMASK_X, 0, nvsSwizzle(src[0], X, X, X, X), nvr_unused, nvr_unused); /* MUL temp.x, temp.x, src1.c */ - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_X, 0, nvsSwizzle(temp, X, X, X, X), nvsSwizzle(src[1], X, X, X, X), nvr_unused); /* EX2 dest, temp.x */ - pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_EX2, dest, mask, sat, nvsSwizzle(temp, X, X, X, X), nvr_unused, nvr_unused); @@ -571,42 +616,42 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) COPY_4V(nvs->params[rec->const_half.index].val, const_half); } pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_LG2, temp, SMASK_X, 0, nvsAbs(nvsSwizzle(src[0], X, X, X, X)), nvr_unused, nvr_unused); - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_X, 0, nvsSwizzle(temp, X, X, X, X), nvsNegate(rec->const_half), nvr_unused); - pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_EX2, dest, mask, sat, nvsSwizzle(temp, X, X, X, X), nvr_unused, nvr_unused); break; case OPCODE_SCS: if (mask & SMASK_X) - pass0_emit(nvs, NVS_OP_COS, dest, SMASK_X, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_COS, dest, SMASK_X, sat, nvsSwizzle(src[0], X, X, X, X), nvr_unused, nvr_unused); if (mask & SMASK_Y) - pass0_emit(nvs, NVS_OP_SIN, dest, SMASK_Y, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_SIN, dest, SMASK_Y, sat, nvsSwizzle(src[0], X, X, X, X), nvr_unused, nvr_unused); break; case OPCODE_SUB: - pass0_emit(nvs, NVS_OP_ADD, dest, mask, sat, + pass0_emit(nvs, parent, fpos, NVS_OP_ADD, dest, mask, sat, src[0], nvsNegate(src[1]), nvr_unused); break; case OPCODE_XPD: pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_ALL, 0, + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_ALL, 0, nvsSwizzle(src[0], Z, X, Y, Y), nvsSwizzle(src[1], Y, Z, X, X), nvr_unused); - pass0_emit(nvs, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, nvsSwizzle(src[0], Y, Z, X, X), nvsSwizzle(src[1], Z, X, Y, Y), nvsNegate(temp)); @@ -621,90 +666,132 @@ pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) } static GLboolean -pass0_translate_instructions(nouveauShader *nvs) +pass0_translate_arith(nouveauShader *nvs, struct gl_program *prog, + int ipos, int fpos, + nvsFragmentHeader *parent) { - struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp; - nvsFunc *shader = nvs->func; - int ipos; - - for (ipos=0; iposNumInstructions; ipos++) { - struct prog_instruction *inst = &prog->Instructions[ipos]; - - if (inst->Opcode == OPCODE_END) - break; - - /* Deal with multiple ATTRIB/PARAM in a single instruction */ - pass0_check_sources(nvs, inst); - - /* Now it's safe to do the prog_instruction->nvsInstruction conversion */ - if (shader->SupportsOpcode(shader, pass0_make_opcode(inst->Opcode))) { - nvsInstruction *nvsinst; - nvsRegister src[3], dest; - int i; - - for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) - pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); - pass0_make_dst_reg(nvs, &dest, &inst->DstReg); - - nvsinst = pass0_emit(nvs, - pass0_make_opcode(inst->Opcode), - dest, - pass0_make_mask(inst->DstReg.WriteMask), - (inst->SaturateMode != SATURATE_OFF), - src[0], src[1], src[2]); - nvsinst->tex_unit = inst->TexSrcUnit; - nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget); - /* TODO when NV_fp/vp is implemented */ - nvsinst->cond = COND_TR; - } else { - if (!pass0_emulate_instruction(nvs, inst)) - return GL_FALSE; - } - } + struct prog_instruction *inst = &prog->Instructions[ipos]; + nvsFunc *shader = nvs->func; + nvsInstruction *nvsinst; + GLboolean ret; + + /* Deal with multiple ATTRIB/PARAM in a single instruction */ + pass0_check_sources(nvs, parent, fpos, inst); + + /* Now it's safe to do the prog_instruction->nvsInstruction + * conversion + */ + if (shader->SupportsOpcode(shader, + pass0_make_opcode(inst->Opcode))) { + nvsRegister src[3], dest; + int i; + + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + nvsinst = pass0_emit(nvs, parent, fpos, + pass0_make_opcode(inst->Opcode), + dest, + pass0_make_mask(inst->DstReg.WriteMask), + (inst->SaturateMode != SATURATE_OFF), + src[0], src[1], src[2]); + nvsinst->tex_unit = inst->TexSrcUnit; + nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget); + /* TODO when NV_fp/vp is implemented */ + nvsinst->cond = COND_TR; + + ret = GL_TRUE; + } else + ret = pass0_emulate_instruction(nvs, parent, fpos, inst); + + return ret; +} - return GL_TRUE; +static GLboolean +pass0_translate_instructions(nouveauShader *nvs, int ipos, int fpos, + nvsFragmentHeader *parent) +{ + struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp; + + while (1) { + struct prog_instruction *inst = &prog->Instructions[ipos]; + + switch (inst->Opcode) { + case OPCODE_END: + return GL_TRUE; + case OPCODE_BRA: + case OPCODE_CAL: + //case OPCDOE_RET: + //case OPCODE_LOOP: + //case OPCODE_ENDLOOP: + //case OPCODE_IF: + //case OPCODE_ELSE: + //case OPCODE_ENDIF: + WARN_ONCE("branch ops unimplemented\n"); + return GL_FALSE; + break; + default: + if (!pass0_translate_arith(nvs, prog, + ipos, fpos, parent)) + return GL_FALSE; + break; + } + + ipos++; + } + + return GL_TRUE; } GLboolean nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) { - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - struct gl_program *prog = (struct gl_program*)nvs; - struct gl_vertex_program *vp = (struct gl_vertex_program *)prog; - struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; - struct pass0_rec *rec; - int ret; - - switch (prog->Target) { - case GL_VERTEX_PROGRAM_ARB: - nvs->func = &nmesa->VPfunc; - if (vp->IsPositionInvariant) - _mesa_insert_mvp_code(ctx, vp); + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct gl_program *prog = (struct gl_program*)nvs; + struct gl_vertex_program *vp = (struct gl_vertex_program *)prog; + struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; + struct pass0_rec *rec; + int ret = GL_FALSE; + + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: + nvs->func = &nmesa->VPfunc; + + if (vp->IsPositionInvariant) + _mesa_insert_mvp_code(ctx, vp); #if 0 - if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED) - pass0_insert_ff_clip_planes(); + if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED) + pass0_insert_ff_clip_planes(); #endif - break; - case GL_FRAGMENT_PROGRAM_ARB: - nvs->func = &nmesa->FPfunc; - if (fp->FogOption != GL_NONE) - _mesa_append_fog_code(ctx, fp); - break; - default: - fprintf(stderr, "Unknown program type %d", prog->Target); - return GL_FALSE; - } - - rec = calloc(1, sizeof(struct pass0_rec)); - rec->next_temp = prog->NumTemporaries; - nvs->pass_rec = rec; - - ret = pass0_translate_instructions(nvs); - if (!ret) { - /* DESTROY list */ - } - - free(nvs->pass_rec); - return ret; + break; + case GL_FRAGMENT_PROGRAM_ARB: + nvs->func = &nmesa->FPfunc; + + if (fp->FogOption != GL_NONE) + _mesa_append_fog_code(ctx, fp); + break; + default: + fprintf(stderr, "Unknown program type %d", prog->Target); + return GL_FALSE; + } + + rec = CALLOC_STRUCT(pass0_rec); + if (rec) { + rec->next_temp = prog->NumTemporaries; + nvs->pass_rec = rec; + + nvs->program_tree = (nvsFragmentHeader*) + pass0_create_subroutine(nvs, "program body"); + if (nvs->program_tree) { + ret = pass0_translate_instructions(nvs, + 0, 0, + nvs->program_tree); + /*XXX: if (!ret) DESTROY TREE!!! */ + } + FREE(rec); + } + + return ret; } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c index 0476b05f58..b9b87ccf91 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c @@ -38,6 +38,7 @@ #include "nouveau_context.h" #include "nouveau_shader.h" +#include "nouveau_msg.h" struct pass2_rec { /* Map nvsRegister temp ID onto hw temp ID */ @@ -166,11 +167,37 @@ pass2_assemble_instruction(nvsPtr nvs, nvsInstruction *inst, int last) return 1; } +static GLboolean +pass2_translate(nvsPtr nvs, nvsFragmentHeader *f) +{ + nvsFunc *shader = nvs->func; + GLboolean last; + + while (f) { + last = (f == ((nvsSubroutine*)nvs->program_tree)->insn_tail); + + switch (f->type) { + case NVS_INSTRUCTION: + if (!pass2_assemble_instruction(nvs, + (nvsInstruction *)f, + last)) + return GL_FALSE; + break; + default: + WARN_ONCE("Unimplemented fragment type\n"); + return GL_FALSE; + } + + f = f->next; + } + + return GL_TRUE; +} + /* Translate program into hardware format */ GLboolean nouveau_shader_pass2(nvsPtr nvs) { - nvsFragmentList *list = nvs->list_head; struct pass2_rec *rec; int i; @@ -182,21 +209,15 @@ nouveau_shader_pass2(nvsPtr nvs) /* Start off with allocating 4 uint32_t's for each inst, will be grown * if necessary.. */ - nvs->program_alloc_size = nvs->inst_count * 4; + nvs->program_alloc_size = nvs->mesa.vp.Base.NumInstructions * 4; nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t)); nvs->program_size = 0; nvs->program_current = 0; - while (list) { - assert(list->fragment->type == NVS_INSTRUCTION); - - if (!pass2_assemble_instruction(nvs, (nvsInstruction *)list->fragment, list->next ? 0 : 1)) { - free(nvs->program); - nvs->program = NULL; - return GL_FALSE; - } - - list = list->next; + if (!pass2_translate(nvs, ((nvsSubroutine*)nvs->program_tree)->insn_head)) { + free(nvs->program); + nvs->program = NULL; + return GL_FALSE; } /* Shrink allocated memory to only what we need */ -- cgit v1.2.3