gallium: reorganize fragment shader execution, unbreak sse
authorKeith Whitwell <keith@tungstengraphics.com>
Fri, 15 Feb 2008 09:31:22 +0000 (09:31 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Fri, 15 Feb 2008 09:31:22 +0000 (09:31 +0000)
This is probably going to get further reworked in the near future.

Right now there's a new interface wrapped around each shader execution
mode - exec, sse2, llvm.  The llvm code was disabled already and has
just been moved as-is to a new file, whereas the sse2 and exec code is
actually enabled.

The way the interfaces has turned out suggests to me that the correct
approach is to actually have each shader include a pointer to a quad stage
which will do a better job of encapsulating the execution environment than
what I have here -- that's a second step however.

12 files changed:
src/mesa/pipe/draw/draw_vertex_shader.c
src/mesa/pipe/softpipe/Makefile
src/mesa/pipe/softpipe/sp_context.h
src/mesa/pipe/softpipe/sp_fs_exec.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_fs_llvm.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_fs_sse.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_fs.c
src/mesa/pipe/softpipe/sp_state.h
src/mesa/pipe/softpipe/sp_state_fs.c
src/mesa/pipe/tgsi/exec/tgsi_exec.c
src/mesa/pipe/tgsi/exec/tgsi_exec.h
src/mesa/pipe/tgsi/exec/tgsi_sse2.c

index c824c1407e9c6c88b375aa5f8e66fdb0755619c8..bf340ef9b08b9269e1f2e7c31ae98fa0e0906dc5 100644 (file)
@@ -305,11 +305,13 @@ draw_bind_vertex_shader(struct draw_context *draw,
    draw->vertex_shader = dvs;
    draw->num_vs_outputs = dvs->state->num_outputs;
 
+   tgsi_exec_machine_init(&draw->machine);
+
    /* specify the vertex program to interpret/execute */
-   tgsi_exec_machine_init(&draw->machine,
-                          draw->vertex_shader->state->tokens,
-                          PIPE_MAX_SAMPLERS,
-                          NULL /*samplers*/ );
+   tgsi_exec_machine_bind_shader(&draw->machine,
+                                draw->vertex_shader->state->tokens,
+                                PIPE_MAX_SAMPLERS,
+                                NULL /*samplers*/ );
 }
 
 
index 31438a882e62d2fbaa268dad6d37a8d1a97b9e0b..304632abb2844eed09500b8b9990c887ff278eb9 100644 (file)
@@ -5,6 +5,9 @@ include $(TOP)/configs/current
 LIBNAME = softpipe
 
 DRIVER_SOURCES = \
+       sp_fs_exec.c \
+       sp_fs_sse.c \
+       sp_fs_llvm.c \
        sp_clear.c \
        sp_flush.c \
        sp_query.c \
index aff8c2cc5dc58e6d111a67a3f5246d87091fc5a4..5e24baf93863b043ad05f58c1f5b670d3c5edfa9 100644 (file)
@@ -44,8 +44,8 @@ struct softpipe_vbuf_render;
 struct draw_context;
 struct draw_stage;
 struct softpipe_tile_cache;
-struct sp_fragment_shader_state;
-struct sp_vertex_shader_state;
+struct sp_fragment_shader;
+struct sp_vertex_shader;
 
 
 struct softpipe_context {
@@ -59,8 +59,8 @@ struct softpipe_context {
    const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
    const struct pipe_depth_stencil_alpha_state   *depth_stencil;
    const struct pipe_rasterizer_state *rasterizer;
-   const struct sp_fragment_shader_state *fs;
-   const struct sp_vertex_shader_state *vs;
+   const struct sp_fragment_shader *fs;
+   const struct sp_vertex_shader *vs;
 
    struct pipe_blend_color blend_color;
    struct pipe_clip_state clip;
diff --git a/src/mesa/pipe/softpipe/sp_fs_exec.c b/src/mesa/pipe/softpipe/sp_fs_exec.c
new file mode 100644 (file)
index 0000000..b949492
--- /dev/null
@@ -0,0 +1,112 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+#include "sp_headers.h"
+
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+#include "pipe/tgsi/exec/tgsi_exec.h"
+
+struct sp_exec_fragment_shader {
+   struct sp_fragment_shader base;
+};
+
+
+
+
+static void
+exec_prepare( struct sp_fragment_shader *base,
+             struct tgsi_exec_machine *machine,
+             struct tgsi_sampler *samplers )
+{
+   tgsi_exec_machine_bind_shader( machine,
+                                 base->shader.tokens,
+                                 PIPE_MAX_SAMPLERS,
+                                 samplers );
+}
+
+
+
+
+/* TODO: hide the machine struct in here somewhere, remove from this
+ * interface:
+ */
+static unsigned 
+exec_run( struct sp_fragment_shader *base,
+         struct tgsi_exec_machine *machine,
+         struct quad_header *quad )
+{
+
+   /* Compute X, Y, Z, W vals for this quad */
+   sp_setup_pos_vector(quad->posCoef, 
+                      (float)quad->x0, (float)quad->y0, 
+                      &machine->QuadPos);
+   
+   return tgsi_exec_machine_run( machine );
+}
+
+
+
+static void 
+exec_delete( struct sp_fragment_shader *base )
+{
+   FREE(base);
+}
+
+
+
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_exec(struct softpipe_context *softpipe,
+                       const struct pipe_shader_state *templ)
+{
+   struct sp_exec_fragment_shader *shader;
+
+   /* Decide whether we'll be codegenerating this shader and if so do
+    * that now.
+    */
+
+   shader = CALLOC_STRUCT(sp_exec_fragment_shader);
+   if (!shader)
+      return NULL;
+
+   shader->base.shader = *templ;
+   shader->base.prepare = exec_prepare;
+   shader->base.run = exec_run;
+   shader->base.delete = exec_delete;
+
+   return &shader->base;
+}
+
diff --git a/src/mesa/pipe/softpipe/sp_fs_llvm.c b/src/mesa/pipe/softpipe/sp_fs_llvm.c
new file mode 100644 (file)
index 0000000..9237c1f
--- /dev/null
@@ -0,0 +1,200 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/* Authors:
+ *   Zack Rusin
+ */
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+#include "pipe/tgsi/exec/tgsi_sse2.h"
+
+#if 0
+
+struct sp_llvm_fragment_shader {
+   struct sp_fragment_shader base;
+   struct gallivm_prog *llvm_prog;
+};
+
+static void
+shade_quad_llvm(struct quad_stage *qs,
+                struct quad_header *quad)
+{
+   struct quad_shade_stage *qss = quad_shade_stage(qs);
+   struct softpipe_context *softpipe = qs->softpipe;
+   float dests[4][16][4] ALIGN16_ATTRIB;
+   float inputs[4][16][4] ALIGN16_ATTRIB;
+   const float fx = (float) quad->x0;
+   const float fy = (float) quad->y0;
+   struct gallivm_prog *llvm = qss->llvm_prog;
+
+   inputs[0][0][0] = fx;
+   inputs[1][0][0] = fx + 1.0f;
+   inputs[2][0][0] = fx;
+   inputs[3][0][0] = fx + 1.0f;
+
+   inputs[0][0][1] = fy;
+   inputs[1][0][1] = fy;
+   inputs[2][0][1] = fy + 1.0f;
+   inputs[3][0][1] = fy + 1.0f;
+
+
+   gallivm_prog_inputs_interpolate(llvm, inputs, quad->coef);
+
+#if DLLVM
+   debug_printf("MASK = %d\n", quad->mask);
+   for (int i = 0; i < 4; ++i) {
+      for (int j = 0; j < 2; ++j) {
+         debug_printf("IN(%d,%d) [%f %f %f %f]\n", i, j, 
+                inputs[i][j][0], inputs[i][j][1], inputs[i][j][2], inputs[i][j][3]);
+      }
+   }
+#endif
+
+   quad->mask &=
+      gallivm_fragment_shader_exec(llvm, fx, fy, dests, inputs,
+                                   softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
+                                   qss->samplers);
+#if DLLVM
+   debug_printf("OUT LLVM = 1[%f %f %f %f], 2[%f %f %f %f]\n",
+          dests[0][0][0], dests[0][0][1], dests[0][0][2], dests[0][0][3], 
+          dests[0][1][0], dests[0][1][1], dests[0][1][2], dests[0][1][3]);
+#endif
+
+   /* store result color */
+   if (qss->colorOutSlot >= 0) {
+      unsigned i;
+      /* XXX need to handle multiple color outputs someday */
+      allvmrt(qss->stage.softpipe->fs->shader.output_semantic_name[qss->colorOutSlot]
+             == TGSI_SEMANTIC_COLOR);
+      for (i = 0; i < QUAD_SIZE; ++i) {
+         quad->outputs.color[0][i] = dests[i][qss->colorOutSlot][0];
+         quad->outputs.color[1][i] = dests[i][qss->colorOutSlot][1];
+         quad->outputs.color[2][i] = dests[i][qss->colorOutSlot][2];
+         quad->outputs.color[3][i] = dests[i][qss->colorOutSlot][3];
+      }
+   }
+#if DLLVM
+   for (int i = 0; i < QUAD_SIZE; ++i) {
+      debug_printf("QLLVM%d(%d) [%f, %f, %f, %f]\n", i, qss->colorOutSlot,
+             quad->outputs.color[0][i],
+             quad->outputs.color[1][i],
+             quad->outputs.color[2][i],
+             quad->outputs.color[3][i]);
+   }
+#endif
+
+   /* store result Z */
+   if (qss->depthOutSlot >= 0) {
+      /* output[slot] is new Z */
+      uint i;
+      for (i = 0; i < 4; i++) {
+         quad->outputs.depth[i] = dests[i][0][2];
+      }
+   }
+   else {
+      /* copy input Z (which was interpolated by the executor) to output Z */
+      uint i;
+      for (i = 0; i < 4; i++) {
+         quad->outputs.depth[i] = inputs[i][0][2];
+      }
+   }
+#if DLLVM
+   debug_printf("D [%f, %f, %f, %f] mask = %d\n",
+             quad->outputs.depth[0],
+             quad->outputs.depth[1],
+             quad->outputs.depth[2],
+             quad->outputs.depth[3], quad->mask);
+#endif
+
+   /* shader may cull fragments */
+   if( quad->mask ) {
+      qs->next->run( qs->next, quad );
+   }
+}
+
+
+unsigned 
+run_llvm_fs( struct sp_fragment_shader *base,
+            struct foo *machine )
+{
+}
+
+
+void 
+delete_llvm_fs( struct sp_fragment_shader *base )
+{
+   FREE(base);
+}
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_llvm(struct softpipe_context *softpipe,
+                      const struct pipe_shader_state *templ)
+{
+   struct sp_llvm_fragment_shader *shader = NULL;
+
+   /* LLVM fragment shaders currently disabled:
+    */
+   state = CALLOC_STRUCT(sp_llvm_shader_state);
+   if (!state)
+      return NULL;
+
+   state->llvm_prog = 0;
+
+   if (!gallivm_global_cpu_engine()) {
+      gallivm_cpu_engine_create(state->llvm_prog);
+   }
+   else
+      gallivm_cpu_jit_compile(gallivm_global_cpu_engine(), state->llvm_prog);
+   
+   if (shader) {
+      shader->base.run = run_llvm_fs;
+      shader->base.delete = delete_llvm_fs;
+   }
+
+   return shader;
+}
+
+
+#else
+
+struct sp_fragment_shader *
+softpipe_create_fs_llvm(struct softpipe_context *softpipe,
+                      const struct pipe_shader_state *templ)
+{
+   return NULL;
+}
+
+#endif
diff --git a/src/mesa/pipe/softpipe/sp_fs_sse.c b/src/mesa/pipe/softpipe/sp_fs_sse.c
new file mode 100644 (file)
index 0000000..713ece3
--- /dev/null
@@ -0,0 +1,192 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+#include "sp_headers.h"
+
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+#include "pipe/tgsi/exec/tgsi_exec.h"
+#include "pipe/tgsi/exec/tgsi_sse2.h"
+
+
+#if defined(__i386__) || defined(__386__)
+
+#include "x86/rtasm/x86sse.h"
+
+/* Surely this should be defined somewhere in a tgsi header:
+ */
+typedef void (XSTDCALL *codegen_function)(
+   const struct tgsi_exec_vector *input,
+   struct tgsi_exec_vector *output,
+   float (*constant)[4],
+   struct tgsi_exec_vector *temporary,
+   const struct tgsi_interp_coef *coef
+   //, const struct tgsi_exec_vector *quadPos
+ );
+
+
+struct sp_sse_fragment_shader {
+   struct sp_fragment_shader base;
+   struct x86_function             sse2_program;
+   codegen_function func;
+};
+
+
+/**
+ * Compute quad X,Y,Z,W for the four fragments in a quad.
+ *
+ * This should really be part of the compiled shader.
+ */
+void
+sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
+                   float x, float y,
+                   struct tgsi_exec_vector *quadpos)
+{
+   uint chan;
+   /* do X */
+   quadpos->xyzw[0].f[0] = x;
+   quadpos->xyzw[0].f[1] = x + 1;
+   quadpos->xyzw[0].f[2] = x;
+   quadpos->xyzw[0].f[3] = x + 1;
+
+   /* do Y */
+   quadpos->xyzw[1].f[0] = y;
+   quadpos->xyzw[1].f[1] = y;
+   quadpos->xyzw[1].f[2] = y + 1;
+   quadpos->xyzw[1].f[3] = y + 1;
+
+   /* do Z and W for all fragments in the quad */
+   for (chan = 2; chan < 4; chan++) {
+      const float dadx = coef->dadx[chan];
+      const float dady = coef->dady[chan];
+      const float a0 = coef->a0[chan] + dadx * x + dady * y;
+      quadpos->xyzw[chan].f[0] = a0;
+      quadpos->xyzw[chan].f[1] = a0 + dadx;
+      quadpos->xyzw[chan].f[2] = a0 + dady;
+      quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
+   }
+}
+
+
+static void
+sse_prepare( struct sp_fragment_shader *base,
+             struct tgsi_exec_machine *machine,
+             struct tgsi_sampler *samplers )
+{
+}
+
+
+/* TODO: codegenerate the whole run function, skip this wrapper.
+ * TODO: break dependency on tgsi_exec_machine struct
+ * TODO: push Position calculation into the generated shader
+ * TODO: process >1 quad at a time
+ */
+static unsigned 
+sse_run( struct sp_fragment_shader *base,
+        struct tgsi_exec_machine *machine,
+        struct quad_header *quad )
+{
+   struct sp_sse_fragment_shader *shader = (struct sp_sse_fragment_shader *) base;
+
+   /* Compute X, Y, Z, W vals for this quad -- place in temp[0] for now */
+   sp_setup_pos_vector(quad->posCoef, 
+                      (float)quad->x0, (float)quad->y0, 
+                      machine->Temps);
+
+   shader->func( machine->Inputs,
+                machine->Outputs,
+                machine->Consts,
+                machine->Temps,
+                machine->InterpCoefs
+                //      , &machine->QuadPos
+      );
+
+   return ~(machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0]);
+}
+
+
+static void 
+sse_delete( struct sp_fragment_shader *base )
+{
+   struct sp_sse_fragment_shader *shader = (struct sp_sse_fragment_shader *) base;
+
+   x86_release_func( &shader->sse2_program );
+   FREE(shader);
+}
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_sse(struct softpipe_context *softpipe,
+                      const struct pipe_shader_state *templ)
+{
+   struct sp_sse_fragment_shader *shader;
+
+   if (!softpipe->use_sse)
+      return NULL;
+
+   shader = CALLOC_STRUCT(sp_sse_fragment_shader);
+   if (!shader)
+      return NULL;
+
+   x86_init_func( &shader->sse2_program );
+   
+   if (!tgsi_emit_sse2_fs( templ->tokens, &shader->sse2_program )) {
+      FREE(shader);
+      return NULL;
+   }
+
+   shader->func = (codegen_function) x86_get_func( &shader->sse2_program );
+   assert(shader->func);
+
+   shader->base.shader = *templ;
+   shader->base.prepare = sse_prepare;
+   shader->base.run = sse_run;
+   shader->base.delete = sse_delete;
+
+   return &shader->base;
+}
+
+
+#else
+
+/* Maybe put this varient in the header file.
+ */
+struct sp_fragment_shader *
+softpipe_create_fs_sse(struct softpipe_context *softpipe,
+                      const struct pipe_shader_state *templ)
+{
+   return NULL;
+}
+
+#endif
index 33168584137892d6ca5f84e8f1b1fe9fc864360a..cf1b1eff75c66918d82ee48016affbf90d492c1f 100644 (file)
 #include "pipe/p_defines.h"
 #include "pipe/p_shader_tokens.h"
 
-#include "x86/rtasm/x86sse.h"
-
-#ifdef MESA_LLVM
-#include "pipe/llvm/gallivm.h"
-#endif
-
 #include "sp_context.h"
 #include "sp_state.h"
 #include "sp_headers.h"
@@ -60,9 +54,6 @@ struct quad_shade_stage
    struct tgsi_exec_machine machine;
    struct tgsi_exec_vector *inputs, *outputs;
    int colorOutSlot, depthOutSlot;
-#ifdef MESA_LLVM
-   struct gallivm_prog *llvm_prog;
-#endif
 };
 
 
