Module: Mesa
Branch: master
Commit: df86f1e7d50e01b92e03dc25fa9e9258d2d4fa2f
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=df86f1e7d50e01b92e03dc25fa9e9258d2d4fa2f

Author: Luca Barbieri <[email protected]>
Date:   Sun Aug 22 16:15:51 2010 +0200

nvfx: refactor to support multiple fragment program versions

---

 src/gallium/drivers/nvfx/nvfx_context.c  |    4 +
 src/gallium/drivers/nvfx/nvfx_context.h  |    5 +-
 src/gallium/drivers/nvfx/nvfx_draw.c     |   10 +-
 src/gallium/drivers/nvfx/nvfx_fragprog.c |  174 ++++++++++++++++++-----------
 src/gallium/drivers/nvfx/nvfx_state.h    |   10 +-
 5 files changed, 127 insertions(+), 76 deletions(-)

diff --git a/src/gallium/drivers/nvfx/nvfx_context.c 
b/src/gallium/drivers/nvfx/nvfx_context.c
index 99ad7bf..80b36fb 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.c
+++ b/src/gallium/drivers/nvfx/nvfx_context.c
@@ -33,6 +33,9 @@ nvfx_destroy(struct pipe_context *pipe)
 {
        struct nvfx_context *nvfx = nvfx_context(pipe);
 
+       if(nvfx->dummy_fs)
+               pipe->delete_fs_state(pipe, nvfx->dummy_fs);
+
        for(unsigned i = 0; i < nvfx->vtxbuf_nr; ++i)
                pipe_resource_reference(&nvfx->vtxbuf[i].buffer, 0);
        pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
@@ -42,6 +45,7 @@ nvfx_destroy(struct pipe_context *pipe)
 
        if (nvfx->draw)
                draw_destroy(nvfx->draw);
+
        FREE(nvfx);
 }
 
