From 73af91e938eb27b001404f11195fb06ff9b08903 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Fri, 14 Aug 2009 10:27:32 +0100 Subject: [PATCH] llvmpipe: Eliminate non-LLVM fs execution paths. --- src/gallium/drivers/llvmpipe/Makefile | 3 - src/gallium/drivers/llvmpipe/SConscript | 3 - src/gallium/drivers/llvmpipe/lp_context.c | 8 - src/gallium/drivers/llvmpipe/lp_context.h | 4 +- src/gallium/drivers/llvmpipe/lp_fs.h | 54 ---- src/gallium/drivers/llvmpipe/lp_fs_exec.c | 162 ---------- src/gallium/drivers/llvmpipe/lp_fs_llvm.c | 360 --------------------- src/gallium/drivers/llvmpipe/lp_fs_sse.c | 169 ---------- src/gallium/drivers/llvmpipe/lp_quad_fs.c | 119 ++++++- src/gallium/drivers/llvmpipe/lp_state.h | 31 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 178 ++++++++-- 11 files changed, 287 insertions(+), 804 deletions(-) delete mode 100644 src/gallium/drivers/llvmpipe/lp_fs.h delete mode 100644 src/gallium/drivers/llvmpipe/lp_fs_exec.c delete mode 100644 src/gallium/drivers/llvmpipe/lp_fs_llvm.c delete mode 100644 src/gallium/drivers/llvmpipe/lp_fs_sse.c diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 1b6cd5ed85d..236062a5f3e 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -4,9 +4,6 @@ include $(TOP)/configs/current LIBNAME = llvmpipe C_SOURCES = \ - lp_fs_exec.c \ - lp_fs_sse.c \ - lp_fs_llvm.c \ lp_bld_arit.c \ lp_bld_pack.c \ lp_bld_unpack.c \ diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 705a8bdfd44..154964bf7ac 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -7,9 +7,6 @@ env.ParseConfig('llvm-config --cppflags') llvmpipe = env.ConvenienceLibrary( target = 'llvmpipe', source = [ - 'lp_fs_exec.c', - 'lp_fs_sse.c', - 'lp_fs_llvm.c', 'lp_bld_arit.c', 'lp_bld_blend_aos.c', 'lp_bld_blend_soa.c', diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index a30db444d4a..66d0cf77592 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -148,14 +148,6 @@ llvmpipe_create( struct pipe_screen *screen ) util_init_math(); -#ifdef PIPE_ARCH_X86 - llvmpipe->use_sse = !debug_get_bool_option( "GALLIUM_NOSSE", FALSE ); -#else - llvmpipe->use_sse = FALSE; -#endif - - llvmpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); - llvmpipe->pipe.winsys = screen->winsys; llvmpipe->pipe.screen = screen; llvmpipe->pipe.destroy = llvmpipe_destroy; diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 7ac83c1e7c1..6cda5e602f1 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -57,7 +57,7 @@ struct llvmpipe_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 lp_fragment_shader *fs; + struct lp_fragment_shader *fs; const struct lp_vertex_shader *vs; /** Other rendering state */ @@ -145,8 +145,6 @@ struct llvmpipe_context { unsigned tex_timestamp; struct llvmpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; - unsigned use_sse : 1; - unsigned dump_fs : 1; unsigned no_rast : 1; }; diff --git a/src/gallium/drivers/llvmpipe/lp_fs.h b/src/gallium/drivers/llvmpipe/lp_fs.h deleted file mode 100644 index 505e21138f5..00000000000 --- a/src/gallium/drivers/llvmpipe/lp_fs.h +++ /dev/null @@ -1,54 +0,0 @@ -/************************************************************************** - * - * 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: Keith Whitwell - */ - -#ifndef LP_FS_H -#define LP_FS_H - -struct lp_fragment_shader * -llvmpipe_create_fs_exec(struct llvmpipe_context *llvmpipe, - const struct pipe_shader_state *templ); - -struct lp_fragment_shader * -llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe, - const struct pipe_shader_state *templ); - -struct lp_fragment_shader * -llvmpipe_create_fs_llvm(struct llvmpipe_context *llvmpipe, - const struct pipe_shader_state *templ); - -struct tgsi_interp_coef; -struct tgsi_exec_vector; - -void lp_setup_pos_vector(const struct tgsi_interp_coef *coef, - float x, float y, - struct tgsi_exec_vector *quadpos); - - -#endif diff --git a/src/gallium/drivers/llvmpipe/lp_fs_exec.c b/src/gallium/drivers/llvmpipe/lp_fs_exec.c deleted file mode 100644 index ea85697fe21..00000000000 --- a/src/gallium/drivers/llvmpipe/lp_fs_exec.c +++ /dev/null @@ -1,162 +0,0 @@ -/************************************************************************** - * - * 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 the TGSI interpreter. - */ - -#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_parse.h" - - -/** - * Subclass of lp_fragment_shader - */ -struct lp_exec_fragment_shader -{ - struct lp_fragment_shader base; - /* No other members for now */ -}; - - -/** cast wrapper */ -static INLINE struct lp_exec_fragment_shader * -lp_exec_fragment_shader(const struct lp_fragment_shader *base) -{ - return (struct lp_exec_fragment_shader *) base; -} - - -/** - * Compute quad X,Y,Z,W for the four fragments in a quad. - * - * This should really be part of the compiled shader. - */ -void -lp_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 -exec_prepare( const struct lp_fragment_shader *base, - struct tgsi_exec_machine *machine, - struct tgsi_sampler **samplers ) -{ - /* - * Bind tokens/shader to the interpreter's machine state. - * Avoid redundant binding. - */ - if (machine->Tokens != base->shader.tokens) { - 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( const struct lp_fragment_shader *base, - struct tgsi_exec_machine *machine, - struct quad_header *quad ) -{ - /* Compute X, Y, Z, W vals for this quad */ - lp_setup_pos_vector(quad->posCoef, - (float)quad->input.x0, (float)quad->input.y0, - &machine->QuadPos); - - return tgsi_exec_machine_run( machine ); -} - - -static void -exec_delete( struct lp_fragment_shader *base ) -{ - FREE((void *) base->shader.tokens); - FREE(base); -} - - -struct lp_fragment_shader * -llvmpipe_create_fs_exec(struct llvmpipe_context *llvmpipe, - const struct pipe_shader_state *templ) -{ - struct lp_exec_fragment_shader *shader; - - /* Decide whether we'll be codegenerating this shader and if so do - * that now. - */ - - shader = CALLOC_STRUCT(lp_exec_fragment_shader); - if (!shader) - return NULL; - - /* we need to keep a local copy of the tokens */ - shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens); - shader->base.prepare = exec_prepare; - shader->base.run = exec_run; - shader->base.delete = exec_delete; - - return &shader->base; -} diff --git a/src/gallium/drivers/llvmpipe/lp_fs_llvm.c b/src/gallium/drivers/llvmpipe/lp_fs_llvm.c deleted file mode 100644 index ef1c8c32c2f..00000000000 --- a/src/gallium/drivers/llvmpipe/lp_fs_llvm.c +++ /dev/null @@ -1,360 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * 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 LLVM code generation. - */ - - -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_memory.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_exec.h" -#include "tgsi/tgsi_dump.h" -#include "lp_bld_type.h" -#include "lp_bld_tgsi.h" -#include "lp_screen.h" -#include "lp_context.h" -#include "lp_state.h" -#include "lp_fs.h" -#include "lp_quad.h" - - -typedef void -(*lp_shader_fs_func)(void *pos, - void *a0, - void *dadx, - void *dady, - void *consts, - void *outputs, - struct tgsi_sampler **samplers); - - -/** - * Subclass of lp_fragment_shader - */ -struct lp_llvm_fragment_shader -{ - struct lp_fragment_shader base; - - struct llvmpipe_screen *screen; - - LLVMValueRef function; - - lp_shader_fs_func jit_function; - - union tgsi_exec_channel ALIGN16_ATTRIB pos[NUM_CHANNELS]; - union tgsi_exec_channel ALIGN16_ATTRIB a0[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - union tgsi_exec_channel ALIGN16_ATTRIB dadx[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - union tgsi_exec_channel ALIGN16_ATTRIB dady[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - - uint32_t magic; -}; - - -/** cast wrapper */ -static INLINE struct lp_llvm_fragment_shader * -lp_llvm_fragment_shader(const struct lp_fragment_shader *base) -{ - return (struct lp_llvm_fragment_shader *) base; -} - - -static void -shader_generate(struct llvmpipe_screen *screen, - struct lp_llvm_fragment_shader *shader) -{ - const struct tgsi_token *tokens = shader->base.shader.tokens; - union lp_type type; - LLVMTypeRef elem_type; - LLVMTypeRef vec_type; - LLVMTypeRef arg_types[7]; - LLVMTypeRef func_type; - LLVMValueRef pos_ptr; - LLVMValueRef a0_ptr; - LLVMValueRef dadx_ptr; - LLVMValueRef dady_ptr; - LLVMValueRef consts_ptr; - LLVMValueRef outputs_ptr; - LLVMValueRef samplers_ptr; - LLVMBasicBlockRef block; - LLVMBuilderRef builder; - LLVMValueRef pos[NUM_CHANNELS]; - LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; - char name[32]; - unsigned i, j; - - type.value = 0; - type.floating = TRUE; - type.sign = TRUE; - type.norm = FALSE; - type.width = 32; - type.length = 4; - - elem_type = lp_build_elem_type(type); - vec_type = lp_build_vec_type(type); - - arg_types[0] = LLVMPointerType(vec_type, 0); /* pos */ - arg_types[1] = LLVMPointerType(vec_type, 0); /* a0 */ - arg_types[2] = LLVMPointerType(vec_type, 0); /* dadx */ - arg_types[3] = LLVMPointerType(vec_type, 0); /* dady */ - arg_types[4] = LLVMPointerType(elem_type, 0); /* consts */ - arg_types[5] = LLVMPointerType(vec_type, 0); /* outputs */ - arg_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */ - - func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); - - shader->function = LLVMAddFunction(screen->module, "shader", func_type); - LLVMSetFunctionCallConv(shader->function, LLVMCCallConv); - - pos_ptr = LLVMGetParam(shader->function, 0); - a0_ptr = LLVMGetParam(shader->function, 1); - dadx_ptr = LLVMGetParam(shader->function, 2); - dady_ptr = LLVMGetParam(shader->function, 3); - consts_ptr = LLVMGetParam(shader->function, 4); - outputs_ptr = LLVMGetParam(shader->function, 5); - samplers_ptr = LLVMGetParam(shader->function, 6); - - LLVMSetValueName(pos_ptr, "pos"); - LLVMSetValueName(a0_ptr, "a0"); - LLVMSetValueName(dadx_ptr, "dadx"); - LLVMSetValueName(dady_ptr, "dady"); - LLVMSetValueName(consts_ptr, "consts"); - LLVMSetValueName(outputs_ptr, "outputs"); - LLVMSetValueName(samplers_ptr, "samplers"); - - block = LLVMAppendBasicBlock(shader->function, "entry"); - builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, block); - - for(j = 0; j < NUM_CHANNELS; ++j) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), j, 0); - util_snprintf(name, sizeof name, "pos.%c", "xyzw"[j]); - pos[j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, pos_ptr, &index, 1, ""), name); - } - - memset(outputs, 0, sizeof outputs); - - lp_build_tgsi_soa(builder, tokens, type, - pos, a0_ptr, dadx_ptr, dady_ptr, - consts_ptr, outputs, samplers_ptr); - - for(i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) { - for(j = 0; j < NUM_CHANNELS; ++j) { - if(outputs[i][j]) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*NUM_CHANNELS + j, 0); - util_snprintf(name, sizeof name, "output%u.%c", i, "xyzw"[j]); - LLVMBuildStore(builder, outputs[i][j], LLVMBuildGEP(builder, outputs_ptr, &index, 1, name)); - } - } - } - - LLVMBuildRetVoid(builder);; - - LLVMDisposeBuilder(builder); -} - - - -static void -fs_llvm_prepare( const struct lp_fragment_shader *base, - struct tgsi_exec_machine *machine, - struct tgsi_sampler **samplers ) -{ - /* - * Bind tokens/shader to the interpreter's machine state. - * Avoid redundant binding. - */ - if (machine->Tokens != base->shader.tokens) { - tgsi_exec_machine_bind_shader( machine, - base->shader.tokens, - PIPE_MAX_SAMPLERS, - samplers ); - } -} - - - -static void -setup_pos_vector(struct lp_llvm_fragment_shader *shader, - const struct tgsi_interp_coef *coef, - float x, float y) -{ - uint chan; - - /* do X */ - shader->pos[0].f[0] = x; - shader->pos[0].f[1] = x + 1; - shader->pos[0].f[2] = x; - shader->pos[0].f[3] = x + 1; - - /* do Y */ - shader->pos[1].f[0] = y; - shader->pos[1].f[1] = y; - shader->pos[1].f[2] = y + 1; - shader->pos[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; - shader->pos[chan].f[0] = a0; - shader->pos[chan].f[1] = a0 + dadx; - shader->pos[chan].f[2] = a0 + dady; - shader->pos[chan].f[3] = a0 + dadx + dady; - } -} - - -static void -setup_coef_vector(struct lp_llvm_fragment_shader *shader, - const struct tgsi_interp_coef *coef) -{ - unsigned attrib, chan, i; - - for (attrib = 0; attrib < PIPE_MAX_SHADER_INPUTS; ++attrib) { - for (chan = 0; chan < NUM_CHANNELS; ++chan) { - for( i = 0; i < QUAD_SIZE; ++i ) { - shader->a0[attrib][chan].f[i] = coef[attrib].a0[chan]; - shader->dadx[attrib][chan].f[i] = coef[attrib].dadx[chan]; - shader->dady[attrib][chan].f[i] = coef[attrib].dady[chan]; - } - } - } -} - - -/* 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_llvm_run( const struct lp_fragment_shader *base, - struct tgsi_exec_machine *machine, - struct quad_header *quad ) -{ - struct lp_llvm_fragment_shader *shader = lp_llvm_fragment_shader(base); - unsigned mask; - - /* Compute X, Y, Z, W vals for this quad */ - setup_pos_vector(shader, - quad->posCoef, - (float)quad->input.x0, (float)quad->input.y0); - - setup_coef_vector(shader, - quad->coef); - - /* init kill mask */ - tgsi_set_kill_mask(machine, 0x0); - tgsi_set_exec_mask(machine, 1, 1, 1, 1); - - memset(machine->Outputs, 0, sizeof machine->Outputs); - - shader->jit_function( shader->pos, - shader->a0, shader->dadx, shader->dady, - machine->Consts, - machine->Outputs, - machine->Samplers); - - /* FIXME */ - mask = ~0; - - return mask; -} - - -static void -fs_llvm_delete( struct lp_fragment_shader *base ) -{ - struct lp_llvm_fragment_shader *shader = lp_llvm_fragment_shader(base); - struct llvmpipe_screen *screen = shader->screen; - - if(shader->function) { - if(shader->jit_function) - LLVMFreeMachineCodeForFunction(screen->engine, shader->function); - LLVMDeleteFunction(shader->function); - } - - FREE((void *) shader->base.shader.tokens); - FREE(shader); -} - - -struct lp_fragment_shader * -llvmpipe_create_fs_llvm(struct llvmpipe_context *llvmpipe, - const struct pipe_shader_state *templ) -{ - struct llvmpipe_screen *screen = llvmpipe_screen(llvmpipe->pipe.screen); - struct lp_llvm_fragment_shader *shader; - LLVMValueRef fetch_texel; - - shader = CALLOC_STRUCT(lp_llvm_fragment_shader); - if (!shader) - return NULL; - - /* we need to keep a local copy of the tokens */ - shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens); - shader->base.prepare = fs_llvm_prepare; - shader->base.run = fs_llvm_run; - shader->base.delete = fs_llvm_delete; - - shader->screen = screen; - - tgsi_dump(templ->tokens, 0); - - shader_generate(screen, shader); - - LLVMRunFunctionPassManager(screen->pass, shader->function); - -#if 1 - LLVMDumpValue(shader->function); - debug_printf("\n"); -#endif - - if(LLVMVerifyFunction(shader->function, LLVMPrintMessageAction)) { - LLVMDumpValue(shader->function); - abort(); - } - - fetch_texel = LLVMGetNamedFunction(screen->module, "fetch_texel"); - if(fetch_texel) { - static boolean first_time = TRUE; - if(first_time) { - LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_build_tgsi_fetch_texel_soa); - first_time = FALSE; - } - } - - shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function); - - return &shader->base; -} - diff --git a/src/gallium/drivers/llvmpipe/lp_fs_sse.c b/src/gallium/drivers/llvmpipe/lp_fs_sse.c deleted file mode 100644 index 61c40dd4b39..00000000000 --- a/src/gallium/drivers/llvmpipe/lp_fs_sse.c +++ /dev/null @@ -1,169 +0,0 @@ -/************************************************************************** - * - * 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 diff --git a/src/gallium/drivers/llvmpipe/lp_quad_fs.c b/src/gallium/drivers/llvmpipe/lp_quad_fs.c index 1da50e493b5..338a6be80c4 100644 --- a/src/gallium/drivers/llvmpipe/lp_quad_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_quad_fs.c @@ -1,8 +1,8 @@ /************************************************************************** * + * Copyright 2008-2009 VMware, Inc. * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * Copyright 2008 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -65,6 +65,114 @@ quad_shade_stage(struct quad_stage *qs) } +static void +shader_prepare( const struct lp_fragment_shader *shader, + struct tgsi_exec_machine *machine, + struct tgsi_sampler **samplers ) +{ + /* + * Bind tokens/shader to the interpreter's machine state. + * Avoid redundant binding. + */ + if (machine->Tokens != shader->base.tokens) { + tgsi_exec_machine_bind_shader( machine, + shader->base.tokens, + PIPE_MAX_SAMPLERS, + samplers ); + } +} + + + +static void +setup_pos_vector(struct lp_fragment_shader *shader, + const struct tgsi_interp_coef *coef, + float x, float y) +{ + uint chan; + + /* do X */ + shader->pos[0].f[0] = x; + shader->pos[0].f[1] = x + 1; + shader->pos[0].f[2] = x; + shader->pos[0].f[3] = x + 1; + + /* do Y */ + shader->pos[1].f[0] = y; + shader->pos[1].f[1] = y; + shader->pos[1].f[2] = y + 1; + shader->pos[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; + shader->pos[chan].f[0] = a0; + shader->pos[chan].f[1] = a0 + dadx; + shader->pos[chan].f[2] = a0 + dady; + shader->pos[chan].f[3] = a0 + dadx + dady; + } +} + + +static void +setup_coef_vector(struct lp_fragment_shader *shader, + const struct tgsi_interp_coef *coef) +{ + unsigned attrib, chan, i; + + for (attrib = 0; attrib < PIPE_MAX_SHADER_INPUTS; ++attrib) { + for (chan = 0; chan < NUM_CHANNELS; ++chan) { + for( i = 0; i < QUAD_SIZE; ++i ) { + shader->a0[attrib][chan].f[i] = coef[attrib].a0[chan]; + shader->dadx[attrib][chan].f[i] = coef[attrib].dadx[chan]; + shader->dady[attrib][chan].f[i] = coef[attrib].dady[chan]; + } + } + } +} + + +/* 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 +shader_run( struct lp_fragment_shader *shader, + struct tgsi_exec_machine *machine, + struct quad_header *quad ) +{ + unsigned mask; + + /* Compute X, Y, Z, W vals for this quad */ + setup_pos_vector(shader, + quad->posCoef, + (float)quad->input.x0, (float)quad->input.y0); + + setup_coef_vector(shader, + quad->coef); + + /* init kill mask */ + tgsi_set_kill_mask(machine, 0x0); + tgsi_set_exec_mask(machine, 1, 1, 1, 1); + + memset(machine->Outputs, 0, sizeof machine->Outputs); + + shader->jit_function( shader->pos, + shader->a0, shader->dadx, shader->dady, + machine->Consts, + machine->Outputs, + machine->Samplers); + + /* FIXME */ + mask = ~0; + + return mask; +} + + /** * Execute fragment shader for the four fragments in the quad. */ @@ -77,7 +185,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad) boolean z_written; /* run shader */ - quad->inout.mask &= llvmpipe->fs->run( llvmpipe->fs, machine, quad ); + quad->inout.mask &= shader_run( llvmpipe->fs, machine, quad ); if (quad->inout.mask == 0) return FALSE; @@ -177,10 +285,9 @@ shade_begin(struct quad_stage *qs) struct quad_shade_stage *qss = quad_shade_stage(qs); struct llvmpipe_context *llvmpipe = qs->llvmpipe; - llvmpipe->fs->prepare( llvmpipe->fs, - qss->machine, - (struct tgsi_sampler **) - llvmpipe->tgsi.frag_samplers_list ); + shader_prepare( llvmpipe->fs, + qss->machine, + (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list ); qs->next->begin(qs->next); } diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 6b757a6ba71..8638732b51f 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -59,29 +59,36 @@ struct tgsi_exec_machine; struct vertex_info; +typedef void +(*lp_shader_fs_func)(void *pos, + void *a0, + void *dadx, + void *dady, + void *consts, + void *outputs, + struct tgsi_sampler **samplers); + /** * 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 lp_fragment_shader { - struct pipe_shader_state shader; +struct lp_fragment_shader +{ + struct pipe_shader_state base; struct tgsi_shader_info info; - void (*prepare)( const struct lp_fragment_shader *shader, - struct tgsi_exec_machine *machine, - struct tgsi_sampler **samplers); + struct llvmpipe_screen *screen; - /* Run the shader - this interface will get cleaned up in the - * future: - */ - unsigned (*run)( const struct lp_fragment_shader *shader, - struct tgsi_exec_machine *machine, - struct quad_header *quad ); + LLVMValueRef function; + lp_shader_fs_func jit_function; - void (*delete)( struct lp_fragment_shader * ); + union tgsi_exec_channel ALIGN16_ATTRIB pos[NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB a0[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB dadx[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB dady[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; }; diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 1dc0dadef68..e6efa426fe0 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -1,5 +1,6 @@ /************************************************************************** * + * Copyright 2009 VMware, Inc. * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * @@ -25,10 +26,6 @@ * **************************************************************************/ -#include "lp_context.h" -#include "lp_state.h" -#include "lp_fs.h" - #include "pipe/p_defines.h" #include "util/u_memory.h" #include "pipe/internal/p_winsys_screen.h" @@ -37,34 +34,159 @@ #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" +#include "lp_bld_type.h" +#include "lp_bld_tgsi.h" +#include "lp_screen.h" +#include "lp_context.h" +#include "lp_state.h" +#include "lp_quad.h" + + +static void +shader_generate(struct llvmpipe_screen *screen, + struct lp_fragment_shader *shader) +{ + const struct tgsi_token *tokens = shader->base.tokens; + union lp_type type; + LLVMTypeRef elem_type; + LLVMTypeRef vec_type; + LLVMTypeRef arg_types[7]; + LLVMTypeRef func_type; + LLVMValueRef pos_ptr; + LLVMValueRef a0_ptr; + LLVMValueRef dadx_ptr; + LLVMValueRef dady_ptr; + LLVMValueRef consts_ptr; + LLVMValueRef outputs_ptr; + LLVMValueRef samplers_ptr; + LLVMBasicBlockRef block; + LLVMBuilderRef builder; + LLVMValueRef pos[NUM_CHANNELS]; + LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; + char name[32]; + unsigned i, j; + + type.value = 0; + type.floating = TRUE; + type.sign = TRUE; + type.norm = FALSE; + type.width = 32; + type.length = 4; + + elem_type = lp_build_elem_type(type); + vec_type = lp_build_vec_type(type); + + arg_types[0] = LLVMPointerType(vec_type, 0); /* pos */ + arg_types[1] = LLVMPointerType(vec_type, 0); /* a0 */ + arg_types[2] = LLVMPointerType(vec_type, 0); /* dadx */ + arg_types[3] = LLVMPointerType(vec_type, 0); /* dady */ + arg_types[4] = LLVMPointerType(elem_type, 0); /* consts */ + arg_types[5] = LLVMPointerType(vec_type, 0); /* outputs */ + arg_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */ + + func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); + + shader->function = LLVMAddFunction(screen->module, "shader", func_type); + LLVMSetFunctionCallConv(shader->function, LLVMCCallConv); + + pos_ptr = LLVMGetParam(shader->function, 0); + a0_ptr = LLVMGetParam(shader->function, 1); + dadx_ptr = LLVMGetParam(shader->function, 2); + dady_ptr = LLVMGetParam(shader->function, 3); + consts_ptr = LLVMGetParam(shader->function, 4); + outputs_ptr = LLVMGetParam(shader->function, 5); + samplers_ptr = LLVMGetParam(shader->function, 6); + + LLVMSetValueName(pos_ptr, "pos"); + LLVMSetValueName(a0_ptr, "a0"); + LLVMSetValueName(dadx_ptr, "dadx"); + LLVMSetValueName(dady_ptr, "dady"); + LLVMSetValueName(consts_ptr, "consts"); + LLVMSetValueName(outputs_ptr, "outputs"); + LLVMSetValueName(samplers_ptr, "samplers"); + + block = LLVMAppendBasicBlock(shader->function, "entry"); + builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, block); + + for(j = 0; j < NUM_CHANNELS; ++j) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), j, 0); + util_snprintf(name, sizeof name, "pos.%c", "xyzw"[j]); + pos[j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, pos_ptr, &index, 1, ""), name); + } + + memset(outputs, 0, sizeof outputs); + + lp_build_tgsi_soa(builder, tokens, type, + pos, a0_ptr, dadx_ptr, dady_ptr, + consts_ptr, outputs, samplers_ptr); + + for(i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) { + for(j = 0; j < NUM_CHANNELS; ++j) { + if(outputs[i][j]) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*NUM_CHANNELS + j, 0); + util_snprintf(name, sizeof name, "output%u.%c", i, "xyzw"[j]); + LLVMBuildStore(builder, outputs[i][j], LLVMBuildGEP(builder, outputs_ptr, &index, 1, name)); + } + } + } + + LLVMBuildRetVoid(builder);; + + LLVMDisposeBuilder(builder); +} void * llvmpipe_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { - struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - struct lp_fragment_shader *state; - - /* debug */ - if (llvmpipe->dump_fs) - tgsi_dump(templ->tokens, 0); - - /* codegen */ - state = llvmpipe_create_fs_llvm( llvmpipe, templ ); - if (!state) { - state = llvmpipe_create_fs_sse( llvmpipe, templ ); - if (!state) { - state = llvmpipe_create_fs_exec( llvmpipe, templ ); - } - } + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + struct lp_fragment_shader *shader; + LLVMValueRef fetch_texel; - assert(state); + shader = CALLOC_STRUCT(lp_fragment_shader); + if (!shader) + return NULL; /* get/save the summary info for this shader */ - tgsi_scan_shader(templ->tokens, &state->info); + tgsi_scan_shader(templ->tokens, &shader->info); - return state; + /* we need to keep a local copy of the tokens */ + shader->base.tokens = tgsi_dup_tokens(templ->tokens); + + shader->screen = screen; + +#ifdef DEBUG + tgsi_dump(templ->tokens, 0); +#endif + + shader_generate(screen, shader); + + LLVMRunFunctionPassManager(screen->pass, shader->function); + +#ifdef DEBUG + LLVMDumpValue(shader->function); + debug_printf("\n"); +#endif + + if(LLVMVerifyFunction(shader->function, LLVMPrintMessageAction)) { + LLVMDumpValue(shader->function); + abort(); + } + + fetch_texel = LLVMGetNamedFunction(screen->module, "fetch_texel"); + if(fetch_texel) { + static boolean first_time = TRUE; + if(first_time) { + LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_build_tgsi_fetch_texel_soa); + first_time = FALSE; + } + } + + shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function); + + return shader; } @@ -82,11 +204,19 @@ llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs) void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { - struct lp_fragment_shader *state = fs; + struct lp_fragment_shader *shader = fs; + struct llvmpipe_screen *screen = shader->screen; assert(fs != llvmpipe_context(pipe)->fs); - state->delete( state ); + if(shader->function) { + if(shader->jit_function) + LLVMFreeMachineCodeForFunction(screen->engine, shader->function); + LLVMDeleteFunction(shader->function); + } + + FREE((void *) shader->base.tokens); + FREE(shader); } -- 2.30.2