summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-02-15 09:31:22 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2008-02-15 09:31:22 +0000
commitc04a7f8929d674971a472ffa4d3a31200c22aa5a (patch)
treeea06d63c3ed61311ee5bf2e7e8a49bbf83a55a07
parentfa9c160389ffc6d7a20773b77c937193f30339d8 (diff)
gallium: reorganize fragment shader execution, unbreak sse
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.
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader.c10
-rw-r--r--src/mesa/pipe/softpipe/Makefile3
-rw-r--r--src/mesa/pipe/softpipe/sp_context.h8
-rw-r--r--src/mesa/pipe/softpipe/sp_fs_exec.c112
-rw-r--r--src/mesa/pipe/softpipe/sp_fs_llvm.c200
-rw-r--r--src/mesa/pipe/softpipe/sp_fs_sse.c192
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_fs.c200
-rw-r--r--src/mesa/pipe/softpipe/sp_state.h37
-rw-r--r--src/mesa/pipe/softpipe/sp_state_fs.c69
-rw-r--r--src/mesa/pipe/tgsi/exec/tgsi_exec.c71
-rw-r--r--src/mesa/pipe/tgsi/exec/tgsi_exec.h8
-rwxr-xr-xsrc/mesa/pipe/tgsi/exec/tgsi_sse2.c10
12 files changed, 613 insertions, 307 deletions
diff --git a/src/mesa/pipe/draw/draw_vertex_shader.c b/src/mesa/pipe/draw/draw_vertex_shader.c
index c824c1407e..bf340ef9b0 100644
--- a/src/mesa/pipe/draw/draw_vertex_shader.c
+++ b/src/mesa/pipe/draw/draw_vertex_shader.c
@@ -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*/ );
}
diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile
index 31438a882e..304632abb2 100644
--- a/src/mesa/pipe/softpipe/Makefile
+++ b/src/mesa/pipe/softpipe/Makefile
@@ -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 \
diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h
index aff8c2cc5d..5e24baf938 100644
--- a/src/mesa/pipe/softpipe/sp_context.h
+++ b/src/mesa/pipe/softpipe/sp_context.h
@@ -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
index 0000000000..b949492e09
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_fs_exec.c
@@ -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
index 0000000000..9237c1fbda
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_fs_llvm.c
@@ -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
index 0000000000..713ece369e
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_fs_sse.c
@@ -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
diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c
index 3316858413..cf1b1eff75 100644
--- a/src/mesa/pipe/softpipe/sp_quad_fs.c
+++ b/src/mesa/pipe/softpipe/sp_quad_fs.c
@@ -39,12 +39,6 @@
#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;
}
diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h
index af955c1e17..431952f1aa 100644
--- a/src/mesa/pipe/softpipe/sp_state.h
+++ b/src/mesa/pipe/softpipe/sp_state.h
@@ -33,8 +33,6 @@
#include "pipe/p_state.h"
-#include "x86/rtasm/x86sse.h"
-
#define SP_NEW_VIEWPORT 0x1
#define SP_NEW_RASTERIZER 0x2
@@ -53,27 +51,36 @@
#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;
};
diff --git a/src/mesa/pipe/softpipe/sp_state_fs.c b/src/mesa/pipe/softpipe/sp_state_fs.c
index 0b814fc284..c43f28583e 100644
--- a/src/mesa/pipe/softpipe/sp_state_fs.c
+++ b/src/mesa/pipe/softpipe/sp_state_fs.c
@@ -27,16 +27,15 @@
#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 );
diff --git a/src/mesa/pipe/tgsi/exec/tgsi_exec.c b/src/mesa/pipe/tgsi/exec/tgsi_exec.c
index 336ae1c8b6..92a6fd4d62 100644
--- a/src/mesa/pipe/tgsi/exec/tgsi_exec.c
+++ b/src/mesa/pipe/tgsi/exec/tgsi_exec.c
@@ -120,18 +120,41 @@
-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 );
}
diff --git a/src/mesa/pipe/tgsi/exec/tgsi_exec.h b/src/mesa/pipe/tgsi/exec/tgsi_exec.h
index 1fb66ee960..45c49dd007 100644
--- a/src/mesa/pipe/tgsi/exec/tgsi_exec.h
+++ b/src/mesa/pipe/tgsi/exec/tgsi_exec.h
@@ -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
diff --git a/src/mesa/pipe/tgsi/exec/tgsi_sse2.c b/src/mesa/pipe/tgsi/exec/tgsi_sse2.c
index 6df7588c92..9bc9483e3b 100755
--- a/src/mesa/pipe/tgsi/exec/tgsi_sse2.c
+++ b/src/mesa/pipe/tgsi/exec/tgsi_sse2.c
@@ -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 */