diff --git a/src/gallium/drivers/nvfx/nvfx_context.h 
b/src/gallium/drivers/nvfx/nvfx_context.h
index 02e8ed0..2134f3c 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.h
+++ b/src/gallium/drivers/nvfx/nvfx_context.h
@@ -161,7 +161,7 @@ struct nvfx_context {
        unsigned stipple[32];
        struct pipe_clip_state clip;
        struct nvfx_vertex_program *vertprog;
-       struct nvfx_fragment_program *fragprog;
+       struct nvfx_pipe_fragment_program *fragprog;
        struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
        unsigned constbuf_nr[PIPE_SHADER_TYPES];
        struct nvfx_rasterizer_state *rasterizer;
@@ -174,6 +174,8 @@ struct nvfx_context {
        struct pipe_index_buffer idxbuf;
        struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
        struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
+       struct nvfx_pipe_fragment_program* dummy_fs;
+
        unsigned nr_samplers;
        unsigned nr_textures;
        unsigned dirty_samplers;
@@ -195,6 +197,7 @@ struct nvfx_context {
        struct nvfx_render_target hw_zeta;
        int hw_pointsprite_control;
        int hw_vp_output;
+       struct nvfx_fragment_program* hw_fragprog;
 };
 
 static INLINE struct nvfx_context *
diff --git a/src/gallium/drivers/nvfx/nvfx_draw.c 
b/src/gallium/drivers/nvfx/nvfx_draw.c
index 331e284..0b17921 100644
--- a/src/gallium/drivers/nvfx/nvfx_draw.c
+++ b/src/gallium/drivers/nvfx/nvfx_draw.c
@@ -274,19 +274,19 @@ emit_attrib(struct nvfx_context *nvfx, unsigned hw, 
unsigned emit,
 void
 nvfx_vtxfmt_validate(struct nvfx_context *nvfx)
 {
-       struct nvfx_fragment_program *fp = nvfx->fragprog;
+       struct nvfx_pipe_fragment_program *pfp = nvfx->fragprog;
        unsigned colour = 0, texcoords = 0, fog = 0, i;
 
        /* Determine needed fragprog inputs */
-       for (i = 0; i < fp->info.num_inputs; i++) {
-               switch (fp->info.input_semantic_name[i]) {
+       for (i = 0; i < pfp->info.num_inputs; i++) {
+               switch (pfp->info.input_semantic_name[i]) {
                case TGSI_SEMANTIC_POSITION:
                        break;
                case TGSI_SEMANTIC_COLOR:
-                       colour |= (1 << fp->info.input_semantic_index[i]);
+                       colour |= (1 << pfp->info.input_semantic_index[i]);
                        break;
                case TGSI_SEMANTIC_GENERIC:
-                       texcoords |= (1 << fp->info.input_semantic_index[i]);
+                       texcoords |= (1 << pfp->info.input_semantic_index[i]);
                        break;
                case TGSI_SEMANTIC_FOG:
                        fog = 1;
diff --git a/src/gallium/drivers/nvfx/nvfx_fragprog.c 
b/src/gallium/drivers/nvfx/nvfx_fragprog.c
index e0e31e4..c4394b2 100644
--- a/src/gallium/drivers/nvfx/nvfx_fragprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c
@@ -8,6 +8,7 @@
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_util.h"
 #include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
 
 #include "nvfx_context.h"
 #include "nvfx_shader.h"
@@ -17,6 +18,7 @@
 #define MAX_IMM 32
 
 struct nvfx_fpc {
+       struct nvfx_pipe_fragment_program* pfp;
        struct nvfx_fragment_program *fp;
 
        unsigned r_temps;
@@ -379,27 +381,27 @@ tgsi_src(struct nvfx_fpc *fpc, const struct 
tgsi_full_src_register *fsrc)
 
        switch (fsrc->Register.File) {
        case TGSI_FILE_INPUT:
-               if(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_POSITION) {
-                       
assert(fpc->fp->info.input_semantic_index[fsrc->Register.Index] == 0);
+               if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_POSITION) {
+                       
assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
                        src.reg = nvfx_reg(NVFXSR_INPUT, 
NVFX_FP_OP_INPUT_SRC_POSITION);
-               } else 
if(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_COLOR) {
-                       
if(fpc->fp->info.input_semantic_index[fsrc->Register.Index] == 0)
+               } else 
if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_COLOR) {
+                       
if(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0)
                                src.reg = nvfx_reg(NVFXSR_INPUT, 
NVFX_FP_OP_INPUT_SRC_COL0);
-                       else 
if(fpc->fp->info.input_semantic_index[fsrc->Register.Index] == 1)
+                       else 
if(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 1)
                                src.reg = nvfx_reg(NVFXSR_INPUT, 
NVFX_FP_OP_INPUT_SRC_COL1);
                        else
                                assert(0);
-               } else 
if(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_FOG) {
-                       
assert(fpc->fp->info.input_semantic_index[fsrc->Register.Index] == 0);
+               } else 
if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_FOG) {
+                       
assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
                        src.reg = nvfx_reg(NVFXSR_INPUT, 
NVFX_FP_OP_INPUT_SRC_FOGC);
-               } else 
if(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_FACE) {
+               } else 
if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_FACE) {
                        /* TODO: check this has the correct values */
                        /* XXX: what do we do for nv30 here (assuming it lacks 
facing)?!  */
-                       
assert(fpc->fp->info.input_semantic_index[fsrc->Register.Index] == 0);
+                       
assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
                        src.reg = nvfx_reg(NVFXSR_INPUT, 
NV40_FP_OP_INPUT_SRC_FACING);
                } else {
-                       
assert(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_GENERIC);
-                       src.reg = nvfx_reg(NVFXSR_RELOCATED, 
fpc->generic_to_slot[fpc->fp->info.input_semantic_index[fsrc->Register.Index]]);
+                       
assert(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == 
TGSI_SEMANTIC_GENERIC);
+                       src.reg = nvfx_reg(NVFXSR_RELOCATED, 
fpc->generic_to_slot[fpc->pfp->info.input_semantic_index[fsrc->Register.Index]]);
                }
                break;
        case TGSI_FILE_CONSTANT:
@@ -922,7 +924,7 @@ nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct 
nvfx_fpc *fpc)
        float const0v[4] = {0, 0, 0, 0};
        struct nvfx_reg const0;
 
-       fpc->fp->num_slots = util_semantic_set_from_program_file(&set, 
fpc->fp->pipe.tokens, TGSI_FILE_INPUT);
+       fpc->fp->num_slots = util_semantic_set_from_program_file(&set, 
fpc->pfp->pipe.tokens, TGSI_FILE_INPUT);
        if(fpc->fp->num_slots > 8)
                return FALSE;
        util_semantic_layout_from_set(fpc->fp->slot_to_generic, &set, 0, 8);
@@ -933,7 +935,7 @@ nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct 
nvfx_fpc *fpc)
        const0 = constant(fpc, -1, const0v);
        assert(const0.index == 0);
 
-       tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+       tgsi_parse_init(&p, fpc->pfp->pipe.tokens);
        while (!tgsi_parse_end_of_tokens(&p)) {
                const union tgsi_full_token *tok = &p.FullToken;
 
@@ -999,26 +1001,32 @@ out_err:
 
 DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_fp, "NVFX_DUMP_FP", FALSE)
 
-static void
+static struct nvfx_fragment_program*
 nvfx_fragprog_translate(struct nvfx_context *nvfx,
-                       struct nvfx_fragment_program *fp)
+                       struct nvfx_pipe_fragment_program *pfp)
 {
        struct tgsi_parse_context parse;
        struct nvfx_fpc *fpc = NULL;
        struct util_dynarray insns;
+       struct nvfx_fragment_program* fp = NULL;
+        const int min_size = 4096;
+
+       fp = CALLOC_STRUCT(nvfx_fragment_program);
+       if(!fp)
+               goto out_err;
 
-       fpc = CALLOC(1, sizeof(struct nvfx_fpc));
+       fpc = CALLOC_STRUCT(nvfx_fpc);
        if (!fpc)
-               return;
+               goto out_err;
+
+       fpc->pfp = pfp;
        fpc->fp = fp;
        fpc->num_regs = 2;
 
-       if (!nvfx_fragprog_prepare(nvfx, fpc)) {
-               FREE(fpc);
-               return;
-       }
+       if (!nvfx_fragprog_prepare(nvfx, fpc))
+               goto out_err;
 
-       tgsi_parse_init(&parse, fp->pipe.tokens);
+       tgsi_parse_init(&parse, pfp->pipe.tokens);
 
        util_dynarray_init(&insns);
        while (!tgsi_parse_end_of_tokens(&parse)) {
@@ -1068,7 +1076,7 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
        if(debug_get_option_nvfx_dump_fp())
        {
                debug_printf("\n");
-               tgsi_dump(fp->pipe.tokens, 0);
+               tgsi_dump(pfp->pipe.tokens, 0);
 
                debug_printf("\n%s fragment program:\n", nvfx->is_nv4x ? "nv4x" 
: "nv3x");
                for (unsigned i = 0; i < fp->insn_len; i += 4)
@@ -1076,15 +1084,37 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
                debug_printf("\n");
        }
 
-       fp->translated = TRUE;
-out_err:
+        fp->prog_size = (fp->insn_len * 4 + 63) & ~63;
+
+        if(fp->prog_size >= min_size)
+                fp->progs_per_bo = 1;
+        else
+                fp->progs_per_bo = min_size / fp->prog_size;
+        fp->bo_prog_idx = fp->progs_per_bo - 1;
+
+out:
        tgsi_parse_free(&parse);
-       if (fpc->r_temp)
-               FREE(fpc->r_temp);
-       util_dynarray_fini(&fpc->if_stack);
-       util_dynarray_fini(&fpc->label_relocs);
-       //util_dynarray_fini(&fpc->loop_stack);
-       FREE(fpc);
+       if(fpc)
+       {
+               if (fpc->r_temp)
+                       FREE(fpc->r_temp);
+               util_dynarray_fini(&fpc->if_stack);
+               util_dynarray_fini(&fpc->label_relocs);
+               //util_dynarray_fini(&fpc->loop_stack);
+               FREE(fpc);
+       }
+       return fp;
+
+out_err:
+       _debug_printf("Error: failed to compile this fragment program:\n");
+       tgsi_dump(pfp->pipe.tokens, 0);
+
+       if(fp)
+       {
+               FREE(fp);
+               fp = NULL;
+       }
+       goto out;
 }
 
 static inline void
@@ -1134,43 +1164,49 @@ void
 nvfx_fragprog_validate(struct nvfx_context *nvfx)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
-       struct nvfx_fragment_program *fp = nvfx->fragprog;
-       int update = 0;
+       struct nvfx_pipe_fragment_program *pfp = nvfx->fragprog;
        struct nvfx_vertex_program* vp;
        unsigned sprite_coord_enable;
-       boolean update_pointsprite = !!(nvfx->dirty & NVFX_NEW_FRAGPROG);
+       unsigned key = 0;
+       struct nvfx_fragment_program* fp;
 
-       if (!fp->translated)
+       fp = pfp->fps[key];
+       if (!fp)
        {
-               const int min_size = 4096;
+               fp = nvfx_fragprog_translate(nvfx, pfp);
 
-               nvfx_fragprog_translate(nvfx, fp);
-               if (!fp->translated) {
-                       static unsigned dummy[8] = {1, 0, 0, 0, 1, 0, 0, 0};
-                       static int warned = 0;
-                       if(!warned)
+               if(!fp)
+               {
+                       if(!nvfx->dummy_fs)
                        {
-                               fprintf(stderr, "nvfx: failed to translate 
fragment program!\n");
-                               warned = 1;
+                               struct ureg_program *ureg = ureg_create( 
TGSI_PROCESSOR_FRAGMENT );
+                               if (ureg)
+                               {
+                                       ureg_END( ureg );
+                                       nvfx->dummy_fs = 
ureg_create_shader_and_destroy( ureg, &nvfx->pipe );
+                               }
+
+                               if(!nvfx->dummy_fs)
+                               {
+                                       _debug_printf("Error: unable to create 
a dummy fragment shader: aborting.");
+                                       abort();
+                               }
                        }
 
-                       /* use dummy program: we cannot fail here */
-                       fp->translated = TRUE;
-                       fp->insn = malloc(sizeof(dummy));
-                       memcpy(fp->insn, dummy, sizeof(dummy));
-                       fp->insn_len = sizeof(dummy) / sizeof(dummy[0]);
-               }
-               update = TRUE;
+                       fp = nvfx_fragprog_translate(nvfx, nvfx->dummy_fs);
 
-               fp->prog_size = (fp->insn_len * 4 + 63) & ~63;
+                       if(!fp)
+                       {
+                               _debug_printf("Error: unable to compile even a 
dummy fragment shader: aborting.");
+                               abort();
+                       }
+               }
 
-               if(fp->prog_size >= min_size)
-                       fp->progs_per_bo = 1;
-               else
-                       fp->progs_per_bo = min_size / fp->prog_size;
-               fp->bo_prog_idx = fp->progs_per_bo - 1;
+               pfp->fps[key] = fp;
        }
 
+       nvfx->hw_fragprog = fp;
+
        vp = nvfx->render_mode == HW ? nvfx->vertprog : nvfx->swtnl.vertprog;
         sprite_coord_enable = nvfx->rasterizer->pipe.point_quad_rasterization 
* nvfx->rasterizer->pipe.sprite_coord_enable;
 
@@ -1391,7 +1427,7 @@ void
 nvfx_fragprog_relocate(struct nvfx_context *nvfx)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
-       struct nvfx_fragment_program *fp = nvfx->fragprog;
+       struct nvfx_fragment_program *fp = nvfx->hw_fragprog;
        struct nouveau_bo* bo = fp->fpbo->bo;
        int offset = fp->bo_prog_idx * fp->prog_size;
        unsigned fp_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; // TODO: GART?
@@ -1433,14 +1469,14 @@ static void *
 nvfx_fp_state_create(struct pipe_context *pipe,
                      const struct pipe_shader_state *cso)
 {
-        struct nvfx_fragment_program *fp;
+        struct nvfx_pipe_fragment_program *pfp;
 
-        fp = CALLOC(1, sizeof(struct nvfx_fragment_program));
-        fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+        pfp = CALLOC(1, sizeof(struct nvfx_pipe_fragment_program));
+        pfp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
 
-        tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+        tgsi_scan_shader(pfp->pipe.tokens, &pfp->info);
 
-        return (void *)fp;
+        return (void *)pfp;
 }
 
 static void
@@ -1456,11 +1492,17 @@ static void
 nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
 {
         struct nvfx_context *nvfx = nvfx_context(pipe);
-        struct nvfx_fragment_program *fp = hwcso;
+        struct nvfx_pipe_fragment_program *pfp = hwcso;
+        unsigned i;
+
+        for(i = 0; i < Elements(pfp->fps); ++i)
+        {
+               nvfx_fragprog_destroy(nvfx, pfp->fps[i]);
+               FREE(pfp->fps[i]);
+        }
 
-        nvfx_fragprog_destroy(nvfx, fp);
-        FREE((void*)fp->pipe.tokens);
-        FREE(fp);
+        FREE((void*)pfp->pipe.tokens);
+        FREE(pfp);
 }
 
 void
diff --git a/src/gallium/drivers/nvfx/nvfx_state.h 
b/src/gallium/drivers/nvfx/nvfx_state.h
index 05d41cf..fd2174e 100644
--- a/src/gallium/drivers/nvfx/nvfx_state.h
+++ b/src/gallium/drivers/nvfx/nvfx_state.h
@@ -61,10 +61,6 @@ struct nvfx_fragment_program_bo {
 };
 
 struct nvfx_fragment_program {
-       struct pipe_shader_state pipe;
-       struct tgsi_shader_info info;
-
-       boolean translated;
        unsigned samplers;
        unsigned point_sprite_control;
        unsigned or;
@@ -99,5 +95,11 @@ struct nvfx_fragment_program {
        struct nvfx_fragment_program_bo* fpbo;
 };
 
+struct nvfx_pipe_fragment_program {
+        struct pipe_shader_state pipe;
+        struct tgsi_shader_info info;
+
+        struct nvfx_fragment_program* fps[1];
+};
 
 #endif

_______________________________________________
mesa-commit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to