@@ -74,46 +65,6 @@ quad_shade_stage(struct quad_stage *qs)
 }
 
 
-/**
- * Compute quad X,Y,Z,W for the four fragments in a quad.
- * Note that we only need to "compute" X and Y for the upper-left fragment.
- * We could do less work if we're not depth testing, or there's no
- * perspective-corrected attributes, but that's seldom.
- */
-static void
-setup_pos_vector(const struct tgsi_interp_coef *coef,
-                 float x, float y,
-                 struct tgsi_exec_vector *quadpos)
-{
-   uint chan;
-   /* do X */
-   quadpos->xyzw[0].f[0] = x;
-   /* do Y */
-   quadpos->xyzw[1].f[0] = y;
-   /* do Z and W for all fragments in the quad */
-   for (chan = 2; chan < 4; chan++) {
-      const float dadx = coef->dadx[chan];
-      const float dady = coef->dady[chan];
-      const float a0 = coef->a0[chan] + dadx * x + dady * y;
-      quadpos->xyzw[chan].f[0] = a0;
-      quadpos->xyzw[chan].f[1] = a0 + dadx;
-      quadpos->xyzw[chan].f[2] = a0 + dady;
-      quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
-   }
-}
-
-
-typedef void (XSTDCALL *codegen_function)(
-   const struct tgsi_exec_vector *input,
-   struct tgsi_exec_vector *output,
-   float (*constant)[4],
-   struct tgsi_exec_vector *temporary,
-   const struct tgsi_interp_coef *coef
-#if 0
-   ,const struct tgsi_exec_vector *quadPos
-#endif
- );
-
 
 /**
  * Execute fragment shader for the four fragments in the quad.
@@ -132,30 +83,10 @@ shade_quad(
 
    machine->InterpCoefs = quad->coef;
 
-   /* Compute X, Y, Z, W vals for this quad */
-   setup_pos_vector(quad->posCoef, (float) quad->x0, (float) quad->y0, &machine->QuadPos);
-
    /* run shader */
