Commit c61bf363 authored by Zack Rusin's avatar Zack Rusin

llvmpipe: export the tgsi translation code to a common layer

the llvmpipe tgsi translation is a lot more complete than what was in
gallivm so replacing the latter with the former. this is needed since
the draw llvm paths will use the same code. effectively the proven
llvmpipe code becomes gallivm.
parent 74d23546
......@@ -79,9 +79,10 @@ Help(opts.GenerateHelpText(env))
# replicate options values in local variables
debug = env['debug']
dri = env['dri']
llvm = env['llvm']
machine = env['machine']
platform = env['platform']
drawllvm = 'llvmpipe' in env['drivers']
# derived options
x86 = machine == 'x86'
......@@ -94,7 +95,7 @@ Export([
'x86',
'ppc',
'dri',
'llvm',
'drawllvm',
'platform',
'gcc',
'msvc',
......@@ -165,13 +166,12 @@ if dri:
'GLX_INDIRECT_RENDERING',
])
# LLVM
if llvm:
# LLVM support in the Draw module
if drawllvm:
# See also http://www.scons.org/wiki/UsingPkgConfig
env.ParseConfig('llvm-config --cflags --ldflags --libs backend bitreader engine instrumentation interpreter ipo')
env.Append(CPPDEFINES = ['MESA_LLVM'])
# Force C++ linkage
env['LINK'] = env['CXX']
# currently --ldflags --libsdisabled since the driver will force the correct linkage
env.ParseConfig('llvm-config --cflags backend bitreader engine instrumentation interpreter ipo')
env.Append(CPPDEFINES = ['DRAW_LLVM'])
# libGL
if platform in ('linux', 'freebsd', 'darwin'):
......
......@@ -12,7 +12,7 @@ GALLIUM_DRIVERS_DIRS += llvmpipe
OPT_FLAGS = -O3 -ansi -pedantic
ARCH_FLAGS = -m32 -mmmx -msse -msse2 -mstackrealign
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DHAVE_UDIS86
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DDRAW_LLVM -DHAVE_UDIS86
# override -std=c99
CFLAGS += -std=gnu99
......
......@@ -130,41 +130,40 @@ C_SOURCES = \
vl/vl_shader_build.c
GALLIVM_SOURCES = \
gallivm/gallivm.cpp \
gallivm/gallivm_cpu.cpp \
gallivm/instructions.cpp \
gallivm/loweringpass.cpp \
gallivm/tgsitollvm.cpp \
gallivm/storage.cpp \
gallivm/storagesoa.cpp \
gallivm/instructionssoa.cpp
gallivm/lp_bld_alpha.c \
gallivm/lp_bld_arit.c \
gallivm/lp_bld_blend_aos.c \
gallivm/lp_bld_blend_logicop.c \
gallivm/lp_bld_blend_soa.c \
gallivm/lp_bld_const.c \
gallivm/lp_bld_conv.c \
gallivm/lp_bld_debug.c \
gallivm/lp_bld_depth.c \
gallivm/lp_bld_flow.c \
gallivm/lp_bld_format_aos.c \
gallivm/lp_bld_format_query.c \
gallivm/lp_bld_format_soa.c \
gallivm/lp_bld_interp.c \
gallivm/lp_bld_intr.c \
gallivm/lp_bld_logic.c \
gallivm/lp_bld_pack.c \
gallivm/lp_bld_sample.c \
gallivm/lp_bld_sample_soa.c \
gallivm/lp_bld_struct.c \
gallivm/lp_bld_swizzle.c \
gallivm/lp_bld_tgsi_soa.c \
gallivm/lp_bld_type.c
INC_SOURCES = \
gallivm/gallivm_builtins.cpp \
gallivm/gallivmsoabuiltins.cpp
# XXX: gallivm doesn't build correctly so disable for now
#ifeq ($(MESA_LLVM),1)
#DEFINES += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
#CPP_SOURCES += \
# $(GALLIVM_SOURCES)
#endif
ifeq ($(MESA_LLVM),1)
C_SOURCES += \
$(GALLIVM_SOURCES)
endif
include ../Makefile.template
gallivm/gallivm_builtins.cpp: gallivm/llvm_builtins.c
clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp1.bin
(echo "static const unsigned char llvm_builtins_data[] = {"; od -txC temp1.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
rm temp1.bin
gallivm/gallivmsoabuiltins.cpp: gallivm/soabuiltins.c
clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp2.bin
(echo "static const unsigned char soabuiltins_data[] = {"; od -txC temp2.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
rm temp2.bin
indices/u_indices_gen.c: indices/u_indices_gen.py
python $< > $@
......
......@@ -166,16 +166,31 @@ source = [
'vl/vl_shader_build.c',
]
if env['llvm']:
if drawllvm:
source += [
'gallivm/gallivm.cpp',
'gallivm/gallivm_cpu.cpp',
'gallivm/instructions.cpp',
'gallivm/loweringpass.cpp',
'gallivm/tgsitollvm.cpp',
'gallivm/storage.cpp',
'gallivm/storagesoa.cpp',
'gallivm/instructionssoa.cpp',
'gallivm/lp_bld_alpha.c',
'gallivm/lp_bld_arit.c',
'gallivm/lp_bld_blend_aos.c',
'gallivm/lp_bld_blend_logicop.c',
'gallivm/lp_bld_blend_soa.c',
'gallivm/lp_bld_const.c',
'gallivm/lp_bld_conv.c',
'gallivm/lp_bld_debug.c',
'gallivm/lp_bld_depth.c',
'gallivm/lp_bld_flow.c',
'gallivm/lp_bld_format_aos.c',
'gallivm/lp_bld_format_query.c',
'gallivm/lp_bld_format_soa.c',
'gallivm/lp_bld_interp.c',
'gallivm/lp_bld_intr.c',
'gallivm/lp_bld_logic.c',
'gallivm/lp_bld_pack.c',
'gallivm/lp_bld_sample.c',
'gallivm/lp_bld_sample_soa.c',
'gallivm/lp_bld_struct.c',
'gallivm/lp_bld_swizzle.c',
'gallivm/lp_bld_tgsi_soa.c',
'gallivm/lp_bld_type.c',
]
gallium = env.ConvenienceLibrary(
......
......@@ -48,8 +48,6 @@
struct pipe_context;
struct gallivm_prog;
struct gallivm_cpu_engine;
struct draw_vertex_shader;
struct draw_context;
struct draw_stage;
......@@ -193,10 +191,6 @@ struct draw_context
uint num_samplers;
struct tgsi_sampler **samplers;
/* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private.
*/
struct gallivm_cpu_engine *engine;
/* Here's another one:
*/
struct aos_machine *aos_machine;
......
......@@ -42,11 +42,8 @@
#ifdef MESA_LLVM
#include "gallivm/gallivm.h"
struct draw_llvm_vertex_shader {
struct draw_vertex_shader base;
struct gallivm_prog *llvm_prog;
struct tgsi_exec_machine *machine;
};
......@@ -58,8 +55,6 @@ vs_llvm_prepare( struct draw_vertex_shader *base,
}
static void
vs_llvm_run_linear( struct draw_vertex_shader *base,
const float (*input)[4],
......@@ -71,11 +66,6 @@ vs_llvm_run_linear( struct draw_vertex_shader *base,
{
struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
gallivm_cpu_vs_exec(shader->llvm_prog, shader->machine,
input, base->info.num_inputs, output, base->info.num_outputs,
(const float (*)[4])constants[0],
count, input_stride, output_stride);
}
......@@ -122,27 +112,6 @@ draw_create_vs_llvm(struct draw_context *draw,
vs->base.delete = vs_llvm_delete;
vs->machine = draw->vs.machine;
{
struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS);
gallivm_ir_set_layout(ir, GALLIVM_SOA);
gallivm_ir_set_components(ir, 4);
gallivm_ir_fill_from_tgsi(ir, vs->base.state.tokens);
vs->llvm_prog = gallivm_ir_compile(ir);
gallivm_ir_delete(ir);
}
draw->vs.engine = gallivm_global_cpu_engine();
/* XXX: Why are there two versions of this? Shouldn't creating the
* engine be a separate operation to compiling a shader?
*/
if (!draw->vs.engine) {
draw->vs.engine = gallivm_cpu_engine_create(vs->llvm_prog);
}
else {
gallivm_cpu_jit_compile(draw->vs.engine, vs->llvm_prog);
}
return &vs->base;
}
......
This diff is collapsed.
/**************************************************************************
*
* 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 zack@tungstengraphics.com
*/
#ifndef GALLIVM_H
#define GALLIVM_H
/*
LLVM representation consists of two stages - layout independent
intermediate representation gallivm_ir and driver specific
gallivm_prog. TGSI is first being translated into gallivm_ir
after that driver can set number of options on gallivm_ir and
have it compiled into gallivm_prog. gallivm_prog can be either
executed (assuming there's LLVM JIT backend for the current
target) or machine code generation can be done (assuming there's
a LLVM code generator for thecurrent target)
*/
#if defined __cplusplus
extern "C" {
#endif
#include "pipe/p_state.h"
#ifdef MESA_LLVM
struct tgsi_token;
struct gallivm_ir;
struct gallivm_prog;
struct gallivm_cpu_engine;
struct tgsi_interp_coef;
struct tgsi_sampler;
struct tgsi_exec_vector;
enum gallivm_shader_type {
GALLIVM_VS,
GALLIVM_FS
};
enum gallivm_vector_layout {
GALLIVM_AOS,
GALLIVM_SOA
};
struct gallivm_ir *gallivm_ir_new(enum gallivm_shader_type type);
void gallivm_ir_set_layout(struct gallivm_ir *ir,
enum gallivm_vector_layout layout);
void gallivm_ir_set_components(struct gallivm_ir *ir, int num);
void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
const struct tgsi_token *tokens);
void gallivm_ir_delete(struct gallivm_ir *ir);
struct gallivm_prog *gallivm_ir_compile(struct gallivm_ir *ir);
void gallivm_prog_inputs_interpolate(struct gallivm_prog *prog,
float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
const struct tgsi_interp_coef *coefs);
void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix);
struct gallivm_cpu_engine *gallivm_cpu_engine_create(struct gallivm_prog *prog);
struct gallivm_cpu_engine *gallivm_global_cpu_engine();
int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
struct tgsi_exec_machine *machine,
const float (*input)[4],
unsigned num_inputs,
float (*output)[4],
unsigned num_outputs,
const float (*constants)[4],
unsigned count,
unsigned input_stride,
unsigned output_stride);
int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
float x, float y,
float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
float (*consts)[4],
struct tgsi_sampler *samplers);
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
}
#endif
#endif
This diff is collapsed.
/**************************************************************************
*
* 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 zack@tungstengraphics.com
*/
#ifdef MESA_LLVM
#include "gallivm.h"
#include "gallivm_p.h"
#include "instructions.h"
#include "loweringpass.h"
#include "storage.h"
#include "tgsitollvm.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_dump.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include <llvm/Module.h>
#include <llvm/CallingConv.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Instructions.h>
#include <llvm/ModuleProvider.h>
#include <llvm/Pass.h>
#include <llvm/PassManager.h>
#include <llvm/Attributes.h>
#include <llvm/Support/PatternMatch.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/Interpreter.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/LinkAllPasses.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Analysis/LoopPass.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include <sstream>
#include <fstream>
#include <iostream>
struct gallivm_cpu_engine {
llvm::ExecutionEngine *engine;
};
static struct gallivm_cpu_engine *CPU = 0;
typedef int (*fragment_shader_runner)(float x, float y,
float (*dests)[16][4],
float (*inputs)[16][4],
int num_attribs,
float (*consts)[4], int num_consts,
struct tgsi_sampler *samplers);
int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
float fx, float fy,
float (*dests)[16][4],
float (*inputs)[16][4],
float (*consts)[4],
struct tgsi_sampler *samplers)
{
fragment_shader_runner runner = reinterpret_cast<fragment_shader_runner>(prog->function);
assert(runner);
return runner(fx, fy, dests, inputs, prog->num_interp,
consts, prog->num_consts,
samplers);
}
static inline llvm::Function *func_for_shader(struct gallivm_prog *prog)
{
llvm::Module *mod = prog->module;
llvm::Function *func = 0;
switch (prog->type) {
case GALLIVM_VS:
func = mod->getFunction("vs_shader");
break;
case GALLIVM_FS:
func = mod->getFunction("fs_shader");
break;
default:
assert(!"Unknown shader type!");
break;
}
return func;
}
/*!
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);
ee->DisableLazyCompilation();
cpu->engine = ee;
llvm::Function *func = func_for_shader(prog);
prog->function = ee->getPointerToFunction(func);
CPU = cpu;
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);
/*FIXME : why was this disabled ? we need it for pow/sqrt/... */
ee->DisableLazyCompilation(false);
ee->addModuleProvider(mp);
llvm::Function *func = func_for_shader(prog);
prog->function = ee->getPointerToFunction(func);
}
void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *cpu)
{
free(cpu);
}
struct gallivm_cpu_engine * gallivm_global_cpu_engine()
{
return CPU;
}
typedef void (*vertex_shader_runner)(void *ainputs,
void *dests,
float (*aconsts)[4]);
#define MAX_TGSI_VERTICES 4
/*!
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_cpu_vs_exec(struct gallivm_prog *prog,
struct tgsi_exec_machine *machine,
const float (*input)[4],
unsigned num_inputs,
float (*output)[4],
unsigned num_outputs,
const float (*constants)[4],
unsigned count,
unsigned input_stride,
unsigned output_stride )
{
unsigned int i, j;
unsigned slot;
vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
assert(runner);
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
/* Swizzle inputs.
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < num_inputs; slot++) {
machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
}
input = (const float (*)[4])((const char *)input + input_stride);
}
/* run shader */
runner(machine->Inputs,
machine->Outputs,
(float (*)[4]) constants);
/* Unswizzle all output results
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < num_outputs; slot++) {
output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
output = (float (*)[4])((char *)output + output_stride);
}
}
return 0;
}
#endif
#ifndef GALLIVM_P_H
#define GALLIVM_P_H
#ifdef MESA_LLVM
#include "gallivm.h"