Finish unifying the surface and texture tile caches.
This commit is contained in:
@@ -343,6 +343,20 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
|
|||||||
softpipe->pipe.mipmap_tree_layout = softpipe_mipmap_tree_layout;
|
softpipe->pipe.mipmap_tree_layout = softpipe_mipmap_tree_layout;
|
||||||
softpipe->pipe.get_tex_surface = softpipe_get_tex_surface;
|
softpipe->pipe.get_tex_surface = softpipe_get_tex_surface;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alloc caches for accessing drawing surfaces and textures.
|
||||||
|
* Must be before quad stage setup!
|
||||||
|
*/
|
||||||
|
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
|
||||||
|
softpipe->cbuf_cache[i] = sp_create_tile_cache();
|
||||||
|
softpipe->zbuf_cache = sp_create_tile_cache();
|
||||||
|
softpipe->sbuf_cache_sep = sp_create_tile_cache();
|
||||||
|
softpipe->sbuf_cache = softpipe->sbuf_cache_sep; /* initial value */
|
||||||
|
|
||||||
|
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
|
||||||
|
softpipe->tex_cache[i] = sp_create_tile_cache();
|
||||||
|
|
||||||
|
|
||||||
/* setup quad rendering stages */
|
/* setup quad rendering stages */
|
||||||
softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe);
|
softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe);
|
||||||
softpipe->quad.shade = sp_quad_shade_stage(softpipe);
|
softpipe->quad.shade = sp_quad_shade_stage(softpipe);
|
||||||
@@ -380,11 +394,5 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
|
|||||||
sp_init_region_functions(softpipe);
|
sp_init_region_functions(softpipe);
|
||||||
sp_init_surface_functions(softpipe);
|
sp_init_surface_functions(softpipe);
|
||||||
|
|
||||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
|
|
||||||
softpipe->cbuf_cache[i] = sp_create_tile_cache();
|
|
||||||
softpipe->zbuf_cache = sp_create_tile_cache();
|
|
||||||
softpipe->sbuf_cache_sep = sp_create_tile_cache();
|
|
||||||
softpipe->sbuf_cache = softpipe->sbuf_cache_sep; /* initial value */
|
|
||||||
|
|
||||||
return &softpipe->pipe;
|
return &softpipe->pipe;
|
||||||
}
|
}
|
||||||
|
@@ -163,6 +163,8 @@ struct softpipe_context {
|
|||||||
/** This either points to zbuf_cache or sbuf_cache_sep */
|
/** This either points to zbuf_cache or sbuf_cache_sep */
|
||||||
struct softpipe_tile_cache *sbuf_cache;
|
struct softpipe_tile_cache *sbuf_cache;
|
||||||
|
|
||||||
|
struct softpipe_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
|
||||||
|
|
||||||
int use_sse : 1;
|
int use_sse : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -153,19 +153,10 @@ static void shade_begin(struct quad_stage *qs)
|
|||||||
struct softpipe_context *softpipe = qs->softpipe;
|
struct softpipe_context *softpipe = qs->softpipe;
|
||||||
unsigned i, entry;
|
unsigned i, entry;
|
||||||
|
|
||||||
|
/* set TGSI sampler state that varies */
|
||||||
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
|
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
|
||||||
qss->samplers[i].state = softpipe->sampler[i];
|
qss->samplers[i].state = softpipe->sampler[i];
|
||||||
qss->samplers[i].texture = softpipe->texture[i];
|
qss->samplers[i].texture = softpipe->texture[i];
|
||||||
qss->samplers[i].get_samples = sp_get_samples;
|
|
||||||
qss->samplers[i].pipe = &softpipe->pipe;
|
|
||||||
/* init cache info here */
|
|
||||||
for (entry = 0; entry < TEX_CACHE_NUM_ENTRIES; entry++) {
|
|
||||||
qss->samplers[i].cache[entry].x = -1;
|
|
||||||
qss->samplers[i].cache[entry].y = -1;
|
|
||||||
qss->samplers[i].cache[entry].level = -1;
|
|
||||||
qss->samplers[i].cache[entry].face = -1;
|
|
||||||
qss->samplers[i].cache[entry].zslice = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX only do this if the fragment shader changes... */
|
/* XXX only do this if the fragment shader changes... */
|
||||||
@@ -196,6 +187,7 @@ static void shade_begin(struct quad_stage *qs)
|
|||||||
struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
|
struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
|
||||||
{
|
{
|
||||||
struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
|
struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
|
||||||
|
uint i;
|
||||||
|
|
||||||
/* allocate storage for program inputs/outputs, aligned to 16 bytes */
|
/* allocate storage for program inputs/outputs, aligned to 16 bytes */
|
||||||
qss->inputs = malloc(PIPE_ATTRIB_MAX * sizeof(*qss->inputs) + 16);
|
qss->inputs = malloc(PIPE_ATTRIB_MAX * sizeof(*qss->inputs) + 16);
|
||||||
@@ -207,5 +199,13 @@ struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
|
|||||||
qss->stage.begin = shade_begin;
|
qss->stage.begin = shade_begin;
|
||||||
qss->stage.run = shade_quad;
|
qss->stage.run = shade_quad;
|
||||||
|
|
||||||
|
/* set TGSI sampler state that's constant */
|
||||||
|
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
|
||||||
|
assert(softpipe->tex_cache[i]);
|
||||||
|
qss->samplers[i].get_samples = sp_get_samples;
|
||||||
|
qss->samplers[i].pipe = &softpipe->pipe;
|
||||||
|
qss->samplers[i].cache = softpipe->tex_cache[i];
|
||||||
|
}
|
||||||
|
|
||||||
return &qss->stage;
|
return &qss->stage;
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include "sp_context.h"
|
#include "sp_context.h"
|
||||||
#include "sp_state.h"
|
#include "sp_state.h"
|
||||||
|
#include "sp_tile_cache.h"
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
softpipe_create_sampler_state(struct pipe_context *pipe,
|
softpipe_create_sampler_state(struct pipe_context *pipe,
|
||||||
@@ -72,5 +74,7 @@ softpipe_set_texture_state(struct pipe_context *pipe,
|
|||||||
assert(unit < PIPE_MAX_SAMPLERS);
|
assert(unit < PIPE_MAX_SAMPLERS);
|
||||||
softpipe->texture[unit] = texture; /* ptr, not struct */
|
softpipe->texture[unit] = texture; /* ptr, not struct */
|
||||||
|
|
||||||
|
sp_tile_cache_set_texture(softpipe->tex_cache[unit], texture);
|
||||||
|
|
||||||
softpipe->dirty |= SP_NEW_TEXTURE;
|
softpipe->dirty |= SP_NEW_TEXTURE;
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include "sp_context.h"
|
#include "sp_context.h"
|
||||||
#include "sp_surface.h"
|
#include "sp_surface.h"
|
||||||
#include "sp_tex_sample.h"
|
#include "sp_tex_sample.h"
|
||||||
|
#include "sp_tile_cache.h"
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
#include "pipe/p_defines.h"
|
#include "pipe/p_defines.h"
|
||||||
#include "pipe/p_util.h"
|
#include "pipe/p_util.h"
|
||||||
@@ -522,28 +523,6 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the texture face, level, zslice, x and y values, compute
|
|
||||||
* the cache entry position/index where we'd hope to find the
|
|
||||||
* cached texture tile.
|
|
||||||
* This is basically a direct-map cache.
|
|
||||||
* XXX There's probably lots of ways in which we can improve
|
|
||||||
* texture caching....
|
|
||||||
*/
|
|
||||||
static unsigned
|
|
||||||
compute_cache_pos(unsigned face, unsigned level, unsigned zslice,
|
|
||||||
int tx, int ty)
|
|
||||||
{
|
|
||||||
#if 01
|
|
||||||
unsigned entry = tx + ty * 2 + zslice * 4 + face + level;
|
|
||||||
return entry % TEX_CACHE_NUM_ENTRIES;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a texel from a texture, using the texture tile cache.
|
* Get a texel from a texture, using the texture tile cache.
|
||||||
*
|
*
|
||||||
@@ -551,74 +530,27 @@ compute_cache_pos(unsigned face, unsigned level, unsigned zslice,
|
|||||||
* \param level the mipmap level
|
* \param level the mipmap level
|
||||||
* \param x the x coord of texel within 2D image
|
* \param x the x coord of texel within 2D image
|
||||||
* \param y the y coord of texel within 2D image
|
* \param y the y coord of texel within 2D image
|
||||||
* \param zslice which slice of a 3D texture
|
* \param z which slice of a 3D texture
|
||||||
* \param rgba the quad to put the texel/color into
|
* \param rgba the quad to put the texel/color into
|
||||||
* \param j which element of the rgba quad to write to
|
* \param j which element of the rgba quad to write to
|
||||||
|
*
|
||||||
|
* XXX maybe move this into sp_tile_cache.c and merge with the
|
||||||
|
* sp_get_cached_tile_tex() function. Also, get 4 texels instead of 1...
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_texel(struct tgsi_sampler *sampler,
|
get_texel(struct tgsi_sampler *sampler,
|
||||||
unsigned face, unsigned level, int x, int y, unsigned zslice,
|
unsigned face, unsigned level, int x, int y, int z,
|
||||||
float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
|
float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
|
||||||
{
|
{
|
||||||
int tx = x / TEX_CACHE_TILE_SIZE;
|
const int tx = x % TILE_SIZE;
|
||||||
int ty = y / TEX_CACHE_TILE_SIZE;
|
const int ty = y % TILE_SIZE;
|
||||||
unsigned entry = compute_cache_pos(face, level, zslice, tx, ty);
|
const struct softpipe_cached_tile *tile
|
||||||
|
= sp_get_cached_tile_tex(sampler->pipe, sampler->cache,
|
||||||
if (tx != sampler->cache[entry].x ||
|
x, y, z, face, level);
|
||||||
ty != sampler->cache[entry].y ||
|
rgba[0][j] = tile->data.color[ty][tx][0];
|
||||||
face != sampler->cache[entry].face ||
|
rgba[1][j] = tile->data.color[ty][tx][1];
|
||||||
level != sampler->cache[entry].level ||
|
rgba[2][j] = tile->data.color[ty][tx][2];
|
||||||
zslice != sampler->cache[entry].zslice) {
|
rgba[3][j] = tile->data.color[ty][tx][3];
|
||||||
/* entry is not what's expected */
|
|
||||||
struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
|
|
||||||
struct pipe_surface *ps
|
|
||||||
= pipe->get_tex_surface(pipe, sampler->texture, face, level, zslice);
|
|
||||||
|
|
||||||
/*
|
|
||||||
printf("cache miss (%d, %d) face %u\n", tx, ty, face);
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(ps->width == sampler->texture->level[level].width);
|
|
||||||
assert(ps->height == sampler->texture->level[level].height);
|
|
||||||
sampler->cache[entry].x = tx;
|
|
||||||
sampler->cache[entry].y = ty;
|
|
||||||
sampler->cache[entry].level = level;
|
|
||||||
sampler->cache[entry].face = face;
|
|
||||||
sampler->cache[entry].zslice = zslice;
|
|
||||||
ps->get_tile(ps,
|
|
||||||
tx * TEX_CACHE_TILE_SIZE,
|
|
||||||
ty * TEX_CACHE_TILE_SIZE,
|
|
||||||
TEX_CACHE_TILE_SIZE, TEX_CACHE_TILE_SIZE,
|
|
||||||
(float *) sampler->cache[entry].data);
|
|
||||||
|
|
||||||
pipe_surface_reference(&ps, NULL);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
printf("cache hit (%d, %d)\n", x, y);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the texel from cache entry */
|
|
||||||
tx = x % TEX_CACHE_TILE_SIZE;
|
|
||||||
ty = y % TEX_CACHE_TILE_SIZE;
|
|
||||||
if (sampler->texture->format == PIPE_FORMAT_U_Z16 ||
|
|
||||||
sampler->texture->format == PIPE_FORMAT_U_Z32 ||
|
|
||||||
sampler->texture->format == PIPE_FORMAT_S8_Z24) {
|
|
||||||
/* get_tile() returned one float per texel */
|
|
||||||
float *src = (float *) sampler->cache[entry].data;
|
|
||||||
rgba[0][j] =
|
|
||||||
rgba[1][j] =
|
|
||||||
rgba[2][j] =
|
|
||||||
rgba[3][j] = src[ty * TEX_CACHE_TILE_SIZE + tx];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* get_tile() returned four floats per texel */
|
|
||||||
rgba[0][j] = sampler->cache[entry].data[ty][tx][0];
|
|
||||||
rgba[1][j] = sampler->cache[entry].data[ty][tx][1];
|
|
||||||
rgba[2][j] = sampler->cache[entry].data[ty][tx][2];
|
|
||||||
rgba[3][j] = sampler->cache[entry].data[ty][tx][3];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -129,7 +129,15 @@ void
|
|||||||
sp_tile_cache_set_texture(struct softpipe_tile_cache *tc,
|
sp_tile_cache_set_texture(struct softpipe_tile_cache *tc,
|
||||||
struct pipe_mipmap_tree *texture)
|
struct pipe_mipmap_tree *texture)
|
||||||
{
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
tc->texture = texture;
|
tc->texture = texture;
|
||||||
|
|
||||||
|
/* mark as entries as invalid/empty */
|
||||||
|
/* XXX we should try to avoid this when the teximage hasn't changed */
|
||||||
|
for (i = 0; i < NUM_ENTRIES; i++) {
|
||||||
|
tc->entries[i].x = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -263,10 +271,10 @@ sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y)
|
|||||||
* This is basically a direct-map cache.
|
* This is basically a direct-map cache.
|
||||||
* XXX There's probably lots of ways in which we can improve this.
|
* XXX There's probably lots of ways in which we can improve this.
|
||||||
*/
|
*/
|
||||||
static uint
|
static INLINE uint
|
||||||
tex_cache_pos(int x, int y, int z, int face, int level)
|
tex_cache_pos(int x, int y, int z, int face, int level)
|
||||||
{
|
{
|
||||||
uint entry = x + y * 2 + z * 4 + face + level;
|
uint entry = x + y * 5 + z * 4 + face + level;
|
||||||
return entry % NUM_ENTRIES;
|
return entry % NUM_ENTRIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,19 +283,17 @@ tex_cache_pos(int x, int y, int z, int face, int level)
|
|||||||
* Similar to sp_get_cached_tile() but for textures.
|
* Similar to sp_get_cached_tile() but for textures.
|
||||||
* Tiles are read-only and indexed with more params.
|
* Tiles are read-only and indexed with more params.
|
||||||
*/
|
*/
|
||||||
struct softpipe_cached_tile *
|
const struct softpipe_cached_tile *
|
||||||
sp_get_cached_tile_tex(struct softpipe_tile_cache *tc, int x, int y, int z,
|
sp_get_cached_tile_tex(struct pipe_context *pipe,
|
||||||
|
struct softpipe_tile_cache *tc, int x, int y, int z,
|
||||||
int face, int level)
|
int face, int level)
|
||||||
{
|
{
|
||||||
struct pipe_context *pipe; /* XXX need this */
|
|
||||||
|
|
||||||
/* tile pos in framebuffer: */
|
/* tile pos in framebuffer: */
|
||||||
const int tile_x = x & ~(TILE_SIZE - 1);
|
const int tile_x = x & ~(TILE_SIZE - 1);
|
||||||
const int tile_y = y & ~(TILE_SIZE - 1);
|
const int tile_y = y & ~(TILE_SIZE - 1);
|
||||||
|
|
||||||
/* cache pos/entry: */
|
/* cache pos/entry: */
|
||||||
const int pos = tex_cache_pos(x / TILE_SIZE, y / TILE_SIZE,
|
const uint pos = tex_cache_pos(x / TILE_SIZE, y / TILE_SIZE, z,
|
||||||
z, face, level);
|
face, level);
|
||||||
struct softpipe_cached_tile *tile = tc->entries + pos;
|
struct softpipe_cached_tile *tile = tc->entries + pos;
|
||||||
|
|
||||||
if (tile_x != tile->x ||
|
if (tile_x != tile->x ||
|
||||||
@@ -295,6 +301,7 @@ sp_get_cached_tile_tex(struct softpipe_tile_cache *tc, int x, int y, int z,
|
|||||||
z != tile->z ||
|
z != tile->z ||
|
||||||
face != tile->face ||
|
face != tile->face ||
|
||||||
level != tile->level) {
|
level != tile->level) {
|
||||||
|
/* XXX this call is a bit heavier than we'd like: */
|
||||||
struct pipe_surface *ps
|
struct pipe_surface *ps
|
||||||
= pipe->get_tex_surface(pipe, tc->texture, face, level, z);
|
= pipe->get_tex_surface(pipe, tc->texture, face, level, z);
|
||||||
|
|
||||||
@@ -303,6 +310,12 @@ sp_get_cached_tile_tex(struct softpipe_tile_cache *tc, int x, int y, int z,
|
|||||||
(float *) tile->data.color);
|
(float *) tile->data.color);
|
||||||
|
|
||||||
pipe_surface_reference(&ps, NULL);
|
pipe_surface_reference(&ps, NULL);
|
||||||
|
|
||||||
|
tile->x = tile_x;
|
||||||
|
tile->y = tile_y;
|
||||||
|
tile->z = z;
|
||||||
|
tile->face = face;
|
||||||
|
tile->level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tile;
|
return tile;
|
||||||
|
@@ -79,8 +79,9 @@ sp_clear_tile_cache(struct softpipe_tile_cache *tc, unsigned clearval);
|
|||||||
extern struct softpipe_cached_tile *
|
extern struct softpipe_cached_tile *
|
||||||
sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y);
|
sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y);
|
||||||
|
|
||||||
extern struct softpipe_cached_tile *
|
extern const struct softpipe_cached_tile *
|
||||||
sp_get_cached_tile_tex(struct softpipe_tile_cache *tc, int x, int y, int z,
|
sp_get_cached_tile_tex(struct pipe_context *pipe,
|
||||||
|
struct softpipe_tile_cache *tc, int x, int y, int z,
|
||||||
int face, int level);
|
int face, int level);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -29,14 +29,8 @@ struct tgsi_interp_coef
|
|||||||
float dady[NUM_CHANNELS];
|
float dady[NUM_CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TEX_CACHE_TILE_SIZE 8
|
|
||||||
#define TEX_CACHE_NUM_ENTRIES 8
|
|
||||||
|
|
||||||
struct tgsi_texture_cache_entry
|
struct softpipe_tile_cache; /**< Opaque to TGSI */
|
||||||
{
|
|
||||||
int x, y, face, level, zslice;
|
|
||||||
float data[TEX_CACHE_TILE_SIZE][TEX_CACHE_TILE_SIZE][4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tgsi_sampler
|
struct tgsi_sampler
|
||||||
{
|
{
|
||||||
@@ -50,7 +44,7 @@ struct tgsi_sampler
|
|||||||
float lodbias,
|
float lodbias,
|
||||||
float rgba[NUM_CHANNELS][QUAD_SIZE]);
|
float rgba[NUM_CHANNELS][QUAD_SIZE]);
|
||||||
void *pipe; /*XXX temporary*/
|
void *pipe; /*XXX temporary*/
|
||||||
struct tgsi_texture_cache_entry cache[TEX_CACHE_NUM_ENTRIES];
|
struct softpipe_tile_cache *cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tgsi_exec_labels
|
struct tgsi_exec_labels
|
||||||
|
Reference in New Issue
Block a user