-#if defined(__i386__) || defined(__386__)
-   if( softpipe->use_sse ) {
-      codegen_function func = (codegen_function) x86_get_func( &softpipe->fs->sse2_program );
-      func(
-         machine->Inputs,
-         machine->Outputs,
-         machine->Consts,
-         machine->Temps,
-         machine->InterpCoefs
-#if 0
-         ,machine->QuadPos
-#endif
-           );
-      quad->mask &= ~(machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0]);
-   }
-   else
-#endif
-   {
-      quad->mask &= tgsi_exec_machine_run( machine );
-   }
+   quad->mask &= softpipe->fs->run( softpipe->fs, 
+                                   &qss->machine,
+                                   quad );
 
    /* store result color */
    if (qss->colorOutSlot >= 0) {
@@ -199,107 +130,6 @@ shade_quad(
    }
 }
 
-#if 0
-#ifdef MESA_LLVM
-#define DLLVM 0
-static void
-shade_quad_llvm(struct quad_stage *qs,
-                struct quad_header *quad)
-{
-   struct quad_shade_stage *qss = quad_shade_stage(qs);
-   struct softpipe_context *softpipe = qs->softpipe;
-   float dests[4][16][4] ALIGN16_ATTRIB;
-   float inputs[4][16][4] ALIGN16_ATTRIB;
-   const float fx = (float) quad->x0;
-   const float fy = (float) quad->y0;
-   struct gallivm_prog *llvm = qss->llvm_prog;
-
-   inputs[0][0][0] = fx;
-   inputs[1][0][0] = fx + 1.0f;
-   inputs[2][0][0] = fx;
-   inputs[3][0][0] = fx + 1.0f;
-
-   inputs[0][0][1] = fy;
-   inputs[1][0][1] = fy;
-   inputs[2][0][1] = fy + 1.0f;
-   inputs[3][0][1] = fy + 1.0f;
-#if DLLVM
-   debug_printf("MASK = %d\n", quad->mask);
-#endif
-   gallivm_prog_inputs_interpolate(llvm, inputs, quad->coef);
-#if DLLVM
-   for (int i = 0; i < 4; ++i) {
-      for (int j = 0; j < 2; ++j) {
-         debug_printf("IN(%d,%d) [%f %f %f %f]\n", i, j, 
-                inputs[i][j][0], inputs[i][j][1], inputs[i][j][2], inputs[i][j][3]);
-      }
-   }
-#endif
-
-   quad->mask &=
-      gallivm_fragment_shader_exec(llvm, fx, fy, dests, inputs,
-                                   softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
-                                   qss->samplers);
-#if DLLVM
-   debug_printf("OUT LLVM = 1[%f %f %f %f], 2[%f %f %f %f]\n",
-          dests[0][0][0], dests[0][0][1], dests[0][0][2], dests[0][0][3], 
-          dests[0][1][0], dests[0][1][1], dests[0][1][2], dests[0][1][3]);
-#endif
-
-   /* store result color */
-   if (qss->colorOutSlot >= 0) {
-      unsigned i;
-      /* XXX need to handle multiple color outputs someday */
-      assert(qss->stage.softpipe->fs->shader.output_semantic_name[qss->colorOutSlot]
-             == TGSI_SEMANTIC_COLOR);
-      for (i = 0; i < QUAD_SIZE; ++i) {
-         quad->outputs.color[0][i] = dests[i][qss->colorOutSlot][0];
-         quad->outputs.color[1][i] = dests[i][qss->colorOutSlot][1];
-         quad->outputs.color[2][i] = dests[i][qss->colorOutSlot][2];
-         quad->outputs.color[3][i] = dests[i][qss->colorOutSlot][3];
-      }
-   }
-#if DLLVM
-   for (int i = 0; i < QUAD_SIZE; ++i) {
-      debug_printf("QLLVM%d(%d) [%f, %f, %f, %f]\n", i, qss->colorOutSlot,
-             quad->outputs.color[0][i],
-             quad->outputs.color[1][i],
-             quad->outputs.color[2][i],
-             quad->outputs.color[3][i]);
-   }
-#endif
-
-   /* store result Z */
-   if (qss->depthOutSlot >= 0) {
-      /* output[slot] is new Z */
-      uint i;
-      for (i = 0; i < 4; i++) {
-         quad->outputs.depth[i] = dests[i][0][2];
-      }
-   }
-   else {
-      /* copy input Z (which was interpolated by the executor) to output Z */
-      uint i;
-      for (i = 0; i < 4; i++) {
-         quad->outputs.depth[i] = inputs[i][0][2];
-      }
-   }
-#if DLLVM
-   debug_printf("D [%f, %f, %f, %f] mask = %d\n",
-             quad->outputs.depth[0],
-             quad->outputs.depth[1],
-             quad->outputs.depth[2],
-             quad->outputs.depth[3], quad->mask);
-#endif
-
-   /* shader may cull fragments */
-   if( quad->mask ) {
-      qs->next->run( qs->next, quad );
-   }
-}
-#endif /*MESA_LLVM*/
-#endif
-
 /**
  * Per-primitive (or per-begin?) setup
  */
