mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-02 11:00:27 +01:00
cell: initial work for mipmap texture filtering
This commit is contained in:
parent
b0c136cfb1
commit
978799beb2
10 changed files with 178 additions and 79 deletions
|
|
@ -67,6 +67,7 @@
|
|||
#define CELL_MAX_SPUS 6
|
||||
|
||||
#define CELL_MAX_SAMPLERS 4
|
||||
#define CELL_MAX_TEXTURE_LEVELS 12 /* 2k x 2k */
|
||||
|
||||
#define TILE_SIZE 32
|
||||
|
||||
|
|
@ -251,8 +252,9 @@ struct cell_command_texture
|
|||
{
|
||||
uint64_t opcode; /**< CELL_CMD_STATE_TEXTURE */
|
||||
uint unit;
|
||||
void *start; /**< Address in main memory */
|
||||
ushort width, height;
|
||||
void *start[CELL_MAX_TEXTURE_LEVELS]; /**< Address in main memory */
|
||||
ushort width[CELL_MAX_TEXTURE_LEVELS];
|
||||
ushort height[CELL_MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ cell_get_param(struct pipe_screen *screen, int param)
|
|||
case PIPE_CAP_TEXTURE_SHADOW_MAP:
|
||||
return 10;
|
||||
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
|
||||
return 12; /* max 2Kx2K */
|
||||
return CELL_MAX_TEXTURE_LEVELS;
|
||||
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
|
||||
return 8; /* max 128x128x128 */
|
||||
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
|
||||
return 12; /* max 2Kx2K */
|
||||
return CELL_MAX_TEXTURE_LEVELS;
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,14 +211,20 @@ cell_emit_state(struct cell_context *cell)
|
|||
texture->opcode = CELL_CMD_STATE_TEXTURE;
|
||||
texture->unit = i;
|
||||
if (cell->texture[i]) {
|
||||
texture->start = cell->texture[i]->tiled_data;
|
||||
texture->width = cell->texture[i]->base.width[0];
|
||||
texture->height = cell->texture[i]->base.height[0];
|
||||
uint level;
|
||||
for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
|
||||
texture->start[level] = cell->texture[i]->tiled_data[level];
|
||||
texture->width[level] = cell->texture[i]->base.width[level];
|
||||
texture->height[level] = cell->texture[i]->base.height[level];
|
||||
}
|
||||
}
|
||||
else {
|
||||
texture->start = NULL;
|
||||
texture->width = 1;
|
||||
texture->height = 1;
|
||||
uint level;
|
||||
for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
|
||||
texture->start[level] = NULL;
|
||||
texture->width[level] = 1;
|
||||
texture->height[level] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ cell_texture_layout(struct cell_texture * spt)
|
|||
unsigned size;
|
||||
unsigned w_tile, h_tile;
|
||||
|
||||
assert(level < CELL_MAX_TEXTURE_LEVELS);
|
||||
|
||||
/* width, height, rounded up to tile size */
|
||||
w_tile = align(width, TILE_SIZE);
|
||||
h_tile = align(height, TILE_SIZE);
|
||||
|
|
@ -249,33 +251,41 @@ cell_tile_texture(struct cell_context *cell,
|
|||
struct cell_texture *texture)
|
||||
{
|
||||
struct pipe_screen *screen = cell->pipe.screen;
|
||||
uint face = 0, level = 0, zslice = 0;
|
||||
struct pipe_surface *surf;
|
||||
const uint w = texture->base.width[0], h = texture->base.height[0];
|
||||
uint face = 0, level, zslice = 0;
|
||||
const uint *src;
|
||||
|
||||
/* temporary restrictions: */
|
||||
assert(w >= TILE_SIZE);
|
||||
assert(h >= TILE_SIZE);
|
||||
assert(w % TILE_SIZE == 0);
|
||||
assert(h % TILE_SIZE == 0);
|
||||
for (level = 0; level <= texture->base.last_level; level++) {
|
||||
if (!texture->tiled_data[level]) {
|
||||
struct pipe_surface *surf;
|
||||
|
||||
surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice,
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
ASSERT(surf);
|
||||
const uint w = texture->base.width[level], h = texture->base.height[level];
|
||||
|
||||
src = (const uint *) pipe_surface_map(surf, PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
if (w < 32 || h < 32)
|
||||
continue;
|
||||
/* temporary restrictions: */
|
||||
assert(w >= TILE_SIZE);
|
||||
assert(h >= TILE_SIZE);
|
||||
assert(w % TILE_SIZE == 0);
|
||||
assert(h % TILE_SIZE == 0);
|
||||
|
||||
if (texture->tiled_data) {
|
||||
align_free(texture->tiled_data);
|
||||
surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice,
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
ASSERT(surf);
|
||||
|
||||
src = (const uint *) pipe_surface_map(surf, PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
|
||||
if (texture->tiled_data[level]) {
|
||||
align_free(texture->tiled_data[level]);
|
||||
}
|
||||
texture->tiled_data[level] = align_malloc(w * h * 4, 16);
|
||||
|
||||
tile_copy_data(w, h, TILE_SIZE, texture->tiled_data[level], src);
|
||||
|
||||
pipe_surface_unmap(surf);
|
||||
|
||||
pipe_surface_reference(&surf, NULL);
|
||||
}
|
||||
}
|
||||
texture->tiled_data = align_malloc(w * h * 4, 16);
|
||||
|
||||
tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src);
|
||||
|
||||
pipe_surface_unmap(surf);
|
||||
|
||||
pipe_surface_reference(&surf, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,15 +40,15 @@ struct cell_texture
|
|||
{
|
||||
struct pipe_texture base;
|
||||
|
||||
unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
|
||||
unsigned long stride[PIPE_MAX_TEXTURE_LEVELS];
|
||||
unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS];
|
||||
unsigned long stride[CELL_MAX_TEXTURE_LEVELS];
|
||||
|
||||
/* The data is held here:
|
||||
*/
|
||||
struct pipe_buffer *buffer;
|
||||
unsigned long buffer_size;
|
||||
|
||||
void *tiled_data; /* XXX this may be temporary */ /*ALIGN16*/
|
||||
void *tiled_data[CELL_MAX_TEXTURE_LEVELS]; /* XXX this may be temporary */ /*ALIGN16*/
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -301,6 +301,12 @@ cmd_state_sampler(const struct cell_command_sampler *sampler)
|
|||
DEBUG_PRINTF("SAMPLER [%u]\n", sampler->unit);
|
||||
|
||||
spu.sampler[sampler->unit] = sampler->state;
|
||||
#if 0
|
||||
if (spu.sampler[sampler->unit].min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
|
||||
spu.sample_texture4[sampler->unit] = sample_texture4_lod;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (spu.sampler[sampler->unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
|
||||
spu.sample_texture4[sampler->unit] = sample_texture4_bilinear;
|
||||
}
|
||||
|
|
@ -314,24 +320,29 @@ static void
|
|||
cmd_state_texture(const struct cell_command_texture *texture)
|
||||
{
|
||||
const uint unit = texture->unit;
|
||||
const uint width = texture->width;
|
||||
const uint height = texture->height;
|
||||
uint i;
|
||||
|
||||
DEBUG_PRINTF("TEXTURE [%u] at %p size %u x %u\n",
|
||||
texture->unit, texture->start,
|
||||
texture->width, texture->height);
|
||||
DEBUG_PRINTF("TEXTURE [%u]\n", texture->unit);
|
||||
|
||||
spu.texture[unit].start = texture->start;
|
||||
spu.texture[unit].width = width;
|
||||
spu.texture[unit].height = height;
|
||||
for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
|
||||
uint width = texture->width[i];
|
||||
uint height = texture->height[i];
|
||||
|
||||
spu.texture[unit].width4 = spu_splats((float) width);
|
||||
spu.texture[unit].height4 = spu_splats((float) height);
|
||||
DEBUG_PRINTF(" LEVEL %u: at %p size[0] %u x %u\n", i,
|
||||
texture->start[i], texture->width[i], texture->height[i]);
|
||||
|
||||
spu.texture[unit].tiles_per_row = width / TILE_SIZE;
|
||||
spu.texture[unit].level[i].start = texture->start[i];
|
||||
spu.texture[unit].level[i].width = width;
|
||||
spu.texture[unit].level[i].height = height;
|
||||
|
||||
spu.texture[unit].tex_size_x_mask = spu_splats(width - 1);
|
||||
spu.texture[unit].tex_size_y_mask = spu_splats(height - 1);
|
||||
spu.texture[unit].level[i].tiles_per_row = width / TILE_SIZE;
|
||||
|
||||
spu.texture[unit].level[i].width4 = spu_splats((float) width);
|
||||
spu.texture[unit].level[i].height4 = spu_splats((float) height);
|
||||
|
||||
spu.texture[unit].level[i].tex_size_x_mask = spu_splats(width - 1);
|
||||
spu.texture[unit].level[i].tex_size_y_mask = spu_splats(height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ spu_log2(vector float x)
|
|||
return spu_mul(v, k);
|
||||
}
|
||||
|
||||
|
||||
static struct vec_4x4
|
||||
spu_txp(vector float s, vector float t, vector float r, vector float q,
|
||||
unsigned unit)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ struct spu_framebuffer
|
|||
} ALIGN16_ATTRIB;
|
||||
|
||||
|
||||
struct spu_texture
|
||||
struct spu_texture_level
|
||||
{
|
||||
void *start;
|
||||
ushort width, height;
|
||||
|
|
@ -118,6 +118,11 @@ struct spu_texture
|
|||
vector unsigned int tex_size_y_mask; /**< splat(height-1) */
|
||||
} ALIGN16_ATTRIB;
|
||||
|
||||
struct spu_texture
|
||||
{
|
||||
struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
|
||||
} ALIGN16_ATTRIB;
|
||||
|
||||
|
||||
/**
|
||||
* All SPU global/context state will be in a singleton object of this type:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
|
||||
#include <transpose_matrix4x4.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "spu_main.h"
|
||||
|
|
@ -42,11 +43,12 @@
|
|||
void
|
||||
invalidate_tex_cache(void)
|
||||
{
|
||||
uint lvl = 0;
|
||||
uint unit = 0;
|
||||
uint bytes = 4 * spu.texture[unit].width
|
||||
* spu.texture[unit].height;
|
||||
uint bytes = 4 * spu.texture[unit].level[lvl].width
|
||||
* spu.texture[unit].level[lvl].height;
|
||||
|
||||
spu_dcache_mark_dirty((unsigned) spu.texture[unit].start, bytes);
|
||||
spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -64,15 +66,17 @@ invalidate_tex_cache(void)
|
|||
* a time.
|
||||
*/
|
||||
static void
|
||||
get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels)
|
||||
get_four_texels(uint unit, uint level, vec_uint4 x, vec_uint4 y,
|
||||
vec_uint4 *texels)
|
||||
{
|
||||
const unsigned texture_ea = (uintptr_t) spu.texture[unit].start;
|
||||
const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
|
||||
const unsigned texture_ea = (uintptr_t) tlevel->start;
|
||||
vec_uint4 tile_x = spu_rlmask(x, -5); /* tile_x = x / 32 */
|
||||
vec_uint4 tile_y = spu_rlmask(y, -5); /* tile_y = y / 32 */
|
||||
const qword offset_x = si_andi((qword) x, 0x1f); /* offset_x = x & 0x1f */
|
||||
const qword offset_y = si_andi((qword) y, 0x1f); /* offset_y = y & 0x1f */
|
||||
|
||||
const qword tiles_per_row = (qword) spu_splats(spu.texture[unit].tiles_per_row);
|
||||
const qword tiles_per_row = (qword) spu_splats(tlevel->tiles_per_row);
|
||||
const qword tile_size = (qword) spu_splats((unsigned) sizeof(tile_t));
|
||||
|
||||
qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x);
|
||||
|
|
@ -104,17 +108,18 @@ sample_texture4_nearest(vector float s, vector float t,
|
|||
vector float r, vector float q,
|
||||
uint unit, vector float colors[4])
|
||||
{
|
||||
vector float ss = spu_mul(s, spu.texture[unit].width4);
|
||||
vector float tt = spu_mul(t, spu.texture[unit].height4);
|
||||
const uint lvl = 0;
|
||||
vector float ss = spu_mul(s, spu.texture[unit].level[lvl].width4);
|
||||
vector float tt = spu_mul(t, spu.texture[unit].level[lvl].height4);
|
||||
vector unsigned int is = spu_convtu(ss, 0);
|
||||
vector unsigned int it = spu_convtu(tt, 0);
|
||||
vec_uint4 texels[4];
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is = spu_and(is, spu.texture[unit].tex_size_x_mask);
|
||||
it = spu_and(it, spu.texture[unit].tex_size_y_mask);
|
||||
is = spu_and(is, spu.texture[unit].level[lvl].tex_size_x_mask);
|
||||
it = spu_and(it, spu.texture[unit].level[lvl].tex_size_y_mask);
|
||||
|
||||
get_four_texels(unit, is, it, texels);
|
||||
get_four_texels(unit, lvl, is, it, texels);
|
||||
|
||||
/* convert four packed ARGBA pixels to float RRRR,GGGG,BBBB,AAAA */
|
||||
spu_unpack_A8R8G8B8_transpose4(texels, colors);
|
||||
|
|
@ -130,8 +135,9 @@ sample_texture4_bilinear(vector float s, vector float t,
|
|||
vector float r, vector float q,
|
||||
uint unit, vector float colors[4])
|
||||
{
|
||||
vector float ss = spu_madd(s, spu.texture[unit].width4, spu_splats(-0.5f));
|
||||
vector float tt = spu_madd(t, spu.texture[unit].height4, spu_splats(-0.5f));
|
||||
const uint lvl = 0;
|
||||
vector float ss = spu_madd(s, spu.texture[unit].level[lvl].width4, spu_splats(-0.5f));
|
||||
vector float tt = spu_madd(t, spu.texture[unit].level[lvl].height4, spu_splats(-0.5f));
|
||||
|
||||
vector unsigned int is0 = spu_convtu(ss, 0);
|
||||
vector unsigned int it0 = spu_convtu(tt, 0);
|
||||
|
|
@ -141,17 +147,17 @@ sample_texture4_bilinear(vector float s, vector float t,
|
|||
vector unsigned int it1 = spu_add(it0, 1);
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is0 = spu_and(is0, spu.texture[unit].tex_size_x_mask);
|
||||
it0 = spu_and(it0, spu.texture[unit].tex_size_y_mask);
|
||||
is1 = spu_and(is1, spu.texture[unit].tex_size_x_mask);
|
||||
it1 = spu_and(it1, spu.texture[unit].tex_size_y_mask);
|
||||
is0 = spu_and(is0, spu.texture[unit].level[lvl].tex_size_x_mask);
|
||||
it0 = spu_and(it0, spu.texture[unit].level[lvl].tex_size_y_mask);
|
||||
is1 = spu_and(is1, spu.texture[unit].level[lvl].tex_size_x_mask);
|
||||
it1 = spu_and(it1, spu.texture[unit].level[lvl].tex_size_y_mask);
|
||||
|
||||
/* get packed int texels */
|
||||
vector unsigned int texels[16];
|
||||
get_four_texels(unit, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(unit, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(unit, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(unit, is1, it1, texels + 12); /* lower-right */
|
||||
get_four_texels(unit, lvl, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(unit, lvl, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(unit, lvl, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(unit, lvl, is1, it1, texels + 12); /* lower-right */
|
||||
|
||||
/* XXX possibly rework following code to compute the weighted sample
|
||||
* colors with integer arithmetic for fewer int->float conversions.
|
||||
|
|
@ -270,10 +276,11 @@ sample_texture4_bilinear_2(vector float s, vector float t,
|
|||
vector float r, vector float q,
|
||||
uint unit, vector float colors[4])
|
||||
{
|
||||
const uint lvl = 0;
|
||||
static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
|
||||
/* Scale texcoords by size of texture, and add half pixel bias */
|
||||
vector float ss = spu_madd(s, spu.texture[unit].width4, half);
|
||||
vector float tt = spu_madd(t, spu.texture[unit].height4, half);
|
||||
vector float ss = spu_madd(s, spu.texture[unit].level[lvl].width4, half);
|
||||
vector float tt = spu_madd(t, spu.texture[unit].level[lvl].height4, half);
|
||||
|
||||
/* convert float coords to fixed-pt coords with 8 fraction bits */
|
||||
vector unsigned int is = spu_convtu(ss, 8);
|
||||
|
|
@ -294,17 +301,17 @@ sample_texture4_bilinear_2(vector float s, vector float t,
|
|||
vector unsigned int it1 = spu_add(it0, 1);
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is0 = spu_and(is0, spu.texture[unit].tex_size_x_mask);
|
||||
it0 = spu_and(it0, spu.texture[unit].tex_size_y_mask);
|
||||
is1 = spu_and(is1, spu.texture[unit].tex_size_x_mask);
|
||||
it1 = spu_and(it1, spu.texture[unit].tex_size_y_mask);
|
||||
is0 = spu_and(is0, spu.texture[unit].level[lvl].tex_size_x_mask);
|
||||
it0 = spu_and(it0, spu.texture[unit].level[lvl].tex_size_y_mask);
|
||||
is1 = spu_and(is1, spu.texture[unit].level[lvl].tex_size_x_mask);
|
||||
it1 = spu_and(it1, spu.texture[unit].level[lvl].tex_size_y_mask);
|
||||
|
||||
/* get packed int texels */
|
||||
vector unsigned int texels[16];
|
||||
get_four_texels(unit, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(unit, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(unit, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(unit, is1, it1, texels + 12); /* lower-right */
|
||||
get_four_texels(unit, lvl, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(unit, lvl, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(unit, lvl, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(unit, lvl, is1, it1, texels + 12); /* lower-right */
|
||||
|
||||
/* twiddle packed 32-bit BGRA pixels into RGBA as four unsigned ints */
|
||||
{
|
||||
|
|
@ -363,3 +370,54 @@ sample_texture4_bilinear_2(vector float s, vector float t,
|
|||
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
|
||||
colors[3] = spu_convtf(cSum, 24);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute level of detail factor from texcoords.
|
||||
*/
|
||||
static float
|
||||
compute_lambda(uint unit, vector float s, vector float t)
|
||||
{
|
||||
uint lvl = 0;
|
||||
float width = spu.texture[unit].level[lvl].width;
|
||||
float height = spu.texture[unit].level[lvl].width;
|
||||
float dsdx = width * (spu_extract(s, 1) - spu_extract(s, 0));
|
||||
float dsdy = width * (spu_extract(s, 2) - spu_extract(s, 0));
|
||||
float dtdx = height * (spu_extract(t, 1) - spu_extract(t, 0));
|
||||
float dtdy = height * (spu_extract(t, 2) - spu_extract(t, 0));
|
||||
float x = dsdx * dsdx + dtdx * dtdx;
|
||||
float y = dsdy * dsdy + dtdy * dtdy;
|
||||
float rho = x > y ? x : y;
|
||||
rho = sqrtf(rho);
|
||||
float lambda = logf(rho) * 1.442695f;
|
||||
return lambda;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Texture sampling with level of detail selection.
|
||||
*/
|
||||
void
|
||||
sample_texture4_lod(vector float s, vector float t,
|
||||
vector float r, vector float q,
|
||||
uint unit, vector float colors[4])
|
||||
{
|
||||
float lambda = compute_lambda(unit, s, t);
|
||||
|
||||
if (lambda < spu.sampler[unit].min_lod)
|
||||
lambda = spu.sampler[unit].min_lod;
|
||||
else if (lambda > spu.sampler[unit].max_lod)
|
||||
lambda = spu.sampler[unit].max_lod;
|
||||
|
||||
/* hack for now */
|
||||
int level = (int) lambda;
|
||||
if (level > 3)
|
||||
level = 3;
|
||||
|
||||
/*
|
||||
sample_texture4_bilinear_2(s, t, r, q, unit, level, colors);
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,4 +53,10 @@ sample_texture4_bilinear_2(vector float s, vector float t,
|
|||
uint unit, vector float colors[4]);
|
||||
|
||||
|
||||
extern void
|
||||
sample_texture4_lod(vector float s, vector float t,
|
||||
vector float r, vector float q,
|
||||
uint unit, vector float colors[4]);
|
||||
|
||||
|
||||
#endif /* SPU_TEXTURE_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue