llvmpipe: Further abstract the texture sampling generation from TGSI translation.

This commit is contained in:
José Fonseca 2009-09-06 11:20:14 +01:00
parent 970823978c
commit 8be72bb764
5 changed files with 186 additions and 125 deletions

View file

@ -44,14 +44,30 @@ struct lp_build_context;
struct lp_build_mask_context;
typedef void
(*lp_emit_fetch_texel_soa_callback)( LLVMBuilderRef builder,
void *context,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
LLVMValueRef lodbias,
LLVMValueRef *texel);
/**
* Sampler code generation interface.
*
* Although texture sampling is a requirement for TGSI translation, it is
* a very different problem with several different approaches to it. This
* structure establishes an interface for texture sampling code generation, so
* that we can easily use different texture sampling strategies.
*/
struct lp_build_sampler_soa
{
void
(*destroy)( struct lp_build_sampler_soa *sampler );
void
(*emit_fetch_texel)( struct lp_build_sampler_soa *sampler,
LLVMBuilderRef builder,
union lp_type type,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
LLVMValueRef lodbias,
LLVMValueRef *texel);
};
void
lp_build_tgsi_soa(LLVMBuilderRef builder,
@ -62,8 +78,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
const LLVMValueRef *pos,
const LLVMValueRef (*inputs)[4],
LLVMValueRef (*outputs)[4],
lp_emit_fetch_texel_soa_callback emit_fetch_texel,
void *emit_fetch_texel_context);
struct lp_build_sampler_soa *sampler);
#endif /* LP_BLD_TGSI_H */

View file