@@ -315,15 +145,6 @@ static void shade_begin(struct quad_stage *qs)
       qss->samplers[i].texture = &softpipe->texture[i]->base;
    }
 
-#ifdef MESA_LLVM
-   qss->llvm_prog = softpipe->fs->llvm_prog;
-#endif
-   /* XXX only do this if the fragment shader changes... */
-   tgsi_exec_machine_init(&qss->machine,
-                          softpipe->fs->shader.tokens,
-                          PIPE_MAX_SAMPLERS,
-                          qss->samplers );
-
    /* find output slots for depth, color */
    qss->colorOutSlot = -1;
    qss->depthOutSlot = -1;
@@ -337,6 +158,10 @@ static void shade_begin(struct quad_stage *qs)
          break;
       }
    }
+   
+   softpipe->fs->prepare( softpipe->fs, 
+                         &qss->machine,
+                         qss->samplers );
 
    qs->next->begin(qs->next);
 }
@@ -366,16 +191,7 @@ struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
 
    qss->stage.softpipe = softpipe;
    qss->stage.begin = shade_begin;
-#ifdef MESA_LLVM
-   /* disable until ported to accept
-    * x/y and soa layout
-   qss->stage.run = shade_quad_llvm;
-   */
-   softpipe->use_sse = FALSE;
-   qss->stage.run = shade_quad;
-#else
    qss->stage.run = shade_quad;
