nv30: Emit fragment program using state objects
authorPatrice Mandin <pmandin@caramail.com>
Fri, 11 Jul 2008 22:48:26 +0000 (00:48 +0200)
committerPatrice Mandin <pmandin@caramail.com>
Fri, 11 Jul 2008 22:48:26 +0000 (00:48 +0200)
src/gallium/drivers/nv30/nv30_context.h
src/gallium/drivers/nv30/nv30_fragprog.c
src/gallium/drivers/nv30/nv30_fragtex.c
src/gallium/drivers/nv30/nv30_state.c
src/gallium/drivers/nv30/nv30_state.h
src/gallium/drivers/nv30/nv30_state_emit.c

index 5d7080a555dd5856df94ebb1a9c61b4cf246e2da..0c900c5598f73e7111a1e84c140ff92135f830c6 100644 (file)
@@ -125,6 +125,7 @@ struct nv30_context {
        struct pipe_scissor_state scissor;
        unsigned stipple[32];
        struct nv30_vertex_program *vertprog;
+       struct nv30_fragment_program *fragprog;
        struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
        unsigned constbuf_nr[PIPE_SHADER_TYPES];
        struct nv30_rasterizer_state *rasterizer;
@@ -151,11 +152,6 @@ struct nv30_context {
                unsigned delta;
        } vb[16];
 
-       struct {
-               struct nv30_fragment_program *active;
-               struct nv30_fragment_program *current;
-       } fragprog;
-
        struct pipe_vertex_buffer  vtxbuf[PIPE_MAX_ATTRIBS];
        struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
 };
@@ -188,10 +184,6 @@ extern void nv30_vertprog_destroy(struct nv30_context *,
                                  struct nv30_vertex_program *);
 
 /* nv30_fragprog.c */
-extern void nv30_fragprog_translate(struct nv30_context *,
-                                   struct nv30_fragment_program *);
-extern void nv30_fragprog_bind(struct nv30_context *,
-                              struct nv30_fragment_program *);
 extern void nv30_fragprog_destroy(struct nv30_context *,
                                  struct nv30_fragment_program *);
 
@@ -205,6 +197,7 @@ extern void nv30_state_tex_update(struct nv30_context *nv30);
 extern struct nv30_state_entry nv30_state_rasterizer;
 extern struct nv30_state_entry nv30_state_scissor;
 extern struct nv30_state_entry nv30_state_stipple;
+extern struct nv30_state_entry nv30_state_fragprog;
 extern struct nv30_state_entry nv30_state_vertprog;
 extern struct nv30_state_entry nv30_state_blend;
 extern struct nv30_state_entry nv30_state_blend_colour;
index b560455a02f99691e689555e4d3a25a887de696d..06ed04cbfeb0dca09376b93b55f682668f6f5803 100644 (file)
@@ -723,7 +723,7 @@ out_err:
        return FALSE;
 }
 
-void
+static void
 nv30_fragprog_translate(struct nv30_context *nv30,
                        struct nv30_fragment_program *fp)
 {
@@ -817,23 +817,46 @@ nv30_fragprog_upload(struct nv30_context *nv30,
        ws->buffer_unmap(ws, fp->buffer);
 }
 
-void
-nv30_fragprog_bind(struct nv30_context *nv30, struct nv30_fragment_program *fp)
+static boolean
+nv30_fragprog_validate(struct nv30_context *nv30)
 {
+       struct nv30_fragment_program *fp = nv30->fragprog;
        struct pipe_buffer *constbuf =
                nv30->constbuf[PIPE_SHADER_FRAGMENT];
        struct pipe_winsys *ws = nv30->pipe.winsys;
+       struct nouveau_stateobj *so;
+       boolean new_consts = FALSE;
        int i;
 
+       if (fp->translated)
+               goto update_constants;
+
+       /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/
+       nv30_fragprog_translate(nv30, fp);
        if (!fp->translated) {
-               nv30_fragprog_translate(nv30, fp);
-               if (!fp->translated)
-                       assert(0);
+               /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/
+               return FALSE;
        }
 
+       fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+       nv30_fragprog_upload(nv30, fp);
+
+       so = so_new(4, 1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
+       so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                 NV34TCL_FP_ACTIVE_PROGRAM_DMA0, NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1);
+       so_data  (so, fp->fp_control);
+       /* FIXME: Add these, and you'll have big slowdown */
+       /*so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1);
+       so_data  (so, fp->fp_control);*/
+       so_ref(so, &fp->so);
+
+update_constants:
        if (fp->nr_consts) {
                float *map;
-
+               
                map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
                for (i = 0; i < fp->nr_consts; i++) {
                        struct nv30_fragment_program_data *fpd = &fp->consts[i];
@@ -843,25 +866,20 @@ nv30_fragprog_bind(struct nv30_context *nv30, struct nv30_fragment_program *fp)
                        if (!memcmp(p, cb, 4 * sizeof(float)))
                                continue;
                        memcpy(p, cb, 4 * sizeof(float));
-                       fp->on_hw = 0;
+                       new_consts = TRUE;
                }
                ws->buffer_unmap(ws, constbuf);
-       }
 
-       if (!fp->on_hw) {
-               if (!fp->buffer)
-                       fp->buffer = ws->buffer_create(ws, 0x100, 0,
-                                                      fp->insn_len * 4);
-               nv30_fragprog_upload(nv30, fp);
-               fp->on_hw = TRUE;
+               if (new_consts)
+                       nv30_fragprog_upload(nv30, fp);
        }
 
-       BEGIN_RING(rankine, NV34TCL_FP_CONTROL, 1);
-       OUT_RING  (fp->fp_control);
-       BEGIN_RING(rankine, NV34TCL_FP_REG_CONTROL, 1);
-       OUT_RING  (fp->fp_reg_control);
+       if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) {
+               so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]);
+               return TRUE;
+       }
 