@ -88,8 +88,7 @@ struct lp_build_tgsi_soa_context
const LLVMValueRef (*inputs)[NUM_CHANNELS];
LLVMValueRef (*outputs)[NUM_CHANNELS];
lp_emit_fetch_texel_soa_callback emit_fetch_texel;
void *emit_fetch_texel_context;
struct lp_build_sampler_soa *sampler;
LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS];
LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS];
@ -289,8 +288,11 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
coords[i] = lp_build_mul(&bld->base, coords[i], oow);
}
bld->emit_fetch_texel(bld->base.builder, bld->emit_fetch_texel_context,
unit, num_coords, coords, lodbias, texel);
bld->sampler->emit_fetch_texel(bld->sampler,
bld->base.builder,
bld->base.type,
unit, num_coords, coords, lodbias,
texel);
FOR_EACH_DST0_ENABLED_CHANNEL( inst, i ) {
emit_store( bld, inst, 0, i, texel[i] );
@ -1283,8 +1285,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
const LLVMValueRef *pos,
const LLVMValueRef (*inputs)[NUM_CHANNELS],
LLVMValueRef (*outputs)[NUM_CHANNELS],
lp_emit_fetch_texel_soa_callback emit_fetch_texel,
void *emit_fetch_texel_context)
struct lp_build_sampler_soa *sampler)
{
struct lp_build_tgsi_soa_context bld;
struct tgsi_parse_context parse;
@ -1299,8 +1300,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
bld.inputs = inputs;
bld.outputs = outputs;
bld.consts_ptr = consts_ptr;
bld.emit_fetch_texel = emit_fetch_texel;
bld.emit_fetch_texel_context = emit_fetch_texel_context;
bld.sampler = sampler;
tgsi_parse_init( &parse, tokens );

View file

@ -85,6 +85,7 @@
#include "lp_context.h"
#include "lp_state.h"
#include "lp_quad.h"
#include "lp_tex_sample.h"
static const unsigned char quad_offset_x[4] = {0, 1, 0, 1};
@ -173,107 +174,6 @@ generate_depth(struct llvmpipe_context *lp,
}
struct build_fetch_texel_context
{
LLVMValueRef context_ptr;
LLVMValueRef samplers_ptr;
/** Coords/texels store */
LLVMValueRef store_ptr;
};
void PIPE_CDECL
lp_fetch_texel_soa( struct tgsi_sampler **samplers,
uint32_t unit,
float *store )
{
struct tgsi_sampler *sampler = samplers[unit];
#if 0
uint j;
debug_printf("%s sampler: %p (%p) store: %p\n",
__FUNCTION__,
sampler, *sampler,
store );
debug_printf("lodbias %f\n", store[12]);
for (j = 0; j < 4; j++)
debug_printf("sample %d texcoord %f %f\n",
j,
store[0+j],
store[4+j]);
#endif
{
float rgba[NUM_CHANNELS][QUAD_SIZE];
sampler->get_samples(sampler,
&store[0],
&store[4],
&store[8],
0.0f, /*store[12], lodbias */
rgba);
memcpy(store, rgba, sizeof rgba);
}
#if 0
for (j = 0; j < 4; j++)
debug_printf("sample %d result %f %f %f %f\n",
j,
store[0+j],
store[4+j],
store[8+j],
store[12+j]);
#endif
}
static void
emit_fetch_texel( LLVMBuilderRef builder,
void *context,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
LLVMValueRef lodbias,
LLVMValueRef *texel)
{
struct build_fetch_texel_context *bld = context;
LLVMTypeRef vec_type = LLVMTypeOf(coords[0]);
LLVMValueRef args[3];
unsigned i;
if(!bld->samplers_ptr)
bld->samplers_ptr = lp_jit_context_samplers(builder, bld->context_ptr);
if(!bld->store_ptr)
bld->store_ptr = LLVMBuildArrayAlloca(builder,
vec_type,
LLVMConstInt(LLVMInt32Type(), 4, 0),
"texel_store");
for (i = 0; i < num_coords; i++) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef coord_ptr = LLVMBuildGEP(builder, bld->store_ptr, &index, 1, "");
LLVMBuildStore(builder, coords[i], coord_ptr);
}
args[0] = bld->samplers_ptr;
args[1] = LLVMConstInt(LLVMInt32Type(), unit, 0);
args[2] = bld->store_ptr;
lp_build_intrinsic(builder, "fetch_texel", LLVMVoidType(), args, 3);
for (i = 0; i < NUM_CHANNELS; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef texel_ptr = LLVMBuildGEP(builder, bld->store_ptr, &index, 1, "");
texel[i] = LLVMBuildLoad(builder, texel_ptr, "");
}
}
/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
*/
@ -286,7 +186,7 @@ generate_fs(struct llvmpipe_context *lp,
LLVMValueRef context_ptr,
unsigned i,
const struct lp_build_interp_soa_context *interp,
struct build_fetch_texel_context *sampler,
struct lp_build_sampler_soa *sampler,
LLVMValueRef *pmask,
LLVMValueRef *color,
LLVMValueRef depth_ptr)
@ -327,7 +227,7 @@ generate_fs(struct llvmpipe_context *lp,
lp_build_tgsi_soa(builder, tokens, type, &mask,
consts_ptr, interp->pos, interp->inputs,
outputs, emit_fetch_texel, sampler);
outputs, sampler);
for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) {
for(chan = 0; chan < NUM_CHANNELS; ++chan) {
@ -462,7 +362,7 @@ generate_fragment(struct llvmpipe_context *lp,
LLVMBuilderRef builder;
LLVMValueRef x0;
LLVMValueRef y0;
struct build_fetch_texel_context sampler;
struct lp_build_sampler_soa *sampler;
struct lp_build_interp_soa_context interp;
LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH];
LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH];
@ -586,8 +486,7 @@ generate_fragment(struct llvmpipe_context *lp,
a0_ptr, dadx_ptr, dady_ptr,
x0, y0, 2, 0);
memset(&sampler, 0, sizeof sampler);
sampler.context_ptr = context_ptr;
sampler = lp_c_sampler_soa_create(context_ptr);
for(i = 0; i < num_fs; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
@ -606,7 +505,7 @@ generate_fragment(struct llvmpipe_context *lp,
context_ptr,
i,
&interp,
&sampler,
sampler,
&fs_mask[i],
out_color,
depth_ptr_i);
@ -615,6 +514,8 @@ generate_fragment(struct llvmpipe_context *lp,
fs_out_color[chan][i] = out_color[chan];
}
sampler->destroy(sampler);
/*
* Convert the fs's output color and mask to fit to the blending type.
*/

View file

@ -1578,3 +1578,136 @@ out:
tgsi_sampler->get_samples( tgsi_sampler, s, t, p, lodbias, rgba );
}
void PIPE_CDECL
lp_fetch_texel_soa( struct tgsi_sampler **samplers,
uint32_t unit,
float *store )
{
struct tgsi_sampler *sampler = samplers[unit];
#if 0
uint j;
debug_printf("%s sampler: %p (%p) store: %p\n",
__FUNCTION__,
sampler, *sampler,
store );
debug_printf("lodbias %f\n", store[12]);
for (j = 0; j < 4; j++)
debug_printf("sample %d texcoord %f %f\n",
j,
store[0+j],
store[4+j]);
#endif
{
float rgba[NUM_CHANNELS][QUAD_SIZE];
sampler->get_samples(sampler,
&store[0],
&store[4],
&store[8],
0.0f, /*store[12], lodbias */
rgba);
memcpy(store, rgba, sizeof rgba);
}
#if 0
for (j = 0; j < 4; j++)
debug_printf("sample %d result %f %f %f %f\n",
j,
store[0+j],
store[4+j],
store[8+j],
store[12+j]);
#endif
}
#include "lp_bld_type.h"
#include "lp_bld_intr.h"
#include "lp_bld_tgsi.h"
struct lp_c_sampler_soa
{
struct lp_build_sampler_soa base;
LLVMValueRef context_ptr;
LLVMValueRef samplers_ptr;
/** Coords/texels store */
LLVMValueRef store_ptr;
};
static void
lp_c_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
{
FREE(sampler);
}
static void
lp_c_sampler_soa_emit_fetch_texel(struct lp_build_sampler_soa *_sampler,
LLVMBuilderRef builder,
union lp_type type,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
LLVMValueRef lodbias,
LLVMValueRef *texel)
{
struct lp_c_sampler_soa *sampler = (struct lp_c_sampler_soa *)_sampler;
LLVMTypeRef vec_type = LLVMTypeOf(coords[0]);
LLVMValueRef args[3];
unsigned i;
if(!sampler->samplers_ptr)
sampler->samplers_ptr = lp_jit_context_samplers(builder, sampler->context_ptr);
if(!sampler->store_ptr)
sampler->store_ptr = LLVMBuildArrayAlloca(builder,
vec_type,
LLVMConstInt(LLVMInt32Type(), 4, 0),
"texel_store");
for (i = 0; i < num_coords; i++) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef coord_ptr = LLVMBuildGEP(builder, sampler->store_ptr, &index, 1, "");
LLVMBuildStore(builder, coords[i], coord_ptr);
}
args[0] = sampler->samplers_ptr;
args[1] = LLVMConstInt(LLVMInt32Type(), unit, 0);
args[2] = sampler->store_ptr;
lp_build_intrinsic(builder, "fetch_texel", LLVMVoidType(), args, 3);
for (i = 0; i < NUM_CHANNELS; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef texel_ptr = LLVMBuildGEP(builder, sampler->store_ptr, &index, 1, "");
texel[i] = LLVMBuildLoad(builder, texel_ptr, "");
}
}
struct lp_build_sampler_soa *
lp_c_sampler_soa_create(LLVMValueRef context_ptr)
{
struct lp_c_sampler_soa *sampler;
sampler = CALLOC_STRUCT(lp_c_sampler_soa);
if(!sampler)
return NULL;
sampler->base.destroy = lp_c_sampler_soa_destroy;
sampler->base.emit_fetch_texel = lp_c_sampler_soa_emit_fetch_texel;
sampler->context_ptr = context_ptr;
return &sampler->base;
}

View file

@ -29,6 +29,8 @@
#define LP_TEX_SAMPLE_H
#include <llvm-c/Core.h>
#include "tgsi/tgsi_exec.h"
@ -75,4 +77,14 @@ lp_get_samples(struct tgsi_sampler *tgsi_sampler,
float rgba[NUM_CHANNELS][QUAD_SIZE]);
/**
* Texture sampling code generator that just calls lp_get_samples C function
* for the actual sampling computation.
*
* @param context_ptr LLVM value with the pointer to the struct lp_jit_context.
*/
struct lp_build_sampler_soa *
lp_c_sampler_soa_create(LLVMValueRef context_ptr);
#endif /* LP_TEX_SAMPLE_H */