diff options
author | José Fonseca <jfonseca@vmware.com> | 2009-07-26 23:44:38 +0100 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2009-08-29 09:21:15 +0100 |
commit | 946f432a08112148d743eb9faf6b27bb8cc7fa76 (patch) | |
tree | d0648a6e40f6aba20322631c139c28b9654f5299 /src/gallium/drivers/llvmpipe/lp_fs_sse.c | |
parent | 1814d6b49c8144180231c3e43ff6b5dc9c32e12b (diff) |
llvmpipe: Fork softpipe for experimentation with llvm.
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_fs_sse.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_fs_sse.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_fs_sse.c b/src/gallium/drivers/llvmpipe/lp_fs_sse.c new file mode 100644 index 0000000000..61c40dd4b3 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_fs_sse.c @@ -0,0 +1,169 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * Execute fragment shader using runtime SSE code generation. + */ + +#include "lp_context.h" +#include "lp_state.h" +#include "lp_fs.h" +#include "lp_quad.h" + +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_memory.h" +#include "tgsi/tgsi_exec.h" +#include "tgsi/tgsi_sse2.h" + + +#if defined(PIPE_ARCH_X86) + +#include "rtasm/rtasm_x86sse.h" + + + +/** + * Subclass of lp_fragment_shader + */ +struct lp_sse_fragment_shader +{ + struct lp_fragment_shader base; + struct x86_function sse2_program; + tgsi_sse2_fs_function func; + float immediates[TGSI_EXEC_NUM_IMMEDIATES][4]; +}; + + +/** cast wrapper */ +static INLINE struct lp_sse_fragment_shader * +lp_sse_fragment_shader(const struct lp_fragment_shader *base) +{ + return (struct lp_sse_fragment_shader *) base; +} + + +static void +fs_sse_prepare( const struct lp_fragment_shader *base, + struct tgsi_exec_machine *machine, + struct tgsi_sampler **samplers ) +{ + machine->Samplers = 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 +fs_sse_run( const struct lp_fragment_shader *base, + struct tgsi_exec_machine *machine, + struct quad_header *quad ) +{ + struct lp_sse_fragment_shader *shader = lp_sse_fragment_shader(base); + + /* Compute X, Y, Z, W vals for this quad -- place in temp[0] for now */ + lp_setup_pos_vector(quad->posCoef, + (float)quad->input.x0, (float)quad->input.y0, + machine->Temps); + + /* init kill mask */ + tgsi_set_kill_mask(machine, 0x0); + tgsi_set_exec_mask(machine, 1, 1, 1, 1); + + shader->func( machine, + machine->Consts, + (const float (*)[4])shader->immediates, + machine->InterpCoefs + // , &machine->QuadPos + ); + + return ~(machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0]); +} + + +static void +fs_sse_delete( struct lp_fragment_shader *base ) +{ + struct lp_sse_fragment_shader *shader = lp_sse_fragment_shader(base); + + x86_release_func( &shader->sse2_program ); + FREE(shader); +} + + +struct lp_fragment_shader * +llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe, + const struct pipe_shader_state *templ) +{ + struct lp_sse_fragment_shader *shader; + + if (!llvmpipe->use_sse) + return NULL; + + shader = CALLOC_STRUCT(lp_sse_fragment_shader); + if (!shader) + return NULL; + + x86_init_func( &shader->sse2_program ); + + if (!tgsi_emit_sse2( templ->tokens, &shader->sse2_program, + shader->immediates, FALSE )) { + FREE(shader); + return NULL; + } + + shader->func = (tgsi_sse2_fs_function) x86_get_func( &shader->sse2_program ); + if (!shader->func) { + x86_release_func( &shader->sse2_program ); + FREE(shader); + return NULL; + } + + shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */ + shader->base.prepare = fs_sse_prepare; + shader->base.run = fs_sse_run; + shader->base.delete = fs_sse_delete; + + return &shader->base; +} + + +#else + +/* Maybe put this variant in the header file. + */ +struct lp_fragment_shader * +llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe, + const struct pipe_shader_state *templ) +{ + return NULL; +} + +#endif |