From 5138ac033ad3708e2b82f2beebc887f65a77309e Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sat, 11 Dec 2010 16:23:43 +0100 Subject: [PATCH] nvc0: support user clip planes --- src/gallium/drivers/nvc0/nvc0_program.c | 7 +++ src/gallium/drivers/nvc0/nvc0_program.h | 2 + src/gallium/drivers/nvc0/nvc0_screen.c | 12 ++++- src/gallium/drivers/nvc0/nvc0_shader_state.c | 8 ++++ src/gallium/drivers/nvc0/nvc0_state.c | 5 ++ .../drivers/nvc0/nvc0_state_validate.c | 17 +++++++ src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c | 48 ++++++++++++++++++- 7 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index 7aa6ef02bcd..e159b7161d4 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -418,6 +418,8 @@ nvc0_vp_gen_header(struct nvc0_program *vp, struct nvc0_translation_info *ti) vp->hdr[0] = 0x20461; vp->hdr[4] = 0xff000; + vp->hdr[18] = (1 << vp->vp.num_ucps) - 1; + return nvc0_vp_gp_gen_header(vp, ti); } @@ -605,6 +607,9 @@ nvc0_program_translate(struct nvc0_program *prog) ti->edgeflag_out = PIPE_MAX_SHADER_OUTPUTS; + if (prog->type == PIPE_SHADER_VERTEX && prog->vp.num_ucps) + ti->append_ucp = TRUE; + ret = nvc0_prog_scan(ti); if (ret) { NOUVEAU_ERR("unsupported shader program\n"); @@ -646,5 +651,7 @@ nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog) if (prog->relocs) FREE(prog->relocs); + memset(prog->hdr, 0, sizeof(prog->hdr)); + prog->translated = FALSE; } diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h index 42d9be38307..1271303144e 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nvc0/nvc0_program.h @@ -27,6 +27,7 @@ struct nvc0_program { struct { uint8_t edgeflag; + uint8_t num_ucps; } vp; void *relocs; @@ -71,6 +72,7 @@ struct nvc0_translation_info { ubyte edgeflag_out; struct nvc0_subroutine *subr; unsigned num_subrs; + boolean append_ucp; struct tgsi_shader_info scan; }; diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index fb100e5233a..f0d06be9ce4 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -457,11 +457,21 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nouveau_resource_init(&screen->text_heap, 0, 1 << 20); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 5 << 16, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 6 << 16, &screen->uniforms); if (ret) goto fail; + /* auxiliary constants (6 user clip planes, base instance id) */ + BEGIN_RING(chan, RING_3D(CB_SIZE), 3); + OUT_RING (chan, 256); + OUT_RELOCh(chan, screen->uniforms, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->uniforms, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + for (i = 0; i < 5; ++i) { + BEGIN_RING(chan, RING_3D(CB_BIND(i)), 1); + OUT_RING (chan, (15 << 4) | 1); + } + screen->tls_size = 4 * 4 * 32 * 128 * 4; ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, screen->tls_size, &screen->tls); diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c index a16fa6cf5b2..a6595c56106 100644 --- a/src/gallium/drivers/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c @@ -67,6 +67,14 @@ nvc0_vertprog_validate(struct nvc0_context *nvc0) struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *vp = nvc0->vertprog; + if (nvc0->clip.nr > vp->vp.num_ucps) { + assert(nvc0->clip.nr <= 6); + vp->vp.num_ucps = 6; + + if (vp->translated) + nvc0_program_destroy(nvc0, vp); + } + if (!nvc0_program_validate(nvc0, vp)) return; diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index c7a8c4b747f..8d293233b12 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -699,8 +699,13 @@ nvc0_set_clip_state(struct pipe_context *pipe, const struct pipe_clip_state *clip) { struct nvc0_context *nvc0 = nvc0_context(pipe); + const unsigned size = clip->nr * sizeof(clip->ucp[0]); + + memcpy(&nvc0->clip.ucp[0][0], &clip->ucp[0][0], size); + nvc0->clip.nr = clip->nr; nvc0->clip.depth_clamp = clip->depth_clamp; + nvc0->dirty |= NVC0_NEW_CLIP; } diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index 2b38ebc8ba0..ded461b9c51 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -193,6 +193,23 @@ nvc0_validate_clip(struct nvc0_context *nvc0) BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); OUT_RING (chan, clip); + + if (nvc0->clip.nr) { + struct nouveau_bo *bo = nvc0->screen->uniforms; + + BEGIN_RING(chan, RING_3D(CB_SIZE), 3); + OUT_RING (chan, 256); + OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + BEGIN_RING_1I(chan, RING_3D(CB_POS), nvc0->clip.nr * 4 + 1); + OUT_RING (chan, 0); + OUT_RINGp (chan, &nvc0->clip.ucp[0][0], nvc0->clip.nr * 4); + + BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1); + OUT_RING (chan, (1 << nvc0->clip.nr) - 1); + } else { + INLIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 0); + } } static void diff --git a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c index 8a20983a7e2..d0c82754894 100644 --- a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c +++ b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c @@ -111,6 +111,7 @@ struct bld_context { struct bld_register ovs[BLD_MAX_OUTPS][4]; /* TGSI_FILE_OUTPUT, FP only */ uint32_t outputs_written[(PIPE_MAX_SHADER_OUTPUTS + 7) / 8]; + int hpos_index; struct nv_value *zero; struct nv_value *frag_coord[4]; @@ -903,6 +904,38 @@ bld_is_output_written(struct bld_context *bld, int i, int c) return bld->outputs_written[i / 8] & (1 << ((i * 4 + c) % 32)); } +static void +bld_append_vp_ucp(struct bld_context *bld) +{ + struct nv_value *res[6]; + struct nv_value *ucp, *vtx, *out; + struct nv_instruction *insn; + int i, c; + + assert(bld->ti->prog->vp.num_ucps <= 6); + + for (c = 0; c < 4; ++c) { + vtx = bld_fetch_global(bld, &bld->ovs[bld->hpos_index][c]); + + for (i = 0; i < bld->ti->prog->vp.num_ucps; ++i) { + ucp = new_value(bld->pc, NV_FILE_MEM_C(15), 4); + ucp->reg.address = i * 16 + c * 4; + + if (c == 0) + res[i] = bld_insn_2(bld, NV_OP_MUL_F32, vtx, ucp); + else + res[i] = bld_insn_3(bld, NV_OP_MAD_F32, vtx, ucp, res[i]); + } + } + + for (i = 0; i < bld->ti->prog->vp.num_ucps; ++i) { + (out = new_value(bld->pc, NV_FILE_MEM_V, 4))->reg.address = 0x2c0 + i * 4; + (insn = new_instruction(bld->pc, NV_OP_EXPORT))->fixed = 1; + nv_reference(bld->pc, insn, 0, out); + nv_reference(bld->pc, insn, 1, res[i]); + } +} + static void bld_export_fp_outputs(struct bld_context *bld) { @@ -1755,11 +1788,13 @@ bld_instruction(struct bld_context *bld, /* VP outputs are exported in-place as scalars, optimization later */ if (bld->pc->is_fragprog) bld_export_fp_outputs(bld); - break; + if (bld->ti->append_ucp) + bld_append_vp_ucp(bld); + return; default: NOUVEAU_ERR("unhandled opcode %u\n", insn->Instruction.Opcode); abort(); - break; + return; } if (insn->Dst[0].Register.File == TGSI_FILE_OUTPUT && @@ -1767,6 +1802,15 @@ bld_instruction(struct bld_context *bld, struct nv_instruction *mi = NULL; uint size; + if (bld->ti->append_ucp) { + if (bld->ti->output_loc[insn->Dst[0].Register.Index][0] == 0x70) { + bld->hpos_index = insn->Dst[0].Register.Index; + for (c = 0; c < 4; ++c) + if (mask & (1 << c)) + STORE_OUTP(insn->Dst[0].Register.Index, c, dst0[c]); + } + } + for (c = 0; c < 4; ++c) if ((mask & (1 << c)) && ((dst0[c]->reg.file == NV_FILE_IMM) || -- 2.30.2