-#endif
    qss->stage.destroy = shade_destroy;
 
    /* set TGSI sampler state that's constant */
@@ -386,5 +202,7 @@ struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
       qss->samplers[i].cache = softpipe->tex_cache[i];
    }
 
+   tgsi_exec_machine_init( &qss->machine );
+
    return &qss->stage;
 }
index af955c1e17b1e3cc638ce66663539b9a88fd8d5c..431952f1aac6212e3d8ae73c5ee0c45bc7505aeb 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "pipe/p_state.h"
 
-#include "x86/rtasm/x86sse.h"
-
 
 #define SP_NEW_VIEWPORT      0x1
 #define SP_NEW_RASTERIZER    0x2
 #define SP_NEW_QUERY         0x4000
 
 
+struct tgsi_sampler;
+struct tgsi_interp_coef;
+struct tgsi_exec_machine;
 
-#ifdef MESA_LLVM
-struct gallivm_prog;
-#endif
 
+/** Subclass of pipe_shader_state (though it doesn't really need to be).
+ *
+ * This is starting to look an awful lot like a quad pipeline stage...
+ */
+struct sp_fragment_shader {
+   struct pipe_shader_state   shader;
 
+   void (*prepare)( struct sp_fragment_shader *shader,
+                   struct tgsi_exec_machine *machine,
+                   struct tgsi_sampler *samplers);
 
-/** Subclass of pipe_shader_state */
-struct sp_fragment_shader_state {
-   struct pipe_shader_state   shader;
-#if defined(__i386__) || defined(__386__)
-   struct x86_function        sse2_program;
-#endif
-#ifdef MESA_LLVM
-   struct gallivm_prog *llvm_prog;
-#endif
+   /* Run the shader - this interface will get cleaned up in the
+    * future:
+    */
+   unsigned (*run)( struct sp_fragment_shader *shader,
+                   struct tgsi_exec_machine *machine,
+                   struct quad_header *quad );
+
+
+   void (*delete)( struct sp_fragment_shader * );
 };
 
 
 /** Subclass of pipe_shader_state */
-struct sp_vertex_shader_state {
+struct sp_vertex_shader {
    struct pipe_shader_state shader;
    struct draw_vertex_shader *draw_data;
 };
index 0b814fc2847f049ccf301965eb8c322503d7dc8a..c43f28583eed354e584b540441b10039bdfc41da 100644 (file)
 
 #include "sp_context.h"
 #include "sp_state.h"
+#include "sp_fs.h"
 
 #include "pipe/p_defines.h"
 #include "pipe/p_util.h"
 #include "pipe/p_inlines.h"
 #include "pipe/p_winsys.h"
-#include "pipe/draw/draw_context.h"
 #include "pipe/p_shader_tokens.h"
-#include "pipe/llvm/gallivm.h"
+#include "pipe/draw/draw_context.h"
 #include "pipe/tgsi/util/tgsi_dump.h"
-#include "pipe/tgsi/exec/tgsi_sse2.h"
 
 
 void *
@@ -44,40 +43,22 @@ softpipe_create_fs_state(struct pipe_context *pipe,
                          const struct pipe_shader_state *templ)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
-   struct sp_fragment_shader_state *state;
+   struct sp_fragment_shader *state;
 
-   /* Decide whether we'll be codegenerating this shader and if so do
-    * that now.
-    */
-
-   state = CALLOC_STRUCT(sp_fragment_shader_state);
-   if (!state)
-      return NULL;
+   if (softpipe->dump_fs) 
+      tgsi_dump(templ->tokens, 0);
 
-   state->shader = *templ;
-
-   if (softpipe->dump_fs) {
-      tgsi_dump(state->shader.tokens, 0);
-   }
+   state = softpipe_create_fs_llvm( softpipe, templ );
+   if (state)
+      return state;
+   
+   state = softpipe_create_fs_sse( softpipe, templ );
+   if (state)
+      return state;
 
-#ifdef MESA_LLVM
-   state->llvm_prog = 0;
-
-#if 0
-   if (!gallivm_global_cpu_engine()) {
-      gallivm_cpu_engine_create(state->llvm_prog);
-   }
-   else
-      gallivm_cpu_jit_compile(gallivm_global_cpu_engine(), state->llvm_prog);
-#endif
-
-#elif defined(__i386__) || defined(__386__)
-   if (softpipe->use_sse) {
-      x86_init_func( &state->sse2_program );
-      tgsi_emit_sse2_fs( state->shader.tokens, &state->sse2_program );
-   }
-#endif
+   state = softpipe_create_fs_exec( softpipe, templ );
 
+   assert(state);
    return state;
 }
 
@@ -87,7 +68,7 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
-   softpipe->fs = (struct sp_fragment_shader_state *) fs;
+   softpipe->fs = (struct sp_fragment_shader *) fs;
 
    softpipe->dirty |= SP_NEW_FS;
 }
