#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 "util/os_time.h"
+#include "state_tracker/winsys_handle.h"
#include <errno.h>
#include <inttypes.h>
{
*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;
/* 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;
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) {
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;
}
* 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) {
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)
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);
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;
/* 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)) {
}
/* 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.
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,
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;
}
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);
}
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. */
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;
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);
}
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);
"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),
"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),
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;
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));
}
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. */
{
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;
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;
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;
}
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;
}
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 &&
* 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;
}
/* 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,
} 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,
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
!(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) {
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;
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;
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;
}
{
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;