mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 04:48:08 +02:00
llvmpipe: Eliminate non-LLVM fs execution paths.
This commit is contained in:
parent
95f38dd67c
commit
73af91e938
11 changed files with 285 additions and 802 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
|
||||
struct lp_fragment_shader *shader;
|
||||
LLVMValueRef fetch_texel;
|
||||
|
||||
/* debug */
|
||||
if (llvmpipe->dump_fs)
|
||||
tgsi_dump(templ->tokens, 0);
|
||||
shader = CALLOC_STRUCT(lp_fragment_shader);
|
||||
if (!shader)
|
||||
return NULL;
|
||||
|
||||
/* 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 );
|
||||
/* get/save the summary info for this shader */
|
||||
tgsi_scan_shader(templ->tokens, &shader->info);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
assert(state);
|
||||
shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function);
|
||||
|
||||
/* get/save the summary info for this shader */
|
||||
tgsi_scan_shader(templ->tokens, &state->info);
|
||||
|
||||
return state;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue