nouveau: start converting shaders into a tree format again..
authorBen Skeggs <darktama@iinet.net.au>
Sun, 21 Jan 2007 05:45:40 +0000 (16:45 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Mon, 22 Jan 2007 23:54:54 +0000 (10:54 +1100)
No branching stuff implemented yet.  Works enough for gears, probably
other stuff broken.

src/mesa/drivers/dri/nouveau/nouveau_shader.c
src/mesa/drivers/dri/nouveau/nouveau_shader.h
src/mesa/drivers/dri/nouveau/nouveau_shader_0.c
src/mesa/drivers/dri/nouveau/nouveau_shader_2.c

index e4db115..f911347 100644 (file)
@@ -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"
index 1a971e5..a3ab027 100644 (file)
@@ -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);
 
index 34475ca..503eae3 100644 (file)
@@ -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; ipos<prog->NumInstructions; 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;
 }
 
index 0476b05..b9b87cc 100644 (file)
@@ -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 */