diff options
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_context.h | 6 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_miptree.c | 137 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_resource.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_resource.h | 23 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_state_validate.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_surface.c | 156 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_tex.c | 21 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_transfer.c | 68 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_transfer.h | 2 |
9 files changed, 251 insertions, 201 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index 0ea18d74ee3..df8a6da075b 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -130,7 +130,11 @@ nvc0_context(struct pipe_context *pipe) } struct nvc0_surface { - struct pipe_surface pipe; + struct pipe_surface base; + uint32_t offset; + uint32_t width; + uint16_t height; + uint16_t depth; }; static INLINE struct nvc0_surface * diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index cca307b37f1..70b10a0fc39 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -60,12 +60,12 @@ get_tile_dims(unsigned nx, unsigned ny, unsigned nz) static INLINE unsigned get_zslice_offset(uint32_t tile_mode, unsigned z, unsigned pitch, unsigned nbh) { - unsigned tile_h = NVC0_TILE_H(tile_mode); - unsigned tile_d = NVC0_TILE_D(tile_mode); + unsigned tile_h = NVC0_TILE_HEIGHT(tile_mode); + unsigned tile_d = NVC0_TILE_DEPTH(tile_mode); /* pitch_2d == to next slice within this volume tile */ /* pitch_3d == size (in bytes) of a volume tile */ - unsigned pitch_2d = tile_h * 64; + unsigned pitch_2d = tile_h * NVC0_TILE_PITCH(tile_mode); unsigned pitch_3d = tile_d * align(nbh, tile_h) * pitch; return (z % tile_d) * pitch_2d + (z / tile_d) * pitch_3d; @@ -75,10 +75,6 @@ static void nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) { struct nvc0_miptree *mt = nvc0_miptree(pt); - unsigned l; - - for (l = 0; l <= pt->last_level; ++l) - FREE(mt->level[l].image_offset); nouveau_screen_bo_release(pscreen, mt->base.bo); @@ -125,8 +121,8 @@ nvc0_miptree_create(struct pipe_screen *pscreen, struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nvc0_miptree *mt = CALLOC_STRUCT(nvc0_miptree); struct pipe_resource *pt = &mt->base.base; - int ret, i; - unsigned w, h, d, l, image_alignment, alloc_size; + int ret; + unsigned w, h, d, l, alloc_size; uint32_t tile_flags; if (!mt) @@ -137,9 +133,11 @@ nvc0_miptree_create(struct pipe_screen *pscreen, pipe_reference_init(&pt->reference, 1); pt->screen = pscreen; + mt->layout_3d = pt->target == PIPE_TEXTURE_3D; + w = pt->width0; h = pt->height0; - d = pt->depth0; + d = mt->layout_3d ? pt->depth0 : 1; switch (pt->format) { case PIPE_FORMAT_Z16_UNORM: @@ -180,47 +178,32 @@ nvc0_miptree_create(struct pipe_screen *pscreen, break; } - /* XXX: texture arrays */ - mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1; - - for (l = 0; l <= pt->last_level; l++) { + /* For 3D textures, a mipmap is spanned by all the layers, for array + * textures and cube maps, each layer contains its own mipmaps. + */ + for (l = 0; l <= pt->last_level; ++l) { struct nvc0_miptree_level *lvl = &mt->level[l]; + unsigned nbx = util_format_get_nblocksx(pt->format, w); unsigned nby = util_format_get_nblocksy(pt->format, h); + unsigned blocksize = util_format_get_blocksize(pt->format); + + lvl->offset = mt->total_size; + lvl->tile_mode = get_tile_dims(nbx, nby, d); + lvl->pitch = align(nbx * blocksize, NVC0_TILE_PITCH(lvl->tile_mode)); - lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); - lvl->pitch = align(util_format_get_stride(pt->format, w), 64); - lvl->tile_mode = get_tile_dims(w, nby, d); + mt->total_size += lvl->pitch * + align(nby, NVC0_TILE_HEIGHT(lvl->tile_mode)) * + align(d, NVC0_TILE_DEPTH(lvl->tile_mode)); w = u_minify(w, 1); h = u_minify(h, 1); d = u_minify(d, 1); } - image_alignment = NVC0_TILE_H(mt->level[0].tile_mode) * 64; - image_alignment *= NVC0_TILE_D(mt->level[0].tile_mode); - - /* NOTE the distinction between arrays of mip-mapped 2D textures and - * mip-mapped 3D textures. We can't use image_nr == depth for 3D mip. - */ - for (i = 0; i < mt->image_nr; i++) { - for (l = 0; l <= pt->last_level; l++) { - struct nvc0_miptree_level *lvl = &mt->level[l]; - int size; - unsigned tile_h = NVC0_TILE_H(lvl->tile_mode); - unsigned tile_d = NVC0_TILE_D(lvl->tile_mode); - - h = u_minify(pt->height0, l); - d = u_minify(pt->depth0, l); - - size = lvl->pitch; - size *= align(util_format_get_nblocksy(pt->format, h), tile_h); - size *= align(d, tile_d); - - lvl->image_offset[i] = mt->total_size; - - mt->total_size += size; - } - mt->total_size = align(mt->total_size, image_alignment); + if (pt->array_size > 1) { + mt->layer_stride = align(mt->total_size, + NVC0_TILE_SIZE(mt->level[0].tile_mode)); + mt->total_size = mt->layer_stride * pt->array_size; } alloc_size = mt->total_size; @@ -231,11 +214,10 @@ nvc0_miptree_create(struct pipe_screen *pscreen, mt->level[0].tile_mode, tile_flags, &mt->base.bo); if (ret) { - for (l = 0; l <= pt->last_level; ++l) - FREE(mt->level[l].image_offset); FREE(mt); return NULL; } + mt->base.domain = NOUVEAU_BO_VRAM; return pt; } @@ -248,11 +230,12 @@ nvc0_miptree_from_handle(struct pipe_screen *pscreen, struct nvc0_miptree *mt; unsigned stride; - /* only supports 2D, non-mip mapped textures for the moment */ + /* only supports 2D, non-mipmapped textures for the moment */ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) || templ->last_level != 0 || - templ->depth0 != 1) + templ->depth0 != 1 || + templ->array_size > 1) return NULL; mt = CALLOC_STRUCT(nvc0_miptree); @@ -269,9 +252,8 @@ nvc0_miptree_from_handle(struct pipe_screen *pscreen, mt->base.vtbl = &nvc0_miptree_vtbl; pipe_reference_init(&mt->base.base.reference, 1); mt->base.base.screen = pscreen; - mt->image_nr = 1; mt->level[0].pitch = stride; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); + mt->level[0].offset = 0; mt->level[0].tile_mode = mt->base.bo->tile_mode; /* no need to adjust bo reference count */ @@ -283,41 +265,52 @@ nvc0_miptree_from_handle(struct pipe_screen *pscreen, */ struct pipe_surface * -nvc0_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +nvc0_miptree_surface_new(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *templ) { - struct nvc0_miptree *mt = nvc0_miptree(pt); - struct nvc0_miptree_level *lvl = &mt->level[level]; + struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */ + struct nvc0_surface *ns; struct pipe_surface *ps; - unsigned img = 0; - - if (pt->target == PIPE_TEXTURE_CUBE) - img = face; + struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level]; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nvc0_surface); + if (!ns) return NULL; + ps = &ns->base; + + pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); + ps->context = pipe; ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->usage = flags; - pipe_reference_init(&ps->reference, 1); - ps->face = face; - ps->level = level; - ps->zslice = zslice; - ps->offset = lvl->image_offset[img]; - - if (pt->target == PIPE_TEXTURE_3D) - ps->offset += get_zslice_offset(lvl->tile_mode, zslice, lvl->pitch, + ps->usage = templ->usage; + ps->u.tex.level = templ->u.tex.level; + ps->u.tex.first_layer = templ->u.tex.first_layer; + ps->u.tex.last_layer = templ->u.tex.last_layer; + + ns->width = u_minify(pt->width0, ps->u.tex.level); + ns->height = u_minify(pt->height0, ps->u.tex.level); + ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1; + ns->offset = lvl->offset; + + /* comment says there are going to be removed, but they're used by the st */ + ps->width = ns->width; + ps->height = ns->height; + + if (mt->layout_3d) { + ns->offset += get_zslice_offset(lvl->tile_mode, ps->u.tex.first_layer, + lvl->pitch, util_format_get_nblocksy(pt->format, - ps->height)); + ns->height)); + } else { + ns->offset += mt->layer_stride * ps->u.tex.first_layer; + } + return ps; } void -nvc0_miptree_surface_del(struct pipe_surface *ps) +nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps) { struct nvc0_surface *s = nvc0_surface(ps); diff --git a/src/gallium/drivers/nvc0/nvc0_resource.c b/src/gallium/drivers/nvc0/nvc0_resource.c index 181d917f220..7e42cedd163 100644 --- a/src/gallium/drivers/nvc0/nvc0_resource.c +++ b/src/gallium/drivers/nvc0/nvc0_resource.c @@ -6,7 +6,7 @@ static unsigned nvc0_resource_is_referenced(struct pipe_context *pipe, struct pipe_resource *resource, - unsigned face, unsigned level) + unsigned face, int layer) { struct nvc0_resource *res = nvc0_resource(resource); unsigned flags = 0; @@ -56,6 +56,8 @@ nvc0_init_resource_functions(struct pipe_context *pcontext) pcontext->transfer_destroy = u_transfer_destroy_vtbl; pcontext->transfer_inline_write = u_transfer_inline_write_vtbl; pcontext->is_resource_referenced = nvc0_resource_is_referenced; + pcontext->create_surface = nvc0_miptree_surface_new; + pcontext->surface_destroy = nvc0_miptree_surface_del; } void @@ -66,6 +68,4 @@ nvc0_screen_init_resource_functions(struct pipe_screen *pscreen) pscreen->resource_get_handle = u_resource_get_handle_vtbl; pscreen->resource_destroy = u_resource_destroy_vtbl; pscreen->user_buffer_create = nvc0_user_buffer_create; - pscreen->get_tex_surface = nvc0_miptree_surface_new; - pscreen->tex_surface_destroy = nvc0_miptree_surface_del; } diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h index b9f3f7b5d81..0ff7a03198e 100644 --- a/src/gallium/drivers/nvc0/nvc0_resource.h +++ b/src/gallium/drivers/nvc0/nvc0_resource.h @@ -66,11 +66,15 @@ nvc0_resource_unmap(struct nvc0_resource *res) nouveau_bo_unmap(res->bo); } -#define NVC0_TILE_H(m) (8 << ((m >> 4) & 0xf)) -#define NVC0_TILE_D(m) (1 << (m >> 8)) +#define NVC0_TILE_PITCH(m) (64 << ((m) & 0xf)) +#define NVC0_TILE_HEIGHT(m) (8 << (((m) >> 4) & 0xf)) +#define NVC0_TILE_DEPTH(m) (1 << ((m) >> 8)) + +#define NVC0_TILE_SIZE(m) \ + (NVC0_TILE_PITCH(m) * NVC0_TILE_HEIGHT(m) * NVC0_TILE_DEPTH(m)) struct nvc0_miptree_level { - int *image_offset; + uint32_t offset; uint32_t pitch; uint32_t tile_mode; }; @@ -80,8 +84,9 @@ struct nvc0_miptree_level { struct nvc0_miptree { struct nvc0_resource base; struct nvc0_miptree_level level[NVC0_MAX_TEXTURE_LEVELS]; - int image_nr; - int total_size; + uint32_t total_size; + uint32_t layer_stride; + boolean layout_3d; /* TRUE if layer count varies with mip level */ }; static INLINE struct nvc0_miptree * @@ -132,12 +137,12 @@ nvc0_user_buffer_create(struct pipe_screen *screen, struct pipe_surface * -nvc0_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags); +nvc0_miptree_surface_new(struct pipe_context *, + struct pipe_resource *, + const struct pipe_surface *templ); void -nvc0_miptree_surface_del(struct pipe_surface *ps); +nvc0_miptree_surface_del(struct pipe_context *, struct pipe_surface *); struct nvc0_context; diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index a1419bb310c..a395b18a99f 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -7,12 +7,15 @@ nvc0_validate_zcull(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct pipe_framebuffer_state *fb = &nvc0->framebuffer; - struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture); + struct nvc0_surface *sf = nvc0_surface(fb->zsbuf); + struct nvc0_miptree *mt = nvc0_miptree(sf->base.texture); struct nouveau_bo *bo = mt->base.bo; uint32_t size; uint32_t offset = align(mt->total_size, 1 << 17); unsigned width, height; + assert(mt->base.base.depth0 == 1 && mt->base.base.array_size < 2); + size = mt->total_size * 2; height = align(fb->height, 32); @@ -65,18 +68,20 @@ nvc0_validate_fb(struct nvc0_context *nvc0) for (i = 0; i < fb->nr_cbufs; ++i) { struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture); + struct nvc0_surface *sf = nvc0_surface(fb->cbufs[i]); struct nouveau_bo *bo = mt->base.bo; - unsigned offset = fb->cbufs[i]->offset; + uint32_t offset = sf->offset; BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 8); OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); - OUT_RING (chan, fb->cbufs[i]->width); - OUT_RING (chan, fb->cbufs[i]->height); - OUT_RING (chan, nvc0_format_table[fb->cbufs[i]->format].rt); - OUT_RING (chan, mt->level[fb->cbufs[i]->level].tile_mode); - OUT_RING (chan, 1); - OUT_RING (chan, 0); + OUT_RING (chan, sf->width); + OUT_RING (chan, sf->height); + OUT_RING (chan, nvc0_format_table[sf->base.format].rt); + OUT_RING (chan, (mt->layout_3d << 16) | + mt->level[sf->base.u.tex.level].tile_mode); + OUT_RING (chan, sf->depth); + OUT_RING (chan, mt->layer_stride); nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); @@ -84,21 +89,23 @@ nvc0_validate_fb(struct nvc0_context *nvc0) if (fb->zsbuf) { struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture); + struct nvc0_surface *sf = nvc0_surface(fb->zsbuf); struct nouveau_bo *bo = mt->base.bo; - unsigned offset = fb->zsbuf->offset; + int unk = mt->base.base.target == PIPE_TEXTURE_2D; + uint32_t offset = sf->offset; BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RING (chan, nvc0_format_table[fb->zsbuf->format].rt); - OUT_RING (chan, mt->level[fb->zsbuf->level].tile_mode); + OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode); OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3); - OUT_RING (chan, fb->zsbuf->width); - OUT_RING (chan, fb->zsbuf->height); - OUT_RING (chan, (1 << 16) | 1); + OUT_RING (chan, sf->width); + OUT_RING (chan, sf->height); + OUT_RING (chan, (unk << 16) | sf->depth); nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c index b52b09877c4..cc0a65687dc 100644 --- a/src/gallium/drivers/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nvc0/nvc0_surface.c @@ -78,75 +78,90 @@ nvc0_2d_format(enum pipe_format format) } static int -nvc0_surface_set(struct nvc0_screen *screen, struct pipe_surface *ps, int dst) +nvc0_2d_texture_set(struct nouveau_channel *chan, int dst, + struct nvc0_miptree *mt, unsigned level, unsigned layer) { - struct nvc0_miptree *mt = nvc0_miptree(ps->texture); - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_bo *bo = nvc0_miptree(ps->texture)->base.bo; - int format, mthd = dst ? NVC0_2D_DST_FORMAT : NVC0_2D_SRC_FORMAT; - int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); - - format = nvc0_2d_format(ps->format); + struct nouveau_bo *bo = mt->base.bo; + uint32_t width, height, depth; + uint32_t format; + uint32_t mthd = dst ? NVC0_2D_DST_FORMAT : NVC0_2D_SRC_FORMAT; + uint32_t flags = mt->base.domain | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); + uint32_t offset = mt->level[level].offset; + + format = nvc0_2d_format(mt->base.base.format); if (!format) { NOUVEAU_ERR("invalid/unsupported surface format: %s\n", - util_format_name(ps->format)); + util_format_name(mt->base.base.format)); return 1; } - if (!bo->tile_flags) { + width = u_minify(mt->base.base.width0, level); + height = u_minify(mt->base.base.height0, level); + + offset = mt->level[level].offset; + if (!mt->layout_3d) { + offset += mt->layer_stride * layer; + depth = 1; + layer = 0; + } else { + depth = u_minify(mt->base.base.depth0, level); + } + + if (!(bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)) { BEGIN_RING(chan, RING_2D_(mthd), 2); OUT_RING (chan, format); OUT_RING (chan, 1); BEGIN_RING(chan, RING_2D_(mthd + 0x14), 5); - OUT_RING (chan, mt->level[ps->level].pitch); - OUT_RING (chan, ps->width); - OUT_RING (chan, ps->height); - OUT_RELOCh(chan, bo, ps->offset, flags); - OUT_RELOCl(chan, bo, ps->offset, flags); + OUT_RING (chan, mt->level[level].pitch); + OUT_RING (chan, width); + OUT_RING (chan, height); + OUT_RELOCh(chan, bo, offset, flags); + OUT_RELOCl(chan, bo, offset, flags); } else { BEGIN_RING(chan, RING_2D_(mthd), 5); OUT_RING (chan, format); OUT_RING (chan, 0); - OUT_RING (chan, mt->level[ps->level].tile_mode); - OUT_RING (chan, 1); - OUT_RING (chan, 0); + OUT_RING (chan, mt->level[level].tile_mode); + OUT_RING (chan, depth); + OUT_RING (chan, layer); BEGIN_RING(chan, RING_2D_(mthd + 0x18), 4); - OUT_RING (chan, ps->width); - OUT_RING (chan, ps->height); - OUT_RELOCh(chan, bo, ps->offset, flags); - OUT_RELOCl(chan, bo, ps->offset, flags); + OUT_RING (chan, width); + OUT_RING (chan, height); + OUT_RELOCh(chan, bo, offset, flags); + OUT_RELOCl(chan, bo, offset, flags); } - + #if 0 if (dst) { BEGIN_RING(chan, RING_2D_(NVC0_2D_CLIP_X), 4); OUT_RING (chan, 0); OUT_RING (chan, 0); - OUT_RING (chan, surf->width); - OUT_RING (chan, surf->height); + OUT_RING (chan, width); + OUT_RING (chan, height); } #endif return 0; } static int -nvc0_surface_do_copy(struct nvc0_screen *screen, - struct pipe_surface *dst, int dx, int dy, - struct pipe_surface *src, int sx, int sy, - int w, int h) +nvc0_2d_texture_do_copy(struct nouveau_channel *chan, + struct nvc0_miptree *dst, unsigned dst_level, + unsigned dx, unsigned dy, unsigned dz, + struct nvc0_miptree *src, unsigned src_level, + unsigned sx, unsigned sy, unsigned sz, + unsigned w, unsigned h) { - struct nouveau_channel *chan = screen->base.channel; int ret; - ret = MARK_RING(chan, 2*16 + 32, 4); + ret = MARK_RING(chan, 2 * 16 + 32, 4); if (ret) return ret; - ret = nvc0_surface_set(screen, dst, 1); + ret = nvc0_2d_texture_set(chan, 1, dst, dst_level, dz); if (ret) return ret; - ret = nvc0_surface_set(screen, src, 0); + ret = nvc0_2d_texture_set(chan, 0, src, src_level, sz); if (ret) return ret; @@ -173,44 +188,44 @@ nvc0_surface_do_copy(struct nvc0_screen *screen, } static void -nvc0_surface_copy(struct pipe_context *pipe, - struct pipe_resource *dest, struct pipe_subresource subdst, - unsigned destx, unsigned desty, unsigned destz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) +nvc0_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dst, unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, unsigned src_level, + const struct pipe_box *src_box) { - struct nvc0_context *nv50 = nvc0_context(pipe); - struct nvc0_screen *screen = nv50->screen; - struct pipe_surface *ps_dst, *ps_src; + struct nvc0_screen *screen = nvc0_context(pipe)->screen; + int ret; + unsigned dst_layer = dstz, src_layer = src_box->z; - assert((src->format == dest->format) || + assert((src->format == dst->format) || (nvc0_2d_format_faithful(src->format) && - nvc0_2d_format_faithful(dest->format))); - - ps_src = nvc0_miptree_surface_new(pipe->screen, src, subsrc.face, - subsrc.level, srcz, 0 /* bind flags */); - ps_dst = nvc0_miptree_surface_new(pipe->screen, dest, subdst.face, - subdst.level, destz, 0 /* bind flags */); - - nvc0_surface_do_copy(screen, ps_dst, destx, desty, ps_src, srcx, - srcy, width, height); - - nvc0_miptree_surface_del(ps_src); - nvc0_miptree_surface_del(ps_dst); + nvc0_2d_format_faithful(dst->format))); + + for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) { + ret = nvc0_2d_texture_do_copy(screen->base.channel, + nvc0_miptree(dst), dst_level, + dstx, dsty, dst_layer, + nvc0_miptree(src), src_level, + src_box->x, src_box->y, src_layer, + src_box->width, src_box->height); + if (ret) + return; + } } static void nvc0_clear_render_target(struct pipe_context *pipe, - struct pipe_surface *dst, - const float *rgba, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { struct nvc0_context *nv50 = nvc0_context(pipe); struct nvc0_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->base.channel; struct nvc0_miptree *mt = nvc0_miptree(dst->texture); + struct nvc0_surface *sf = nvc0_surface(dst); struct nouveau_bo *bo = mt->base.bo; BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4); @@ -225,12 +240,12 @@ nvc0_clear_render_target(struct pipe_context *pipe, BEGIN_RING(chan, RING_3D(RT_CONTROL), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 8); - OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RING (chan, dst->width); - OUT_RING (chan, dst->height); + OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RING (chan, sf->width); + OUT_RING (chan, sf->height); OUT_RING (chan, nvc0_format_table[dst->format].rt); - OUT_RING (chan, mt->level[dst->level].tile_mode); + OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode); OUT_RING (chan, 1); OUT_RING (chan, 0); @@ -259,6 +274,7 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe, struct nvc0_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->base.channel; struct nvc0_miptree *mt = nvc0_miptree(dst->texture); + struct nvc0_surface *sf = nvc0_surface(dst); struct nouveau_bo *bo = mt->base.bo; uint32_t mode = 0; @@ -278,16 +294,16 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe, return; BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); - OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, nvc0_format_table[dst->format].rt); - OUT_RING (chan, mt->level[dst->level].tile_mode); + OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode); OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3); - OUT_RING (chan, dst->width); - OUT_RING (chan, dst->height); + OUT_RING (chan, sf->width); + OUT_RING (chan, sf->height); OUT_RING (chan, (1 << 16) | 1); BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); @@ -353,7 +369,7 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers, void nvc0_init_surface_functions(struct nvc0_context *nvc0) { - nvc0->pipe.resource_copy_region = nvc0_surface_copy; + nvc0->pipe.resource_copy_region = nvc0_resource_copy_region; nvc0->pipe.clear_render_target = nvc0_clear_render_target; nvc0->pipe.clear_depth_stencil = nvc0_clear_depth_stencil; } diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c index 5f28b832821..bf6ffc7da94 100644 --- a/src/gallium/drivers/nvc0/nvc0_tex.c +++ b/src/gallium/drivers/nvc0/nvc0_tex.c @@ -54,6 +54,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe, const struct util_format_description *desc; uint32_t *tic; uint32_t swz[4]; + uint32_t depth; struct nvc0_tic_entry *view; struct nvc0_miptree *mt = nvc0_miptree(texture); @@ -101,7 +102,9 @@ nvc0_create_sampler_view(struct pipe_context *pipe, tic[2] |= ((mt->base.bo->tile_mode & 0x0f0) << (22 - 4)) | - ((mt->base.bo->tile_mode & 0xf00) << (21 - 4)); + ((mt->base.bo->tile_mode & 0xf00) << (25 - 8)); + + depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); switch (mt->base.base.target) { case PIPE_TEXTURE_1D: @@ -117,7 +120,17 @@ nvc0_create_sampler_view(struct pipe_context *pipe, tic[2] |= NV50_TIC_2_TARGET_3D; break; case PIPE_TEXTURE_CUBE: - tic[2] |= NV50_TIC_2_TARGET_CUBE; + depth /= 6; + if (depth > 1) + tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY; + else + tic[2] |= NV50_TIC_2_TARGET_CUBE; + break; + case PIPE_TEXTURE_1D_ARRAY: + tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY; + break; + case PIPE_TEXTURE_2D_ARRAY: + tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY; break; case PIPE_BUFFER: tic[2] |= NV50_TIC_2_TARGET_BUFFER | /* NV50_TIC_2_LINEAR */ (1 << 18); @@ -134,12 +147,12 @@ nvc0_create_sampler_view(struct pipe_context *pipe, tic[4] = (1 << 31) | mt->base.base.width0; tic[5] = mt->base.base.height0 & 0xffff; - tic[5] |= mt->base.base.depth0 << 16; + tic[5] |= depth << 16; tic[5] |= mt->base.base.last_level << 28; tic[6] = 0x03000000; - tic[7] = (view->pipe.last_level << 4) | view->pipe.first_level; + tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; return &view->pipe; } diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index 10d0995a5a5..f6c78f239e9 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c @@ -231,7 +231,7 @@ nvc0_m2mf_push_rect(struct pipe_screen *pscreen, struct pipe_transfer * nvc0_miptree_transfer_new(struct pipe_context *pctx, struct pipe_resource *res, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { @@ -239,16 +239,21 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, struct pipe_screen *pscreen = pctx->screen; struct nouveau_device *dev = nvc0->screen->base.device; struct nvc0_miptree *mt = nvc0_miptree(res); - struct nvc0_miptree_level *lvl = &mt->level[sr.level]; + struct nvc0_miptree_level *lvl = &mt->level[level]; struct nvc0_transfer *tx; - uint32_t image; - uint32_t w, h, z; + uint32_t size; + uint32_t w, h, d, z, layer; int ret; - if (res->target == PIPE_TEXTURE_CUBE) - image = sr.face; - else - image = 0; + if (mt->layout_3d) { + z = box->z; + d = u_minify(res->depth0, level); + layer = 0; + } else { + z = 0; + d = 1; + layer = box->z; + } tx = CALLOC_STRUCT(nvc0_transfer); if (!tx) @@ -256,7 +261,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, pipe_resource_reference(&tx->base.resource, res); - tx->base.sr = sr; + tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; @@ -265,30 +270,27 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); - w = u_minify(res->width0, sr.level); - h = u_minify(res->height0, sr.level); + w = u_minify(res->width0, level); + h = u_minify(res->height0, level); tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format); tx->rect[0].bo = mt->base.bo; - tx->rect[0].base = lvl->image_offset[image]; + tx->rect[0].base = lvl->offset + layer * mt->layer_stride; tx->rect[0].tile_mode = lvl->tile_mode; tx->rect[0].x = util_format_get_nblocksx(res->format, box->x); - tx->rect[0].y = util_format_get_nblocksx(res->format, box->y); - tx->rect[0].z = box->z; + tx->rect[0].y = util_format_get_nblocksy(res->format, box->y); + tx->rect[0].z = z; tx->rect[0].width = util_format_get_nblocksx(res->format, w); - tx->rect[0].height = util_format_get_nblocksx(res->format, h); - tx->rect[0].depth = res->depth0; + tx->rect[0].height = util_format_get_nblocksy(res->format, h); + tx->rect[0].depth = d; tx->rect[0].pitch = lvl->pitch; tx->rect[0].domain = NOUVEAU_BO_VRAM; - if (!(usage & PIPE_TRANSFER_READ) && - (res->depth0 == 1) && (tx->nblocksy * tx->base.stride < 512 * 4)) { - /* don't allocate scratch buffer, upload through FIFO */ - } + size = tx->nblocksy * tx->base.stride; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, - tx->nblocksy * tx->base.stride, &tx->rect[1].bo); + size * tx->base.box.depth, &tx->rect[1].bo); if (ret) { FREE(tx); return NULL; @@ -296,18 +298,23 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->rect[1].width = tx->nblocksx; tx->rect[1].height = tx->nblocksy; - tx->rect[1].depth = box->depth; + tx->rect[1].depth = 1; tx->rect[1].pitch = tx->base.stride; tx->rect[1].domain = NOUVEAU_BO_GART; if (usage & PIPE_TRANSFER_READ) { - for (z = 0; z < box->depth; ++z) { + unsigned i; + for (i = 0; i < box->depth; ++i) { nvc0_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0], tx->nblocksx, tx->nblocksy); - tx->rect[0].z++; + if (mt->layout_3d) + tx->rect[0].z++; + else + tx->rect[0].base += mt->layer_stride; + tx->rect[1].base += size; } } - tx->rect[0].z = box->z; + tx->rect[0].z = z; return &tx->base; } @@ -318,13 +325,18 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx, { struct pipe_screen *pscreen = pctx->screen; struct nvc0_transfer *tx = (struct nvc0_transfer *)transfer; - unsigned z; + struct nvc0_miptree *mt = nvc0_miptree(tx->base.resource); + unsigned i; if (tx->base.usage & PIPE_TRANSFER_WRITE) { - for (z = 0; z < tx->base.box.depth; ++z) { + for (i = 0; i < tx->base.box.depth; ++i) { nvc0_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1], tx->nblocksx, tx->nblocksy); - tx->rect[0].z++; + if (mt->layout_3d) + tx->rect[0].z++; + else + tx->rect[0].base += mt->layer_stride; + tx->rect[1].base += tx->nblocksy * tx->base.stride; } } diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.h b/src/gallium/drivers/nvc0/nvc0_transfer.h index aaebe408b59..222f72d2748 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.h +++ b/src/gallium/drivers/nvc0/nvc0_transfer.h @@ -7,7 +7,7 @@ struct pipe_transfer * nvc0_miptree_transfer_new(struct pipe_context *pcontext, struct pipe_resource *pt, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box); void |