@@ -96,13 +77,9 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
 void
 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
 {
-   struct sp_fragment_shader_state *state = fs;
-
-#if defined(__i386__) || defined(__386__)
-   x86_release_func( &state->sse2_program );
-#endif
-
-   FREE( state );
+   struct sp_fragment_shader *state = fs;
+   
+   state->delete( state );
 }
 
 
@@ -111,9 +88,9 @@ softpipe_create_vs_state(struct pipe_context *pipe,
                          const struct pipe_shader_state *templ)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
-   struct sp_vertex_shader_state *state;
+   struct sp_vertex_shader *state;
 
-   state = CALLOC_STRUCT(sp_vertex_shader_state);
+   state = CALLOC_STRUCT(sp_vertex_shader);
    if (state == NULL ) {
       return NULL;
    }
@@ -136,7 +113,7 @@ softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
-   softpipe->vs = (const struct sp_vertex_shader_state *)vs;
+   softpipe->vs = (const struct sp_vertex_shader *)vs;
 
    draw_bind_vertex_shader(softpipe->draw, softpipe->vs->draw_data);
 
@@ -149,8 +126,8 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
-   struct sp_vertex_shader_state *state =
-      (struct sp_vertex_shader_state *)vs;
+   struct sp_vertex_shader *state =
+      (struct sp_vertex_shader *)vs;
 
    draw_delete_vertex_shader(softpipe->draw, state->draw_data);
    FREE( state );
