mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-30 16:30:10 +01:00
freedreno/a4xx: mipmaps
Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
parent
cf80694df5
commit
0ebd623f60
4 changed files with 80 additions and 24 deletions
|
|
@ -208,13 +208,14 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring,
|
|||
fd4_pipe_sampler_view(tex->textures[i]) :
|
||||
&dummy_view;
|
||||
struct fd_resource *rsc = view->tex_resource;
|
||||
struct fd_resource_slice *slice = fd_resource_slice(rsc, 0);
|
||||
unsigned start = view->base.u.tex.first_level;
|
||||
uint32_t offset = fd_resource_offset(rsc, start, 0);
|
||||
|
||||
OUT_RING(ring, view->texconst0);
|
||||
OUT_RING(ring, view->texconst1);
|
||||
OUT_RING(ring, view->texconst2);
|
||||
OUT_RING(ring, view->texconst3);
|
||||
OUT_RELOC(ring, rsc->bo, slice->offset,
|
||||
view->textconst4, 0);
|
||||
OUT_RELOC(ring, rsc->bo, offset, view->textconst4, 0);
|
||||
OUT_RING(ring, 0x00000000);
|
||||
OUT_RING(ring, 0x00000000);
|
||||
OUT_RING(ring, 0x00000000);
|
||||
|
|
|
|||
|
|
@ -86,13 +86,18 @@ fd4_sampler_state_create(struct pipe_context *pctx,
|
|||
const struct pipe_sampler_state *cso)
|
||||
{
|
||||
struct fd4_sampler_stateobj *so = CALLOC_STRUCT(fd4_sampler_stateobj);
|
||||
bool miplinear = false;
|
||||
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
|
||||
miplinear = true;
|
||||
|
||||
so->base = *cso;
|
||||
|
||||
so->texsamp0 =
|
||||
COND(miplinear, A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
|
||||
A4XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter)) |
|
||||
A4XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter)) |
|
||||
A4XX_TEX_SAMP_0_WRAP_S(tex_clamp(cso->wrap_s)) |
|
||||
|
|
@ -100,6 +105,7 @@ fd4_sampler_state_create(struct pipe_context *pctx,
|
|||
A4XX_TEX_SAMP_0_WRAP_R(tex_clamp(cso->wrap_r));
|
||||
|
||||
so->texsamp1 =
|
||||
// COND(miplinear, A4XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR) |
|
||||
COND(!cso->normalized_coords, A4XX_TEX_SAMP_1_UNNORM_COORDS);
|
||||
|
||||
if (cso->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
|
||||
|
|
@ -143,6 +149,7 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
|
|||
struct fd4_pipe_sampler_view *so = CALLOC_STRUCT(fd4_pipe_sampler_view);
|
||||
struct fd_resource *rsc = fd_resource(prsc);
|
||||
unsigned lvl = cso->u.tex.first_level;
|
||||
unsigned miplevels = cso->u.tex.last_level - lvl;
|
||||
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
|
@ -158,12 +165,13 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
|
|||
so->texconst0 =
|
||||
A4XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) |
|
||||
A4XX_TEX_CONST_0_FMT(fd4_pipe2tex(cso->format)) |
|
||||
A4XX_TEX_CONST_0_MIPLVLS(miplevels) |
|
||||
fd4_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
|
||||
cso->swizzle_b, cso->swizzle_a);
|
||||
|
||||
so->texconst1 =
|
||||
A4XX_TEX_CONST_1_WIDTH(prsc->width0) |
|
||||
A4XX_TEX_CONST_1_HEIGHT(prsc->height0);
|
||||
A4XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
|
||||
A4XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
|
||||
so->texconst2 =
|
||||
A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(cso->format)) |
|
||||
A4XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp);
|
||||
|
|
@ -173,13 +181,13 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
|
|||
case PIPE_TEXTURE_2D_ARRAY:
|
||||
so->texconst3 =
|
||||
A4XX_TEX_CONST_3_DEPTH(prsc->array_size) |
|
||||
A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0);
|
||||
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
|
||||
break;
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
case PIPE_TEXTURE_CUBE_ARRAY: /* ?? not sure about _CUBE_ARRAY */
|
||||
so->texconst3 =
|
||||
A4XX_TEX_CONST_3_DEPTH(1) |
|
||||
A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0);
|
||||
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
|
||||
break;
|
||||
case PIPE_TEXTURE_3D:
|
||||
so->texconst3 =
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ fd_resource_transfer_map(struct pipe_context *pctx,
|
|||
struct pipe_transfer *ptrans;
|
||||
enum pipe_format format = prsc->format;
|
||||
uint32_t op = 0;
|
||||
uint32_t offset;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -146,10 +147,19 @@ fd_resource_transfer_map(struct pipe_context *pctx,
|
|||
|
||||
*pptrans = ptrans;
|
||||
|
||||
return buf + slice->offset +
|
||||
box->y / util_format_get_blockheight(format) * ptrans->stride +
|
||||
box->x / util_format_get_blockwidth(format) * rsc->cpp +
|
||||
box->z * slice->size0;
|
||||
if (rsc->layer_first) {
|
||||
offset = slice->offset +
|
||||
box->y / util_format_get_blockheight(format) * ptrans->stride +
|
||||
box->x / util_format_get_blockwidth(format) * rsc->cpp +
|
||||
box->z * rsc->layer_size;
|
||||
} else {
|
||||
offset = slice->offset +
|
||||
box->y / util_format_get_blockheight(format) * ptrans->stride +
|
||||
box->x / util_format_get_blockwidth(format) * rsc->cpp +
|
||||
box->z * slice->size0;
|
||||
}
|
||||
|
||||
return buf + offset;
|
||||
|
||||
fail:
|
||||
fd_resource_transfer_unmap(pctx, ptrans);
|
||||
|
|
@ -195,6 +205,10 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
|
|||
uint32_t width = prsc->width0;
|
||||
uint32_t height = prsc->height0;
|
||||
uint32_t depth = prsc->depth0;
|
||||
/* in layer_first layout, the level (slice) contains just one
|
||||
* layer (since in fact the layer contains the slices)
|
||||
*/
|
||||
uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size;
|
||||
|
||||
for (level = 0; level <= prsc->last_level; level++) {
|
||||
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
|
||||
|
|
@ -203,7 +217,7 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
|
|||
slice->offset = size;
|
||||
slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
|
||||
|
||||
size += slice->size0 * depth * prsc->array_size;
|
||||
size += slice->size0 * depth * layers_in_level;
|
||||
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
|
|
@ -216,12 +230,6 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
|
|||
static uint32_t
|
||||
slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl)
|
||||
{
|
||||
struct fd_screen *screen = fd_screen(pscreen);
|
||||
|
||||
/* on a4xx, seems like everything is aligned to page: */
|
||||
if ((screen->gpu_id >= 400) && (screen->gpu_id < 500))
|
||||
return 4096;
|
||||
|
||||
/* on a3xx, 2d array and 3d textures seem to want their
|
||||
* layers aligned to page boundaries:
|
||||
*/
|
||||
|
|
@ -266,8 +274,25 @@ fd_resource_create(struct pipe_screen *pscreen,
|
|||
|
||||
assert(rsc->cpp);
|
||||
|
||||
if (is_a4xx(fd_screen(pscreen))) {
|
||||
switch (tmpl->target) {
|
||||
case PIPE_TEXTURE_3D:
|
||||
/* TODO 3D_ARRAY? */
|
||||
rsc->layer_first = false;
|
||||
break;
|
||||
default:
|
||||
rsc->layer_first = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size = setup_slices(rsc, slice_alignment(pscreen, tmpl));
|
||||
|
||||
if (rsc->layer_first) {
|
||||
rsc->layer_size = align(size, 4096);
|
||||
size = rsc->layer_size * prsc->array_size;
|
||||
}
|
||||
|
||||
realloc_bo(rsc, size);
|
||||
if (!rsc->bo)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -33,11 +33,24 @@
|
|||
|
||||
#include "freedreno_util.h"
|
||||
|
||||
/* for mipmap, cubemap, etc, each level is represented by a slice.
|
||||
* Currently all slices are part of same bo (just different offsets),
|
||||
* this is at least how it needs to be for cubemaps, although mipmap
|
||||
* can be different bo's (although, not sure if there is a strong
|
||||
* advantage to doing that)
|
||||
/* Texture Layout on a3xx:
|
||||
*
|
||||
* Each mipmap-level contains all of it's layers (ie. all cubmap
|
||||
* faces, all 1d/2d array elements, etc). The texture sampler is
|
||||
* programmed with the start address of each mipmap level, and hw
|
||||
* derives the layer offset within the level.
|
||||
*
|
||||
* Texture Layout on a4xx:
|
||||
*
|
||||
* For cubemap and 2d array, each layer contains all of it's mipmap
|
||||
* levels (layer_first layout).
|
||||
*
|
||||
* 3d textures are layed out as on a3xx, but unknown about 3d-array
|
||||
* textures.
|
||||
*
|
||||
* In either case, the slice represents the per-miplevel information,
|
||||
* but in layer_first layout it only includes the first layer, and
|
||||
* an additional offset of (rsc->layer_size * layer) must be added.
|
||||
*/
|
||||
struct fd_resource_slice {
|
||||
uint32_t offset; /* offset of first layer in slice */
|
||||
|
|
@ -49,6 +62,8 @@ struct fd_resource {
|
|||
struct u_resource base;
|
||||
struct fd_bo *bo;
|
||||
uint32_t cpp;
|
||||
bool layer_first; /* see above description */
|
||||
uint32_t layer_size;
|
||||
struct fd_resource_slice slices[MAX_MIP_LEVELS];
|
||||
uint32_t timestamp;
|
||||
bool dirty;
|
||||
|
|
@ -72,7 +87,14 @@ static INLINE uint32_t
|
|||
fd_resource_offset(struct fd_resource *rsc, unsigned level, unsigned layer)
|
||||
{
|
||||
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
|
||||
return slice->offset + (slice->size0 * layer);
|
||||
unsigned offset;
|
||||
if (rsc->layer_first) {
|
||||
offset = slice->offset + (rsc->layer_size * layer);
|
||||
} else {
|
||||
offset = slice->offset + (slice->size0 * layer);
|
||||
}
|
||||
debug_assert(offset < fd_bo_size(rsc->bo));
|
||||
return offset;
|
||||
}
|
||||
|
||||
void fd_resource_screen_init(struct pipe_screen *pscreen);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue