From 7494b829052a87d7a8c56c68300a110b40e401e8 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sun, 29 Nov 2009 13:33:16 +0100 Subject: nv50: match VP outputs to FP inputs ourselves For each FP input, don't assume that the VP output will be at the same position, but scan the semantics instead, then put the correct output reg indices into VP_RESULT_MAP. Position is still assumed to be the first output/input. See 07fafc7c9346aa260829603bf3188596481e9e62, which renders previous assumptions incorrect. --- src/gallium/drivers/nv50/nv50_program.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_program.h') diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index d78dee083f..255c7c737e 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -17,8 +17,7 @@ struct nv50_program_exec { struct nv50_sreg4 { uint8_t hw; - uint8_t id_vp; - uint8_t id_fp; + uint8_t id; /* tgsi index, nv50 needs them sorted: flat ones last */ uint8_t mask; boolean linear; -- cgit v1.2.3 From 1778ddaf74aba72df167769bf42150810aac91a3 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Mon, 14 Dec 2009 11:10:16 +0100 Subject: nv50: store immediates as uint32 Sometimes we want non-float immediates, hacking them into floats isn't nice. Sorry, this should have already been committed before. --- src/gallium/drivers/nv50/nv50_program.c | 62 ++++++++++++++++----------------- src/gallium/drivers/nv50/nv50_program.h | 2 +- 2 files changed, 31 insertions(+), 33 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_program.h') diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index feb3d42286..fe8ccd0349 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -119,7 +119,7 @@ struct nv50_pc { struct nv50_reg *param; int param_nr; struct nv50_reg *immd; - float *immd_buf; + uint32_t *immd_buf; int immd_nr; struct nv50_reg **addr; int addr_nr; @@ -365,10 +365,13 @@ kill_temp_temp(struct nv50_pc *pc) } static int -ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w) +ctor_immd_4u32(struct nv50_pc *pc, + uint32_t x, uint32_t y, uint32_t z, uint32_t w) { - pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * 4 * sizeof(float)), - (pc->immd_nr + 1) * 4 * sizeof(float)); + unsigned size = pc->immd_nr * 4 * sizeof(uint32_t); + + pc->immd_buf = REALLOC(pc->immd_buf, size, size + 4 * sizeof(uint32_t)); + pc->immd_buf[(pc->immd_nr * 4) + 0] = x; pc->immd_buf[(pc->immd_nr * 4) + 1] = y; pc->immd_buf[(pc->immd_nr * 4) + 2] = z; @@ -377,17 +380,10 @@ ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w) return pc->immd_nr++; } -static int -ctor_immd_4u32(struct nv50_pc *pc, uint32_t x, uint32_t y, uint32_t z, uint32_t w) +static INLINE int +ctor_immd_4f32(struct nv50_pc *pc, float x, float y, float z, float w) { - pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * 4 * sizeof(uint32_t)), - (pc->immd_nr + 1) * 4 * sizeof(uint32_t)); - pc->immd_buf[(pc->immd_nr * 4) + 0] = x; - pc->immd_buf[(pc->immd_nr * 4) + 1] = y; - pc->immd_buf[(pc->immd_nr * 4) + 2] = z; - pc->immd_buf[(pc->immd_nr * 4) + 3] = w; - - return pc->immd_nr++; + return ctor_immd_4u32(pc, fui(x), fui(y), fui(z), fui(w)); } static struct nv50_reg * @@ -397,11 +393,11 @@ alloc_immd(struct nv50_pc *pc, float f) unsigned hw; for (hw = 0; hw < pc->immd_nr * 4; hw++) - if (pc->immd_buf[hw] == f) + if (pc->immd_buf[hw] == fui(f)) break; if (hw == pc->immd_nr * 4) - hw = ctor_immd(pc, f, -f, 0.5 * f, 0) * 4; + hw = ctor_immd_4f32(pc, f, -f, 0.5 * f, 0) * 4; ctor_reg(r, P_IMMD, -1, hw); return r; @@ -493,22 +489,24 @@ set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e) static INLINE void set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) { - unsigned val; - float f = pc->immd_buf[imm->hw]; + union { + float f; + uint32_t ui; + } u; + u.ui = pc->immd_buf[imm->hw]; - if (imm->mod & NV50_MOD_ABS) - f = fabsf(f); - val = fui((imm->mod & NV50_MOD_NEG) ? -f : f); + u.f = (imm->mod & NV50_MOD_ABS) ? fabsf(u.f) : u.f; + u.f = (imm->mod & NV50_MOD_NEG) ? -u.f : u.f; set_long(pc, e); - /*XXX: can't be predicated - bits overlap.. catch cases where both - * are required and avoid them. */ + /* XXX: can't be predicated - bits overlap; cases where both + * are required should be avoided by using pc->allow32 */ set_pred(pc, 0, 0, e); set_pred_wr(pc, 0, 0, e); e->inst[1] |= 0x00000002 | 0x00000001; - e->inst[0] |= (val & 0x3f) << 16; - e->inst[1] |= (val >> 6) << 2; + e->inst[0] |= (u.ui & 0x3f) << 16; + e->inst[1] |= (u.ui >> 6) << 2; } static INLINE void @@ -2762,10 +2760,10 @@ nv50_program_tx_prep(struct nv50_pc *pc) const struct tgsi_full_immediate *imm = &tp.FullToken.FullImmediate; - ctor_immd(pc, imm->u[0].Float, - imm->u[1].Float, - imm->u[2].Float, - imm->u[3].Float); + ctor_immd_4f32(pc, imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); } break; case TGSI_TOKEN_TYPE_DECLARATION: @@ -3245,7 +3243,7 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p) } static void -nv50_program_upload_data(struct nv50_context *nv50, float *map, +nv50_program_upload_data(struct nv50_context *nv50, uint32_t *map, unsigned start, unsigned count, unsigned cbuf) { struct nouveau_channel *chan = nv50->screen->base.channel; @@ -3293,8 +3291,8 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) if (p->param_nr) { unsigned cb; - float *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type], - PIPE_BUFFER_USAGE_CPU_READ); + uint32_t *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type], + PIPE_BUFFER_USAGE_CPU_READ); if (p->type == PIPE_SHADER_VERTEX) cb = NV50_CB_PVP; diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index 255c7c737e..4a90c372ce 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -37,7 +37,7 @@ struct nv50_program { struct nouveau_bo *bo; - float *immd; + uint32_t *immd; unsigned immd_nr; unsigned param_nr; -- cgit v1.2.3 From d29f55546dec74ca77dce3a3bf581c251be1d397 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Thu, 24 Dec 2009 12:39:42 +0100 Subject: nv50: make edgeflags work It doesn't seem to be possible to set the egdeflag in the vertex shader, so we need to fallback to pushing vertices through the FIFO and use method 0x15e4 if they are used. This only works if VP does MOV OUT[X] IN[Y] where X is the edgeflag output, and Y is saved so we can tell the correct input later. The VP still writes the useless values to wasted outputs as punishment. --- src/gallium/drivers/nv50/nv50_program.c | 19 +++++++++++--- src/gallium/drivers/nv50/nv50_program.h | 1 + src/gallium/drivers/nv50/nv50_screen.c | 3 +++ src/gallium/drivers/nv50/nv50_vbo.c | 45 ++++++++++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 4 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_program.h') diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 679c28ce4b..ce3fa5fc88 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -159,6 +159,8 @@ struct nv50_pc { unsigned insn_nr; boolean allow32; + + uint8_t edgeflag_out; }; static INLINE struct nv50_reg * @@ -2554,10 +2556,16 @@ prep_inspect_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *insn) mask = dst->WriteMask; if (dst->File == TGSI_FILE_TEMPORARY) - reg = pc->temp; + reg = pc->temp; else - if (dst->File == TGSI_FILE_OUTPUT) - reg = pc->result; + if (dst->File == TGSI_FILE_OUTPUT) { + reg = pc->result; + + if (insn->Instruction.Opcode == TGSI_OPCODE_MOV && + dst->Index == pc->edgeflag_out && + insn->Src[0].Register.File == TGSI_FILE_INPUT) + pc->p->cfg.edgeflag_in = insn->Src[0].Register.Index; + } if (reg) { for (c = 0; c < 4; c++) { @@ -2856,6 +2864,9 @@ nv50_program_tx_prep(struct nv50_pc *pc) if (p->cfg.io_nr > first) p->cfg.io_nr = first; break; + case TGSI_SEMANTIC_EDGEFLAG: + pc->edgeflag_out = first; + break; /* case TGSI_SEMANTIC_CLIP_DISTANCE: p->cfg.clpd = MIN2(p->cfg.clpd, first); @@ -3104,6 +3115,8 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) p->cfg.two_side[0].hw = 0x40; p->cfg.two_side[1].hw = 0x40; + p->cfg.edgeflag_in = pc->edgeflag_out = 0xff; + switch (p->type) { case PIPE_SHADER_VERTEX: p->cfg.psiz = 0x40; diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index 4a90c372ce..461fec1d89 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -58,6 +58,7 @@ struct nv50_program { /* VP only */ uint8_t clpd, clpd_nr; uint8_t psiz; + uint8_t edgeflag_in; } cfg; }; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index d443ca3ad0..2435f65ed2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -441,6 +441,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1); so_data (so, 1); + so_method(so, screen->tesla, 0x15e4, 1); + so_data (so, 1); /* default edgeflag to TRUE */ + so_emit(chan, so); so_ref (so, &screen->static_init); so_ref (NULL, &so); diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index f7fa0659e8..39324e30f6 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -372,6 +372,10 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, so_data (so, fui(v[1])); break; case 1: + if (attrib == nv50->vertprog->cfg.edgeflag_in) { + so_method(so, tesla, 0x15e4, 1); + so_data (so, v[0] ? 1 : 0); + } so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 1); so_data (so, fui(v[0])); break; @@ -401,6 +405,9 @@ nv50_vbo_validate(struct nv50_context *nv50) !(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)) nv50->vbo_fifo = 0xffff; + if (nv50->vertprog->cfg.edgeflag_in < 16) + nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */ + n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr); vtxattr = NULL; @@ -479,6 +486,9 @@ struct nv50_vbo_emitctx unsigned nr_ve; unsigned vtx_dwords; unsigned vtx_max; + + float edgeflag; + unsigned ve_edgeflag; }; static INLINE void @@ -622,6 +632,9 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, if (nv50_map_vbufs(nv50) == FALSE) return FALSE; + emit->ve_edgeflag = nv50->vertprog->cfg.edgeflag_in; + + emit->edgeflag = 0.5f; emit->nr_ve = 0; emit->vtx_dwords = 0; @@ -644,7 +657,8 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, desc = util_format_description(ve->src_format); assert(desc); - size = util_format_get_component_bits(ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0); + size = util_format_get_component_bits( + ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0); assert(ve->nr_components > 0 && ve->nr_components <= 4); @@ -686,10 +700,31 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, } emit->vtx_max = 512 / emit->vtx_dwords; + if (emit->ve_edgeflag < 16) + emit->vtx_max = 1; return TRUE; } +static INLINE void +set_edgeflag(struct nouveau_channel *chan, + struct nouveau_grobj *tesla, + struct nv50_vbo_emitctx *emit, uint32_t index) +{ + unsigned i = emit->ve_edgeflag; + + if (i < 16) { + float f = *((float *)(emit->map[i] + index * emit->stride[i])); + + if (emit->edgeflag != f) { + emit->edgeflag = f; + + BEGIN_RING(chan, tesla, 0x15e4, 1); + OUT_RING (chan, f ? 1 : 0); + } + } +} + static boolean nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) { @@ -704,6 +739,8 @@ nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) unsigned i, dw, nr = MIN2(count, emit.vtx_max); dw = nr * emit.vtx_dwords; + set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */ + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); for (i = 0; i < nr; ++i) emit_vtx_next(chan, &emit); @@ -729,6 +766,8 @@ nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count) unsigned i, dw, nr = MIN2(count, emit.vtx_max); dw = nr * emit.vtx_dwords; + set_edgeflag(chan, tesla, &emit, *map); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); @@ -754,6 +793,8 @@ nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count) unsigned i, dw, nr = MIN2(count, emit.vtx_max); dw = nr * emit.vtx_dwords; + set_edgeflag(chan, tesla, &emit, *map); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); @@ -779,6 +820,8 @@ nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count) unsigned i, dw, nr = MIN2(count, emit.vtx_max); dw = nr * emit.vtx_dwords; + set_edgeflag(chan, tesla, &emit, *map); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); -- cgit v1.2.3