index 336ae1c8b6d73abb5b7bc7f4470cfd7ba00a6f5f..92a6fd4d620d75f16e228464e308caed8d04f5e5 100644 (file)
 
 
 
-static void
-tgsi_exec_prepare( struct tgsi_exec_machine *mach )
+/**
+ * Initialize machine state by expanding tokens to full instructions,
+ * allocating temporary storage, setting up constants, etc.
+ * After this, we can call tgsi_exec_machine_run() many times.
+ */
+void 
+tgsi_exec_machine_bind_shader(
+   struct tgsi_exec_machine *mach,
+   const struct tgsi_token *tokens,
+   uint numSamplers,
+   struct tgsi_sampler *samplers)
 {
-   struct tgsi_exec_labels *labels = &mach->Labels;
+   uint k;
    struct tgsi_parse_context parse;
+   struct tgsi_exec_labels *labels = &mach->Labels;
    struct tgsi_full_instruction *instructions;
    struct tgsi_full_declaration *declarations;
    uint maxInstructions = 10, numInstructions = 0;
    uint maxDeclarations = 10, numDeclarations = 0;
-   uint k;
    uint instno = 0;
 
+#if 0
+   tgsi_dump(tokens, 0);
+#endif
+
+   mach->Tokens = tokens;
+   mach->Samplers = samplers;
+
+   k = tgsi_parse_init (&parse, mach->Tokens);
+   if (k != TGSI_PARSE_OK) {
+      debug_printf( "Problem parsing!\n" );
+      return;
+   }
+
+   mach->Processor = parse.FullHeader.Processor.Processor;
    mach->ImmLimit = 0;
    labels->count = 0;
 
@@ -141,11 +164,6 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
    instructions = (struct tgsi_full_instruction *)
       MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) );
 
