summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv30/nv30_vertprog.c
diff options
context:
space:
mode:
authorLuca Barbieri <[email protected]>2010-02-21 13:33:48 +0100
committerYounes Manton <[email protected]>2010-03-15 00:03:03 -0400
commit840c36f5e6d940343a3154af7e76fec341ca46e6 (patch)
tree36dbe9be2fc50eb7818f6e76aa8a3468a38456f7 /src/gallium/drivers/nv30/nv30_vertprog.c
parentc65a8f3ed2ab1650df38a3ed32d1e91e84b50520 (diff)
nv30, nv40: non-trivially unify nv[34]0_vertprog.c
vertprog.c is similar but has substantial differences: 1. nv40 supports clip planes 2. nv40 uses a more advanced register allocator 3. Some register setup is different 4. Constants with the same name have different values This patch unifies the two files. nv30 gains clip plane support and the nv40 register allocator. A new NVFX_VP(x) macro is introduced that at runtime resolved to either the nv30 or the nv40 constant value. nv30 clip planes are not tested and might not work
Diffstat (limited to 'src/gallium/drivers/nv30/nv30_vertprog.c')
-rw-r--r--src/gallium/drivers/nv30/nv30_vertprog.c842
1 files changed, 0 insertions, 842 deletions
diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c
deleted file mode 100644
index ec6d63889bc..00000000000
--- a/src/gallium/drivers/nv30/nv30_vertprog.c
+++ /dev/null
@@ -1,842 +0,0 @@
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_state.h"
-#include "util/u_inlines.h"
-
-#include "pipe/p_shader_tokens.h"
-#include "tgsi/tgsi_parse.h"
-#include "tgsi/tgsi_dump.h"
-
-#include "nv30_context.h"
-#include "nvfx_state.h"
-
-/* TODO (at least...):
- * 1. Indexed consts + ARL
- * 2. Arb. swz/negation
- * 3. NV_vp11, NV_vp2, NV_vp3 features
- * - extra arith opcodes
- * - branching
- * - texture sampling
- * - indexed attribs
- * - indexed results
- * 4. bugs
- */
-
-#define SWZ_X 0
-#define SWZ_Y 1
-#define SWZ_Z 2
-#define SWZ_W 3
-#define MASK_X 8
-#define MASK_Y 4
-#define MASK_Z 2
-#define MASK_W 1
-#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
-#define DEF_SCALE 0
-#define DEF_CTEST 0
-#include "nv30_shader.h"
-
-#define swz(s,x,y,z,w) nvfx_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
-#define neg(s) nvfx_sr_neg((s))
-#define abs(s) nvfx_sr_abs((s))
-
-struct nv30_vpc {
- struct nvfx_vertex_program *vp;
-
- struct nvfx_vertex_program_exec *vpi;
-
- unsigned output_map[PIPE_MAX_SHADER_OUTPUTS];
-
- int high_temp;
- int temp_temp_count;
-
- struct nvfx_sreg *imm;
- unsigned nr_imm;
-};
-
-static struct nvfx_sreg
-temp(struct nv30_vpc *vpc)
-{
- int idx;
-
- idx = vpc->temp_temp_count++;
- idx += vpc->high_temp + 1;
- return nvfx_sr(NVFXSR_TEMP, idx);
-}
-
-static struct nvfx_sreg
-constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w)
-{
- struct nvfx_vertex_program *vp = vpc->vp;
- struct nvfx_vertex_program_data *vpd;
- int idx;
-
- if (pipe >= 0) {
- for (idx = 0; idx < vp->nr_consts; idx++) {
- if (vp->consts[idx].index == pipe)
- return nvfx_sr(NVFXSR_CONST, idx);
- }
- }
-
- idx = vp->nr_consts++;
- vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
- vpd = &vp->consts[idx];
-
- vpd->index = pipe;
- vpd->value[0] = x;
- vpd->value[1] = y;
- vpd->value[2] = z;
- vpd->value[3] = w;
- return nvfx_sr(NVFXSR_CONST, idx);
-}
-
-#define arith(cc,s,o,d,m,s0,s1,s2) \
- nv30_vp_arith((cc), NVFX_VP_INST_SLOT_##s, NVFX_VP_INST_##s##_OP_##o, (d), (m), (s0), (s1), (s2))
-
-static void
-emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nvfx_sreg src)
-{
- struct nvfx_vertex_program *vp = vpc->vp;
- uint32_t sr = 0;
-
- switch (src.type) {
- case NVFXSR_TEMP:
- sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT);
- sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT);
- break;
- case NVFXSR_INPUT:
- sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
- NV30_VP_SRC_REG_TYPE_SHIFT);
- vp->ir |= (1 << src.index);
- hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT);
- break;
- case NVFXSR_CONST:
- sr |= (NV30_VP_SRC_REG_TYPE_CONST <<
- NV30_VP_SRC_REG_TYPE_SHIFT);
- assert(vpc->vpi->const_index == -1 ||
- vpc->vpi->const_index == src.index);
- vpc->vpi->const_index = src.index;
- break;
- case NVFXSR_NONE:
- sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
- NV30_VP_SRC_REG_TYPE_SHIFT);
- break;
- default:
- assert(0);
- }
-
- if (src.negate)
- sr |= NV30_VP_SRC_NEGATE;
-
- if (src.abs)
- hw[0] |= (1 << (21 + pos));
-
- sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) |
- (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) |
- (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) |
- (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT));
-
-/*
- * |VVV|
- * d�.�b
- * \u/
- *
- */
-
- switch (pos) {
- case 0:
- hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >>
- NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT;
- hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) <<
- NV30_VP_INST_SRC0L_SHIFT;
- break;
- case 1:
- hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT;
- break;
- case 2:
- hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >>
- NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT;
- hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) <<
- NV30_VP_INST_SRC2L_SHIFT;
- break;
- default:
- assert(0);
- }
-}
-
-static void
-emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nvfx_sreg dst)
-{
- struct nvfx_vertex_program *vp = vpc->vp;
-
- switch (dst.type) {
- case NVFXSR_TEMP:
- hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
- break;
- case NVFXSR_OUTPUT:
- switch (dst.index) {
- case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
- case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
- case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
- case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
- case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break;
- case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
- case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
- case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
- case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
- case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
- case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
- case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
- case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
- case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
- default:
- break;
- }
-
- hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
- hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
-
- /*XXX: no way this is entirely correct, someone needs to
- * figure out what exactly it is.
- */
- hw[3] |= 0x800;
- break;
- default:
- assert(0);
- }
-}
-
-static void
-nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op,
- struct nvfx_sreg dst, int mask,
- struct nvfx_sreg s0, struct nvfx_sreg s1,
- struct nvfx_sreg s2)
-{
- struct nvfx_vertex_program *vp = vpc->vp;
- uint32_t *hw;
-
- vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
- vpc->vpi = &vp->insns[vp->nr_insns - 1];
- memset(vpc->vpi, 0, sizeof(*vpc->vpi));
- vpc->vpi->const_index = -1;
-
- hw = vpc->vpi->data;
-
- hw[0] |= (NVFX_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT);
- hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) |
- (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) |
- (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) |
- (3 << NV30_VP_INST_COND_SWZ_W_SHIFT));
-
- hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
-// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK;
-// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT);
-
- if (dst.type == NVFXSR_OUTPUT) {
- if (slot)
- hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
- else
- hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
- } else {
- if (slot)
- hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
- else
- hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
- }
-
- emit_dst(vpc, hw, slot, dst);
- emit_src(vpc, hw, 0, s0);
- emit_src(vpc, hw, 1, s1);
- emit_src(vpc, hw, 2, s2);
-}
-
-static INLINE struct nvfx_sreg
-tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
- struct nvfx_sreg src;
-
- switch (fsrc->Register.File) {
- case TGSI_FILE_INPUT:
- src = nvfx_sr(NVFXSR_INPUT, fsrc->Register.Index);
- break;
- case TGSI_FILE_CONSTANT:
- src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0);
- break;
- case TGSI_FILE_IMMEDIATE:
- src = vpc->imm[fsrc->Register.Index];
- break;
- case TGSI_FILE_TEMPORARY:
- if (vpc->high_temp < fsrc->Register.Index)
- vpc->high_temp = fsrc->Register.Index;
- src = nvfx_sr(NVFXSR_TEMP, fsrc->Register.Index);
- break;
- default:
- NOUVEAU_ERR("bad src file\n");
- break;
- }
-
- src.abs = fsrc->Register.Absolute;
- src.negate = fsrc->Register.Negate;
- src.swz[0] = fsrc->Register.SwizzleX;
- src.swz[1] = fsrc->Register.SwizzleY;
- src.swz[2] = fsrc->Register.SwizzleZ;
- src.swz[3] = fsrc->Register.SwizzleW;
- return src;
-}
-
-static INLINE struct nvfx_sreg
-tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
- struct nvfx_sreg dst;
-
- switch (fdst->Register.File) {
- case TGSI_FILE_OUTPUT:
- dst = nvfx_sr(NVFXSR_OUTPUT,
- vpc->output_map[fdst->Register.Index]);
-
- break;
- case TGSI_FILE_TEMPORARY:
- dst = nvfx_sr(NVFXSR_TEMP, fdst->Register.Index);
- if (vpc->high_temp < dst.index)
- vpc->high_temp = dst.index;
- break;
- default:
- NOUVEAU_ERR("bad dst file\n");
- break;
- }
-
- return dst;
-}
-
-static INLINE int
-tgsi_mask(uint tgsi)
-{
- int mask = 0;
-
- if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
- if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
- if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
- if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
- return mask;
-}
-
-static boolean
-nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
- const struct tgsi_full_instruction *finst)
-{
- struct nvfx_sreg src[3], dst, tmp;
- struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0);
- int mask;
- int ai = -1, ci = -1;
- int i;
-
- if (finst->Instruction.Opcode == TGSI_OPCODE_END)
- return TRUE;
-
- vpc->temp_temp_count = 0;
- for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
- const struct tgsi_full_src_register *fsrc;
-
- fsrc = &finst->Src[i];
- if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
- src[i] = tgsi_src(vpc, fsrc);
- }
- }
-
- for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
- const struct tgsi_full_src_register *fsrc;
-
- fsrc = &finst->Src[i];
- switch (fsrc->Register.File) {
- case TGSI_FILE_INPUT:
- if (ai == -1 || ai == fsrc->Register.Index) {
- ai = fsrc->Register.Index;
- src[i] = tgsi_src(vpc, fsrc);
- } else {
- src[i] = temp(vpc);
- arith(vpc, VEC, MOV, src[i], MASK_ALL,
- tgsi_src(vpc, fsrc), none, none);
- }
- break;
- /*XXX: index comparison is broken now that consts come from
- * two different register files.
- */
- case TGSI_FILE_CONSTANT:
- case TGSI_FILE_IMMEDIATE:
- if (ci == -1 || ci == fsrc->Register.Index) {
- ci = fsrc->Register.Index;
- src[i] = tgsi_src(vpc, fsrc);
- } else {
- src[i] = temp(vpc);
- arith(vpc, VEC, MOV, src[i], MASK_ALL,
- tgsi_src(vpc, fsrc), none, none);
- }
- break;
- case TGSI_FILE_TEMPORARY:
- /* handled above */
- break;
- default:
- NOUVEAU_ERR("bad src file\n");
- return FALSE;
- }
- }
-
- dst = tgsi_dst(vpc, &finst->Dst[0]);
- mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
-
- switch (finst->Instruction.Opcode) {
- case TGSI_OPCODE_ABS:
- arith(vpc, VEC, MOV, dst, mask, abs(src[0]), none, none);
- break;
- case TGSI_OPCODE_ADD:
- arith(vpc, VEC, ADD, dst, mask, src[0], none, src[1]);
- break;
- case TGSI_OPCODE_ARL:
- arith(vpc, VEC, ARL, dst, mask, src[0], none, none);
- break;
- case TGSI_OPCODE_DP3:
- arith(vpc, VEC, DP3, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_DP4:
- arith(vpc, VEC, DP4, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_DPH:
- arith(vpc, VEC, DPH, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_DST:
- arith(vpc, VEC, DST, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_EX2:
- arith(vpc, SCA, EX2, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_EXP:
- arith(vpc, SCA, EXP, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_FLR:
- arith(vpc, VEC, FLR, dst, mask, src[0], none, none);
- break;
- case TGSI_OPCODE_FRC:
- arith(vpc, VEC, FRC, dst, mask, src[0], none, none);
- break;
- case TGSI_OPCODE_LG2:
- arith(vpc, SCA, LG2, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_LIT:
- arith(vpc, SCA, LIT, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_LOG:
- arith(vpc, SCA, LOG, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_MAD:
- arith(vpc, VEC, MAD, dst, mask, src[0], src[1], src[2]);
- break;
- case TGSI_OPCODE_MAX:
- arith(vpc, VEC, MAX, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_MIN:
- arith(vpc, VEC, MIN, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_MOV:
- arith(vpc, VEC, MOV, dst, mask, src[0], none, none);
- break;
- case TGSI_OPCODE_MUL:
- arith(vpc, VEC, MUL, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_POW:
- tmp = temp(vpc);
- arith(vpc, SCA, LG2, tmp, MASK_X, none, none,
- swz(src[0], X, X, X, X));
- arith(vpc, VEC, MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
- swz(src[1], X, X, X, X), none);
- arith(vpc, SCA, EX2, dst, mask, none, none,
- swz(tmp, X, X, X, X));
- break;
- case TGSI_OPCODE_RCP:
- arith(vpc, SCA, RCP, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_RET:
- break;
- case TGSI_OPCODE_RSQ:
- arith(vpc, SCA, RSQ, dst, mask, none, none, src[0]);
- break;
- case TGSI_OPCODE_SGE:
- arith(vpc, VEC, SGE, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_SGT:
- arith(vpc, VEC, SGT, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_SLT:
- arith(vpc, VEC, SLT, dst, mask, src[0], src[1], none);
- break;
- case TGSI_OPCODE_SUB:
- arith(vpc, VEC, ADD, dst, mask, src[0], none, neg(src[1]));
- break;
- case TGSI_OPCODE_XPD:
- tmp = temp(vpc);
- arith(vpc, VEC, MUL, tmp, mask,
- swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
- arith(vpc, VEC, MAD, dst, (mask & ~MASK_W),
- swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
- neg(tmp));
- break;
- default:
- NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static boolean
-nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
- const struct tgsi_full_declaration *fdec)
-{
- int hw;
-
- switch (fdec->Semantic.Name) {
- case TGSI_SEMANTIC_POSITION:
- hw = NV30_VP_INST_DEST_POS;
- break;
- case TGSI_SEMANTIC_COLOR:
- if (fdec->Semantic.Index == 0) {
- hw = NV30_VP_INST_DEST_COL0;
- } else
- if (fdec->Semantic.Index == 1) {
- hw = NV30_VP_INST_DEST_COL1;
- } else {
- NOUVEAU_ERR("bad colour semantic index\n");
- return FALSE;
- }
- break;
- case TGSI_SEMANTIC_BCOLOR:
- if (fdec->Semantic.Index == 0) {
- hw = NV30_VP_INST_DEST_BFC0;
- } else
- if (fdec->Semantic.Index == 1) {
- hw = NV30_VP_INST_DEST_BFC1;
- } else {
- NOUVEAU_ERR("bad bcolour semantic index\n");
- return FALSE;
- }
- break;
- case TGSI_SEMANTIC_FOG:
- hw = NV30_VP_INST_DEST_FOGC;
- break;
- case TGSI_SEMANTIC_PSIZE:
- hw = NV30_VP_INST_DEST_PSZ;
- break;
- case TGSI_SEMANTIC_GENERIC:
- if (fdec->Semantic.Index <= 7) {
- hw = NV30_VP_INST_DEST_TC(fdec->Semantic.Index);
- } else {
- NOUVEAU_ERR("bad generic semantic index\n");
- return FALSE;
- }
- break;
- case TGSI_SEMANTIC_EDGEFLAG:
- NOUVEAU_ERR("cannot handle edgeflag output\n");
- return FALSE;
- default:
- NOUVEAU_ERR("bad output semantic\n");
- return FALSE;
- }
-
- vpc->output_map[fdec->Range.First] = hw;
- return TRUE;
-}
-
-static boolean
-nv30_vertprog_prepare(struct nv30_vpc *vpc)
-{
- struct tgsi_parse_context p;
- int nr_imm = 0;
-
- tgsi_parse_init(&p, vpc->vp->pipe.tokens);
- while (!tgsi_parse_end_of_tokens(&p)) {
- const union tgsi_full_token *tok = &p.FullToken;
-
- tgsi_parse_token(&p);
- switch(tok->Token.Type) {
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- nr_imm++;
- break;
- default:
- break;
- }
- }
- tgsi_parse_free(&p);
-
- if (nr_imm) {
- vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_sreg));
- assert(vpc->imm);
- }
-
- return TRUE;
-}
-
-static void
-nv30_vertprog_translate(struct nvfx_context *nvfx,
- struct nvfx_vertex_program *vp)
-{
- struct tgsi_parse_context parse;
- struct nv30_vpc *vpc = NULL;
-
- tgsi_dump(vp->pipe.tokens,0);
-
- vpc = CALLOC(1, sizeof(struct nv30_vpc));
- if (!vpc)
- return;
- vpc->vp = vp;
- vpc->high_temp = -1;
-
- if (!nv30_vertprog_prepare(vpc)) {
- FREE(vpc);
- return;
- }
-
- tgsi_parse_init(&parse, vp->pipe.tokens);
-
- while (!tgsi_parse_end_of_tokens(&parse)) {
- tgsi_parse_token(&parse);
-
- switch (parse.FullToken.Token.Type) {
- case TGSI_TOKEN_TYPE_DECLARATION:
- {
- const struct tgsi_full_declaration *fdec;
- fdec = &parse.FullToken.FullDeclaration;
- switch (fdec->Declaration.File) {
- case TGSI_FILE_OUTPUT:
- if (!nv30_vertprog_parse_decl_output(vpc, fdec))
- goto out_err;
- break;
- default:
- break;
- }
- }
- break;
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- {
- const struct tgsi_full_immediate *imm;
-
- imm = &parse.FullToken.FullImmediate;
- assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
- assert(imm->Immediate.NrTokens == 4 + 1);
- vpc->imm[vpc->nr_imm++] =
- constant(vpc, -1,
- imm->u[0].Float,
- imm->u[1].Float,
- imm->u[2].Float,
- imm->u[3].Float);
- }
- break;
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- {
- const struct tgsi_full_instruction *finst;
- finst = &parse.FullToken.FullInstruction;
- if (!nv30_vertprog_parse_instruction(vpc, finst))
- goto out_err;
- }
- break;
- default:
- break;
- }
- }
-
- vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
- vp->translated = TRUE;
-out_err:
- tgsi_parse_free(&parse);
- FREE(vpc);
-}
-
-static boolean
-nv30_vertprog_validate(struct nvfx_context *nvfx)
-{
- struct pipe_screen *pscreen = nvfx->pipe.screen;
- struct nvfx_screen *screen = nvfx->screen;
- struct nouveau_channel *chan = screen->base.channel;
- struct nouveau_grobj *eng3d = screen->eng3d;
- struct nvfx_vertex_program *vp;
- struct pipe_buffer *constbuf;
- boolean upload_code = FALSE, upload_data = FALSE;
- int i;
-
- vp = nvfx->vertprog;
- constbuf = nvfx->constbuf[PIPE_SHADER_VERTEX];
-
- /* Translate TGSI shader into hw bytecode */
- if (!vp->translated) {
- nv30_vertprog_translate(nvfx, vp);
- if (!vp->translated)
- return FALSE;
- }
-
- /* Allocate hw vtxprog exec slots */
- if (!vp->exec) {
- struct nouveau_resource *heap = nvfx->screen->vp_exec_heap;
- struct nouveau_stateobj *so;
- uint vplen = vp->nr_insns;
-
- if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) {
- while (heap->next && heap->size < vplen) {
- struct nvfx_vertex_program *evict;
-
- evict = heap->next->priv;
- nouveau_resource_free(&evict->exec);
- }
-
- if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec))
- assert(0);
- }
-
- so = so_new(1, 1, 0);
- so_method(so, eng3d, NV34TCL_VP_START_FROM_ID, 1);
- so_data (so, vp->exec->start);
- so_ref(so, &vp->so);
- so_ref(NULL, &so);
-
- upload_code = TRUE;
- }
-
- /* Allocate hw vtxprog const slots */
- if (vp->nr_consts && !vp->data) {
- struct nouveau_resource *heap = nvfx->screen->vp_data_heap;
-
- if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) {
- while (heap->next && heap->size < vp->nr_consts) {
- struct nvfx_vertex_program *evict;
-
- evict = heap->next->priv;
- nouveau_resource_free(&evict->data);
- }
-
- if (nouveau_resource_alloc(heap, vp->nr_consts, vp,
- &vp->data))
- assert(0);
- }
-
- /*XXX: handle this some day */
- assert(vp->data->start >= vp->data_start_min);
-
- upload_data = TRUE;
- if (vp->data_start != vp->data->start)
- upload_code = TRUE;
- }
-
- /* If exec or data segments moved we need to patch the program to
- * fixup offsets and register IDs.
- */
- if (vp->exec_start != vp->exec->start) {
- for (i = 0; i < vp->nr_insns; i++) {
- struct nvfx_vertex_program_exec *vpi = &vp->insns[i];
-
- if (vpi->has_branch_offset) {
- assert(0);
- }
- }
-
- vp->exec_start = vp->exec->start;
- }
-
- if (vp->nr_consts && vp->data_start != vp->data->start) {
- for (i = 0; i < vp->nr_insns; i++) {
- struct nvfx_vertex_program_exec *vpi = &vp->insns[i];
-
- if (vpi->const_index >= 0) {
- vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK;
- vpi->data[1] |=
- (vpi->const_index + vp->data->start) <<
- NV30_VP_INST_CONST_SRC_SHIFT;
-
- }
- }
-
- vp->data_start = vp->data->start;
- }
-
- /* Update + Upload constant values */
- if (vp->nr_consts) {
- float *map = NULL;
-
- if (constbuf) {
- map = pipe_buffer_map(pscreen, constbuf,
- PIPE_BUFFER_USAGE_CPU_READ);
- }
-
- for (i = 0; i < vp->nr_consts; i++) {
- struct nvfx_vertex_program_data *vpd = &vp->consts[i];
-
- if (vpd->index >= 0) {
- if (!upload_data &&
- !memcmp(vpd->value, &map[vpd->index * 4],
- 4 * sizeof(float)))
- continue;
- memcpy(vpd->value, &map[vpd->index * 4],
- 4 * sizeof(float));
- }
-
- 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);
- }
-
- if (constbuf)
- pipe_buffer_unmap(pscreen, constbuf);
- }
-
- /* Upload vtxprog */
- if (upload_code) {
-#if 0
- for (i = 0; i < vp->nr_insns; i++) {
- NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- i, vp->insns[i].data[0], vp->insns[i].data[1],
- vp->insns[i].data[2], vp->insns[i].data[3]);
- }
-#endif
- BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_FROM_ID, 1);
- OUT_RING (chan, vp->exec->start);
- for (i = 0; i < vp->nr_insns; i++) {
- BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_INST(0), 4);
- OUT_RINGp (chan, vp->insns[i].data, 4);
- }
- }
-
- if (vp->so != nvfx->state.hw[NVFX_STATE_VERTPROG]) {
- so_ref(vp->so, &nvfx->state.hw[NVFX_STATE_VERTPROG]);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-nv30_vertprog_destroy(struct nvfx_context *nvfx, struct nvfx_vertex_program *vp)
-{
- vp->translated = FALSE;
-
- if (vp->nr_insns) {
- FREE(vp->insns);
- vp->insns = NULL;
- vp->nr_insns = 0;
- }
-
- if (vp->nr_consts) {
- FREE(vp->consts);
- vp->consts = NULL;
- vp->nr_consts = 0;
- }
-
- nouveau_resource_free(&vp->exec);
- vp->exec_start = 0;
- nouveau_resource_free(&vp->data);
- vp->data_start = 0;
- vp->data_start_min = 0;
-
- vp->ir = vp->or = 0;
- so_ref(NULL, &vp->so);
-}
-
-struct nvfx_state_entry nv30_state_vertprog = {
- .validate = nv30_vertprog_validate,
- .dirty = {
- .pipe = NVFX_NEW_VERTPROG /*| NVFX_NEW_UCP*/,
- .hw = NVFX_STATE_VERTPROG,
- }
-};