diff options
author | Dave Airlie <[email protected]> | 2012-11-03 20:51:45 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2012-11-09 10:29:26 +1000 |
commit | 309fda2fb28dfe7e8b9be31806346125bef13b21 (patch) | |
tree | 97259d4e5a5a0971dc13d1e4e493916c066c9ce0 /src/gallium/drivers | |
parent | 8c0ccce30038f5d28e74f7f4b5b5c0bbd8ac6dbe (diff) |
softpipe: add ARB_texture_cube_map_array support (v1.1)
This adds support to the softpipe texture sampler and tgsi exec.
In order to handle the extra input to the texture sampling,
I've had to expand the interfaces to take a c1 value for storing
the texture compare value for the TEX2 case.
v1.1: add comments (Brian)
Reviewed-by: Brian Paul <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_screen.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.c | 172 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_texture.c | 4 |
4 files changed, 171 insertions, 14 deletions
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 5051462bf12..3a38182994c 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -169,6 +169,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return 0; case PIPE_CAP_QUERY_TIMESTAMP: + case PIPE_CAP_CUBE_MAP_ARRAY: return 1; } /* should only get here on unhandled cases */ @@ -279,7 +280,8 @@ softpipe_is_format_supported( struct pipe_screen *screen, target == PIPE_TEXTURE_2D_ARRAY || target == PIPE_TEXTURE_RECT || target == PIPE_TEXTURE_3D || - target == PIPE_TEXTURE_CUBE); + target == PIPE_TEXTURE_CUBE || + target == PIPE_TEXTURE_CUBE_ARRAY); format_desc = util_format_description(format); if (!format_desc) diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 992a2f760f8..5bbf11cb0ad 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -739,6 +739,25 @@ get_texel_2d_array(const struct sp_sampler_variant *samp, } +/* Get texel pointer for cube array texture */ +static INLINE const float * +get_texel_cube_array(const struct sp_sampler_variant *samp, + union tex_tile_address addr, int x, int y, int layer) +{ + const struct pipe_resource *texture = samp->view->texture; + unsigned level = addr.bits.level; + + assert(layer < (int) texture->array_size); + assert(layer >= 0); + + if (x < 0 || x >= (int) u_minify(texture->width0, level) || + y < 0 || y >= (int) u_minify(texture->height0, level)) { + return samp->sampler->border_color.f; + } + else { + return get_texel_3d_no_border(samp, addr, x, y, layer); + } +} /** * Given the logbase2 of a mipmap's base level size and a mipmap level, * return the size (in texels) of that mipmap level. @@ -1123,6 +1142,45 @@ img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler, } } +static void +img_filter_cube_array_nearest(struct tgsi_sampler *tgsi_sampler, + float s, + float t, + float p, + unsigned level, + unsigned face_id, + enum tgsi_sampler_control control, + float *rgba) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + int width, height; + int x, y, layer; + union tex_tile_address addr; + const float *out; + int c; + + width = u_minify(texture->width0, level); + height = u_minify(texture->height0, level); + + assert(width > 0); + assert(height > 0); + + addr.value = 0; + addr.bits.level = level; + + samp->nearest_texcoord_s(s, width, &x); + samp->nearest_texcoord_t(t, height, &y); + wrap_array_layer(p, texture->array_size, &layer); + + out = get_texel_cube_array(samp, addr, x, y, layer * 6 + face_id); + for (c = 0; c < TGSI_QUAD_SIZE; c++) + rgba[TGSI_NUM_CHANNELS*c] = out[c]; + + if (DEBUG_TEX) { + print_sample(__FUNCTION__, rgba); + } +} static void img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, @@ -1373,6 +1431,50 @@ img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, static void +img_filter_cube_array_linear(struct tgsi_sampler *tgsi_sampler, + float s, + float t, + float p, + unsigned level, + unsigned face_id, + enum tgsi_sampler_control control, + float *rgba) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + int width, height; + int x0, y0, x1, y1, layer; + float xw, yw; /* weights */ + union tex_tile_address addr, addrj; + const float *tx0, *tx1, *tx2, *tx3; + int c; + + width = u_minify(texture->width0, level); + height = u_minify(texture->height0, level); + + assert(width > 0); + assert(height > 0); + + addr.value = 0; + addr.bits.level = level; + + samp->linear_texcoord_s(s, width, &x0, &x1, &xw); + samp->linear_texcoord_t(t, height, &y0, &y1, &yw); + wrap_array_layer(p, texture->array_size, &layer); + + tx0 = get_texel_cube_array(samp, addr, x0, y0, layer * 6 + face_id); + tx1 = get_texel_cube_array(samp, addr, x1, y0, layer * 6 + face_id); + tx2 = get_texel_cube_array(samp, addr, x0, y1, layer * 6 + face_id); + tx3 = get_texel_cube_array(samp, addr, x1, y1, layer * 6 + face_id); + + /* interpolate R, G, B, A */ + for (c = 0; c < TGSI_QUAD_SIZE; c++) + rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, + tx0[c], tx1[c], + tx2[c], tx3[c]); +} + +static void img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, float s, float t, @@ -1451,6 +1553,7 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1461,11 +1564,18 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, if (control == tgsi_sampler_lod_bias) { float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; - compute_lod(samp->sampler, lambda, c0, lod); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + compute_lod(samp->sampler, lambda, c1, lod); + else + compute_lod(samp->sampler, lambda, c0, lod); } else { assert(control == tgsi_sampler_lod_explicit); - memcpy(lod, c0, sizeof(lod)); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + memcpy(lod, c1, sizeof(lod)); + else + memcpy(lod, c0, sizeof(lod)); + } for (j = 0; j < TGSI_QUAD_SIZE; j++) { @@ -1508,6 +1618,7 @@ mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1518,11 +1629,17 @@ mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, if (control == tgsi_sampler_lod_bias) { float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; - compute_lod(samp->sampler, lambda, c0, lod); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + compute_lod(samp->sampler, lambda, c1, lod); + else + compute_lod(samp->sampler, lambda, c0, lod); } else { assert(control == tgsi_sampler_lod_explicit); - memcpy(lod, c0, sizeof(lod)); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + memcpy(lod, c1, sizeof(lod)); + else + memcpy(lod, c0, sizeof(lod)); } for (j = 0; j < TGSI_QUAD_SIZE; j++) { @@ -1547,6 +1664,7 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1556,11 +1674,17 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler, if (control == tgsi_sampler_lod_bias) { float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; - compute_lod(samp->sampler, lambda, c0, lod); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + compute_lod(samp->sampler, lambda, c1, lod); + else + compute_lod(samp->sampler, lambda, c0, lod); } else { assert(control == tgsi_sampler_lod_explicit); - memcpy(lod, c0, sizeof(lod)); + if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) + memcpy(lod, c1, sizeof(lod)); + else + memcpy(lod, c0, sizeof(lod)); } for (j = 0; j < TGSI_QUAD_SIZE; j++) { @@ -1580,6 +1704,7 @@ mip_filter_none_no_filter_select(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1814,6 +1939,7 @@ mip_filter_linear_aniso(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1913,6 +2039,7 @@ mip_filter_linear_2d_linear_repeat_POT( const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1971,6 +2098,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -1980,7 +2108,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, float val; float pc0, pc1, pc2, pc3; - samp->mip_filter(tgsi_sampler, s, t, p, c0, control, rgba); + samp->mip_filter(tgsi_sampler, s, t, p, c0, c1, control, rgba); /** * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' @@ -1995,6 +2123,11 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, pc1 = CLAMP(c0[1], 0.0F, 1.0F); pc2 = CLAMP(c0[2], 0.0F, 1.0F); pc3 = CLAMP(c0[3], 0.0F, 1.0F); + } else if (samp->view->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { + pc0 = CLAMP(c1[0], 0.0F, 1.0F); + pc1 = CLAMP(c1[1], 0.0F, 1.0F); + pc2 = CLAMP(c1[2], 0.0F, 1.0F); + pc3 = CLAMP(c1[3], 0.0F, 1.0F); } else { pc0 = CLAMP(p[0], 0.0F, 1.0F); pc1 = CLAMP(p[1], 0.0F, 1.0F); @@ -2081,6 +2214,7 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { @@ -2091,8 +2225,12 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, /* Not actually used, but the intermediate steps that do the * dereferencing don't know it. */ - static const float pppp[4] = { 0, 0, 0, 0 }; + static float pppp[4] = { 0, 0, 0, 0 }; + pppp[0] = c0[0]; + pppp[1] = c0[1]; + pppp[2] = c0[2]; + pppp[3] = c0[3]; /* major axis direction target sc tc ma @@ -2160,7 +2298,7 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, * is not active, this will point somewhere deeper into the * pipeline, eg. to mip_filter or even img_filter. */ - samp->compare(tgsi_sampler, ssss, tttt, pppp, c0, control, rgba); + samp->compare(tgsi_sampler, ssss, tttt, pppp, c0, c1, control, rgba); } @@ -2243,13 +2381,14 @@ sample_swizzle(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) { struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; - samp->sample_target(tgsi_sampler, s, t, p, c0, control, rgba_temp); + samp->sample_target(tgsi_sampler, s, t, p, c0, c1, control, rgba_temp); do_swizzling(samp, rgba_temp, rgba); } @@ -2370,6 +2509,7 @@ get_lambda_func(const union sp_sampler_key key) case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_CUBE_ARRAY: return compute_lambda_2d; case PIPE_TEXTURE_3D: return compute_lambda_3d; @@ -2445,6 +2585,12 @@ get_img_filter(const union sp_sampler_key key, else return img_filter_cube_linear; break; + case PIPE_TEXTURE_CUBE_ARRAY: + if (filter == PIPE_TEX_FILTER_NEAREST) + return img_filter_cube_array_nearest; + else + return img_filter_cube_array_linear; + break; case PIPE_TEXTURE_3D: if (filter == PIPE_TEX_FILTER_NEAREST) return img_filter_3d_nearest; @@ -2516,6 +2662,10 @@ sample_get_dims(struct tgsi_sampler *tgsi_sampler, int level, dims[1] = u_minify(texture->height0, level); dims[2] = u_minify(texture->depth0, level); return; + case PIPE_TEXTURE_CUBE_ARRAY: + dims[1] = u_minify(texture->height0, level); + dims[2] = texture->array_size / 6; + return; default: assert(!"unexpected texture target in sample_get_dims()"); return; @@ -2722,7 +2872,7 @@ sp_create_sampler_variant( const struct pipe_sampler_state *sampler, samp->compare = samp->mip_filter; } - if (key.bits.target == PIPE_TEXTURE_CUBE) { + if (key.bits.target == PIPE_TEXTURE_CUBE || key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) { samp->sample_target = sample_cube; } else { diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h index dd847af69d7..8415196dfbd 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.h +++ b/src/gallium/drivers/softpipe/sp_tex_sample.h @@ -63,13 +63,14 @@ typedef void (*filter_func)(struct tgsi_sampler *tgsi_sampler, const float t[TGSI_QUAD_SIZE], const float p[TGSI_QUAD_SIZE], const float c0[TGSI_QUAD_SIZE], + const float c1[TGSI_QUAD_SIZE], enum tgsi_sampler_control control, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]); union sp_sampler_key { struct { - unsigned target:3; + unsigned target:5; unsigned is_pot:1; unsigned processor:2; unsigned unit:4; @@ -77,7 +78,7 @@ union sp_sampler_key { unsigned swizzle_g:3; unsigned swizzle_b:3; unsigned swizzle_a:3; - unsigned pad:10; + unsigned pad:8; } bits; unsigned value; }; diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index b4bca076bda..9c31daa63f3 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -258,6 +258,7 @@ 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_CUBE_ARRAY || spr->base.target == PIPE_TEXTURE_3D || spr->base.target == PIPE_TEXTURE_2D_ARRAY) { offset += layer * nblocksy * spr->stride[level]; @@ -364,6 +365,9 @@ softpipe_transfer_map(struct pipe_context *pipe, else if (resource->target == PIPE_TEXTURE_CUBE) { assert(box->z < 6); } + else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) { + assert(box->z <= resource->array_size); + } else { assert(box->z + box->depth <= (u_minify(resource->depth0, level))); } |