-       nv30->fragprog.active = fp;
+       return FALSE;
 }
 
 void
@@ -872,3 +890,10 @@ nv30_fragprog_destroy(struct nv30_context *nv30,
                FREE(fp->insn);
 }
 
+struct nv30_state_entry nv30_state_fragprog = {
+       .validate = nv30_fragprog_validate,
+       .dirty = {
+               .pipe = NV30_NEW_FRAGPROG,
+               .hw = NV30_STATE_FRAGPROG
+       }
+};
index abe77b51df258f3fb3ff6b9848fc4cd077c09c32..8c5e88ea1da248e815f34f17f391103194efb637 100644 (file)
@@ -143,7 +143,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
 static boolean
 nv30_fragtex_validate(struct nv30_context *nv30)
 {
-       struct nv30_fragment_program *fp = nv30->fragprog.current;
+       struct nv30_fragment_program *fp = nv30->fragprog;
        struct nv30_state *state = &nv30->state;
        struct nouveau_stateobj *so;
        unsigned samplers, unit;
index 92695ce23c02277fcf3a57453246c06b2156d826..8dc16d361d82253a67b2a4bcb45ab20cfbcff23b 100644 (file)
@@ -539,6 +539,8 @@ nv30_fp_state_create(struct pipe_context *pipe,
        fp = CALLOC(1, sizeof(struct nv30_fragment_program));
        fp->pipe = *cso;
 
+       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+
        return (void *)fp;
 }
 
@@ -546,13 +548,8 @@ static void
 nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv30_context *nv30 = nv30_context(pipe);
-       struct nv30_fragment_program *fp = hwcso;
-
-       if (!hwcso) {
-               return;
-       }
 
-       nv30->fragprog.current = fp;
+       nv30->fragprog = hwcso;
        nv30->dirty |= NV30_NEW_FRAGPROG;
 }
 
index a897bc50687534bfbac26150293fc8727b084580..20c5176160769f849a5f466c9bc92c6bf8601590 100644 (file)
@@ -2,6 +2,7 @@
 #define __NV30_STATE_H__
 
 #include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
 
 struct nv30_sampler_state {
        uint32_t fmt;
@@ -50,6 +51,7 @@ struct nv30_fragment_program_data {
 
 struct nv30_fragment_program {
        struct pipe_shader_state pipe;
+       struct tgsi_shader_info info;
 
        boolean translated;
        boolean on_hw;
@@ -65,6 +67,7 @@ struct nv30_fragment_program {
 
        uint32_t fp_control;
        uint32_t fp_reg_control;
+       struct nouveau_stateobj *so;
 };
 
 struct nv30_miptree {
index 4ab62ddc0162e26a1dec70bdbc61fff8776b63df..c4ccc9422be744337cabf05a7722285ef6d79460 100644 (file)
@@ -6,6 +6,7 @@ static struct nv30_state_entry *render_states[] = {
        &nv30_state_rasterizer,
        &nv30_state_scissor,
        &nv30_state_stipple,
+       &nv30_state_fragprog,
        &nv30_state_fragtex,
        &nv30_state_vertprog,
        &nv30_state_blend,
@@ -61,11 +62,6 @@ nv30_emit_hw_state(struct nv30_context *nv30)
                screen->cur_pctx = nv30->pctx_id;
        }
 
-       if (nv30->dirty & NV30_NEW_FRAGPROG) {
-               nv30_fragprog_bind(nv30, nv30->fragprog.current);
-               /*XXX: clear NV30_NEW_FRAGPROG if no new program uploaded */
-       }
-
        for (i = 0, states = state->dirty; states; i++) {
                if (!(states & (1ULL << i)))
                        continue;
@@ -83,13 +79,7 @@ nv30_emit_hw_state(struct nv30_context *nv30)
                                      state->hw[NV30_STATE_FRAGTEX0+i]);
                samplers &= ~(1ULL << i);
        }
-
-       /* Fragment program */
-       BEGIN_RING(rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
-       OUT_RELOC (nv30->fragprog.active->buffer, 0, NOUVEAU_BO_VRAM |
-                  NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
-                  NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0,
-                  NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]);
 }
 
 boolean