#include "nvc0_context.h"
-static boolean
-nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
+static INLINE void
+nvc0_program_update_context_state(struct nvc0_context *nvc0,
+ struct nvc0_program *prog, int stage)
{
- int ret;
- unsigned size;
-
- if (prog->translated)
- return TRUE;
+ struct nouveau_channel *chan = nvc0->screen->base.channel;
- prog->translated = nvc0_program_translate(prog);
- if (!prog->translated)
- return FALSE;
+ if (prog->hdr[1])
+ nvc0->state.tls_required |= 1 << stage;
+ else
+ nvc0->state.tls_required &= ~(1 << stage);
+
+ if (prog->immd_size) {
+ const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
+
+ BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
+ /* NOTE: may overlap code of a different shader */
+ OUT_RING (chan, align(prog->immd_size, 0x100));
+ OUT_RELOCh(chan, nvc0->screen->text, prog->immd_base, rl);
+ OUT_RELOCl(chan, nvc0->screen->text, prog->immd_base, rl);
+ BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
+ OUT_RING (chan, (14 << 4) | 1);
+
+ nvc0->state.c14_bound |= 1 << stage;
+ } else
+ if (nvc0->state.c14_bound & (1 << stage)) {
+ BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
+ OUT_RING (chan, (14 << 4) | 0);
+
+ nvc0->state.c14_bound &= ~(1 << stage);
+ }
+}
- size = align(prog->code_size + NVC0_SHADER_HEADER_SIZE, 0x100);
+static void
+nvc0_program_validate_clip(struct nvc0_context *nvc0, struct nvc0_program *vp)
+{
+ struct nouveau_channel *chan = nvc0->screen->base.channel;
- ret = nouveau_resource_alloc(nvc0->screen->text_heap, size, prog,
- &prog->res);
- if (ret)
- return FALSE;
+ if (nvc0->vertprog->vp.num_ucps)
+ return;
- prog->code_base = prog->res->start;
+ if (nvc0->state.clip_enable != vp->vp.clip_enable) {
+ nvc0->state.clip_enable = vp->vp.clip_enable;
+ IMMED_RING(chan, RING_3D(CLIP_DISTANCE_ENABLE), vp->vp.clip_enable);
+ }
+ if (nvc0->state.clip_mode != vp->vp.clip_mode) {
+ nvc0->state.clip_mode = vp->vp.clip_mode;
+ BEGIN_RING(chan, RING_3D(CLIP_DISTANCE_MODE), 1);
+ OUT_RING (chan, vp->vp.clip_mode);
+ }
+}
- nvc0_m2mf_push_linear(nvc0, nvc0->screen->text, NOUVEAU_BO_VRAM,
- prog->code_base, NVC0_SHADER_HEADER_SIZE, prog->hdr);
- nvc0_m2mf_push_linear(nvc0, nvc0->screen->text, NOUVEAU_BO_VRAM,
- prog->code_base + NVC0_SHADER_HEADER_SIZE,
- prog->code_size, prog->code);
+static INLINE boolean
+nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
+{
+ if (prog->res)
+ return TRUE;
- BEGIN_RING(nvc0->screen->base.channel, RING_3D(MEM_BARRIER), 1);
- OUT_RING (nvc0->screen->base.channel, 0x1111);
+ if (!prog->translated) {
+ prog->translated = nvc0_program_translate(prog);
+ if (!prog->translated)
+ return FALSE;
+ }
- return TRUE;
+ return nvc0_program_upload_code(nvc0, prog);
}
void
if (!nvc0_program_validate(nvc0, vp))
return;
+ nvc0_program_update_context_state(nvc0, vp, 0);
BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2);
OUT_RING (chan, 0x11);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(1)), 1);
OUT_RING (chan, vp->max_gpr);
+ if (!nvc0->gmtyprog && !nvc0->tevlprog)
+ nvc0_program_validate_clip(nvc0, vp);
+
// BEGIN_RING(chan, RING_3D_(0x163c), 1);
// OUT_RING (chan, 0);
- BEGIN_RING(chan, RING_3D(VERT_COLOR_CLAMP_EN), 1);
- OUT_RING (chan, 1);
}
void
if (!nvc0_program_validate(nvc0, fp))
return;
+ nvc0_program_update_context_state(nvc0, fp, 4);
- BEGIN_RING(chan, RING_3D(EARLY_FRAGMENT_TESTS), 1);
- OUT_RING (chan, fp->fp.early_z);
BEGIN_RING(chan, RING_3D(SP_SELECT(5)), 2);
OUT_RING (chan, 0x51);
OUT_RING (chan, fp->code_base);
}
if (!nvc0_program_validate(nvc0, tp))
return;
+ nvc0_program_update_context_state(nvc0, tp, 1);
+ if (tp->tp.tess_mode != ~0) {
+ BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
+ OUT_RING (chan, tp->tp.tess_mode);
+ }
BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2);
OUT_RING (chan, 0x21);
OUT_RING (chan, tp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(2)), 1);
- OUT_RING (chan, tp->max_gpr);
+ OUT_RING (chan, tp->max_gpr);
+
+ if (tp->tp.input_patch_size <= 32)
+ IMMED_RING(chan, RING_3D(PATCH_VERTICES), tp->tp.input_patch_size);
}
void
}
if (!nvc0_program_validate(nvc0, tp))
return;
+ nvc0_program_update_context_state(nvc0, tp, 2);
+ if (tp->tp.tess_mode != ~0) {
+ BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
+ OUT_RING (chan, tp->tp.tess_mode);
+ }
BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
OUT_RING (chan, 0x31);
BEGIN_RING(chan, RING_3D(SP_START_ID(3)), 1);
OUT_RING (chan, tp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(3)), 1);
- OUT_RING (chan, tp->max_gpr);
+ OUT_RING (chan, tp->max_gpr);
+
+ if (!nvc0->gmtyprog)
+ nvc0_program_validate_clip(nvc0, tp);
}
void
if (!gp) {
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
OUT_RING (chan, 0x40);
+ IMMED_RING(chan, RING_3D(LAYER), 0);
return;
}
if (!nvc0_program_validate(nvc0, gp))
return;
+ nvc0_program_update_context_state(nvc0, gp, 3);
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
OUT_RING (chan, 0x41);
BEGIN_RING(chan, RING_3D(SP_START_ID(4)), 1);
OUT_RING (chan, gp->code_base);
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
- OUT_RING (chan, gp->max_gpr);
+ OUT_RING (chan, gp->max_gpr);
+ BEGIN_RING(chan, RING_3D(LAYER), 1);
+ OUT_RING (chan, (gp->hdr[13] & (1 << 9)) ? NVC0_3D_LAYER_USE_GP : 0);
+
+ nvc0_program_validate_clip(nvc0, gp);
}
/* It's *is* kind of shader related. We need to inspect the program
for (b = 0; b < nvc0->num_tfbbufs; ++b) {
uint8_t idx, var[128];
int i, n;
- struct nvc0_resource *buf = nvc0_resource(nvc0->tfbbuf[b]);
+ struct nv04_resource *buf = nv04_resource(nvc0->tfbbuf[b]);
BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5);
OUT_RING (chan, 1);