diff options
author | Zack Rusin <[email protected]> | 2007-10-29 08:27:32 -0400 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2007-10-29 16:14:10 +0000 |
commit | 25b17b213b7ba0d1b93ec37211504ee489944ce8 (patch) | |
tree | 5bc773224011ccc2e06e93f73952ef886e351953 /src/mesa | |
parent | abe8cd19171def0de000e58b9f71c43adf4c6336 (diff) |
Refactor the LLVM code a bit.
Move the CPU vertex shader execution code to the draw
module, remove traces of LLVM from the state tracker,
abstract execution engine for the purposes of the draw module.
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/pipe/draw/draw_private.h | 8 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vertex_shader.c | 10 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vertex_shader_llvm.c | 2 | ||||
-rw-r--r-- | src/mesa/pipe/llvm/llvmtgsi.cpp | 86 | ||||
-rw-r--r-- | src/mesa/pipe/llvm/llvmtgsi.h | 13 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.c | 4 |
6 files changed, 97 insertions, 26 deletions
diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h index ac47d2a76f6..f52ff0bd44e 100644 --- a/src/mesa/pipe/draw/draw_private.h +++ b/src/mesa/pipe/draw/draw_private.h @@ -50,6 +50,8 @@ #include "pipe/tgsi/exec/tgsi_core.h" +struct gallivm_prog; +struct gallivm_cpu_engine; /** * Basic vertex info. * Carry some useful information around with the vertices in the prim pipe. @@ -127,6 +129,9 @@ struct draw_vertex_shader { #if defined(__i386__) || defined(__386__) struct x86_function sse2_program; #endif +#ifdef MESA_LLVM + struct gallivm_prog *llvm_prog; +#endif }; /** @@ -226,6 +231,9 @@ struct draw_context } pq; int use_sse : 1; +#ifdef MESA_LLVM + struct gallivm_cpu_engine *engine; +#endif }; diff --git a/src/mesa/pipe/draw/draw_vertex_shader.c b/src/mesa/pipe/draw/draw_vertex_shader.c index 9dbb317f2a0..7fd17292b85 100644 --- a/src/mesa/pipe/draw/draw_vertex_shader.c +++ b/src/mesa/pipe/draw/draw_vertex_shader.c @@ -39,6 +39,7 @@ #include "x86/rtasm/x86sse.h" #include "pipe/tgsi/exec/tgsi_core.h" +#include "pipe/llvm/llvmtgsi.h" #define DBG 0 @@ -187,7 +188,7 @@ void draw_vertex_shader_queue_flush( struct draw_context *draw ) // fprintf(stderr, " q(%d) ", draw->vs.queue_nr ); #ifdef MESA_LLVM - if (draw->vertex_shader->state->llvm_prog) { + if (draw->vertex_shader->llvm_prog) { draw_vertex_shader_queue_flush_llvm(draw); return; } @@ -233,6 +234,13 @@ draw_create_vertex_shader(struct draw_context *draw, tgsi_emit_sse2( sh->tokens, &vs->sse2_program ); } #endif +#ifdef MESA_LLVM + vs->llvm_prog = gallivm_from_tgsi(shader->tokens); + if (!draw->engine) + draw->engine = gallivm_cpu_engine_create(vs->llvm_prog); + else + gallivm_cpu_jit_compile(draw->engine, vs->llvm_prog); +#endif return vs; } diff --git a/src/mesa/pipe/draw/draw_vertex_shader_llvm.c b/src/mesa/pipe/draw/draw_vertex_shader_llvm.c index c0720d2872e..b340ab38fd5 100644 --- a/src/mesa/pipe/draw/draw_vertex_shader_llvm.c +++ b/src/mesa/pipe/draw/draw_vertex_shader_llvm.c @@ -125,7 +125,7 @@ void draw_vertex_shader_queue_flush_llvm(struct draw_context *draw) float inputs[VS_QUEUE_LENGTH][PIPE_MAX_SHADER_INPUTS][4]; float outputs[VS_QUEUE_LENGTH][PIPE_MAX_SHADER_INPUTS][4]; float (*consts)[4] = (float (*)[4]) draw->mapped_constants; - struct gallivm_prog *prog = (struct gallivm_prog *)draw->vertex_shader->state->llvm_prog; + struct gallivm_prog *prog = draw->vertex_shader->llvm_prog; const float *scale = draw->viewport.scale; const float *trans = draw->viewport.translate; diff --git a/src/mesa/pipe/llvm/llvmtgsi.cpp b/src/mesa/pipe/llvm/llvmtgsi.cpp index af602326ae6..b57a0f83665 100644 --- a/src/mesa/pipe/llvm/llvmtgsi.cpp +++ b/src/mesa/pipe/llvm/llvmtgsi.cpp @@ -70,12 +70,16 @@ #ifdef MESA_LLVM struct gallivm_prog { - void *module; + llvm::Module *module; void *function; int num_consts; int id; }; +struct gallivm_cpu_engine { + llvm::ExecutionEngine *engine; +}; + using namespace llvm; #include "llvm_base_shader.cpp" @@ -698,13 +702,21 @@ tgsi_to_llvm(struct gallivm_prog *prog, const struct tgsi_token *tokens) return mod; } +/*! + Translates the TGSI tokens into LLVM format. Translated representation + is stored in the gallivm_prog and returned. + After calling this function the gallivm_prog can either be used with a custom + code generator to generate machine code for the GPU which the code generator + addresses or it can be jit compiled with gallivm_cpu_jit_compile and executed + with gallivm_prog_exec to run the module on the CPU. + */ struct gallivm_prog * -gallivm_from_tgsi(struct pipe_context *pipe, const struct tgsi_token *tokens) +gallivm_from_tgsi(const struct tgsi_token *tokens) { std::cout << "Creating llvm from: " <<std::endl; ++GLOBAL_ID; struct gallivm_prog *gallivm = - (struct gallivm_prog *)malloc(sizeof(struct gallivm_prog)); + (struct gallivm_prog *)calloc(1, sizeof(struct gallivm_prog)); gallivm->id = GLOBAL_ID; tgsi_dump(tokens, 0); @@ -718,20 +730,8 @@ gallivm_from_tgsi(struct pipe_context *pipe, const struct tgsi_token *tokens) AddStandardCompilePasses(passes); passes.run(*mod); - llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod); - llvm::ExecutionEngine *ee = 0; - if (!pipe->llvm_execution_engine) { - ee = llvm::ExecutionEngine::create(mp, false); - pipe->llvm_execution_engine = ee; - } else { - ee = (llvm::ExecutionEngine*)pipe->llvm_execution_engine; - ee->addModuleProvider(mp); - } gallivm->module = mod; - Function *func = mod->getFunction("run_vertex_shader"); - gallivm->function = ee->getPointerToFunctionOrStub(func); - gallivm_prog_dump(gallivm, 0); return gallivm; @@ -754,6 +754,12 @@ typedef void (*vertex_shader_runner)(float (*ainputs)[PIPE_MAX_SHADER_INPUTS][4] int num_attribs, int num_consts); + +/*! + This function is used to execute the gallivm_prog in software. Before calling + this function the gallivm_prog has to be JIT compiled with the gallivm_cpu_jit_compile + function. + */ int gallivm_prog_exec(struct gallivm_prog *prog, float (*inputs)[PIPE_MAX_SHADER_INPUTS][4], float (*dests)[PIPE_MAX_SHADER_INPUTS][4], @@ -763,6 +769,7 @@ int gallivm_prog_exec(struct gallivm_prog *prog, int num_attribs) { vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function); + assert(runner); runner(inputs, dests, consts, num_vertices, num_inputs, num_attribs, prog->num_consts); @@ -803,4 +810,53 @@ void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix) } } + +/*! + This function creates a CPU based execution engine for the given gallivm_prog. + gallivm_cpu_engine should be used as a singleton throughout the library. Before + executing gallivm_prog_exec one needs to call gallivm_cpu_jit_compile. + The gallivm_prog instance which is being passed to the constructor is being + automatically JIT compiled so one shouldn't call gallivm_cpu_jit_compile + with it again. + */ +struct gallivm_cpu_engine * gallivm_cpu_engine_create(struct gallivm_prog *prog) +{ + struct gallivm_cpu_engine *cpu = (struct gallivm_cpu_engine *) + calloc(1, sizeof(struct gallivm_cpu_engine)); + llvm::Module *mod = static_cast<llvm::Module*>(prog->module); + llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod); + llvm::ExecutionEngine *ee = llvm::ExecutionEngine::create(mp, false); + cpu->engine = ee; + + llvm::Function *func = mod->getFunction("run_vertex_shader"); + prog->function = ee->getPointerToFunctionOrStub(func); + return cpu; +} + + +/*! + This function JIT compiles the given gallivm_prog with the given cpu based execution engine. + The reference to the generated machine code entry point will be stored + in the gallivm_prog program. After executing this function one can call gallivm_prog_exec + in order to execute the gallivm_prog on the CPU. + */ +void gallivm_cpu_jit_compile(struct gallivm_cpu_engine *cpu, struct gallivm_prog *prog) +{ + llvm::Module *mod = static_cast<llvm::Module*>(prog->module); + llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod); + llvm::ExecutionEngine *ee = cpu->engine; + assert(ee); + ee->addModuleProvider(mp); + + llvm::Function *func = mod->getFunction("run_vertex_shader"); + prog->function = ee->getPointerToFunctionOrStub(func); +} + +void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *cpu) +{ + free(cpu); +} + #endif /* MESA_LLVM */ + + diff --git a/src/mesa/pipe/llvm/llvmtgsi.h b/src/mesa/pipe/llvm/llvmtgsi.h index d4cf61ca97c..a76dfd60b5c 100644 --- a/src/mesa/pipe/llvm/llvmtgsi.h +++ b/src/mesa/pipe/llvm/llvmtgsi.h @@ -44,15 +44,12 @@ extern "C" { struct tgsi_exec_machine; struct tgsi_token; struct tgsi_sampler; -struct pipe_context; struct gallivm_prog; +struct gallivm_cpu_engine; -struct gallivm_prog * -gallivm_from_tgsi(struct pipe_context *pipe, const struct tgsi_token *tokens); - +struct gallivm_prog *gallivm_from_tgsi(const struct tgsi_token *tokens); void gallivm_prog_delete(struct gallivm_prog *prog); - int gallivm_prog_exec(struct gallivm_prog *prog, float (*inputs)[PIPE_MAX_SHADER_INPUTS][4], float (*dests)[PIPE_MAX_SHADER_INPUTS][4], @@ -60,9 +57,13 @@ int gallivm_prog_exec(struct gallivm_prog *prog, int num_vertices, int num_inputs, int num_attribs); - void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix); + +struct gallivm_cpu_engine *gallivm_cpu_engine_create(struct gallivm_prog *prog); +void gallivm_cpu_jit_compile(struct gallivm_cpu_engine *ee, struct gallivm_prog *prog); +void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *ee); + #endif /* MESA_LLVM */ #if defined __cplusplus diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 8c61815b9b6..706238cbf53 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -251,9 +251,7 @@ st_translate_vertex_program(struct st_context *st, tokensOut, maxTokens); vs.tokens = tokensOut; -#ifdef MESA_LLVM - vs.llvm_prog = (void*)gallivm_from_tgsi(st->pipe, vs.tokens); -#endif + cso = st_cached_vs_state(st, &vs); stvp->vs = cso; |