summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZack Rusin <zack@tungstengraphics.com>2007-10-29 08:27:32 -0400
committerKeith Whitwell <keith@tungstengraphics.com>2007-10-29 16:14:10 +0000
commit25b17b213b7ba0d1b93ec37211504ee489944ce8 (patch)
tree5bc773224011ccc2e06e93f73952ef886e351953 /src
parentabe8cd19171def0de000e58b9f71c43adf4c6336 (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')
-rw-r--r--src/mesa/pipe/draw/draw_private.h8
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader.c10
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader_llvm.c2
-rw-r--r--src/mesa/pipe/llvm/llvmtgsi.cpp86
-rw-r--r--src/mesa/pipe/llvm/llvmtgsi.h13
-rw-r--r--src/mesa/state_tracker/st_program.c4
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 ac47d2a76f..f52ff0bd44 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 9dbb317f2a..7fd17292b8 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 c0720d2872..b340ab38fd 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 af602326ae..b57a0f8366 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 d4cf61ca97..a76dfd60b5 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 8c61815b9b..706238cbf5 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;