summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nvfx/nvfx_vertprog.c
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-09-03 18:31:18 +0200
committerLuca Barbieri <luca@luca-barbieri.com>2010-09-03 20:48:14 +0200
commitb946984e3bbd91da3111edd0d62f90cfd4967ad3 (patch)
treeff0a2c8912924699d4680bf282ee009173b5259c /src/gallium/drivers/nvfx/nvfx_vertprog.c
parent7e282b8e62fb5d237a2e2cc94ac6a39a2f73f271 (diff)
nvfx: support indirect addressing in vps
Negative or huge offsets not yet supported.
Diffstat (limited to 'src/gallium/drivers/nvfx/nvfx_vertprog.c')
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vertprog.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/src/gallium/drivers/nvfx/nvfx_vertprog.c b/src/gallium/drivers/nvfx/nvfx_vertprog.c
index ea7e88c561..838c3aa208 100644
--- a/src/gallium/drivers/nvfx/nvfx_vertprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_vertprog.c
@@ -46,6 +46,7 @@ struct nvfx_vpc {
struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
struct nvfx_reg *r_address;
struct nvfx_reg *r_temp;
+ struct nvfx_reg *r_const;
struct nvfx_reg *imm;
unsigned nr_imm;
@@ -152,6 +153,18 @@ emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos,
(src.swz[2] << NVFX_VP(SRC_SWZ_Z_SHIFT)) |
(src.swz[3] << NVFX_VP(SRC_SWZ_W_SHIFT)));
+ if(src.indirect) {
+ if(src.reg.type == NVFXSR_CONST)
+ hw[3] |= NVFX_VP(INST_INDEX_CONST);
+ else if(src.reg.type == NVFXSR_INPUT)
+ hw[0] |= NVFX_VP(INST_INDEX_INPUT);
+ else
+ assert(0);
+ if(src.indirect_reg)
+ hw[0] |= NVFX_VP(INST_ADDR_REG_SELECT_1);
+ hw[0] |= src.indirect_swz << NVFX_VP(INST_ADDR_SWZ_SHIFT);
+ }
+
switch (pos) {
case 0:
hw[1] |= ((sr & NVFX_VP(SRC0_HIGH_MASK)) >>
@@ -317,6 +330,9 @@ nvfx_vp_emit(struct nvfx_vpc *vpc, struct nvfx_insn insn)
emit_src(nvfx, vpc, hw, 0, insn.src[0]);
emit_src(nvfx, vpc, hw, 1, insn.src[1]);
emit_src(nvfx, vpc, hw, 2, insn.src[2]);
+
+// if(insn.src[0].indirect || op == NVFX_VP_INST_VEC_OP_ARL)
+// hw[3] |= NV40_VP_INST_SCA_RESULT;
}
static inline struct nvfx_src
@@ -328,7 +344,7 @@ tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
src.reg = nvfx_reg(NVFXSR_INPUT, fsrc->Register.Index);
break;
case TGSI_FILE_CONSTANT:
- src.reg = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0);
+ src.reg = vpc->r_const[fsrc->Register.Index];
break;
case TGSI_FILE_IMMEDIATE:
src.reg = vpc->imm[fsrc->Register.Index];
@@ -339,7 +355,7 @@ tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
default:
NOUVEAU_ERR("bad src file\n");
src.reg.index = 0;
- src.reg.type = 0;
+ src.reg.type = -1;
break;
}
@@ -349,6 +365,22 @@ tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
src.swz[1] = fsrc->Register.SwizzleY;
src.swz[2] = fsrc->Register.SwizzleZ;
src.swz[3] = fsrc->Register.SwizzleW;
+ src.indirect = 0;
+
+ if(fsrc->Register.Indirect) {
+ if(fsrc->Indirect.File == TGSI_FILE_ADDRESS &&
+ (fsrc->Register.File == TGSI_FILE_CONSTANT || fsrc->Register.File == TGSI_FILE_INPUT))
+ {
+ src.indirect = 1;
+ src.indirect_reg = fsrc->Indirect.Index;
+ src.indirect_swz = fsrc->Indirect.SwizzleX;
+ }
+ else
+ {
+ src.reg.index = 0;
+ src.reg.type = -1;
+ }
+ }
return src;
}
@@ -461,6 +493,15 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
}
}
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ if(src[i].reg.type < 0)
+ return FALSE;
+ }
+
+ if(finst->Dst[0].Register.File == TGSI_FILE_ADDRESS &&
+ finst->Instruction.Opcode != TGSI_OPCODE_ARL)
+ return FALSE;
+
dst = tgsi_dst(vpc, &finst->Dst[0]);
mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
@@ -761,7 +802,7 @@ static boolean
nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
{
struct tgsi_parse_context p;
- int high_temp = -1, high_addr = -1, nr_imm = 0, i;
+ int high_const = -1, high_temp = -1, high_addr = -1, nr_imm = 0, i;
struct util_semantic_set set;
unsigned char sem_layout[8];
unsigned num_outputs;
@@ -814,14 +855,18 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
fdec->Range.Last;
}
break;
-#if 0 /* this would be nice.. except gallium doesn't track it */
case TGSI_FILE_ADDRESS:
if (fdec->Range.Last > high_addr) {
high_addr =
fdec->Range.Last;
}
break;
-#endif
+ case TGSI_FILE_CONSTANT:
+ if (fdec->Range.Last > high_const) {
+ high_const =
+ fdec->Range.Last;
+ }
+ break;
case TGSI_FILE_OUTPUT:
if (!nvfx_vertprog_parse_decl_output(nvfx, vpc, fdec))
return FALSE;
@@ -831,23 +876,6 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
}
}
break;
-#if 1 /* yay, parse instructions looking for address regs instead */
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- {
- const struct tgsi_full_instruction *finst;
- const struct tgsi_full_dst_register *fdst;
-
- finst = &p.FullToken.FullInstruction;
- fdst = &finst->Dst[0];
-
- if (fdst->Register.File == TGSI_FILE_ADDRESS) {
- if (fdst->Register.Index > high_addr)
- high_addr = fdst->Register.Index;
- }
-
- }
- break;
-#endif
default:
break;
}
@@ -868,7 +896,13 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
if (++high_addr) {
vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_reg));
for (i = 0; i < high_addr; i++)
- vpc->r_address[i] = temp(vpc);
+ vpc->r_address[i] = nvfx_reg(NVFXSR_TEMP, i);
+ }
+
+ if(++high_const) {
+ vpc->r_const = CALLOC(high_const, sizeof(struct nvfx_reg));
+ for (i = 0; i < high_const; i++)
+ vpc->r_const[i] = constant(vpc, i, 0, 0, 0, 0);
}
vpc->r_temps_discard = 0;
@@ -1037,6 +1071,8 @@ out_err:
FREE(vpc->r_temp);
if (vpc->r_address)
FREE(vpc->r_address);
+ if (vpc->r_const)
+ FREE(vpc->r_const);
if (vpc->imm)
FREE(vpc->imm);
FREE(vpc);
@@ -1116,6 +1152,8 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
}
}
+ //printf("start at %u nc %u\n", vp->data->start, vp->nr_consts);
+
/*XXX: handle this some day */
assert(vp->data->start >= vp->data_start_min);
@@ -1161,6 +1199,8 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
struct nvfx_relocation* reloc = (struct nvfx_relocation*)((char*)vp->const_relocs.data + i);
struct nvfx_vertex_program_exec *vpi = &vp->insns[reloc->location];
+ //printf("reloc %i to %i + %i\n", reloc->location, vp->data->start, reloc->target);
+
vpi->data[1] &= ~NVFX_VP(INST_CONST_SRC_MASK);
vpi->data[1] |=
(reloc->target + vp->data->start) <<
@@ -1178,6 +1218,16 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
if (constbuf)
map = (float*)nvfx_buffer(constbuf)->data;
+ /*
+ for (i = 0; i < 512; i++) {
+ float v[4] = {0.1, 0,2, 0.3, 0.4};
+ BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (chan, i);
+ OUT_RINGp (chan, (uint32_t *)v, 4);
+ printf("frob %i\n", i);
+ }
+ */
+
for (i = nvfx->use_vp_clipping ? 6 : 0; i < vp->nr_consts; i++) {
struct nvfx_vertex_program_data *vpd = &vp->consts[i];
@@ -1190,6 +1240,8 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
4 * sizeof(float));
}
+ //printf("upload into %i + %i: %f %f %f %f\n", vp->data->start, i, vpd->value[0], vpd->value[1], vpd->value[2], vpd->value[3]);
+
BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_CONST_ID, 5);
OUT_RING (chan, i + vp->data->start);
OUT_RINGp (chan, (uint32_t *)vpd->value, 4);
@@ -1202,6 +1254,7 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
OUT_RING (chan, vp->exec->start);
for (i = 0; i < vp->nr_insns; i++) {
BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_INST(0), 4);
+ //printf("%08x %08x %08x %08x\n", vp->insns[i].data[0], vp->insns[i].data[1], vp->insns[i].data[2], vp->insns[i].data[3]);
OUT_RINGp (chan, vp->insns[i].data, 4);
}
vp->clip_nr = -1;