mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-16 00:40:32 +01:00
gallivm: checkpoint: nearest mipmap filtering
The LOD is computed from texcoord partial derivatives and used to select a mipmap level. Still some bugs in texel fetching. Lots of rough edges and unfinished parts but the basics are in place. Lots of changes to the lp_bld_arit.c code to support non-vector/scalar datatypes.
This commit is contained in:
parent
e0f10a6fca
commit
2ccae040a4
5 changed files with 601 additions and 292 deletions
|
|
@ -644,13 +644,26 @@ lp_build_abs(struct lp_build_context *bld,
|
|||
|
||||
if(type.floating) {
|
||||
/* Mask out the sign bit */
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
unsigned long long absMask = ~(1ULL << (type.width - 1));
|
||||
LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask));
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
|
||||
return a;
|
||||
if (type.length == 1) {
|
||||
LLVMTypeRef int_type = LLVMIntType(type.width);
|
||||
LLVMTypeRef float_type = LLVMFloatType();
|
||||
unsigned long long absMask = ~(1ULL << (type.width - 1));
|
||||
LLVMValueRef mask = LLVMConstInt(int_type, absMask, 0);
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_type, "");
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
a = LLVMBuildBitCast(bld->builder, a, float_type, "");
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
/* vector of floats */
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
unsigned long long absMask = ~(1ULL << (type.width - 1));
|
||||
LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask));
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) {
|
||||
|
|
@ -753,7 +766,7 @@ lp_build_set_sign(struct lp_build_context *bld,
|
|||
|
||||
|
||||
/**
|
||||
* Convert vector of int to vector of float.
|
||||
* Convert vector of (or scalar) int to vector of (or scalar) float.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_int_to_float(struct lp_build_context *bld,
|
||||
|
|
@ -764,7 +777,11 @@ lp_build_int_to_float(struct lp_build_context *bld,
|
|||
assert(type.floating);
|
||||
/*assert(lp_check_value(type, a));*/
|
||||
|
||||
{
|
||||
if (type.length == 1) {
|
||||
LLVMTypeRef float_type = LLVMFloatType();
|
||||
return LLVMBuildSIToFP(bld->builder, a, float_type, "");
|
||||
}
|
||||
else {
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
/*LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);*/
|
||||
LLVMValueRef res;
|
||||
|
|
@ -921,12 +938,18 @@ lp_build_itrunc(struct lp_build_context *bld,
|
|||
LLVMValueRef a)
|
||||
{
|
||||
const struct lp_type type = bld->type;
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
|
||||
assert(type.floating);
|
||||
assert(lp_check_value(type, a));
|
||||
|
||||
return LLVMBuildFPToSI(bld->builder, a, int_vec_type, "");
|
||||
if (type.length == 1) {
|
||||
LLVMTypeRef int_type = LLVMIntType(type.width);
|
||||
return LLVMBuildFPTrunc(bld->builder, a, int_type, "");
|
||||
}
|
||||
else {
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
assert(lp_check_value(type, a));
|
||||
return LLVMBuildFPToSI(bld->builder, a, int_vec_type, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -939,6 +962,15 @@ lp_build_iround(struct lp_build_context *bld,
|
|||
LLVMValueRef res;
|
||||
|
||||
assert(type.floating);
|
||||
|
||||
if (type.length == 1) {
|
||||
/* scalar float to int */
|
||||
LLVMTypeRef int_type = LLVMIntType(type.width);
|
||||
/* XXX we want rounding here! */
|
||||
res = LLVMBuildFPToSI(bld->builder, a, int_type, "");
|
||||
return res;
|
||||
}
|
||||
|
||||
assert(lp_check_value(type, a));
|
||||
|
||||
if(util_cpu_caps.has_sse4_1) {
|
||||
|
|
@ -1207,6 +1239,7 @@ lp_build_polynomial(struct lp_build_context *bld,
|
|||
unsigned num_coeffs)
|
||||
{
|
||||
const struct lp_type type = bld->type;
|
||||
LLVMTypeRef float_type = LLVMFloatType();
|
||||
LLVMValueRef res = NULL;
|
||||
unsigned i;
|
||||
|
||||
|
|
@ -1216,7 +1249,13 @@ lp_build_polynomial(struct lp_build_context *bld,
|
|||
__FUNCTION__);
|
||||
|
||||
for (i = num_coeffs; i--; ) {
|
||||
LLVMValueRef coeff = lp_build_const_scalar(type, coeffs[i]);
|
||||
LLVMValueRef coeff;
|
||||
|
||||
if (type.length == 1)
|
||||
coeff = LLVMConstReal(float_type, coeffs[i]);
|
||||
else
|
||||
coeff = lp_build_const_scalar(type, coeffs[i]);
|
||||
|
||||
if(res)
|
||||
res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res));
|
||||
else
|
||||
|
|
@ -1410,11 +1449,87 @@ lp_build_log2_approx(struct lp_build_context *bld,
|
|||
}
|
||||
|
||||
|
||||
/** scalar version of above function */
|
||||
static void
|
||||
lp_build_float_log2_approx(struct lp_build_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef *p_exp,
|
||||
LLVMValueRef *p_floor_log2,
|
||||
LLVMValueRef *p_log2)
|
||||
{
|
||||
const struct lp_type type = bld->type;
|
||||
LLVMTypeRef float_type = LLVMFloatType();
|
||||
LLVMTypeRef int_type = LLVMIntType(type.width);
|
||||
|
||||
LLVMValueRef expmask = LLVMConstInt(int_type, 0x7f800000, 0);
|
||||
LLVMValueRef mantmask = LLVMConstInt(int_type, 0x007fffff, 0);
|
||||
LLVMValueRef one = LLVMConstBitCast(bld->one, int_type);
|
||||
|
||||
LLVMValueRef i = NULL;
|
||||
LLVMValueRef exp = NULL;
|
||||
LLVMValueRef mant = NULL;
|
||||
LLVMValueRef logexp = NULL;
|
||||
LLVMValueRef logmant = NULL;
|
||||
LLVMValueRef res = NULL;
|
||||
|
||||
if(p_exp || p_floor_log2 || p_log2) {
|
||||
/* TODO: optimize the constant case */
|
||||
if(LLVMIsConstant(x))
|
||||
debug_printf("%s: inefficient/imprecise constant arithmetic\n",
|
||||
__FUNCTION__);
|
||||
|
||||
assert(type.floating && type.width == 32);
|
||||
|
||||
i = LLVMBuildBitCast(bld->builder, x, int_type, "");
|
||||
|
||||
/* exp = (float) exponent(x) */
|
||||
exp = LLVMBuildAnd(bld->builder, i, expmask, "");
|
||||
}
|
||||
|
||||
if(p_floor_log2 || p_log2) {
|
||||
LLVMValueRef c23 = LLVMConstInt(int_type, 23, 0);
|
||||
LLVMValueRef c127 = LLVMConstInt(int_type, 127, 0);
|
||||
logexp = LLVMBuildLShr(bld->builder, exp, c23, "");
|
||||
logexp = LLVMBuildSub(bld->builder, logexp, c127, "");
|
||||
logexp = LLVMBuildSIToFP(bld->builder, logexp, float_type, "");
|
||||
}
|
||||
|
||||
if(p_log2) {
|
||||
/* mant = (float) mantissa(x) */
|
||||
mant = LLVMBuildAnd(bld->builder, i, mantmask, "");
|
||||
mant = LLVMBuildOr(bld->builder, mant, one, "");
|
||||
mant = LLVMBuildBitCast(bld->builder, mant, float_type, "");
|
||||
|
||||
logmant = lp_build_polynomial(bld, mant, lp_build_log2_polynomial,
|
||||
Elements(lp_build_log2_polynomial));
|
||||
|
||||
/* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/
|
||||
logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), "");
|
||||
|
||||
res = LLVMBuildAdd(bld->builder, logmant, logexp, "");
|
||||
}
|
||||
|
||||
if(p_exp)
|
||||
*p_exp = exp;
|
||||
|
||||
if(p_floor_log2)
|
||||
*p_floor_log2 = logexp;
|
||||
|
||||
if(p_log2)
|
||||
*p_log2 = res;
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_log2(struct lp_build_context *bld,
|
||||
LLVMValueRef x)
|
||||
{
|
||||
LLVMValueRef res;
|
||||
lp_build_log2_approx(bld, x, NULL, NULL, &res);
|
||||
if (bld->type.length == 1) {
|
||||
lp_build_float_log2_approx(bld, x, NULL, NULL, &res);
|
||||
}
|
||||
else {
|
||||
lp_build_log2_approx(bld, x, NULL, NULL, &res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,10 +264,16 @@ lp_build_one(struct lp_type type)
|
|||
for(i = 1; i < type.length; ++i)
|
||||
elems[i] = elems[0];
|
||||
|
||||
return LLVMConstVector(elems, type.length);
|
||||
if (type.length == 1)
|
||||
return elems[0];
|
||||
else
|
||||
return LLVMConstVector(elems, type.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build constant-valued vector from a scalar value.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_const_scalar(struct lp_type type,
|
||||
double val)
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ lp_build_compare(LLVMBuilderRef builder,
|
|||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
} /* if (type.width * type.length == 128) */
|
||||
#endif
|
||||
|
||||
if(type.floating) {
|
||||
|
|
@ -238,20 +238,25 @@ lp_build_compare(LLVMBuilderRef builder,
|
|||
cond = LLVMBuildFCmp(builder, op, a, b, "");
|
||||
res = LLVMBuildSelect(builder, cond, ones, zeros, "");
|
||||
#else
|
||||
debug_printf("%s: warning: using slow element-wise vector comparison\n",
|
||||
__FUNCTION__);
|
||||
res = LLVMGetUndef(int_vec_type);
|
||||
for(i = 0; i < type.length; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
cond = LLVMBuildFCmp(builder, op,
|
||||
LLVMBuildExtractElement(builder, a, index, ""),
|
||||
LLVMBuildExtractElement(builder, b, index, ""),
|
||||
"");
|
||||
cond = LLVMBuildSelect(builder, cond,
|
||||
LLVMConstExtractElement(ones, index),
|
||||
LLVMConstExtractElement(zeros, index),
|
||||
"");
|
||||
res = LLVMBuildInsertElement(builder, res, cond, index, "");
|
||||
if (type.length == 1) {
|
||||
res = LLVMBuildFCmp(builder, op, a, b, "");
|
||||
}
|
||||
else {
|
||||
debug_printf("%s: warning: using slow element-wise float"
|
||||
" vector comparison\n", __FUNCTION__);
|
||||
for (i = 0; i < type.length; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
cond = LLVMBuildFCmp(builder, op,
|
||||
LLVMBuildExtractElement(builder, a, index, ""),
|
||||
LLVMBuildExtractElement(builder, b, index, ""),
|
||||
"");
|
||||
cond = LLVMBuildSelect(builder, cond,
|
||||
LLVMConstExtractElement(ones, index),
|
||||
LLVMConstExtractElement(zeros, index),
|
||||
"");
|
||||
res = LLVMBuildInsertElement(builder, res, cond, index, "");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -286,20 +291,26 @@ lp_build_compare(LLVMBuilderRef builder,
|
|||
cond = LLVMBuildICmp(builder, op, a, b, "");
|
||||
res = LLVMBuildSelect(builder, cond, ones, zeros, "");
|
||||
#else
|
||||
debug_printf("%s: warning: using slow element-wise int vector comparison\n",
|
||||
__FUNCTION__);
|
||||
res = LLVMGetUndef(int_vec_type);
|
||||
for(i = 0; i < type.length; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
cond = LLVMBuildICmp(builder, op,
|
||||
LLVMBuildExtractElement(builder, a, index, ""),
|
||||
LLVMBuildExtractElement(builder, b, index, ""),
|
||||
"");
|
||||
cond = LLVMBuildSelect(builder, cond,
|
||||
LLVMConstExtractElement(ones, index),
|
||||
LLVMConstExtractElement(zeros, index),
|
||||
"");
|
||||
res = LLVMBuildInsertElement(builder, res, cond, index, "");
|
||||
if (type.length == 1) {
|
||||
res = LLVMBuildICmp(builder, op, a, b, "");
|
||||
}
|
||||
else {
|
||||
debug_printf("%s: warning: using slow element-wise int"
|
||||
" vector comparison\n", __FUNCTION__);
|
||||
|
||||
for(i = 0; i < type.length; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
cond = LLVMBuildICmp(builder, op,
|
||||
LLVMBuildExtractElement(builder, a, index, ""),
|
||||
LLVMBuildExtractElement(builder, b, index, ""),
|
||||
"");
|
||||
cond = LLVMBuildSelect(builder, cond,
|
||||
LLVMConstExtractElement(ones, index),
|
||||
LLVMConstExtractElement(zeros, index),
|
||||
"");
|
||||
res = LLVMBuildInsertElement(builder, res, cond, index, "");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -339,26 +350,31 @@ lp_build_select(struct lp_build_context *bld,
|
|||
if(a == b)
|
||||
return a;
|
||||
|
||||
if(type.floating) {
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||
b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
|
||||
if (type.length == 1) {
|
||||
res = LLVMBuildSelect(bld->builder, mask, a, b, "");
|
||||
}
|
||||
else {
|
||||
if(type.floating) {
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||
b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
|
||||
}
|
||||
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
|
||||
/* This often gets translated to PANDN, but sometimes the NOT is
|
||||
* pre-computed and stored in another constant. The best strategy depends
|
||||
* on available registers, so it is not a big deal -- hopefully LLVM does
|
||||
* the right decision attending the rest of the program.
|
||||
*/
|
||||
b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), "");
|
||||
/* This often gets translated to PANDN, but sometimes the NOT is
|
||||
* pre-computed and stored in another constant. The best strategy depends
|
||||
* on available registers, so it is not a big deal -- hopefully LLVM does
|
||||
* the right decision attending the rest of the program.
|
||||
*/
|
||||
b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), "");
|
||||
|
||||
res = LLVMBuildOr(bld->builder, a, b, "");
|
||||
res = LLVMBuildOr(bld->builder, a, b, "");
|
||||
|
||||
if(type.floating) {
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
|
||||
if(type.floating) {
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ struct lp_build_sample_context
|
|||
|
||||
const struct util_format_description *format_desc;
|
||||
|
||||
/** regular scalar float type */
|
||||
struct lp_type float_type;
|
||||
struct lp_build_context float_bld;
|
||||
|
||||
/** regular scalar float type */
|
||||
struct lp_type int_type;
|
||||
struct lp_build_context int_bld;
|
||||
|
||||
/** Incoming coordinates type and build context */
|
||||
struct lp_type coord_type;
|
||||
struct lp_build_context coord_bld;
|
||||
|
|
@ -108,6 +116,27 @@ wrap_mode_uses_border_color(unsigned mode)
|
|||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_get_mipmap_level(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef data_array, LLVMValueRef level)
|
||||
{
|
||||
LLVMValueRef indexes[2], data_ptr;
|
||||
indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
indexes[1] = level;
|
||||
data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, "");
|
||||
data_ptr = LLVMBuildLoad(bld->builder, data_ptr, "");
|
||||
return data_ptr;
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_get_const_mipmap_level(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef data_array, int level)
|
||||
{
|
||||
LLVMValueRef lvl = LLVMConstInt(LLVMInt32Type(), level, 0);
|
||||
return lp_build_get_mipmap_level(bld, data_array, lvl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gen code to fetch a texel from a texture at int coords (x, y).
|
||||
|
|
@ -124,14 +153,13 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef x,
|
||||
LLVMValueRef y,
|
||||
LLVMValueRef y_stride,
|
||||
LLVMValueRef data_array,
|
||||
LLVMValueRef data_ptr,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef offset;
|
||||
LLVMValueRef packed;
|
||||
LLVMValueRef use_border = NULL;
|
||||
LLVMValueRef data_ptr;
|
||||
|
||||
/* use_border = x < 0 || x >= width || y < 0 || y >= height */
|
||||
if (wrap_mode_uses_border_color(bld->static_state->wrap_s)) {
|
||||
|
|
@ -154,16 +182,6 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
|
|||
}
|
||||
}
|
||||
|
||||
/* XXX always use mipmap level 0 for now */
|
||||
{
|
||||
const int level = 0;
|
||||
LLVMValueRef indexes[2];
|
||||
indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
indexes[1] = LLVMConstInt(LLVMInt32Type(), level, 0);
|
||||
data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, "");
|
||||
data_ptr = LLVMBuildLoad(bld->builder, data_ptr, "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: if we find an app which frequently samples the texture border
|
||||
* we might want to implement a true conditional here to avoid sampling
|
||||
|
|
@ -233,17 +251,8 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
|
|||
assert(bld->format_desc->block.height == 1);
|
||||
assert(bld->format_desc->block.bits <= bld->texel_type.width);
|
||||
|
||||
/* XXX always use mipmap level 0 for now */
|
||||
{
|
||||
const int level = 0;
|
||||
LLVMValueRef indexes[2];
|
||||
/* get data_ptr[level] */
|
||||
indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
indexes[1] = LLVMConstInt(LLVMInt32Type(), level, 0);
|
||||
data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, "");
|
||||
/* load texture base address */
|
||||
data_ptr = LLVMBuildLoad(bld->builder, data_ptr, "");
|
||||
}
|
||||
/* get pointer to mipmap level 0 data */
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
|
||||
|
||||
return lp_build_gather(bld->builder,
|
||||
bld->texel_type.length,
|
||||
|
|
@ -733,7 +742,210 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
|
|||
|
||||
|
||||
/**
|
||||
* Sample 2D texture with nearest filtering.
|
||||
* Codegen equivalent for u_minify().
|
||||
* Return max(1, base_size >> level);
|
||||
*/
|
||||
static LLVMValueRef
|
||||
lp_build_minify(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef base_size,
|
||||
LLVMValueRef level)
|
||||
{
|
||||
LLVMValueRef size = LLVMBuildAShr(bld->builder, base_size, level, "minify");
|
||||
size = lp_build_max(&bld->int_coord_bld, size, bld->int_coord_bld.one);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
texture_dims(enum pipe_texture_target tex)
|
||||
{
|
||||
switch (tex) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
return 1;
|
||||
case PIPE_TEXTURE_2D:
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
return 2;
|
||||
case PIPE_TEXTURE_3D:
|
||||
return 3;
|
||||
default:
|
||||
assert(0 && "bad texture target in texture_dims()");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate code to compute texture level of detail (lambda).
|
||||
* \param s vector of texcoord s values
|
||||
* \param t vector of texcoord t values
|
||||
* \param r vector of texcoord r values
|
||||
* \param width scalar int texture width
|
||||
* \param height scalar int texture height
|
||||
* \param depth scalar int texture depth
|
||||
*/
|
||||
static LLVMValueRef
|
||||
lp_build_lod_selector(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef s,
|
||||
LLVMValueRef t,
|
||||
LLVMValueRef r,
|
||||
LLVMValueRef width,
|
||||
LLVMValueRef height,
|
||||
LLVMValueRef depth)
|
||||
|
||||
{
|
||||
const int dims = texture_dims(bld->static_state->target);
|
||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||
struct lp_build_context *float_bld = &bld->float_bld;
|
||||
LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(), bld->static_state->lod_bias);
|
||||
LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod);
|
||||
LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->max_lod);
|
||||
|
||||
LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0);
|
||||
LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0);
|
||||
|
||||
LLVMValueRef s0, s1, s2;
|
||||
LLVMValueRef t0, t1, t2;
|
||||
LLVMValueRef r0, r1, r2;
|
||||
LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy;
|
||||
LLVMValueRef rho, lod;
|
||||
|
||||
/*
|
||||
* dsdx = abs(s[1] - s[0]);
|
||||
* dsdy = abs(s[2] - s[0]);
|
||||
* dtdx = abs(t[1] - t[0]);
|
||||
* dtdy = abs(t[2] - t[0]);
|
||||
* drdx = abs(r[1] - r[0]);
|
||||
* drdy = abs(r[2] - r[0]);
|
||||
* XXX we're assuming a four-element quad in 2x2 layout here.
|
||||
*/
|
||||
s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0");
|
||||
s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1");
|
||||
s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2");
|
||||
dsdx = LLVMBuildSub(bld->builder, s1, s0, "");
|
||||
dsdx = lp_build_abs(float_bld, dsdx);
|
||||
dsdy = LLVMBuildSub(bld->builder, s2, s0, "");
|
||||
dsdy = lp_build_abs(float_bld, dsdy);
|
||||
if (dims > 1) {
|
||||
t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0");
|
||||
t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1");
|
||||
t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2");
|
||||
dtdx = LLVMBuildSub(bld->builder, t1, t0, "");
|
||||
dtdx = lp_build_abs(float_bld, dtdx);
|
||||
dtdy = LLVMBuildSub(bld->builder, t2, t0, "");
|
||||
dtdy = lp_build_abs(float_bld, dtdy);
|
||||
if (dims > 2) {
|
||||
r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0");
|
||||
r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1");
|
||||
r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2");
|
||||
drdx = LLVMBuildSub(bld->builder, r1, r0, "");
|
||||
drdx = lp_build_abs(float_bld, drdx);
|
||||
drdy = LLVMBuildSub(bld->builder, r2, r0, "");
|
||||
drdy = lp_build_abs(float_bld, drdy);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute rho = max of all partial derivatives scaled by texture size.
|
||||
* XXX this could be vectorized somewhat
|
||||
*/
|
||||
rho = LLVMBuildMul(bld->builder,
|
||||
lp_build_max(float_bld, dsdx, dsdy),
|
||||
lp_build_int_to_float(float_bld, width), "");
|
||||
if (dims > 1) {
|
||||
LLVMValueRef max;
|
||||
max = LLVMBuildMul(bld->builder,
|
||||
lp_build_max(float_bld, dtdx, dtdy),
|
||||
lp_build_int_to_float(float_bld, height), "");
|
||||
rho = lp_build_max(float_bld, rho, max);
|
||||
if (dims > 2) {
|
||||
max = LLVMBuildMul(bld->builder,
|
||||
lp_build_max(float_bld, drdx, drdy),
|
||||
lp_build_int_to_float(float_bld, depth), "");
|
||||
rho = lp_build_max(float_bld, rho, max);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute lod = log2(rho) */
|
||||
lod = lp_build_log2(float_bld, rho);
|
||||
|
||||
/* add lod bias */
|
||||
lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias");
|
||||
|
||||
/* clamp lod */
|
||||
lod = lp_build_clamp(float_bld, lod, min_lod, max_lod);
|
||||
|
||||
return lod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For PIPE_TEX_MIPFILTER_NEAREST, convert float LOD to integer
|
||||
* mipmap level index.
|
||||
* Note: this is all scalar code.
|
||||
* \param lod scalar float texture level of detail
|
||||
* \param level_out returns integer
|
||||
*/
|
||||
static void
|
||||
lp_build_nearest_mip_level(struct lp_build_sample_context *bld,
|
||||
unsigned unit,
|
||||
LLVMValueRef lod,
|
||||
LLVMValueRef *level_out)
|
||||
{
|
||||
struct lp_build_context *float_bld = &bld->float_bld;
|
||||
struct lp_build_context *int_bld = &bld->int_bld;
|
||||
LLVMValueRef last_level, level;
|
||||
|
||||
LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
|
||||
last_level = bld->dynamic_state->last_level(bld->dynamic_state,
|
||||
bld->builder, unit);
|
||||
|
||||
/* convert float lod to integer */
|
||||
level = lp_build_iround(float_bld, lod);
|
||||
|
||||
/* clamp level to legal range of levels */
|
||||
*level_out = lp_build_clamp(int_bld, level, zero, last_level);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For PIPE_TEX_MIPFILTER_LINEAR, convert float LOD to integer to
|
||||
* two (adjacent) mipmap level indexes. Later, we'll sample from those
|
||||
* two mipmap levels and interpolate between them.
|
||||
*/
|
||||
static void
|
||||
lp_build_linear_mip_levels(struct lp_build_sample_context *bld,
|
||||
unsigned unit,
|
||||
LLVMValueRef lod,
|
||||
LLVMValueRef *level0_out,
|
||||
LLVMValueRef *level1_out,
|
||||
LLVMValueRef *weight_out)
|
||||
{
|
||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef last_level, level;
|
||||
|
||||
last_level = bld->dynamic_state->last_level(bld->dynamic_state,
|
||||
bld->builder, unit);
|
||||
|
||||
/* convert float lod to integer */
|
||||
level = lp_build_ifloor(coord_bld, lod);
|
||||
|
||||
/* compute level 0 and clamp to legal range of levels */
|
||||
*level0_out = lp_build_clamp(int_coord_bld, level,
|
||||
int_coord_bld->zero,
|
||||
last_level);
|
||||
/* compute level 1 and clamp to legal range of levels */
|
||||
*level1_out = lp_build_add(int_coord_bld, *level0_out, int_coord_bld->one);
|
||||
*level1_out = lp_build_min(int_coord_bld, *level1_out, int_coord_bld->zero);
|
||||
|
||||
*weight_out = lp_build_fract(coord_bld, lod);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sample 2D texture with nearest filtering, no mipmapping.
|
||||
*/
|
||||
static void
|
||||
lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
|
||||
|
|
@ -746,6 +958,7 @@ lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef *texel)
|
||||
{
|
||||
LLVMValueRef x, y;
|
||||
LLVMValueRef data_ptr;
|
||||
|
||||
x = lp_build_sample_wrap_nearest(bld, s, width,
|
||||
bld->static_state->pot_width,
|
||||
|
|
@ -757,7 +970,63 @@ lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
|
|||
lp_build_name(x, "tex.x.wrapped");
|
||||
lp_build_name(y, "tex.y.wrapped");
|
||||
|
||||
lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_array, texel);
|
||||
/* get pointer to mipmap level 0 data */
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
|
||||
|
||||
lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_ptr, texel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sample 2D texture with nearest filtering, nearest mipmap.
|
||||
*/
|
||||
static void
|
||||
lp_build_sample_2d_nearest_mip_nearest_soa(struct lp_build_sample_context *bld,
|
||||
unsigned unit,
|
||||
LLVMValueRef s,
|
||||
LLVMValueRef t,
|
||||
LLVMValueRef width,
|
||||
LLVMValueRef height,
|
||||
LLVMValueRef width_vec,
|
||||
LLVMValueRef height_vec,
|
||||
LLVMValueRef stride,
|
||||
LLVMValueRef data_array,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
LLVMValueRef x, y;
|
||||
LLVMValueRef lod, ilevel, ilevel_vec;
|
||||
LLVMValueRef data_ptr;
|
||||
|
||||
/* compute float LOD */
|
||||
lod = lp_build_lod_selector(bld, s, t, NULL, width, height, NULL);
|
||||
|
||||
/* convert LOD to int */
|
||||
lp_build_nearest_mip_level(bld, unit, lod, &ilevel);
|
||||
|
||||
ilevel_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel);
|
||||
|
||||
/* compute width_vec, height at mipmap level 'ilevel' */
|
||||
width_vec = lp_build_minify(bld, width_vec, ilevel_vec);
|
||||
height_vec = lp_build_minify(bld, height_vec, ilevel_vec);
|
||||
stride = lp_build_minify(bld, stride, ilevel_vec);
|
||||
|
||||
x = lp_build_sample_wrap_nearest(bld, s, width_vec,
|
||||
bld->static_state->pot_width,
|
||||
bld->static_state->wrap_s);
|
||||
y = lp_build_sample_wrap_nearest(bld, t, height_vec,
|
||||
bld->static_state->pot_height,
|
||||
bld->static_state->wrap_t);
|
||||
|
||||
lp_build_name(x, "tex.x.wrapped");
|
||||
lp_build_name(y, "tex.y.wrapped");
|
||||
|
||||
/* get pointer to mipmap level [ilevel] data */
|
||||
if (0)
|
||||
data_ptr = lp_build_get_mipmap_level(bld, data_array, ilevel);
|
||||
else
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
|
||||
|
||||
lp_build_sample_texel_soa(bld, width_vec, height_vec, x, y, stride, data_ptr, texel);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -779,6 +1048,7 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef x0, x1;
|
||||
LLVMValueRef y0, y1;
|
||||
LLVMValueRef neighbors[2][2][4];
|
||||
LLVMValueRef data_ptr;
|
||||
unsigned chan;
|
||||
|
||||
lp_build_sample_wrap_linear(bld, s, width, bld->static_state->pot_width,
|
||||
|
|
@ -786,10 +1056,13 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
|
|||
lp_build_sample_wrap_linear(bld, t, height, bld->static_state->pot_height,
|
||||
bld->static_state->wrap_t, &y0, &y1, &t_fpart);
|
||||
|
||||
lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_array, neighbors[0][0]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_array, neighbors[0][1]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_array, neighbors[1][0]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_array, neighbors[1][1]);
|
||||
/* get pointer to mipmap level 0 data */
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
|
||||
|
||||
lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_ptr, neighbors[0][0]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_ptr, neighbors[0][1]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_ptr, neighbors[1][0]);
|
||||
lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_ptr, neighbors[1][1]);
|
||||
|
||||
/* TODO: Don't interpolate missing channels */
|
||||
for(chan = 0; chan < 4; ++chan) {
|
||||
|
|
@ -857,7 +1130,7 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef packed, packed_lo, packed_hi;
|
||||
LLVMValueRef unswizzled[4];
|
||||
|
||||
lp_build_context_init(&i32, builder, lp_type_int(32));
|
||||
lp_build_context_init(&i32, builder, lp_type_int_vec(32));
|
||||
lp_build_context_init(&h16, builder, lp_type_ufixed(16));
|
||||
lp_build_context_init(&u8n, builder, lp_type_unorm(8));
|
||||
|
||||
|
|
@ -1066,194 +1339,11 @@ lp_build_sample_compare(struct lp_build_sample_context *bld,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
texture_dims(enum pipe_texture_target tex)
|
||||
{
|
||||
switch (tex) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
return 1;
|
||||
case PIPE_TEXTURE_2D:
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
return 2;
|
||||
case PIPE_TEXTURE_3D:
|
||||
return 3;
|
||||
default:
|
||||
assert(0 && "bad texture target in texture_dims()");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate code to compute texture level of detail (lambda).
|
||||
* \param s vector of texcoord s values
|
||||
* \param t vector of texcoord t values
|
||||
* \param r vector of texcoord r values
|
||||
* \param width scalar int texture width
|
||||
* \param height scalar int texture height
|
||||
* \param depth scalar int texture depth
|
||||
*/
|
||||
static LLVMValueRef
|
||||
lp_build_lod_selector(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef s,
|
||||
LLVMValueRef t,
|
||||
LLVMValueRef r,
|
||||
LLVMValueRef width,
|
||||
LLVMValueRef height,
|
||||
LLVMValueRef depth)
|
||||
|
||||
{
|
||||
const int dims = texture_dims(bld->static_state->target);
|
||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||
|
||||
LLVMValueRef lod_bias = lp_build_const_scalar(bld->coord_bld.type,
|
||||
bld->static_state->lod_bias);
|
||||
LLVMValueRef min_lod = lp_build_const_scalar(bld->coord_bld.type,
|
||||
bld->static_state->min_lod);
|
||||
LLVMValueRef max_lod = lp_build_const_scalar(bld->coord_bld.type,
|
||||
bld->static_state->max_lod);
|
||||
|
||||
LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0);
|
||||
LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0);
|
||||
|
||||
LLVMValueRef s0, s1, s2;
|
||||
LLVMValueRef t0, t1, t2;
|
||||
LLVMValueRef r0, r1, r2;
|
||||
LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy;
|
||||
LLVMValueRef rho, lod;
|
||||
|
||||
/*
|
||||
* dsdx = abs(s[1] - s[0]);
|
||||
* dsdy = abs(s[2] - s[0]);
|
||||
* dtdx = abs(t[1] - t[0]);
|
||||
* dtdy = abs(t[2] - t[0]);
|
||||
* drdx = abs(r[1] - r[0]);
|
||||
* drdy = abs(r[2] - r[0]);
|
||||
* XXX we're assuming a four-element quad in 2x2 layout here.
|
||||
*/
|
||||
s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0");
|
||||
s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1");
|
||||
s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2");
|
||||
dsdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, s1, s0));
|
||||
dsdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, s2, s0));
|
||||
if (dims > 1) {
|
||||
t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0");
|
||||
t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1");
|
||||
t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2");
|
||||
dtdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, t1, t0));
|
||||
dtdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, t2, t0));
|
||||
if (dims > 2) {
|
||||
r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0");
|
||||
r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1");
|
||||
r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2");
|
||||
drdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, r1, r0));
|
||||
drdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, r2, r0));
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute rho = max of all partial derivatives scaled by texture size.
|
||||
* XXX this can be vectorized somewhat
|
||||
*/
|
||||
rho = lp_build_mul(coord_bld,
|
||||
lp_build_max(coord_bld, dsdx, dsdy),
|
||||
lp_build_int_to_float(coord_bld, width));
|
||||
if (dims > 1) {
|
||||
LLVMValueRef max;
|
||||
max = lp_build_mul(coord_bld,
|
||||
lp_build_max(coord_bld, dtdx, dtdy),
|
||||
lp_build_int_to_float(coord_bld, height));
|
||||
rho = lp_build_max(coord_bld, rho, max);
|
||||
if (dims > 2) {
|
||||
max = lp_build_mul(coord_bld,
|
||||
lp_build_max(coord_bld, drdx, drdy),
|
||||
lp_build_int_to_float(coord_bld, depth));
|
||||
rho = lp_build_max(coord_bld, rho, max);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute lod = log2(rho) */
|
||||
lod = lp_build_log2(coord_bld, rho);
|
||||
|
||||
/* add lod bias */
|
||||
lod = lp_build_add(coord_bld, lod, lod_bias);
|
||||
|
||||
/* clamp lod */
|
||||
lod = lp_build_clamp(coord_bld, lod, min_lod, max_lod);
|
||||
|
||||
return lod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For PIPE_TEX_MIPFILTER_NEAREST, convert float LOD to integer
|
||||
* mipmap level index.
|
||||
* \param lod scalar float texture level of detail
|
||||
* \param level_out returns integer
|
||||
*/
|
||||
static void
|
||||
lp_build_nearest_mip_level(struct lp_build_sample_context *bld,
|
||||
unsigned unit,
|
||||
LLVMValueRef lod,
|
||||
LLVMValueRef *level_out)
|
||||
{
|
||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef last_level, level;
|
||||
|
||||
last_level = bld->dynamic_state->last_level(bld->dynamic_state,
|
||||
bld->builder, unit);
|
||||
|
||||
/* convert float lod to integer */
|
||||
level = lp_build_iround(coord_bld, lod);
|
||||
|
||||
/* clamp level to legal range of levels */
|
||||
*level_out = lp_build_clamp(int_coord_bld, level,
|
||||
int_coord_bld->zero,
|
||||
last_level);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For PIPE_TEX_MIPFILTER_LINEAR, convert float LOD to integer to
|
||||
* two (adjacent) mipmap level indexes. Later, we'll sample from those
|
||||
* two mipmap levels and interpolate between them.
|
||||
*/
|
||||
static void
|
||||
lp_build_linear_mip_levels(struct lp_build_sample_context *bld,
|
||||
unsigned unit,
|
||||
LLVMValueRef lod,
|
||||
LLVMValueRef *level0_out,
|
||||
LLVMValueRef *level1_out,
|
||||
LLVMValueRef *weight_out)
|
||||
{
|
||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef last_level, level;
|
||||
|
||||
last_level = bld->dynamic_state->last_level(bld->dynamic_state,
|
||||
bld->builder, unit);
|
||||
|
||||
/* convert float lod to integer */
|
||||
level = lp_build_ifloor(coord_bld, lod);
|
||||
|
||||
/* compute level 0 and clamp to legal range of levels */
|
||||
*level0_out = lp_build_clamp(int_coord_bld, level,
|
||||
int_coord_bld->zero,
|
||||
last_level);
|
||||
/* compute level 1 and clamp to legal range of levels */
|
||||
*level1_out = lp_build_add(int_coord_bld, *level0_out, int_coord_bld->one);
|
||||
*level1_out = lp_build_min(int_coord_bld, *level1_out, int_coord_bld->zero);
|
||||
|
||||
*weight_out = lp_build_fract(coord_bld, lod);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Build texture sampling code.
|
||||
* 'texel' will return a vector of four LLVMValueRefs corresponding to
|
||||
* R, G, B, A.
|
||||
* \param type vector float type to use for coords, etc.
|
||||
*/
|
||||
void
|
||||
lp_build_sample_soa(LLVMBuilderRef builder,
|
||||
|
|
@ -1267,17 +1357,19 @@ lp_build_sample_soa(LLVMBuilderRef builder,
|
|||
LLVMValueRef *texel)
|
||||
{
|
||||
struct lp_build_sample_context bld;
|
||||
LLVMValueRef width;
|
||||
LLVMValueRef height;
|
||||
LLVMValueRef stride;
|
||||
LLVMValueRef width, width_vec;
|
||||
LLVMValueRef height, height_vec;
|
||||
LLVMValueRef stride, stride_vec;
|
||||
LLVMValueRef data_array;
|
||||
LLVMValueRef s;
|
||||
LLVMValueRef t;
|
||||
LLVMValueRef r;
|
||||
boolean done = FALSE;
|
||||
|
||||
(void) lp_build_lod_selector; /* temporary to silence warning */
|
||||
(void) lp_build_nearest_mip_level;
|
||||
(void) lp_build_linear_mip_levels;
|
||||
(void) lp_build_minify;
|
||||
|
||||
/* Setup our build context */
|
||||
memset(&bld, 0, sizeof bld);
|
||||
|
|
@ -1285,10 +1377,16 @@ lp_build_sample_soa(LLVMBuilderRef builder,
|
|||
bld.static_state = static_state;
|
||||
bld.dynamic_state = dynamic_state;
|
||||
bld.format_desc = util_format_description(static_state->format);
|
||||
|
||||
bld.float_type = lp_type_float(32);
|
||||
bld.int_type = lp_type_int(32);
|
||||
bld.coord_type = type;
|
||||
bld.uint_coord_type = lp_uint_type(type);
|
||||
bld.int_coord_type = lp_int_type(type);
|
||||
bld.texel_type = type;
|
||||
|
||||
lp_build_context_init(&bld.float_bld, builder, bld.float_type);
|
||||
lp_build_context_init(&bld.int_bld, builder, bld.int_type);
|
||||
lp_build_context_init(&bld.coord_bld, builder, bld.coord_type);
|
||||
lp_build_context_init(&bld.uint_coord_bld, builder, bld.uint_coord_type);
|
||||
lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type);
|
||||
|
|
@ -1305,30 +1403,56 @@ lp_build_sample_soa(LLVMBuilderRef builder,
|
|||
t = coords[1];
|
||||
r = coords[2];
|
||||
|
||||
width = lp_build_broadcast_scalar(&bld.uint_coord_bld, width);
|
||||
height = lp_build_broadcast_scalar(&bld.uint_coord_bld, height);
|
||||
stride = lp_build_broadcast_scalar(&bld.uint_coord_bld, stride);
|
||||
width_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, width);
|
||||
height_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, height);
|
||||
stride_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, stride);
|
||||
|
||||
if(static_state->target == PIPE_TEXTURE_1D)
|
||||
t = bld.coord_bld.zero;
|
||||
|
||||
switch (static_state->min_img_filter) {
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
lp_build_sample_2d_nearest_soa(&bld, s, t, width, height,
|
||||
stride, data_array, texel);
|
||||
switch (static_state->min_mip_filter) {
|
||||
case PIPE_TEX_MIPFILTER_NONE:
|
||||
break;
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
if(lp_format_is_rgba8(bld.format_desc) &&
|
||||
is_simple_wrap_mode(static_state->wrap_s) &&
|
||||
is_simple_wrap_mode(static_state->wrap_t))
|
||||
lp_build_sample_2d_linear_aos(&bld, s, t, width, height,
|
||||
stride, data_array, texel);
|
||||
else
|
||||
lp_build_sample_2d_linear_soa(&bld, s, t, width, height,
|
||||
stride, data_array, texel);
|
||||
case PIPE_TEX_MIPFILTER_NEAREST:
|
||||
|
||||
switch (static_state->min_img_filter) {
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
lp_build_sample_2d_nearest_mip_nearest_soa(&bld, unit,
|
||||
s, t,
|
||||
width, height,
|
||||
width_vec, height_vec,
|
||||
stride_vec,
|
||||
data_array, texel);
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case PIPE_TEX_MIPFILTER_LINEAR:
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
assert(0 && "invalid mip filter");
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
switch (static_state->min_img_filter) {
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
lp_build_sample_2d_nearest_soa(&bld, s, t, width_vec, height_vec,
|
||||
stride_vec, data_array, texel);
|
||||
break;
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
if(lp_format_is_rgba8(bld.format_desc) &&
|
||||
is_simple_wrap_mode(static_state->wrap_s) &&
|
||||
is_simple_wrap_mode(static_state->wrap_t))
|
||||
lp_build_sample_2d_linear_aos(&bld, s, t, width_vec, height_vec,
|
||||
stride_vec, data_array, texel);
|
||||
else
|
||||
lp_build_sample_2d_linear_soa(&bld, s, t, width_vec, height_vec,
|
||||
stride_vec, data_array, texel);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: respect static_state->min_mip_filter */;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ struct lp_type {
|
|||
unsigned width:14;
|
||||
|
||||
/**
|
||||
* Vector length.
|
||||
* Vector length. If length==1, this is a scalar (float/int) type.
|
||||
*
|
||||
* width*length should be a power of two greater or equal to eight.
|
||||
*
|
||||
|
|
@ -139,11 +139,28 @@ struct lp_build_context
|
|||
};
|
||||
|
||||
|
||||
/** Create scalar float type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_float(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.floating = TRUE;
|
||||
res_type.sign = TRUE;
|
||||
res_type.width = width;
|
||||
res_type.length = 1;
|
||||
|
||||
return res_type;
|
||||
}
|
||||
|
||||
|
||||
/** Create vector of float type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_float_vec(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.floating = TRUE;
|
||||
res_type.sign = TRUE;
|
||||
|
|
@ -154,11 +171,27 @@ lp_type_float(unsigned width)
|
|||
}
|
||||
|
||||
|
||||
/** Create scalar int type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_int(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.sign = TRUE;
|
||||
res_type.width = width;
|
||||
res_type.length = 1;
|
||||
|
||||
return res_type;
|
||||
}
|
||||
|
||||
|
||||
/** Create vector int type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_int_vec(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.sign = TRUE;
|
||||
res_type.width = width;
|
||||
|
|
@ -168,11 +201,26 @@ lp_type_int(unsigned width)
|
|||
}
|
||||
|
||||
|
||||
/** Create scalar uint type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_uint(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.width = width;
|
||||
res_type.length = 1;
|
||||
|
||||
return res_type;
|
||||
}
|
||||
|
||||
|
||||
/** Create vector uint type */
|
||||
static INLINE struct lp_type
|
||||
lp_type_uint_vec(unsigned width)
|
||||
{
|
||||
struct lp_type res_type;
|
||||
|
||||
memset(&res_type, 0, sizeof res_type);
|
||||
res_type.width = width;
|
||||
res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue