mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-01 13:20:25 +01:00
llvmpipe: Further abstract the texture sampling generation from TGSI translation.
This commit is contained in:
parent
970823978c
commit
8be72bb764
5 changed files with 186 additions and 125 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue