nv50: any cpu access to a texture is done on its backing images
Still a little dodgy: - RTT will hit an assertion (hopefully!) and fail - 3D textures with depth >= 32 will cause bad things to happen
This commit is contained in:
@@ -70,7 +70,8 @@ struct nv50_rasterizer_stateobj {
|
||||
struct nv50_miptree_level {
|
||||
struct pipe_buffer **image;
|
||||
int *image_offset;
|
||||
unsigned image_dirty;
|
||||
unsigned image_dirty_cpu;
|
||||
unsigned image_dirty_gpu;
|
||||
};
|
||||
|
||||
struct nv50_miptree {
|
||||
|
||||
@@ -115,12 +115,50 @@ nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_miptree_sync(struct pipe_screen *pscreen, struct nv50_miptree *mt,
|
||||
unsigned level, unsigned image)
|
||||
{
|
||||
struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws;
|
||||
struct nv50_miptree_level *lvl = &mt->level[level];
|
||||
struct pipe_surface *dst, *src;
|
||||
unsigned face = 0, zslice = 0;
|
||||
|
||||
if (!lvl->image_dirty_cpu & (1 << image))
|
||||
return;
|
||||
|
||||
if (mt->base.target == PIPE_TEXTURE_CUBE)
|
||||
face = image;
|
||||
else
|
||||
if (mt->base.target == PIPE_TEXTURE_3D)
|
||||
zslice = image;
|
||||
|
||||
/* Mark as clean already - so we don't continually call this function
|
||||
* trying to get a GPU_WRITE pipe_surface!
|
||||
*/
|
||||
lvl->image_dirty_cpu &= ~(1 << image);
|
||||
|
||||
dst = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice,
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
/* Pretend we're doing CPU access so we get the backing pipe_surface
|
||||
* and not a view into the larger miptree.
|
||||
*/
|
||||
src = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice,
|
||||
PIPE_BUFFER_USAGE_CPU_READ);
|
||||
|
||||
nvws->surface_copy(nvws, dst, 0, 0, src, 0, 0, dst->width, dst->height);
|
||||
|
||||
pscreen->tex_surface_release(pscreen, &dst);
|
||||
pscreen->tex_surface_release(pscreen, &src);
|
||||
}
|
||||
|
||||
static struct pipe_surface *
|
||||
nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
|
||||
unsigned face, unsigned level, unsigned zslice,
|
||||
unsigned flags)
|
||||
{
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
struct nv50_miptree_level *lvl = &mt->level[level];
|
||||
struct nv50_surface *s;
|
||||
struct pipe_surface *ps;
|
||||
int img;
|
||||
@@ -147,12 +185,29 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
|
||||
ps->nblocksx = pt->nblocksx[level];
|
||||
ps->nblocksy = pt->nblocksy[level];
|
||||
ps->stride = ps->width * ps->block.size;
|
||||
ps->offset = mt->level[level].image_offset[img];
|
||||
ps->usage = flags;
|
||||
ps->status = PIPE_SURFACE_STATUS_DEFINED;
|
||||
|
||||
pipe_texture_reference(&ps->texture, pt);
|
||||
pipe_buffer_reference(pscreen, &ps->buffer, mt->buffer);
|
||||
if (flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) {
|
||||
assert(!(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE));
|
||||
assert(!(lvl->image_dirty_cpu & (1 << img)));
|
||||
|
||||
ps->offset = 0;
|
||||
pipe_texture_reference(&ps->texture, pt);
|
||||
pipe_buffer_reference(pscreen, &ps->buffer, lvl->image[img]);
|
||||
|
||||
if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
|
||||
lvl->image_dirty_cpu |= (1 << img);
|
||||
} else {
|
||||
nv50_miptree_sync(pscreen, mt, level, img);
|
||||
|
||||
ps->offset = lvl->image_offset[img];
|
||||
pipe_texture_reference(&ps->texture, pt);
|
||||
pipe_buffer_reference(pscreen, &ps->buffer, mt->buffer);
|
||||
|
||||
if (flags & PIPE_BUFFER_USAGE_GPU_WRITE)
|
||||
lvl->image_dirty_gpu |= (1 << img);
|
||||
}
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
@@ -105,14 +105,23 @@ nv50_tex_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so;
|
||||
int i;
|
||||
int unit, level, image;
|
||||
|
||||
so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2);
|
||||
so_method(so, tesla, 0x0f00, 1);
|
||||
so_data (so, NV50_CB_TIC);
|
||||
so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8);
|
||||
for (i = 0; i < nv50->miptree_nr; i++) {
|
||||
if (nv50_tex_construct(so, nv50->miptree[i])) {
|
||||
for (unit = 0; unit < nv50->miptree_nr; unit++) {
|
||||
struct nv50_miptree *mt = nv50->miptree[unit];
|
||||
|
||||
for (level = 0; level <= mt->base.last_level; level++) {
|
||||
for (image = 0; image < mt->image_nr; image++) {
|
||||
nv50_miptree_sync(&nv50->screen->pipe, mt,
|
||||
level, image);
|
||||
}
|
||||
}
|
||||
|
||||
if (nv50_tex_construct(so, mt)) {
|
||||
NOUVEAU_ERR("failed tex validate\n");
|
||||
so_ref(NULL, &so);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user