-   k = tgsi_parse_init( &parse, mach->Tokens );
-   if (k != TGSI_PARSE_OK) {
-      debug_printf("Problem parsing!\n");
-      return;
-   }
 
    while( !tgsi_parse_end_of_tokens( &parse ) ) {
       uint pointer = parse.Position;
@@ -176,7 +194,8 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
             assert( mach->ImmLimit + size / 4 <= TGSI_EXEC_NUM_IMMEDIATES );
 
             for( i = 0; i < size; i++ ) {
-               mach->Imms[mach->ImmLimit + i / 4][i % 4] = parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+               mach->Imms[mach->ImmLimit + i / 4][i % 4] = 
+                 parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
             }
             mach->ImmLimit += size / 4;
          }
@@ -224,37 +243,11 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
 }
 
 
-/**
- * Initialize machine state by expanding tokens to full instructions,
- * allocating temporary storage, setting up constants, etc.
- * After this, we can call tgsi_exec_machine_run() many times.
- */
 void
 tgsi_exec_machine_init(
-   struct tgsi_exec_machine *mach,
-   const struct tgsi_token *tokens,
-   uint numSamplers,
-   struct tgsi_sampler *samplers)
+   struct tgsi_exec_machine *mach )
 {
-   uint i, k;
-   struct tgsi_parse_context parse;
-
-#if 0
-   tgsi_dump(tokens, 0);
-#endif
-
-   mach->Tokens = tokens;
-
-   mach->Samplers = samplers;
-
-   k = tgsi_parse_init (&parse, mach->Tokens);
-   if (k != TGSI_PARSE_OK) {
-      debug_printf( "Problem parsing!\n" );
-      return;
-   }
-
-   mach->Processor = parse.FullHeader.Processor.Processor;
-   tgsi_parse_free (&parse);
+   uint i;
 
    mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps);
    mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS];
@@ -270,8 +263,6 @@ tgsi_exec_machine_init(
       mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].f[i] = 128.0f;
       mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].f[i] = -128.0f;
    }
-
-   tgsi_exec_prepare( mach );
 }
 
 
index 1fb66ee960fa2cbcef925b3532bd6a0d5777640d..45c49dd007c012791d435ad820f586a37ead64dd 100644 (file)
@@ -215,12 +215,16 @@ struct tgsi_exec_machine
    struct tgsi_exec_labels Labels;
 };
 
-
 void
 tgsi_exec_machine_init(
+   struct tgsi_exec_machine *mach );
+
+
+void 
+tgsi_exec_machine_bind_shader(
    struct tgsi_exec_machine *mach,
    const struct tgsi_token *tokens,
-   unsigned numSamplers,
+   uint numSamplers,
    struct tgsi_sampler *samplers);
 
 uint
index 6df7588c925aeb479efa8c9b49713306b536b1af..9bc9483e3b5047784ceade2c33c59edd968a09eb 100755 (executable)
@@ -2186,9 +2186,9 @@ emit_declaration(
                   break;
 
                case TGSI_INTERPOLATE_LINEAR:
-                  emit_inputf( func, 0, 0, TGSI_SWIZZLE_X );
+                  emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
                   emit_coef_dadx( func, 1, i, j );
-                  emit_inputf( func, 2, 0, TGSI_SWIZZLE_Y );
+                  emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
                   emit_coef_dady( func, 3, i, j );
                   emit_mul( func, 0, 1 );    /* x * dadx */
                   emit_coef_a0( func, 4, i, j );
@@ -2199,12 +2199,12 @@ emit_declaration(
                   break;
 
                case TGSI_INTERPOLATE_PERSPECTIVE:
-                  emit_inputf( func, 0, 0, TGSI_SWIZZLE_X );
+                  emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
                   emit_coef_dadx( func, 1, i, j );
-                  emit_inputf( func, 2, 0, TGSI_SWIZZLE_Y );
+                  emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
                   emit_coef_dady( func, 3, i, j );
                   emit_mul( func, 0, 1 );    /* x * dadx */
-                  emit_inputf( func, 4, 0, TGSI_SWIZZLE_W );
+                  emit_tempf( func, 4, 0, TGSI_SWIZZLE_W );
                   emit_coef_a0( func, 5, i, j );
                   emit_rcp( func, 4, 4 );    /* 1.0 / w */
                   emit_mul( func, 2, 3 );    /* y * dady */