diff options
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_miptree.c')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_miptree.c | 368 |
1 files changed, 185 insertions, 183 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index bced3245524..5da73df2d9b 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -29,8 +29,8 @@ #include "nvc0_resource.h" #include "nvc0_transfer.h" -static INLINE uint32_t -get_tile_dims(unsigned nx, unsigned ny, unsigned nz) +uint32_t +nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz) { uint32_t tile_mode = 0x000; @@ -57,66 +57,182 @@ get_tile_dims(unsigned nx, unsigned ny, unsigned nz) return tile_mode | 0x100; } -uint32_t -nvc0_miptree_zslice_offset(struct nvc0_miptree *mt, unsigned l, unsigned z) +static uint32_t +nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed) { - unsigned nblocksy; /* height of texture level aligned to tile height */ + const unsigned ms = util_logbase2(mt->base.base.nr_samples); - unsigned stride_2d; /* to next slice within a 3D tile */ - unsigned stride_3d; /* to slice in the next (in z direction !) 3D tile */ + uint32_t tile_flags; - unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(mt->level[l].tile_mode, 2); - unsigned tile_d = 1 << tile_d_shift; + compressed = FALSE; /* not yet supported */ - nblocksy = util_format_get_nblocksy(mt->base.base.format, - u_minify(mt->base.base.height0, l)); + if (mt->base.base.bind & PIPE_BIND_CURSOR) + return NOUVEAU_BO_TILE_SCANOUT; - nblocksy = align(nblocksy, NVC0_TILE_HEIGHT(mt->level[l].tile_mode)); + switch (mt->base.base.format) { + case PIPE_FORMAT_Z16_UNORM: + if (compressed) + tile_flags = 0x0200 + (ms << 8); + else + tile_flags = 0x0100; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + if (compressed) + tile_flags = 0x5100 + (ms << 8); + else + tile_flags = 0x4600; + break; + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + if (compressed) + tile_flags = 0x1700 + (ms << 8); + else + tile_flags = 0x1100; + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + if (compressed) + tile_flags = 0xce00 + (ms << 8); + else + tile_flags = 0xc300; + break; + default: + switch (util_format_get_blocksizebits(mt->base.base.format)) { + case 128: + if (compressed) + tile_flags = 0xf400 + (ms << 9); + else + tile_flags = 0xfe00; + break; + case 64: + if (compressed) { + switch (ms) { + case 0: tile_flags = 0xe600; break; + case 1: tile_flags = 0xeb00; break; + case 2: tile_flags = 0xed00; break; + case 3: tile_flags = 0xf200; break; + default: + return 0; + } + } else { + tile_flags = 0xfe00; + } + break; + case 32: + if (compressed) { + switch (ms) { + case 0: tile_flags = 0xdb00; break; + case 1: tile_flags = 0xdd00; break; + case 2: tile_flags = 0xdf00; break; + case 3: tile_flags = 0xe400; break; + default: + return 0; + } + } else { + tile_flags = 0xfe00; + } + break; + case 16: + case 8: + tile_flags = 0xfe00; + break; + default: + return 0; + } + break; + } - stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode); + if (mt->base.base.bind & PIPE_BIND_SCANOUT) + tile_flags |= NOUVEAU_BO_TILE_SCANOUT; - stride_3d = (nblocksy * mt->level[l].pitch) << tile_d_shift; + return tile_flags; +} - return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d; +static INLINE boolean +nvc0_miptree_init_ms_mode(struct nv50_miptree *mt) +{ + switch (mt->base.base.nr_samples) { + case 8: + mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8; + mt->ms_x = 2; + mt->ms_y = 1; + break; + case 4: + mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4; + mt->ms_x = 1; + mt->ms_y = 1; + break; + case 2: + mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2; + mt->ms_x = 1; + break; + case 1: + case 0: + mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1; + break; + default: + NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples); + return FALSE; + } + return TRUE; } +boolean +nv50_miptree_init_layout_linear(struct nv50_miptree *); + static void -nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) +nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt) { - struct nvc0_miptree *mt = nvc0_miptree(pt); + struct pipe_resource *pt = &mt->base.base; + unsigned w, h, d, l; + const unsigned blocksize = util_format_get_blocksize(pt->format); - nouveau_screen_bo_release(pscreen, mt->base.bo); + mt->layout_3d = pt->target == PIPE_TEXTURE_3D; - FREE(mt); -} + w = pt->width0 << mt->ms_x; + h = pt->height0 << mt->ms_y; -static boolean -nvc0_miptree_get_handle(struct pipe_screen *pscreen, - struct pipe_resource *pt, - struct winsys_handle *whandle) -{ - struct nvc0_miptree *mt = nvc0_miptree(pt); - unsigned stride; + /* For 3D textures, a mipmap is spanned by all the layers, for array + * textures and cube maps, each layer contains its own mipmaps. + */ + d = mt->layout_3d ? pt->depth0 : 1; - if (!mt || !mt->base.bo) - return FALSE; + for (l = 0; l <= pt->last_level; ++l) { + struct nv50_miptree_level *lvl = &mt->level[l]; + unsigned tsx, tsy, tsz; + unsigned nbx = util_format_get_nblocksx(pt->format, w); + unsigned nby = util_format_get_nblocksy(pt->format, h); + + lvl->offset = mt->total_size; + + lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d); + + tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */ + tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode); + tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode); + + lvl->pitch = align(nbx * blocksize, tsx); - stride = util_format_get_stride(mt->base.base.format, - mt->base.base.width0); + mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz); - return nouveau_screen_bo_get_handle(pscreen, - mt->base.bo, - stride, - whandle); + w = u_minify(w, 1); + h = u_minify(h, 1); + d = u_minify(d, 1); + } + + 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; + } } const struct u_resource_vtbl nvc0_miptree_vtbl = { - nvc0_miptree_get_handle, /* get_handle */ - nvc0_miptree_destroy, /* resource_destroy */ + nv50_miptree_get_handle, /* get_handle */ + nv50_miptree_destroy, /* resource_destroy */ nvc0_miptree_transfer_new, /* get_transfer */ nvc0_miptree_transfer_del, /* transfer_destroy */ - nvc0_miptree_transfer_map, /* transfer_map */ + nvc0_miptree_transfer_map, /* transfer_map */ u_default_transfer_flush_region, /* transfer_flush_region */ nvc0_miptree_transfer_unmap, /* transfer_unmap */ u_default_transfer_inline_write /* transfer_inline_write */ @@ -127,10 +243,9 @@ nvc0_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *templ) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; - struct nvc0_miptree *mt = CALLOC_STRUCT(nvc0_miptree); + struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); struct pipe_resource *pt = &mt->base.base; int ret; - unsigned w, h, d, l, alloc_size; uint32_t tile_flags; if (!mt) @@ -141,84 +256,23 @@ 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 = mt->layout_3d ? pt->depth0 : 1; + tile_flags = nvc0_mt_choose_storage_type(mt, TRUE); - switch (pt->format) { - case PIPE_FORMAT_Z16_UNORM: - tile_flags = 0x0700; /* COMPRESSED */ - tile_flags = 0x0100; /* NORMAL */ - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - tile_flags = 0x5300; /* MSAA 4, COMPRESSED */ - tile_flags = 0x4600; /* NORMAL */ - break; - case PIPE_FORMAT_Z24X8_UNORM: - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - tile_flags = 0x1100; /* NORMAL */ - if (w * h >= 128 * 128 && 0) - tile_flags = 0x1700; /* COMPRESSED, requires magic */ - break; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - tile_flags = 0xf500; /* COMPRESSED */ - tile_flags = 0xf700; /* MSAA 2 */ - tile_flags = 0xf900; /* MSAA 4 */ - tile_flags = 0xfe00; /* NORMAL */ - break; - case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: - tile_flags = 0xce00; /* COMPRESSED */ - tile_flags = 0xcf00; /* MSAA 2, COMPRESSED */ - tile_flags = 0xd000; /* MSAA 4, COMPRESSED */ - tile_flags = 0xc300; /* NORMAL */ - break; - case PIPE_FORMAT_R16G16B16A16_UNORM: - tile_flags = 0xe900; /* COMPRESSED */ - tile_flags = 0xfe00; /* NORMAL */ - break; - default: - tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */ - tile_flags = 0xfe00; /* NORMAL 32 BIT */ - if (w * h >= 128 * 128 && 0) - tile_flags = 0xdb00; /* COMPRESSED 32 BIT, requires magic */ - break; - } - - /* 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)); - - 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); + if (!nvc0_miptree_init_ms_mode(mt)) { + FREE(mt); + return NULL; } - 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; + if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) { + nvc0_miptree_init_layout_tiled(mt); + } else + if (!nv50_miptree_init_layout_linear(mt)) { + FREE(mt); + return NULL; } - alloc_size = mt->total_size; - if (tile_flags == 0x1700) - alloc_size *= 3; /* HiZ, XXX: correct size */ - - ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size, + ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096, + mt->total_size, mt->level[0].tile_mode, tile_flags, &mt->base.bo); if (ret) { @@ -230,44 +284,26 @@ nvc0_miptree_create(struct pipe_screen *pscreen, return pt; } -struct pipe_resource * -nvc0_miptree_from_handle(struct pipe_screen *pscreen, - const struct pipe_resource *templ, - struct winsys_handle *whandle) +/* Offset of zslice @z from start of level @l. */ +INLINE unsigned +nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z) { - struct nvc0_miptree *mt; - unsigned stride; - - /* 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->array_size > 1) - return NULL; + const struct pipe_resource *pt = &mt->base.base; - mt = CALLOC_STRUCT(nvc0_miptree); - if (!mt) - return NULL; + unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode); + unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode); - mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); - if (mt->base.bo == NULL) { - FREE(mt); - return NULL; - } + unsigned nby = util_format_get_nblocksy(pt->format, + u_minify(pt->height0, l)); - mt->base.base = *templ; - mt->base.vtbl = &nvc0_miptree_vtbl; - pipe_reference_init(&mt->base.base.reference, 1); - mt->base.base.screen = pscreen; - mt->level[0].pitch = stride; - mt->level[0].offset = 0; - mt->level[0].tile_mode = mt->base.bo->tile_mode; - - /* no need to adjust bo reference count */ - return &mt->base.base; -} + /* to next 2D tile slice within a 3D tile */ + unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode); + + /* to slice in the next (in z direction) 3D tile */ + unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds; + return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d; +} /* Surface functions. */ @@ -277,43 +313,9 @@ nvc0_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt, const struct pipe_surface *templ) { - struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */ - struct nvc0_surface *ns; - struct pipe_surface *ps; - struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level]; - - ns = CALLOC_STRUCT(nvc0_surface); + struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ); if (!ns) return NULL; - ps = &ns->base; - - pipe_reference_init(&ps->reference, 1); - pipe_resource_reference(&ps->texture, pt); - ps->context = pipe; - ps->format = templ->format; - 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; - - return ps; -} - -void -nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps) -{ - struct nvc0_surface *s = nvc0_surface(ps); - - pipe_resource_reference(&ps->texture, NULL); - - FREE(s); + ns->base.context = pipe; + return &ns->base; } |