summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv40
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv40')
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h14
-rw-r--r--src/gallium/drivers/nv40/nv40_fragprog.c10
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c5
-rw-r--r--src/gallium/drivers/nv40/nv40_state.h1
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c3
-rw-r--r--src/gallium/drivers/nv40/nv40_vbo.c2
-rw-r--r--src/gallium/drivers/nv40/nv40_vertprog.c57
7 files changed, 55 insertions, 37 deletions
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index ce0933fea4a..28a0274d771 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -75,6 +75,7 @@ struct nv40_state {
} stipple;
struct nouveau_stateobj *fragprog;
+ struct nouveau_stateobj *vertprog;
};
struct nv40_context {
@@ -99,6 +100,7 @@ struct nv40_context {
struct pipe_scissor_state scissor;
unsigned stipple[32];
struct pipe_clip_state clip;
+ struct nv40_vertex_program *vertprog;
struct nv40_fragment_program *fragprog;
struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
} pipe_state;
@@ -117,13 +119,6 @@ struct nv40_context {
struct nouveau_stateobj *so_viewport;
struct nouveau_stateobj *so_stipple;
- struct {
- struct nv40_vertex_program *active;
-
- struct nv40_vertex_program *current;
- struct pipe_buffer *constant_buf;
- } vertprog;
-
struct pipe_vertex_buffer vtxbuf[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vtxelt[PIPE_ATTRIB_MAX];
};
@@ -151,10 +146,6 @@ extern void nv40_init_query_functions(struct nv40_context *nv40);
extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40);
/* nv40_vertprog.c */
-extern void nv40_vertprog_translate(struct nv40_context *,
- struct nv40_vertex_program *);
-extern void nv40_vertprog_bind(struct nv40_context *,
- struct nv40_vertex_program *);
extern void nv40_vertprog_destroy(struct nv40_context *,
struct nv40_vertex_program *);
@@ -172,6 +163,7 @@ extern struct nv40_state_entry nv40_state_clip;
extern struct nv40_state_entry nv40_state_scissor;
extern struct nv40_state_entry nv40_state_stipple;
extern struct nv40_state_entry nv40_state_fragprog;
+extern struct nv40_state_entry nv40_state_vertprog;
/* nv40_vbo.c */
extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c
index bfc75eb4620..77ac8ab2c61 100644
--- a/src/gallium/drivers/nv40/nv40_fragprog.c
+++ b/src/gallium/drivers/nv40/nv40_fragprog.c
@@ -795,7 +795,6 @@ nv40_fragprog_validate(struct nv40_context *nv40)
nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT];
struct pipe_winsys *ws = nv40->pipe.winsys;
struct nouveau_stateobj *so;
- unsigned new_program = FALSE;
int i;
if (fp->translated)
@@ -806,7 +805,6 @@ nv40_fragprog_validate(struct nv40_context *nv40)
nv40->fallback |= NV40_FALLBACK_RAST;
return FALSE;
}
- new_program = TRUE;
fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
nv40_fragprog_upload(nv40, fp);
@@ -843,8 +841,12 @@ update_constants:
nv40_fragprog_upload(nv40, fp);
}
- so_ref(fp->so, &nv40->state.fragprog);
- return new_program;
+ if (fp->so != nv40->state.fragprog) {
+ so_ref(fp->so, &nv40->state.fragprog);
+ return TRUE;
+ }
+
+ return FALSE;
}
void
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index 2886c6b0dc4..8ffbb131f73 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -491,9 +491,8 @@ static void
nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nv40_vertex_program *vp = hwcso;
- nv40->vertprog.current = vp;
+ nv40->pipe_state.vertprog = hwcso;
nv40->dirty |= NV40_NEW_VERTPROG;
}
@@ -573,7 +572,7 @@ nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
struct nv40_context *nv40 = nv40_context(pipe);
if (shader == PIPE_SHADER_VERTEX) {
- nv40->vertprog.constant_buf = buf->buffer;
+ nv40->pipe_state.constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
nv40->dirty |= NV40_NEW_VERTPROG;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h
index 2701294a077..e5217fe91c4 100644
--- a/src/gallium/drivers/nv40/nv40_state.h
+++ b/src/gallium/drivers/nv40/nv40_state.h
@@ -39,6 +39,7 @@ struct nv40_vertex_program {
uint32_t ir;
uint32_t or;
+ struct nouveau_stateobj *so;
};
struct nv40_fragment_program_data {
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index e10e178432e..e702b103236 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -27,6 +27,7 @@ static struct nv40_state_entry *render_states[] = {
&nv40_state_scissor,
&nv40_state_stipple,
&nv40_state_fragprog,
+ &nv40_state_vertprog,
NULL
};
@@ -116,7 +117,7 @@ nv40_emit_hw_state(struct nv40_context *nv40)
}
if (nv40->dirty & NV40_NEW_VERTPROG) {
- nv40_vertprog_bind(nv40, nv40->vertprog.current);
+ so_emit(nv40->nvws, nv40->state.vertprog);
nv40->dirty &= ~NV40_NEW_VERTPROG;
}
diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c
index fa827ef0c5d..3bfcb264db1 100644
--- a/src/gallium/drivers/nv40/nv40_vbo.c
+++ b/src/gallium/drivers/nv40/nv40_vbo.c
@@ -101,7 +101,7 @@ static void
nv40_vbo_arrays_update(struct nv40_context *nv40, struct pipe_buffer *ib,
unsigned ib_format)
{
- struct nv40_vertex_program *vp = nv40->vertprog.active;
+ struct nv40_vertex_program *vp = nv40->pipe_state.vertprog;
struct nouveau_stateobj *vtxbuf, *vtxfmt;
unsigned inputs, hw, num_hw;
unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c
index 9f4738b8308..4a15e51eb33 100644
--- a/src/gallium/drivers/nv40/nv40_vertprog.c
+++ b/src/gallium/drivers/nv40/nv40_vertprog.c
@@ -558,7 +558,7 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc)
return TRUE;
}
-void
+static void
nv40_vertprog_translate(struct nv40_context *nv40,
struct nv40_vertex_program *vp)
{
@@ -631,24 +631,32 @@ out_err:
free(vpc);
}
-void
-nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
+static boolean
+nv40_vertprog_validate(struct nv40_context *nv40)
{
+ struct nv40_vertex_program *vp = nv40->pipe_state.vertprog;
+ struct pipe_buffer *constbuf =
+ nv40->pipe_state.constbuf[PIPE_SHADER_VERTEX];
struct nouveau_winsys *nvws = nv40->nvws;
struct pipe_winsys *ws = nv40->pipe.winsys;
boolean upload_code = FALSE, upload_data = FALSE;
int i;
/* Translate TGSI shader into hw bytecode */
+ if (vp->translated)
+ goto check_gpu_resources;
+
+ nv40_vertprog_translate(nv40, vp);
if (!vp->translated) {
- nv40_vertprog_translate(nv40, vp);
- if (!vp->translated)
- assert(0);
+ nv40->fallback |= NV40_FALLBACK_TNL;
+ return FALSE;
}
+check_gpu_resources:
/* Allocate hw vtxprog exec slots */
if (!vp->exec) {
struct nouveau_resource *heap = nv40->hw->vp_exec_heap;
+ struct nouveau_stateobj *so;
uint vplen = vp->nr_insns;
if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) {
@@ -663,6 +671,15 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
assert(0);
}
+ so = so_new(5, 0);
+ so_method(so, nv40->hw->curie, NV40TCL_VP_START_FROM_ID, 1);
+ so_data (so, vp->exec->start);
+ so_method(so, nv40->hw->curie, NV40TCL_VP_ATTRIB_EN, 2);
+ so_data (so, vp->ir);
+ so_data (so, vp->or);
+ so_ref(so, &vp->so);
+ so_ref(NULL, &so);
+
upload_code = TRUE;
}
@@ -725,8 +742,8 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
if (vp->nr_consts) {
float *map = NULL;
- if (nv40->vertprog.constant_buf) {
- map = ws->buffer_map(ws, nv40->vertprog.constant_buf,
+ if (constbuf) {
+ map = ws->buffer_map(ws, constbuf,
PIPE_BUFFER_USAGE_CPU_READ);
}
@@ -747,9 +764,8 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
OUT_RINGp ((uint32_t *)vpd->value, 4);
}
- if (map) {
- ws->buffer_unmap(ws, nv40->vertprog.constant_buf);
- }
+ if (constbuf)
+ ws->buffer_unmap(ws, constbuf);
}
/* Upload vtxprog */
@@ -770,13 +786,12 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
}
}
- BEGIN_RING(curie, NV40TCL_VP_START_FROM_ID, 1);
- OUT_RING (vp->exec->start);
- BEGIN_RING(curie, NV40TCL_VP_ATTRIB_EN, 2);
- OUT_RING (vp->ir);
- OUT_RING (vp->or);
+ if (vp->so != nv40->state.vertprog) {
+ so_ref(vp->so, &nv40->state.vertprog);
+ return TRUE;
+ }
- nv40->vertprog.active = vp;
+ return FALSE;
}
void
@@ -788,3 +803,11 @@ nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp)
free(vp->insns);
}
+struct nv40_state_entry nv40_state_vertprog = {
+ .validate = nv40_vertprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_VERTPROG,
+ .hw = NV40_NEW_VERTPROG
+ }
+};
+