X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr600%2Fr600_texture.c;h=5c8b9dd4af997a0b2d4b9d369f682decefc43a63;hb=bc9cf6adff663889c3816b590e0b045956164ab0;hp=b84111449000d1c16478c9c73e956d96acd80586;hpb=bee61d16c8c48b0339d1db9bf4e6bf1ddc6685ff;p=mesa.git diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index b8411144900..5c8b9dd4af9 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -27,12 +27,13 @@ #include "r600_pipe_common.h" #include "r600_cs.h" #include "r600_query.h" -#include "util/u_format.h" +#include "util/format/u_format.h" #include "util/u_log.h" #include "util/u_memory.h" #include "util/u_pack_color.h" #include "util/u_surface.h" -#include "os/os_time.h" +#include "util/os_time.h" +#include "state_tracker/winsys_handle.h" #include #include @@ -178,7 +179,8 @@ static unsigned r600_texture_get_offset(struct r600_common_screen *rscreen, { *stride = rtex->surface.u.legacy.level[level].nblk_x * rtex->surface.bpe; - *layer_stride = rtex->surface.u.legacy.level[level].slice_size; + assert((uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4 <= UINT_MAX); + *layer_stride = (uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4; if (!box) return rtex->surface.u.legacy.level[level].offset; @@ -186,7 +188,7 @@ static unsigned r600_texture_get_offset(struct r600_common_screen *rscreen, /* Each texture is an array of mipmap levels. Each level is * an array of slices. */ return rtex->surface.u.legacy.level[level].offset + - box->z * rtex->surface.u.legacy.level[level].slice_size + + box->z * (uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4 + (box->y / rtex->surface.blk_h * rtex->surface.u.legacy.level[level].nblk_x + box->x / rtex->surface.blk_w) * rtex->surface.bpe; @@ -216,7 +218,7 @@ static int r600_init_surface(struct r600_common_screen *rscreen, bpe = 4; /* stencil is allocated separately on evergreen */ } else { bpe = util_format_get_blocksize(ptex->format); - assert(util_is_power_of_two(bpe)); + assert(util_is_power_of_two_or_zero(bpe)); } if (!is_flushed_depth && is_depth) { @@ -244,8 +246,8 @@ static int r600_init_surface(struct r600_common_screen *rscreen, if (!(ptex->flags & R600_RESOURCE_FLAG_FORCE_TILING)) flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE; - r = rscreen->ws->surface_init(rscreen->ws, ptex, flags, bpe, - array_mode, surface); + r = rscreen->ws->surface_init(rscreen->ws, ptex, + flags, bpe, array_mode, surface); if (r) { return r; } @@ -256,8 +258,8 @@ static int r600_init_surface(struct r600_common_screen *rscreen, * for those */ surface->u.legacy.level[0].nblk_x = pitch_in_bytes_override / bpe; - surface->u.legacy.level[0].slice_size = pitch_in_bytes_override * - surface->u.legacy.level[0].nblk_y; + surface->u.legacy.level[0].slice_size_dw = + ((uint64_t)pitch_in_bytes_override * surface->u.legacy.level[0].nblk_y) / 4; } if (offset) { @@ -365,7 +367,7 @@ static void r600_reallocate_texture_inplace(struct r600_common_context *rctx, templ.bind |= new_bind_flag; /* r600g doesn't react to dirty_tex_descriptor_counter */ - if (rctx->chip_class < SI) + if (rctx->chip_class < GFX6) return; if (rtex->resource.b.is_shared) @@ -392,7 +394,7 @@ static void r600_reallocate_texture_inplace(struct r600_common_context *rctx, u_box_3d(0, 0, 0, u_minify(templ.width0, i), u_minify(templ.height0, i), - util_max_layer(&templ, i) + 1, &box); + util_num_layers(&templ, i), &box); rctx->dma_copy(&rctx->b, &new_tex->resource.b.b, i, 0, 0, 0, &rtex->resource.b.b, i, &box); @@ -441,11 +443,37 @@ static void r600_reallocate_texture_inplace(struct r600_common_context *rctx, p_atomic_inc(&rctx->screen->dirty_tex_counter); } -static boolean r600_texture_get_handle(struct pipe_screen* screen, - struct pipe_context *ctx, - struct pipe_resource *resource, - struct winsys_handle *whandle, - unsigned usage) +static void r600_texture_get_info(struct pipe_screen* screen, + struct pipe_resource *resource, + unsigned *pstride, + unsigned *poffset) +{ + struct r600_common_screen *rscreen = (struct r600_common_screen*)screen; + struct r600_texture *rtex = (struct r600_texture*)resource; + unsigned stride = 0; + unsigned offset = 0; + + if (!rscreen || !rtex) + return; + + if (resource->target != PIPE_BUFFER) { + offset = rtex->surface.u.legacy.level[0].offset; + stride = rtex->surface.u.legacy.level[0].nblk_x * + rtex->surface.bpe; + } + + if (pstride) + *pstride = stride; + + if (poffset) + *poffset = offset; +} + +static bool r600_texture_get_handle(struct pipe_screen* screen, + struct pipe_context *ctx, + struct pipe_resource *resource, + struct winsys_handle *whandle, + unsigned usage) { struct r600_common_screen *rscreen = (struct r600_common_screen*)screen; struct r600_common_context *rctx; @@ -492,17 +520,11 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen, /* Set metadata. */ if (!res->b.is_shared || update_metadata) { r600_texture_init_metadata(rscreen, rtex, &metadata); - if (rscreen->query_opaque_metadata) - rscreen->query_opaque_metadata(rscreen, rtex, - &metadata); rscreen->ws->buffer_set_metadata(res->buf, &metadata); } - offset = rtex->surface.u.legacy.level[0].offset; - stride = rtex->surface.u.legacy.level[0].nblk_x * - rtex->surface.bpe; - slice_size = rtex->surface.u.legacy.level[0].slice_size; + slice_size = (uint64_t)rtex->surface.u.legacy.level[0].slice_size_dw * 4; } else { /* Move a suballocated buffer into a non-suballocated allocation. */ if (rscreen->ws->buffer_is_suballocated(res->buf)) { @@ -531,11 +553,11 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen, } /* Buffers */ - offset = 0; - stride = 0; slice_size = 0; } + r600_texture_get_info(screen, resource, &stride, &offset); + if (res->b.is_shared) { /* USAGE_EXPLICIT_FLUSH must be cleared if at least one user * doesn't set it. @@ -548,8 +570,10 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen, res->external_usage = usage; } - return rscreen->ws->buffer_get_handle(res->buf, stride, offset, - slice_size, whandle); + whandle->stride = stride; + whandle->offset = offset + slice_size * whandle->layer; + + return rscreen->ws->buffer_get_handle(rscreen->ws, res->buf, whandle); } static void r600_texture_destroy(struct pipe_screen *screen, @@ -559,6 +583,7 @@ static void r600_texture_destroy(struct pipe_screen *screen, struct r600_resource *resource = &rtex->resource; r600_texture_reference(&rtex->flushed_depth_texture, NULL); + pipe_resource_reference((struct pipe_resource**)&resource->immed_buffer, NULL); if (rtex->cmask_buffer != &rtex->resource) { r600_resource_reference(&rtex->cmask_buffer, NULL); @@ -614,8 +639,8 @@ void r600_texture_get_fmask_info(struct r600_common_screen *rscreen, bpe *= 2; } - if (rscreen->ws->surface_init(rscreen->ws, &templ, flags, bpe, - RADEON_SURF_MODE_2D, &fmask)) { + if (rscreen->ws->surface_init(rscreen->ws, &templ, + flags, bpe, RADEON_SURF_MODE_2D, &fmask)) { R600_ERR("Got error in surface_init while allocating FMASK.\n"); return; } @@ -674,7 +699,7 @@ void r600_texture_get_cmask_info(struct r600_common_screen *rscreen, out->slice_tile_max = ((pitch_elements * height) / (128*128)) - 1; out->alignment = MAX2(256, base_align); - out->size = (util_max_layer(&rtex->resource.b.b, 0) + 1) * + out->size = util_num_layers(&rtex->resource.b.b, 0) * align(slice_bytes, base_align); } @@ -718,6 +743,15 @@ static void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen p_atomic_inc(&rscreen->compressed_colortex_counter); } +void eg_resource_alloc_immed(struct r600_common_screen *rscreen, + struct r600_resource *res, + unsigned immed_size) +{ + res->immed_buffer = (struct r600_resource *) + pipe_buffer_create(&rscreen->b, PIPE_BIND_CUSTOM, + PIPE_USAGE_DEFAULT, immed_size); +} + static void r600_texture_get_htile_size(struct r600_common_screen *rscreen, struct r600_texture *rtex) { @@ -728,7 +762,7 @@ static void r600_texture_get_htile_size(struct r600_common_screen *rscreen, rtex->surface.htile_size = 0; if (rscreen->chip_class <= EVERGREEN && - rscreen->info.drm_major == 2 && rscreen->info.drm_minor < 26) + rscreen->info.drm_minor < 26) return; /* HW bug on R6xx. */ @@ -763,8 +797,8 @@ static void r600_texture_get_htile_size(struct r600_common_screen *rscreen, return; } - width = align(rtex->resource.b.b.width0, cl_width * 8); - height = align(rtex->resource.b.b.height0, cl_height * 8); + width = align(rtex->surface.u.legacy.level[0].nblk_x, cl_width * 8); + height = align(rtex->surface.u.legacy.level[0].nblk_y, cl_height * 8); slice_elements = (width * height) / (8 * 8); slice_bytes = slice_elements * 4; @@ -774,7 +808,7 @@ static void r600_texture_get_htile_size(struct r600_common_screen *rscreen, rtex->surface.htile_alignment = base_align; rtex->surface.htile_size = - (util_max_layer(&rtex->resource.b.b, 0) + 1) * + util_num_layers(&rtex->resource.b.b, 0) * align(slice_bytes, base_align); } @@ -827,7 +861,7 @@ void r600_print_texture_info(struct r600_common_screen *rscreen, rtex->cmask.slice_tile_max); if (rtex->htile_offset) - u_log_printf(log, " HTile: offset=%"PRIu64", size=%"PRIu64", " + u_log_printf(log, " HTile: offset=%"PRIu64", size=%u " "alignment=%u\n", rtex->htile_offset, rtex->surface.htile_size, rtex->surface.htile_alignment); @@ -837,7 +871,7 @@ void r600_print_texture_info(struct r600_common_screen *rscreen, "npix_x=%u, npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, " "mode=%u, tiling_index = %u\n", i, rtex->surface.u.legacy.level[i].offset, - rtex->surface.u.legacy.level[i].slice_size, + (uint64_t)rtex->surface.u.legacy.level[i].slice_size_dw * 4, u_minify(rtex->resource.b.b.width0, i), u_minify(rtex->resource.b.b.height0, i), u_minify(rtex->resource.b.b.depth0, i), @@ -855,7 +889,7 @@ void r600_print_texture_info(struct r600_common_screen *rscreen, "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, " "mode=%u, tiling_index = %u\n", i, rtex->surface.u.legacy.stencil_level[i].offset, - rtex->surface.u.legacy.stencil_level[i].slice_size, + (uint64_t)rtex->surface.u.legacy.stencil_level[i].slice_size_dw * 4, u_minify(rtex->resource.b.b.width0, i), u_minify(rtex->resource.b.b.height0, i), u_minify(rtex->resource.b.b.depth0, i), @@ -942,10 +976,6 @@ r600_texture_create_object(struct pipe_screen *screen, r600_init_resource_fields(rscreen, resource, rtex->size, rtex->surface.surf_alignment); - /* Displayable surfaces are not suballocated. */ - if (resource->b.b.bind & PIPE_BIND_SCANOUT) - resource->flags |= RADEON_FLAG_NO_SUBALLOC; - if (!r600_alloc_resource(rscreen, resource)) { FREE(rtex); return NULL; @@ -985,7 +1015,7 @@ r600_texture_create_object(struct pipe_screen *screen, fprintf(stderr, "VM start=0x%"PRIX64" end=0x%"PRIX64" | Texture %ix%ix%i, %i levels, %i samples, %s\n", rtex->resource.gpu_address, rtex->resource.gpu_address + rtex->resource.buf->size, - base->width0, base->height0, util_max_layer(base, 0)+1, base->last_level+1, + base->width0, base->height0, util_num_layers(base, 0), base->last_level+1, base->nr_samples ? base->nr_samples : 1, util_format_short_name(base->format)); } @@ -1042,12 +1072,9 @@ r600_choose_tiling(struct r600_common_screen *rscreen, if (templ->bind & PIPE_BIND_LINEAR) return RADEON_SURF_MODE_LINEAR_ALIGNED; - /* Textures with a very small height are recommended to be linear. */ + /* 1D textures should be linear - fixes image operations on 1d */ if (templ->target == PIPE_TEXTURE_1D || - templ->target == PIPE_TEXTURE_1D_ARRAY || - /* Only very thin and long 2D textures should benefit from - * linear_aligned. */ - (templ->width0 > 8 && templ->height0 <= 2)) + templ->target == PIPE_TEXTURE_1D_ARRAY) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Textures likely to be mapped often. */ @@ -1091,7 +1118,6 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen { struct r600_common_screen *rscreen = (struct r600_common_screen*)screen; struct pb_buffer *buf = NULL; - unsigned stride = 0, offset = 0; enum radeon_surf_mode array_mode; struct radeon_surf surface = {}; int r; @@ -1104,7 +1130,8 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen templ->depth0 != 1 || templ->last_level != 0) return NULL; - buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, &stride, &offset); + buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, + rscreen->info.max_alignment); if (!buf) return NULL; @@ -1112,8 +1139,9 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen r600_surface_import_metadata(rscreen, &surface, &metadata, &array_mode, &is_scanout); - r = r600_init_surface(rscreen, &surface, templ, array_mode, stride, - offset, true, is_scanout, false); + r = r600_init_surface(rscreen, &surface, templ, array_mode, + whandle->stride, whandle->offset, + true, is_scanout, false); if (r) { return NULL; } @@ -1125,9 +1153,6 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen rtex->resource.b.is_shared = true; rtex->resource.external_usage = usage; - if (rscreen->apply_opaque_metadata) - rscreen->apply_opaque_metadata(rscreen, rtex, &metadata); - assert(rtex->surface.tile_swizzle == 0); return &rtex->resource.b.b; } @@ -1235,7 +1260,7 @@ static bool r600_can_invalidate_texture(struct r600_common_screen *rscreen, const struct pipe_box *box) { /* r600g doesn't react to dirty_tex_descriptor_counter */ - return rscreen->chip_class >= SI && + return rscreen->chip_class >= GFX6 && !rtex->resource.b.is_shared && !(transfer_usage & PIPE_TRANSFER_READ) && rtex->resource.b.b.last_level == 0 && @@ -1489,7 +1514,7 @@ static void r600_texture_transfer_unmap(struct pipe_context *ctx, * The result is that the kernel memory manager is never a bottleneck. */ if (rctx->num_alloc_tex_transfer_bytes > rctx->screen->info.gart_size / 4) { - rctx->gfx.flush(rctx, RADEON_FLUSH_ASYNC, NULL); + rctx->gfx.flush(rctx, PIPE_FLUSH_ASYNC, NULL); rctx->num_alloc_tex_transfer_bytes = 0; } @@ -1610,11 +1635,11 @@ static void r600_clear_texture(struct pipe_context *pipe, /* Depth is always present. */ clear = PIPE_CLEAR_DEPTH; - desc->unpack_z_float(&depth, 0, data, 0, 1, 1); + util_format_unpack_z_float(tex->format, &depth, data, 1); if (rtex->surface.has_stencil) { clear |= PIPE_CLEAR_STENCIL; - desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1); + util_format_unpack_s_8uint(tex->format, &stencil, data, 1); } pipe->clear_depth_stencil(pipe, sf, clear, depth, stencil, @@ -1623,16 +1648,10 @@ static void r600_clear_texture(struct pipe_context *pipe, } else { union pipe_color_union color; - /* pipe_color_union requires the full vec4 representation. */ - if (util_format_is_pure_uint(tex->format)) - desc->unpack_rgba_uint(color.ui, 0, data, 0, 1, 1); - else if (util_format_is_pure_sint(tex->format)) - desc->unpack_rgba_sint(color.i, 0, data, 0, 1, 1); - else - desc->unpack_rgba_float(color.f, 0, data, 0, 1, 1); + util_format_unpack_rgba(tex->format, color.ui, data, 1); if (screen->is_format_supported(screen, tex->format, - tex->target, 0, + tex->target, 0, 0, PIPE_BIND_RENDER_TARGET)) { pipe->clear_render_target(pipe, sf, &color, box->x, box->y, @@ -1726,12 +1745,8 @@ static void evergreen_set_clear_color(struct r600_texture *rtex, color->ui[0] == color->ui[2]); uc.ui[0] = color->ui[0]; uc.ui[1] = color->ui[3]; - } else if (util_format_is_pure_uint(surface_format)) { - util_format_write_4ui(surface_format, color->ui, 0, &uc, 0, 0, 0, 1, 1); - } else if (util_format_is_pure_sint(surface_format)) { - util_format_write_4i(surface_format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { - util_pack_color(color->f, surface_format, &uc); + util_pack_color_union(surface_format, &uc, color); } memcpy(rtex->color_clear_value, &uc, 2 * sizeof(uint32_t)); @@ -1746,7 +1761,7 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx, int i; /* This function is broken in BE, so just disable this path for now */ -#ifdef PIPE_ARCH_BIG_ENDIAN +#if UTIL_ARCH_BIG_ENDIAN return; #endif @@ -1790,6 +1805,16 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx, !(tex->resource.external_usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) continue; + /* Use a slow clear for small surfaces where the cost of + * the eliminate pass can be higher than the benefit of fast + * clear. AMDGPU-pro does this, but the numbers may differ. + * + * This helps on both dGPUs and APUs, even small ones. + */ + if (tex->resource.b.b.nr_samples <= 1 && + tex->resource.b.b.width0 * tex->resource.b.b.height0 <= 300 * 300) + continue; + { /* 128-bit formats are unusupported */ if (tex->surface.bpe > 8) { @@ -1832,13 +1857,12 @@ r600_memobj_from_handle(struct pipe_screen *screen, struct r600_common_screen *rscreen = (struct r600_common_screen*)screen; struct r600_memory_object *memobj = CALLOC_STRUCT(r600_memory_object); struct pb_buffer *buf = NULL; - uint32_t stride, offset; if (!memobj) return NULL; buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, - &stride, &offset); + rscreen->info.max_alignment); if (!buf) { free(memobj); return NULL; @@ -1846,8 +1870,8 @@ r600_memobj_from_handle(struct pipe_screen *screen, memobj->b.dedicated = dedicated; memobj->buf = buf; - memobj->stride = stride; - memobj->offset = offset; + memobj->stride = whandle->stride; + memobj->offset = whandle->offset; return (struct pipe_memory_object *)memobj; @@ -1928,10 +1952,7 @@ r600_texture_from_memobj(struct pipe_screen *screen, pb_reference(&buf, memobj->buf); rtex->resource.b.is_shared = true; - rtex->resource.external_usage = PIPE_HANDLE_USAGE_READ_WRITE; - - if (rscreen->apply_opaque_metadata) - rscreen->apply_opaque_metadata(rscreen, rtex, &metadata); + rtex->resource.external_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; return &rtex->resource.b.b; } @@ -1940,6 +1961,7 @@ void r600_init_screen_texture_functions(struct r600_common_screen *rscreen) { rscreen->b.resource_from_handle = r600_texture_from_handle; rscreen->b.resource_get_handle = r600_texture_get_handle; + rscreen->b.resource_get_info = r600_texture_get_info; rscreen->b.resource_from_memobj = r600_texture_from_memobj; rscreen->b.memobj_create_from_handle = r600_memobj_from_handle; rscreen->b.memobj_destroy = r600_memobj_destroy;