softpipe: support for 1D/2D texture arrays

This commit is contained in:
Brian Paul
2011-01-25 20:27:10 -07:00
parent 9b56a2cb62
commit 779e9cb658
3 changed files with 210 additions and 1 deletions

View File

@@ -125,6 +125,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1;
case PIPE_CAP_INSTANCED_DRAWING:
return 1;
case PIPE_CAP_ARRAY_TEXTURES:
return 1;
default:
return 0;
}
@@ -185,7 +187,9 @@ softpipe_is_format_supported( struct pipe_screen *screen,
assert(target == PIPE_BUFFER ||
target == PIPE_TEXTURE_1D ||
target == PIPE_TEXTURE_1D_ARRAY ||
target == PIPE_TEXTURE_2D ||
target == PIPE_TEXTURE_2D_ARRAY ||
target == PIPE_TEXTURE_RECT ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE);

View File

@@ -539,6 +539,19 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size,
}
/**
* Do coordinate to array index conversion. For array textures.
*/
static INLINE void
wrap_array_layer(const float coord[4], unsigned size, int layer[4])
{
uint ch;
for (ch = 0; ch < 4; ch++) {
int c = util_ifloor(coord[ch] + 0.5F);
layer[ch] = CLAMP(c, 0, size - 1);
}
}
/**
* Examine the quad's texture coordinates to compute the partial
@@ -989,6 +1002,47 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
}
static void
img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
const float c0[QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
const struct pipe_resource *texture = samp->view->texture;
unsigned level0, j;
int width;
int x[4], layer[4];
union tex_tile_address addr;
level0 = samp->level;
width = u_minify(texture->width0, level0);
assert(width > 0);
addr.value = 0;
addr.bits.level = samp->level;
samp->nearest_texcoord_s(s, width, x);
wrap_array_layer(t, texture->height0, layer);
for (j = 0; j < QUAD_SIZE; j++) {
const float *out = get_texel_2d(samp, addr, x[j], layer[j]);
int c;
for (c = 0; c < 4; c++) {
rgba[c][j] = out[c];
}
}
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
static void
img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
@@ -1033,6 +1087,50 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
}
static void
img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
const float c0[QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
const struct pipe_resource *texture = samp->view->texture;
unsigned level0, j;
int width, height;
int x[4], y[4], layer[4];
union tex_tile_address addr;
level0 = samp->level;
width = u_minify(texture->width0, level0);
height = u_minify(texture->height0, level0);
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = samp->level;
samp->nearest_texcoord_s(s, width, x);
samp->nearest_texcoord_t(t, height, y);
wrap_array_layer(p, texture->depth0, layer);
for (j = 0; j < QUAD_SIZE; j++) {
const float *out = get_texel_3d(samp, addr, x[j], y[j], layer[j]);
int c;
for (c = 0; c < 4; c++) {
rgba[c][j] = out[c];
}
}
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
static INLINE union tex_tile_address
face(union tex_tile_address addr, unsigned face )
{
@@ -1167,6 +1265,47 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
}
static void
img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
const float c0[QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
const struct pipe_resource *texture = samp->view->texture;
unsigned level0, j;
int width;
int x0[4], x1[4], layer[4];
float xw[4]; /* weights */
union tex_tile_address addr;
level0 = samp->level;
width = u_minify(texture->width0, level0);
assert(width > 0);
addr.value = 0;
addr.bits.level = samp->level;
samp->linear_texcoord_s(s, width, x0, x1, xw);
wrap_array_layer(t, texture->height0, layer);
for (j = 0; j < QUAD_SIZE; j++) {
const float *tx0 = get_texel_2d(samp, addr, x0[j], layer[j]);
const float *tx1 = get_texel_2d(samp, addr, x1[j], layer[j]);
int c;
/* interpolate R, G, B, A */
for (c = 0; c < 4; c++) {
rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
}
}
}
static void
img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
@@ -1214,6 +1353,54 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
}
static void
img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
const float c0[QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
const struct pipe_resource *texture = samp->view->texture;
unsigned level0, j;
int width, height;
int x0[4], y0[4], x1[4], y1[4], layer[4];
float xw[4], yw[4]; /* weights */
union tex_tile_address addr;
level0 = samp->level;
width = u_minify(texture->width0, level0);
height = u_minify(texture->height0, level0);
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = samp->level;
samp->linear_texcoord_s(s, width, x0, x1, xw);
samp->linear_texcoord_t(t, height, y0, y1, yw);
wrap_array_layer(p, texture->depth0, layer);
for (j = 0; j < QUAD_SIZE; j++) {
const float *tx0 = get_texel_3d(samp, addr, x0[j], y0[j], layer[j]);
const float *tx1 = get_texel_3d(samp, addr, x1[j], y0[j], layer[j]);
const float *tx2 = get_texel_3d(samp, addr, x0[j], y1[j], layer[j]);
const float *tx3 = get_texel_3d(samp, addr, x1[j], y1[j], layer[j]);
int c;
/* interpolate R, G, B, A */
for (c = 0; c < 4; c++) {
rgba[c][j] = lerp_2d(xw[j], yw[j],
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
}
}
static void
img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
@@ -1906,8 +2093,10 @@ get_lambda_func(const union sp_sampler_key key)
switch (key.bits.target) {
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY:
return compute_lambda_1d;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
return compute_lambda_2d;
@@ -1932,6 +2121,12 @@ get_img_filter(const union sp_sampler_key key,
else
return img_filter_1d_linear;
break;
case PIPE_TEXTURE_1D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_1d_array_nearest;
else
return img_filter_1d_array_linear;
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
/* Try for fast path:
@@ -1967,6 +2162,12 @@ get_img_filter(const union sp_sampler_key key,
else
return img_filter_2d_linear;
break;
case PIPE_TEXTURE_2D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_2d_array_nearest;
else
return img_filter_2d_array_linear;
break;
case PIPE_TEXTURE_CUBE:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_nearest;

View File

@@ -227,9 +227,13 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr,
unsigned offset = spr->level_offset[level];
if (spr->base.target == PIPE_TEXTURE_CUBE ||
spr->base.target == PIPE_TEXTURE_3D) {
spr->base.target == PIPE_TEXTURE_3D ||
spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
offset += layer * nblocksy * spr->stride[level];
}
else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
offset += layer * spr->stride[level];
}
else {
assert(layer == 0);
}