summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2007-01-21 16:45:40 +1100
committerBen Skeggs <[email protected]>2007-01-23 10:54:54 +1100
commitc3ac2709967299481928dee175a124bf8a72fecd (patch)
tree23cdd0660456527cbe51510798b4075cd3253d08
parent95fc270b06f07268732ade745084410bbc877168 (diff)
nouveau: start converting shaders into a tree format again..
No branching stuff implemented yet. Works enough for gears, probably other stuff broken.
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.c6
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.h60
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader_0.c375
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader_2.c45
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 e4db1153625..f911347d624 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 1a971e56bf2..a3ab027142f 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 34475cad033..503eae36b70 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; 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;
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
index 0476b05f583..b9b87ccf91b 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 */