2012-10-27 17:07:34 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Rob Clark <robclark@freedesktop.org>
|
|
|
|
*/
|
|
|
|
|
2019-06-27 23:05:31 +01:00
|
|
|
#include "util/format/u_format.h"
|
|
|
|
#include "util/format/u_format_rgtc.h"
|
|
|
|
#include "util/format/u_format_zs.h"
|
2012-10-27 17:07:34 +01:00
|
|
|
#include "util/u_inlines.h"
|
|
|
|
#include "util/u_transfer.h"
|
|
|
|
#include "util/u_string.h"
|
2013-03-21 21:32:00 +00:00
|
|
|
#include "util/u_surface.h"
|
2016-06-27 14:44:15 +01:00
|
|
|
#include "util/set.h"
|
2019-03-14 04:14:37 +00:00
|
|
|
#include "util/u_drm.h"
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2020-08-21 20:50:34 +01:00
|
|
|
#include "decode/util.h"
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
#include "freedreno_resource.h"
|
2016-06-27 14:44:15 +01:00
|
|
|
#include "freedreno_batch_cache.h"
|
2018-12-13 14:14:48 +00:00
|
|
|
#include "freedreno_blitter.h"
|
2018-10-04 13:05:49 +01:00
|
|
|
#include "freedreno_fence.h"
|
2012-10-27 17:07:34 +01:00
|
|
|
#include "freedreno_screen.h"
|
|
|
|
#include "freedreno_surface.h"
|
|
|
|
#include "freedreno_context.h"
|
2014-05-10 18:45:54 +01:00
|
|
|
#include "freedreno_query_hw.h"
|
2012-10-27 17:07:34 +01:00
|
|
|
#include "freedreno_util.h"
|
|
|
|
|
2019-02-12 18:18:03 +00:00
|
|
|
#include "drm-uapi/drm_fourcc.h"
|
2013-09-11 15:08:08 +01:00
|
|
|
#include <errno.h>
|
|
|
|
|
2016-04-25 16:47:21 +01:00
|
|
|
/* XXX this should go away, needed for 'struct winsys_handle' */
|
2019-12-03 23:01:31 +00:00
|
|
|
#include "frontend/drm_driver.h"
|
2015-07-31 17:07:24 +01:00
|
|
|
|
2019-06-07 18:14:12 +01:00
|
|
|
/* A private modifier for now, so we have a way to request tiled but not
|
|
|
|
* compressed. It would perhaps be good to get real modifiers for the
|
|
|
|
* tiled formats, but would probably need to do some work to figure out
|
|
|
|
* the layout(s) of the tiled modes, and whether they are the same
|
|
|
|
* across generations.
|
|
|
|
*/
|
|
|
|
#define FD_FORMAT_MOD_QCOM_TILED fourcc_mod_code(QCOM, 0xffffffff)
|
|
|
|
|
2017-10-05 22:07:27 +01:00
|
|
|
/**
|
|
|
|
* Go through the entire state and see if the resource is bound
|
|
|
|
* anywhere. If it is, mark the relevant state as dirty. This is
|
2020-04-24 21:54:43 +01:00
|
|
|
* called on realloc_bo to ensure the necessary state is re-
|
2017-10-05 22:07:27 +01:00
|
|
|
* emitted so the GPU looks at the new backing bo.
|
|
|
|
*/
|
2015-04-04 03:29:44 +01:00
|
|
|
static void
|
2020-04-24 22:45:04 +01:00
|
|
|
rebind_resource_in_ctx(struct fd_context *ctx, struct fd_resource *rsc)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2015-04-04 03:29:44 +01:00
|
|
|
{
|
2020-04-24 22:45:04 +01:00
|
|
|
struct pipe_resource *prsc = &rsc->base;
|
|
|
|
|
2020-04-24 23:15:09 +01:00
|
|
|
if (ctx->rebind_resource)
|
|
|
|
ctx->rebind_resource(ctx, rsc);
|
|
|
|
|
2015-04-04 03:29:44 +01:00
|
|
|
/* VBOs */
|
2020-04-24 22:45:04 +01:00
|
|
|
if (rsc->dirty & FD_DIRTY_VTXBUF) {
|
|
|
|
struct fd_vertexbuf_stateobj *vb = &ctx->vtx.vertexbuf;
|
|
|
|
for (unsigned i = 0; i < vb->count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) {
|
|
|
|
if (vb->vb[i].buffer.resource == prsc)
|
|
|
|
ctx->dirty |= FD_DIRTY_VTXBUF;
|
|
|
|
}
|
2015-04-04 03:29:44 +01:00
|
|
|
}
|
|
|
|
|
2020-04-24 22:45:04 +01:00
|
|
|
const enum fd_dirty_3d_state per_stage_dirty =
|
|
|
|
FD_DIRTY_CONST | FD_DIRTY_TEX | FD_DIRTY_IMAGE | FD_DIRTY_SSBO;
|
|
|
|
|
|
|
|
if (!(rsc->dirty & per_stage_dirty))
|
|
|
|
return;
|
|
|
|
|
2017-04-15 15:04:55 +01:00
|
|
|
/* per-shader-stage resources: */
|
|
|
|
for (unsigned stage = 0; stage < PIPE_SHADER_TYPES; stage++) {
|
|
|
|
/* Constbufs.. note that constbuf[0] is normal uniforms emitted in
|
|
|
|
* cmdstream rather than by pointer..
|
|
|
|
*/
|
2020-04-24 22:45:04 +01:00
|
|
|
if ((rsc->dirty & FD_DIRTY_CONST) &&
|
|
|
|
!(ctx->dirty_shader[stage] & FD_DIRTY_CONST)) {
|
|
|
|
struct fd_constbuf_stateobj *cb = &ctx->constbuf[stage];
|
|
|
|
const unsigned num_ubos = util_last_bit(cb->enabled_mask);
|
|
|
|
for (unsigned i = 1; i < num_ubos; i++) {
|
|
|
|
if (cb->cb[i].buffer == prsc) {
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_CONST;
|
|
|
|
ctx->dirty |= FD_DIRTY_CONST;
|
|
|
|
break;
|
|
|
|
}
|
2020-04-24 21:54:43 +01:00
|
|
|
}
|
2017-04-15 15:04:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Textures */
|
2020-04-24 22:45:04 +01:00
|
|
|
if ((rsc->dirty & FD_DIRTY_TEX) &&
|
|
|
|
!(ctx->dirty_shader[stage] & FD_DIRTY_TEX)) {
|
|
|
|
struct fd_texture_stateobj *tex = &ctx->tex[stage];
|
|
|
|
for (unsigned i = 0; i < tex->num_textures; i++) {
|
|
|
|
if (tex->textures[i] && (tex->textures[i]->texture == prsc)) {
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_TEX;
|
|
|
|
ctx->dirty |= FD_DIRTY_TEX;
|
|
|
|
break;
|
|
|
|
}
|
2020-04-24 21:54:43 +01:00
|
|
|
}
|
2017-04-15 15:04:55 +01:00
|
|
|
}
|
2017-04-17 15:56:20 +01:00
|
|
|
|
2019-06-07 19:20:11 +01:00
|
|
|
/* Images */
|
2020-04-24 22:45:04 +01:00
|
|
|
if ((rsc->dirty & FD_DIRTY_IMAGE) &&
|
|
|
|
!(ctx->dirty_shader[stage] & FD_DIRTY_IMAGE)) {
|
|
|
|
struct fd_shaderimg_stateobj *si = &ctx->shaderimg[stage];
|
|
|
|
const unsigned num_images = util_last_bit(si->enabled_mask);
|
|
|
|
for (unsigned i = 0; i < num_images; i++) {
|
|
|
|
if (si->si[i].resource == prsc) {
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_IMAGE;
|
|
|
|
ctx->dirty |= FD_DIRTY_IMAGE;
|
|
|
|
break;
|
|
|
|
}
|
2020-04-24 21:54:43 +01:00
|
|
|
}
|
2019-06-07 19:20:11 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 15:56:20 +01:00
|
|
|
/* SSBOs */
|
2020-04-24 22:45:04 +01:00
|
|
|
if ((rsc->dirty & FD_DIRTY_SSBO) &&
|
|
|
|
!(ctx->dirty_shader[stage] & FD_DIRTY_SSBO)) {
|
|
|
|
struct fd_shaderbuf_stateobj *sb = &ctx->shaderbuf[stage];
|
|
|
|
const unsigned num_ssbos = util_last_bit(sb->enabled_mask);
|
|
|
|
for (unsigned i = 0; i < num_ssbos; i++) {
|
|
|
|
if (sb->sb[i].buffer == prsc) {
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_SSBO;
|
|
|
|
ctx->dirty |= FD_DIRTY_SSBO;
|
|
|
|
break;
|
|
|
|
}
|
2020-04-24 21:54:43 +01:00
|
|
|
}
|
2017-04-17 15:56:20 +01:00
|
|
|
}
|
2015-04-04 03:29:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 22:45:04 +01:00
|
|
|
static void
|
2020-04-24 23:00:20 +01:00
|
|
|
rebind_resource(struct fd_resource *rsc)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2020-04-24 22:45:04 +01:00
|
|
|
{
|
2020-04-24 23:00:20 +01:00
|
|
|
struct fd_screen *screen = fd_screen(rsc->base.screen);
|
|
|
|
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_lock(screen);
|
2020-04-24 22:45:04 +01:00
|
|
|
fd_resource_lock(rsc);
|
2020-04-24 23:00:20 +01:00
|
|
|
|
|
|
|
if (rsc->dirty)
|
|
|
|
list_for_each_entry (struct fd_context, ctx, &screen->context_list, node)
|
|
|
|
rebind_resource_in_ctx(ctx, rsc);
|
|
|
|
|
2020-04-24 22:45:04 +01:00
|
|
|
fd_resource_unlock(rsc);
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_unlock(screen);
|
2020-04-24 22:45:04 +01:00
|
|
|
}
|
|
|
|
|
2020-09-01 19:23:49 +01:00
|
|
|
static inline void
|
|
|
|
fd_resource_set_bo(struct fd_resource *rsc, struct fd_bo *bo)
|
|
|
|
{
|
|
|
|
struct fd_screen *screen = fd_screen(rsc->base.screen);
|
|
|
|
|
|
|
|
rsc->bo = bo;
|
|
|
|
rsc->seqno = p_atomic_inc_return(&screen->rsc_seqno);
|
|
|
|
}
|
|
|
|
|
2013-09-11 15:08:08 +01:00
|
|
|
static void
|
|
|
|
realloc_bo(struct fd_resource *rsc, uint32_t size)
|
|
|
|
{
|
2018-11-30 13:29:51 +00:00
|
|
|
struct pipe_resource *prsc = &rsc->base;
|
2017-12-04 14:02:07 +00:00
|
|
|
struct fd_screen *screen = fd_screen(rsc->base.screen);
|
2013-09-11 15:08:08 +01:00
|
|
|
uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
|
2018-11-19 21:02:15 +00:00
|
|
|
DRM_FREEDRENO_GEM_TYPE_KMEM |
|
2018-11-30 13:29:51 +00:00
|
|
|
COND(prsc->bind & PIPE_BIND_SCANOUT, DRM_FREEDRENO_GEM_SCANOUT);
|
2018-11-19 21:02:15 +00:00
|
|
|
/* TODO other flags? */
|
2013-09-11 15:08:08 +01:00
|
|
|
|
2014-05-24 15:07:13 +01:00
|
|
|
/* if we start using things other than write-combine,
|
|
|
|
* be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT
|
|
|
|
*/
|
|
|
|
|
2013-09-11 15:08:08 +01:00
|
|
|
if (rsc->bo)
|
|
|
|
fd_bo_del(rsc->bo);
|
|
|
|
|
2020-09-01 19:23:49 +01:00
|
|
|
struct fd_bo *bo = fd_bo_new(screen->dev, size, flags, "%ux%ux%u@%u:%x",
|
2019-05-05 18:59:37 +01:00
|
|
|
prsc->width0, prsc->height0, prsc->depth0, rsc->layout.cpp, prsc->bind);
|
2020-09-01 19:23:49 +01:00
|
|
|
fd_resource_set_bo(rsc, bo);
|
2020-03-23 21:55:50 +00:00
|
|
|
|
|
|
|
/* Zero out the UBWC area on allocation. This fixes intermittent failures
|
|
|
|
* with UBWC, which I suspect are due to the HW having a hard time
|
|
|
|
* interpreting arbitrary values populating the flags buffer when the BO
|
|
|
|
* was recycled through the bo cache (instead of fresh allocations from
|
|
|
|
* the kernel, which are zeroed). sleep(1) in this spot didn't work
|
|
|
|
* around the issue, but any memset value seems to.
|
|
|
|
*/
|
|
|
|
if (rsc->layout.ubwc) {
|
2020-08-26 19:47:02 +01:00
|
|
|
rsc->needs_ubwc_clear = true;
|
2020-03-23 21:55:50 +00:00
|
|
|
}
|
|
|
|
|
2015-04-03 07:15:17 +01:00
|
|
|
util_range_set_empty(&rsc->valid_buffer_range);
|
2016-06-27 14:44:15 +01:00
|
|
|
fd_bc_invalidate_resource(rsc, true);
|
2013-09-11 15:08:08 +01:00
|
|
|
}
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
static void
|
|
|
|
do_blit(struct fd_context *ctx, const struct pipe_blit_info *blit, bool fallback)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2016-06-29 18:51:26 +01:00
|
|
|
{
|
freedreno: rework blit API
First step to unify the way fd5 and fd6 blitter works. Currently a6xx
bypasses the blit API in order to also accelerate resource_copy_region()
But this approach can lead to infinite recursion:
#0 fd_alloc_staging (ctx=0x5555936480, rsc=0x7fac485f90, level=0, box=0x7fbab29220) at ../src/gallium/drivers/freedreno/freedreno_resource.c:291
#1 0x0000007fbdebed04 in fd_resource_transfer_map (pctx=0x5555936480, prsc=0x7fac485f90, level=0, usage=258, box=0x7fbab29220, pptrans=0x7fbab29240) at ../src/gallium/drivers/freedreno/freedreno_resource.c:479
#2 0x0000007fbe5c5068 in u_transfer_helper_transfer_map (pctx=0x5555936480, prsc=0x7fac485f90, level=0, usage=258, box=0x7fbab29220, pptrans=0x7fbab29240) at ../src/gallium/auxiliary/util/u_transfer_helper.c:243
#3 0x0000007fbde2dcb8 in util_resource_copy_region (pipe=0x5555936480, dst=0x7fac485f90, dst_level=0, dst_x=0, dst_y=0, dst_z=0, src=0x7fac47c780, src_level=0, src_box_in=0x7fbab2945c) at ../src/gallium/auxiliary/util/u_surface.c:350
#4 0x0000007fbdf2282c in fd_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47c780, src_level=0, src_box=0x7fbab2945c) at ../src/gallium/drivers/freedreno/freedreno_blitter.c:173
#5 0x0000007fbdf085d4 in fd6_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47c780, src_level=0, src_box=0x7fbab2945c) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:587
#6 0x0000007fbde2f3d0 in util_try_blit_via_copy_region (ctx=0x5555936480, blit=0x7fbab29430) at ../src/gallium/auxiliary/util/u_surface.c:864
#7 0x0000007fbdec02c4 in fd_blit (pctx=0x5555936480, blit_info=0x7fbab29588) at ../src/gallium/drivers/freedreno/freedreno_resource.c:993
#8 0x0000007fbdf08408 in fd6_blit (pctx=0x5555936480, info=0x7fbab29588) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:546
#9 0x0000007fbdebdc74 in do_blit (ctx=0x5555936480, blit=0x7fbab29588, fallback=false) at ../src/gallium/drivers/freedreno/freedreno_resource.c:129
#10 0x0000007fbdebe58c in fd_blit_from_staging (ctx=0x5555936480, trans=0x7fac47b7e8) at ../src/gallium/drivers/freedreno/freedreno_resource.c:326
#11 0x0000007fbdebea38 in fd_resource_transfer_unmap (pctx=0x5555936480, ptrans=0x7fac47b7e8) at ../src/gallium/drivers/freedreno/freedreno_resource.c:416
#12 0x0000007fbe5c5c68 in u_transfer_helper_transfer_unmap (pctx=0x5555936480, ptrans=0x7fac47b7e8) at ../src/gallium/auxiliary/util/u_transfer_helper.c:516
#13 0x0000007fbde2de24 in util_resource_copy_region (pipe=0x5555936480, dst=0x7fac485f90, dst_level=0, dst_x=0, dst_y=0, dst_z=0, src=0x7fac47b8e0, src_level=0, src_box_in=0x7fbab2997c) at ../src/gallium/auxiliary/util/u_surface.c:376
#14 0x0000007fbdf2282c in fd_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47b8e0, src_level=0, src_box=0x7fbab2997c) at ../src/gallium/drivers/freedreno/freedreno_blitter.c:173
#15 0x0000007fbdf085d4 in fd6_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47b8e0, src_level=0, src_box=0x7fbab2997c) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:587
...
Instead rework the API to push the fallback back to core code, so that
we can rework resource_copy_region() to have it's own fallback path,
and then finally convert fd6 over to work in the same way.
This also makes ctx->blit() optional, and cleans up some unnecessary
callers.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-02 15:54:06 +00:00
|
|
|
struct pipe_context *pctx = &ctx->base;
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
/* TODO size threshold too?? */
|
2019-02-26 16:54:56 +00:00
|
|
|
if (fallback || !fd_blit(pctx, blit)) {
|
2016-06-29 18:51:26 +01:00
|
|
|
/* do blit on cpu: */
|
freedreno: rework blit API
First step to unify the way fd5 and fd6 blitter works. Currently a6xx
bypasses the blit API in order to also accelerate resource_copy_region()
But this approach can lead to infinite recursion:
#0 fd_alloc_staging (ctx=0x5555936480, rsc=0x7fac485f90, level=0, box=0x7fbab29220) at ../src/gallium/drivers/freedreno/freedreno_resource.c:291
#1 0x0000007fbdebed04 in fd_resource_transfer_map (pctx=0x5555936480, prsc=0x7fac485f90, level=0, usage=258, box=0x7fbab29220, pptrans=0x7fbab29240) at ../src/gallium/drivers/freedreno/freedreno_resource.c:479
#2 0x0000007fbe5c5068 in u_transfer_helper_transfer_map (pctx=0x5555936480, prsc=0x7fac485f90, level=0, usage=258, box=0x7fbab29220, pptrans=0x7fbab29240) at ../src/gallium/auxiliary/util/u_transfer_helper.c:243
#3 0x0000007fbde2dcb8 in util_resource_copy_region (pipe=0x5555936480, dst=0x7fac485f90, dst_level=0, dst_x=0, dst_y=0, dst_z=0, src=0x7fac47c780, src_level=0, src_box_in=0x7fbab2945c) at ../src/gallium/auxiliary/util/u_surface.c:350
#4 0x0000007fbdf2282c in fd_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47c780, src_level=0, src_box=0x7fbab2945c) at ../src/gallium/drivers/freedreno/freedreno_blitter.c:173
#5 0x0000007fbdf085d4 in fd6_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47c780, src_level=0, src_box=0x7fbab2945c) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:587
#6 0x0000007fbde2f3d0 in util_try_blit_via_copy_region (ctx=0x5555936480, blit=0x7fbab29430) at ../src/gallium/auxiliary/util/u_surface.c:864
#7 0x0000007fbdec02c4 in fd_blit (pctx=0x5555936480, blit_info=0x7fbab29588) at ../src/gallium/drivers/freedreno/freedreno_resource.c:993
#8 0x0000007fbdf08408 in fd6_blit (pctx=0x5555936480, info=0x7fbab29588) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:546
#9 0x0000007fbdebdc74 in do_blit (ctx=0x5555936480, blit=0x7fbab29588, fallback=false) at ../src/gallium/drivers/freedreno/freedreno_resource.c:129
#10 0x0000007fbdebe58c in fd_blit_from_staging (ctx=0x5555936480, trans=0x7fac47b7e8) at ../src/gallium/drivers/freedreno/freedreno_resource.c:326
#11 0x0000007fbdebea38 in fd_resource_transfer_unmap (pctx=0x5555936480, ptrans=0x7fac47b7e8) at ../src/gallium/drivers/freedreno/freedreno_resource.c:416
#12 0x0000007fbe5c5c68 in u_transfer_helper_transfer_unmap (pctx=0x5555936480, ptrans=0x7fac47b7e8) at ../src/gallium/auxiliary/util/u_transfer_helper.c:516
#13 0x0000007fbde2de24 in util_resource_copy_region (pipe=0x5555936480, dst=0x7fac485f90, dst_level=0, dst_x=0, dst_y=0, dst_z=0, src=0x7fac47b8e0, src_level=0, src_box_in=0x7fbab2997c) at ../src/gallium/auxiliary/util/u_surface.c:376
#14 0x0000007fbdf2282c in fd_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47b8e0, src_level=0, src_box=0x7fbab2997c) at ../src/gallium/drivers/freedreno/freedreno_blitter.c:173
#15 0x0000007fbdf085d4 in fd6_resource_copy_region (pctx=0x5555936480, dst=0x7fac485f90, dst_level=0, dstx=0, dsty=0, dstz=0, src=0x7fac47b8e0, src_level=0, src_box=0x7fbab2997c) at ../src/gallium/drivers/freedreno/a6xx/fd6_blitter.c:587
...
Instead rework the API to push the fallback back to core code, so that
we can rework resource_copy_region() to have it's own fallback path,
and then finally convert fd6 over to work in the same way.
This also makes ctx->blit() optional, and cleans up some unnecessary
callers.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-02 15:54:06 +00:00
|
|
|
util_resource_copy_region(pctx,
|
2016-06-29 18:51:26 +01:00
|
|
|
blit->dst.resource, blit->dst.level, blit->dst.box.x,
|
|
|
|
blit->dst.box.y, blit->dst.box.z,
|
|
|
|
blit->src.resource, blit->src.level, &blit->src.box);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-21 23:58:37 +01:00
|
|
|
static void
|
|
|
|
flush_resource(struct fd_context *ctx, struct fd_resource *rsc, unsigned usage);
|
|
|
|
|
2019-06-07 17:39:30 +01:00
|
|
|
/**
|
|
|
|
* @rsc: the resource to shadow
|
|
|
|
* @level: the level to discard (if box != NULL, otherwise ignored)
|
|
|
|
* @box: the box to discard (or NULL if none)
|
|
|
|
* @modifier: the modifier for the new buffer state
|
|
|
|
*/
|
2016-06-29 18:51:26 +01:00
|
|
|
static bool
|
|
|
|
fd_try_shadow_resource(struct fd_context *ctx, struct fd_resource *rsc,
|
2019-06-07 17:23:16 +01:00
|
|
|
unsigned level, const struct pipe_box *box, uint64_t modifier)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2016-06-29 18:51:26 +01:00
|
|
|
{
|
|
|
|
struct pipe_context *pctx = &ctx->base;
|
2017-12-04 14:02:07 +00:00
|
|
|
struct pipe_resource *prsc = &rsc->base;
|
2016-06-29 18:51:26 +01:00
|
|
|
bool fallback = false;
|
|
|
|
|
2016-10-07 16:59:28 +01:00
|
|
|
if (prsc->next)
|
|
|
|
return false;
|
|
|
|
|
2020-08-21 23:58:37 +01:00
|
|
|
/* If you have a sequence where there is a single rsc associated
|
|
|
|
* with the current render target, and then you end up shadowing
|
|
|
|
* that same rsc on the 3d pipe (u_blitter), because of how we
|
|
|
|
* swap the new shadow and rsc before the back-blit, you could end
|
|
|
|
* up confusing things into thinking that u_blitter's framebuffer
|
|
|
|
* state is the same as the current framebuffer state, which has
|
|
|
|
* the result of blitting to rsc rather than shadow.
|
|
|
|
*
|
|
|
|
* Normally we wouldn't want to unconditionally trigger a flush,
|
|
|
|
* since that defeats the purpose of shadowing, but this is a
|
|
|
|
* case where we'd have to flush anyways.
|
|
|
|
*/
|
|
|
|
if (rsc->write_batch == ctx->batch)
|
|
|
|
flush_resource(ctx, rsc, 0);
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
/* TODO: somehow munge dimensions and format to copy unsupported
|
|
|
|
* render target format to something that is supported?
|
|
|
|
*/
|
|
|
|
if (!pctx->screen->is_format_supported(pctx->screen,
|
|
|
|
prsc->format, prsc->target, prsc->nr_samples,
|
2018-05-23 23:46:19 +01:00
|
|
|
prsc->nr_storage_samples,
|
2016-06-29 18:51:26 +01:00
|
|
|
PIPE_BIND_RENDER_TARGET))
|
|
|
|
fallback = true;
|
|
|
|
|
2017-11-20 20:33:54 +00:00
|
|
|
/* do shadowing back-blits on the cpu for buffers: */
|
|
|
|
if (prsc->target == PIPE_BUFFER)
|
|
|
|
fallback = true;
|
2016-06-29 18:51:26 +01:00
|
|
|
|
2019-06-07 17:39:30 +01:00
|
|
|
bool discard_whole_level = box && util_texrange_covers_whole_level(prsc, level,
|
2016-06-29 18:51:26 +01:00
|
|
|
box->x, box->y, box->z, box->width, box->height, box->depth);
|
|
|
|
|
|
|
|
/* TODO need to be more clever about current level */
|
2019-06-07 17:39:30 +01:00
|
|
|
if ((prsc->target >= PIPE_TEXTURE_2D) && box && !discard_whole_level)
|
2016-06-29 18:51:26 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
struct pipe_resource *pshadow =
|
2019-06-07 17:23:16 +01:00
|
|
|
pctx->screen->resource_create_with_modifiers(pctx->screen,
|
|
|
|
prsc, &modifier, 1);
|
2016-06-29 18:51:26 +01:00
|
|
|
|
|
|
|
if (!pshadow)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert(!ctx->in_shadow);
|
|
|
|
ctx->in_shadow = true;
|
|
|
|
|
|
|
|
/* get rid of any references that batch-cache might have to us (which
|
|
|
|
* should empty/destroy rsc->batches hashset)
|
|
|
|
*/
|
|
|
|
fd_bc_invalidate_resource(rsc, false);
|
2020-04-24 23:10:49 +01:00
|
|
|
rebind_resource(rsc);
|
2016-06-29 18:51:26 +01:00
|
|
|
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_lock(ctx->screen);
|
2016-07-19 23:24:57 +01:00
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
/* Swap the backing bo's, so shadow becomes the old buffer,
|
|
|
|
* blit from shadow to new buffer. From here on out, we
|
|
|
|
* cannot fail.
|
|
|
|
*
|
|
|
|
* Note that we need to do it in this order, otherwise if
|
|
|
|
* we go down cpu blit path, the recursive transfer_map()
|
|
|
|
* sees the wrong status..
|
|
|
|
*/
|
|
|
|
struct fd_resource *shadow = fd_resource(pshadow);
|
|
|
|
|
2017-12-04 14:02:07 +00:00
|
|
|
DBG("shadow: %p (%d) -> %p (%d)\n", rsc, rsc->base.reference.count,
|
|
|
|
shadow, shadow->base.reference.count);
|
2016-06-29 18:51:26 +01:00
|
|
|
|
|
|
|
/* TODO valid_buffer_range?? */
|
|
|
|
swap(rsc->bo, shadow->bo);
|
|
|
|
swap(rsc->write_batch, shadow->write_batch);
|
2019-12-12 20:49:12 +00:00
|
|
|
swap(rsc->layout, shadow->layout);
|
2018-10-12 14:24:21 +01:00
|
|
|
rsc->seqno = p_atomic_inc_return(&ctx->screen->rsc_seqno);
|
2016-06-29 18:51:26 +01:00
|
|
|
|
|
|
|
/* at this point, the newly created shadow buffer is not referenced
|
|
|
|
* by any batches, but the existing rsc (probably) is. We need to
|
|
|
|
* transfer those references over:
|
|
|
|
*/
|
|
|
|
debug_assert(shadow->batch_mask == 0);
|
|
|
|
struct fd_batch *batch;
|
|
|
|
foreach_batch(batch, &ctx->screen->batch_cache, rsc->batch_mask) {
|
|
|
|
struct set_entry *entry = _mesa_set_search(batch->resources, rsc);
|
|
|
|
_mesa_set_remove(batch->resources, entry);
|
|
|
|
_mesa_set_add(batch->resources, shadow);
|
|
|
|
}
|
|
|
|
swap(rsc->batch_mask, shadow->batch_mask);
|
|
|
|
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_unlock(ctx->screen);
|
2016-07-19 23:24:57 +01:00
|
|
|
|
2018-08-15 17:18:39 +01:00
|
|
|
struct pipe_blit_info blit = {};
|
2016-06-29 18:51:26 +01:00
|
|
|
blit.dst.resource = prsc;
|
|
|
|
blit.dst.format = prsc->format;
|
|
|
|
blit.src.resource = pshadow;
|
|
|
|
blit.src.format = pshadow->format;
|
|
|
|
blit.mask = util_format_get_mask(prsc->format);
|
|
|
|
blit.filter = PIPE_TEX_FILTER_NEAREST;
|
|
|
|
|
|
|
|
#define set_box(field, val) do { \
|
|
|
|
blit.dst.field = (val); \
|
|
|
|
blit.src.field = (val); \
|
|
|
|
} while (0)
|
|
|
|
|
2021-02-01 19:52:12 +00:00
|
|
|
/* Disable occlusion queries during shadow blits. */
|
|
|
|
bool saved_active_queries = ctx->active_queries;
|
|
|
|
pctx->set_active_query_state(pctx, false);
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
/* blit the other levels in their entirety: */
|
|
|
|
for (unsigned l = 0; l <= prsc->last_level; l++) {
|
2019-06-07 17:39:30 +01:00
|
|
|
if (box && l == level)
|
2016-06-29 18:51:26 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* just blit whole level: */
|
|
|
|
set_box(level, l);
|
|
|
|
set_box(box.width, u_minify(prsc->width0, l));
|
|
|
|
set_box(box.height, u_minify(prsc->height0, l));
|
|
|
|
set_box(box.depth, u_minify(prsc->depth0, l));
|
|
|
|
|
2019-12-12 22:20:49 +00:00
|
|
|
for (int i = 0; i < prsc->array_size; i++) {
|
|
|
|
set_box(box.z, i);
|
|
|
|
do_blit(ctx, &blit, fallback);
|
|
|
|
}
|
2016-06-29 18:51:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* deal w/ current level specially, since we might need to split
|
|
|
|
* it up into a couple blits:
|
|
|
|
*/
|
2019-06-07 17:39:30 +01:00
|
|
|
if (box && !discard_whole_level) {
|
2016-06-29 18:51:26 +01:00
|
|
|
set_box(level, level);
|
|
|
|
|
|
|
|
switch (prsc->target) {
|
|
|
|
case PIPE_BUFFER:
|
|
|
|
case PIPE_TEXTURE_1D:
|
|
|
|
set_box(box.y, 0);
|
|
|
|
set_box(box.z, 0);
|
|
|
|
set_box(box.height, 1);
|
|
|
|
set_box(box.depth, 1);
|
|
|
|
|
|
|
|
if (box->x > 0) {
|
|
|
|
set_box(box.x, 0);
|
|
|
|
set_box(box.width, box->x);
|
|
|
|
|
|
|
|
do_blit(ctx, &blit, fallback);
|
|
|
|
}
|
|
|
|
if ((box->x + box->width) < u_minify(prsc->width0, level)) {
|
|
|
|
set_box(box.x, box->x + box->width);
|
|
|
|
set_box(box.width, u_minify(prsc->width0, level) - (box->x + box->width));
|
|
|
|
|
|
|
|
do_blit(ctx, &blit, fallback);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIPE_TEXTURE_2D:
|
|
|
|
/* TODO */
|
|
|
|
default:
|
|
|
|
unreachable("TODO");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 19:52:12 +00:00
|
|
|
pctx->set_active_query_state(pctx, saved_active_queries);
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
ctx->in_shadow = false;
|
|
|
|
|
|
|
|
pipe_resource_reference(&pshadow, NULL);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-06-07 18:14:12 +01:00
|
|
|
/**
|
|
|
|
* Uncompress an UBWC compressed buffer "in place". This works basically
|
|
|
|
* like resource shadowing, creating a new resource, and doing an uncompress
|
|
|
|
* blit, and swapping the state between shadow and original resource so it
|
2019-12-04 01:38:14 +00:00
|
|
|
* appears to the gallium frontends as if nothing changed.
|
2019-06-07 18:14:12 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc)
|
|
|
|
{
|
|
|
|
bool success =
|
|
|
|
fd_try_shadow_resource(ctx, rsc, 0, NULL, FD_FORMAT_MOD_QCOM_TILED);
|
|
|
|
|
|
|
|
/* shadow should not fail in any cases where we need to uncompress: */
|
|
|
|
debug_assert(success);
|
|
|
|
}
|
|
|
|
|
2020-08-21 20:50:34 +01:00
|
|
|
/**
|
|
|
|
* Debug helper to hexdump a resource.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
fd_resource_dump(struct fd_resource *rsc, const char *name)
|
|
|
|
{
|
|
|
|
fd_bo_cpu_prep(rsc->bo, NULL, DRM_FREEDRENO_PREP_READ);
|
|
|
|
printf("%s: \n", name);
|
|
|
|
dump_hex(fd_bo_map(rsc->bo), fd_bo_size(rsc->bo));
|
|
|
|
}
|
|
|
|
|
2017-11-20 20:34:40 +00:00
|
|
|
static struct fd_resource *
|
|
|
|
fd_alloc_staging(struct fd_context *ctx, struct fd_resource *rsc,
|
|
|
|
unsigned level, const struct pipe_box *box)
|
|
|
|
{
|
|
|
|
struct pipe_context *pctx = &ctx->base;
|
|
|
|
struct pipe_resource tmpl = rsc->base;
|
|
|
|
|
|
|
|
tmpl.width0 = box->width;
|
|
|
|
tmpl.height0 = box->height;
|
2019-01-02 18:24:31 +00:00
|
|
|
/* for array textures, box->depth is the array_size, otherwise
|
|
|
|
* for 3d textures, it is the depth:
|
|
|
|
*/
|
|
|
|
if (tmpl.array_size > 1) {
|
2019-06-12 21:36:18 +01:00
|
|
|
if (tmpl.target == PIPE_TEXTURE_CUBE)
|
|
|
|
tmpl.target = PIPE_TEXTURE_2D_ARRAY;
|
2019-01-02 18:24:31 +00:00
|
|
|
tmpl.array_size = box->depth;
|
|
|
|
tmpl.depth0 = 1;
|
|
|
|
} else {
|
|
|
|
tmpl.array_size = 1;
|
|
|
|
tmpl.depth0 = box->depth;
|
|
|
|
}
|
2017-11-20 20:34:40 +00:00
|
|
|
tmpl.last_level = 0;
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
tmpl.bind |= PIPE_BIND_LINEAR;
|
2021-01-22 17:19:09 +00:00
|
|
|
tmpl.usage = PIPE_USAGE_STAGING;
|
2017-11-20 20:34:40 +00:00
|
|
|
|
|
|
|
struct pipe_resource *pstaging =
|
|
|
|
pctx->screen->resource_create(pctx->screen, &tmpl);
|
|
|
|
if (!pstaging)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return fd_resource(pstaging);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
fd_blit_from_staging(struct fd_context *ctx, struct fd_transfer *trans)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2017-11-20 20:34:40 +00:00
|
|
|
{
|
|
|
|
struct pipe_resource *dst = trans->base.resource;
|
2018-08-15 17:18:39 +01:00
|
|
|
struct pipe_blit_info blit = {};
|
2017-11-20 20:34:40 +00:00
|
|
|
|
|
|
|
blit.dst.resource = dst;
|
|
|
|
blit.dst.format = dst->format;
|
|
|
|
blit.dst.level = trans->base.level;
|
|
|
|
blit.dst.box = trans->base.box;
|
|
|
|
blit.src.resource = trans->staging_prsc;
|
|
|
|
blit.src.format = trans->staging_prsc->format;
|
|
|
|
blit.src.level = 0;
|
|
|
|
blit.src.box = trans->staging_box;
|
|
|
|
blit.mask = util_format_get_mask(trans->staging_prsc->format);
|
|
|
|
blit.filter = PIPE_TEX_FILTER_NEAREST;
|
|
|
|
|
|
|
|
do_blit(ctx, &blit, false);
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fd_blit_to_staging(struct fd_context *ctx, struct fd_transfer *trans)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
{
|
|
|
|
struct pipe_resource *src = trans->base.resource;
|
2018-08-15 17:18:39 +01:00
|
|
|
struct pipe_blit_info blit = {};
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
|
|
|
|
blit.src.resource = src;
|
|
|
|
blit.src.format = src->format;
|
|
|
|
blit.src.level = trans->base.level;
|
|
|
|
blit.src.box = trans->base.box;
|
|
|
|
blit.dst.resource = trans->staging_prsc;
|
|
|
|
blit.dst.format = trans->staging_prsc->format;
|
|
|
|
blit.dst.level = 0;
|
|
|
|
blit.dst.box = trans->staging_box;
|
|
|
|
blit.mask = util_format_get_mask(trans->staging_prsc->format);
|
|
|
|
blit.filter = PIPE_TEX_FILTER_NEAREST;
|
|
|
|
|
|
|
|
do_blit(ctx, &blit, false);
|
2017-11-20 20:34:40 +00:00
|
|
|
}
|
|
|
|
|
2013-05-26 22:13:27 +01:00
|
|
|
static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
|
|
|
|
struct pipe_transfer *ptrans,
|
|
|
|
const struct pipe_box *box)
|
|
|
|
{
|
2015-04-03 07:15:17 +01:00
|
|
|
struct fd_resource *rsc = fd_resource(ptrans->resource);
|
|
|
|
|
|
|
|
if (ptrans->resource->target == PIPE_BUFFER)
|
2019-09-26 02:38:40 +01:00
|
|
|
util_range_add(&rsc->base, &rsc->valid_buffer_range,
|
2015-04-03 07:15:17 +01:00
|
|
|
ptrans->box.x + box->x,
|
|
|
|
ptrans->box.x + box->x + box->width);
|
2013-05-26 22:13:27 +01:00
|
|
|
}
|
|
|
|
|
2017-11-20 20:34:40 +00:00
|
|
|
static void
|
|
|
|
flush_resource(struct fd_context *ctx, struct fd_resource *rsc, unsigned usage)
|
2021-02-12 20:42:01 +00:00
|
|
|
assert_dt
|
2017-11-20 20:34:40 +00:00
|
|
|
{
|
|
|
|
struct fd_batch *write_batch = NULL;
|
|
|
|
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_lock(ctx->screen);
|
2019-02-19 14:29:49 +00:00
|
|
|
fd_batch_reference_locked(&write_batch, rsc->write_batch);
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_unlock(ctx->screen);
|
2017-11-20 20:34:40 +00:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_WRITE) {
|
2018-08-15 17:18:39 +01:00
|
|
|
struct fd_batch *batch, *batches[32] = {};
|
2017-11-20 20:34:40 +00:00
|
|
|
uint32_t batch_mask;
|
|
|
|
|
|
|
|
/* This is a bit awkward, probably a fd_batch_flush_locked()
|
|
|
|
* would make things simpler.. but we need to hold the lock
|
|
|
|
* to iterate the batches which reference this resource. So
|
|
|
|
* we must first grab references under a lock, then flush.
|
|
|
|
*/
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_lock(ctx->screen);
|
2017-11-20 20:34:40 +00:00
|
|
|
batch_mask = rsc->batch_mask;
|
|
|
|
foreach_batch(batch, &ctx->screen->batch_cache, batch_mask)
|
2019-02-19 14:29:49 +00:00
|
|
|
fd_batch_reference_locked(&batches[batch->idx], batch);
|
2020-04-28 21:04:16 +01:00
|
|
|
fd_screen_unlock(ctx->screen);
|
2017-11-20 20:34:40 +00:00
|
|
|
|
|
|
|
foreach_batch(batch, &ctx->screen->batch_cache, batch_mask)
|
2020-01-22 00:15:28 +00:00
|
|
|
fd_batch_flush(batch);
|
2017-11-20 20:34:40 +00:00
|
|
|
|
|
|
|
foreach_batch(batch, &ctx->screen->batch_cache, batch_mask) {
|
|
|
|
fd_batch_reference(&batches[batch->idx], NULL);
|
|
|
|
}
|
|
|
|
assert(rsc->batch_mask == 0);
|
|
|
|
} else if (write_batch) {
|
2020-01-22 00:15:28 +00:00
|
|
|
fd_batch_flush(write_batch);
|
2017-11-20 20:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fd_batch_reference(&write_batch, NULL);
|
|
|
|
|
|
|
|
assert(!rsc->write_batch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
|
2021-02-12 20:42:01 +00:00
|
|
|
in_dt
|
2017-11-20 20:34:40 +00:00
|
|
|
{
|
2020-07-01 13:16:12 +01:00
|
|
|
flush_resource(fd_context(pctx), fd_resource(prsc), PIPE_MAP_READ);
|
2017-11-20 20:34:40 +00:00
|
|
|
}
|
|
|
|
|
2013-05-26 22:13:27 +01:00
|
|
|
static void
|
|
|
|
fd_resource_transfer_unmap(struct pipe_context *pctx,
|
|
|
|
struct pipe_transfer *ptrans)
|
2021-02-12 20:42:01 +00:00
|
|
|
in_dt /* TODO for threaded-ctx we'll need to split out unsynchronized path */
|
2013-05-26 22:13:27 +01:00
|
|
|
{
|
|
|
|
struct fd_context *ctx = fd_context(pctx);
|
2013-08-29 22:24:33 +01:00
|
|
|
struct fd_resource *rsc = fd_resource(ptrans->resource);
|
2017-11-20 20:34:40 +00:00
|
|
|
struct fd_transfer *trans = fd_transfer(ptrans);
|
|
|
|
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
if (trans->staging_prsc) {
|
2020-07-01 13:16:12 +01:00
|
|
|
if (ptrans->usage & PIPE_MAP_WRITE)
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
fd_blit_from_staging(ctx, trans);
|
|
|
|
pipe_resource_reference(&trans->staging_prsc, NULL);
|
|
|
|
}
|
2015-04-22 19:35:00 +01:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (!(ptrans->usage & PIPE_MAP_UNSYNCHRONIZED)) {
|
2013-08-29 22:24:33 +01:00
|
|
|
fd_bo_cpu_fini(rsc->bo);
|
2015-04-22 19:35:00 +01:00
|
|
|
}
|
2015-04-03 07:15:17 +01:00
|
|
|
|
2019-09-26 02:38:40 +01:00
|
|
|
util_range_add(&rsc->base, &rsc->valid_buffer_range,
|
2015-04-03 07:15:17 +01:00
|
|
|
ptrans->box.x,
|
|
|
|
ptrans->box.x + ptrans->box.width);
|
|
|
|
|
2013-05-26 22:13:27 +01:00
|
|
|
pipe_resource_reference(&ptrans->resource, NULL);
|
2016-09-27 18:06:13 +01:00
|
|
|
slab_free(&ctx->transfer_pool, ptrans);
|
2013-05-26 22:13:27 +01:00
|
|
|
}
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
static void *
|
|
|
|
fd_resource_transfer_map(struct pipe_context *pctx,
|
|
|
|
struct pipe_resource *prsc,
|
|
|
|
unsigned level, unsigned usage,
|
|
|
|
const struct pipe_box *box,
|
|
|
|
struct pipe_transfer **pptrans)
|
2021-02-12 20:42:01 +00:00
|
|
|
in_dt /* TODO for threaded-ctx we'll need to split out unsynchronized path */
|
2012-10-27 17:07:34 +01:00
|
|
|
{
|
|
|
|
struct fd_context *ctx = fd_context(pctx);
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
2015-04-06 06:39:14 +01:00
|
|
|
struct fd_transfer *trans;
|
2013-08-31 14:14:27 +01:00
|
|
|
struct pipe_transfer *ptrans;
|
2012-10-27 17:07:34 +01:00
|
|
|
enum pipe_format format = prsc->format;
|
2013-08-29 22:24:33 +01:00
|
|
|
uint32_t op = 0;
|
2014-12-12 18:38:05 +00:00
|
|
|
uint32_t offset;
|
2012-10-27 17:07:34 +01:00
|
|
|
char *buf;
|
2013-09-11 15:08:08 +01:00
|
|
|
int ret = 0;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2015-04-22 19:35:00 +01:00
|
|
|
DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage,
|
|
|
|
box->width, box->height, box->x, box->y);
|
2014-10-22 21:36:24 +01:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if ((usage & PIPE_MAP_DIRECTLY) && rsc->layout.tile_mode) {
|
2020-05-23 18:56:56 +01:00
|
|
|
DBG("CANNOT MAP DIRECTLY!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-09-27 18:06:13 +01:00
|
|
|
ptrans = slab_alloc(&ctx->transfer_pool);
|
2012-10-27 17:07:34 +01:00
|
|
|
if (!ptrans)
|
|
|
|
return NULL;
|
|
|
|
|
2016-08-28 10:05:14 +01:00
|
|
|
/* slab_alloc_st() doesn't zero: */
|
2015-04-06 06:39:14 +01:00
|
|
|
trans = fd_transfer(ptrans);
|
|
|
|
memset(trans, 0, sizeof(*trans));
|
2013-05-26 22:13:27 +01:00
|
|
|
|
|
|
|
pipe_resource_reference(&ptrans->resource, prsc);
|
2012-10-27 17:07:34 +01:00
|
|
|
ptrans->level = level;
|
|
|
|
ptrans->usage = usage;
|
|
|
|
ptrans->box = *box;
|
2020-07-07 18:38:18 +01:00
|
|
|
ptrans->stride = fd_resource_pitch(rsc, level);
|
2019-11-20 20:55:56 +00:00
|
|
|
ptrans->layer_stride = fd_resource_layer_stride(rsc, level);
|
2012-10-27 17:07:34 +01:00
|
|
|
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
/* we always need a staging texture for tiled buffers:
|
|
|
|
*
|
|
|
|
* TODO we might sometimes want to *also* shadow the resource to avoid
|
|
|
|
* splitting a batch.. for ex, mid-frame texture uploads to a tiled
|
|
|
|
* texture.
|
|
|
|
*/
|
2019-05-05 18:59:37 +01:00
|
|
|
if (rsc->layout.tile_mode) {
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
struct fd_resource *staging_rsc;
|
|
|
|
|
|
|
|
staging_rsc = fd_alloc_staging(ctx, rsc, level, box);
|
|
|
|
if (staging_rsc) {
|
2020-07-01 13:16:12 +01:00
|
|
|
// TODO for PIPE_MAP_READ, need to do untiling blit..
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
trans->staging_prsc = &staging_rsc->base;
|
2020-07-07 18:38:18 +01:00
|
|
|
trans->base.stride = fd_resource_pitch(staging_rsc, 0);
|
2019-11-20 20:55:56 +00:00
|
|
|
trans->base.layer_stride = fd_resource_layer_stride(staging_rsc, 0);
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
trans->staging_box = *box;
|
|
|
|
trans->staging_box.x = 0;
|
|
|
|
trans->staging_box.y = 0;
|
|
|
|
trans->staging_box.z = 0;
|
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_READ) {
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
fd_blit_to_staging(ctx, trans);
|
2019-01-17 19:32:14 +00:00
|
|
|
|
|
|
|
fd_bo_cpu_prep(staging_rsc->bo, ctx->pipe,
|
|
|
|
DRM_FREEDRENO_PREP_READ);
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
buf = fd_bo_map(staging_rsc->bo);
|
|
|
|
offset = 0;
|
|
|
|
|
|
|
|
*pptrans = ptrans;
|
|
|
|
|
|
|
|
ctx->stats.staging_uploads++;
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (ctx->in_shadow && !(usage & PIPE_MAP_READ))
|
|
|
|
usage |= PIPE_MAP_UNSYNCHRONIZED;
|
2016-06-29 18:51:26 +01:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_READ)
|
2013-09-11 15:08:08 +01:00
|
|
|
op |= DRM_FREEDRENO_PREP_READ;
|
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_WRITE)
|
2013-09-11 15:08:08 +01:00
|
|
|
op |= DRM_FREEDRENO_PREP_WRITE;
|
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
bool needs_flush = pending(rsc, !!(usage & PIPE_MAP_WRITE));
|
2020-04-24 21:56:09 +01:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) {
|
2020-04-24 21:56:09 +01:00
|
|
|
if (needs_flush || fd_resource_busy(rsc, op)) {
|
2020-04-24 23:00:20 +01:00
|
|
|
rebind_resource(rsc);
|
2020-04-24 23:10:49 +01:00
|
|
|
realloc_bo(rsc, fd_bo_size(rsc->bo));
|
2020-04-24 21:56:09 +01:00
|
|
|
}
|
2020-07-01 13:16:12 +01:00
|
|
|
} else if ((usage & PIPE_MAP_WRITE) &&
|
2015-04-03 07:15:17 +01:00
|
|
|
prsc->target == PIPE_BUFFER &&
|
|
|
|
!util_ranges_intersect(&rsc->valid_buffer_range,
|
|
|
|
box->x, box->x + box->width)) {
|
|
|
|
/* We are trying to write to a previously uninitialized range. No need
|
|
|
|
* to wait.
|
|
|
|
*/
|
2020-07-01 13:16:12 +01:00
|
|
|
} else if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
|
2016-07-19 23:24:57 +01:00
|
|
|
struct fd_batch *write_batch = NULL;
|
|
|
|
|
|
|
|
/* hold a reference, so it doesn't disappear under us: */
|
2020-10-27 23:44:38 +00:00
|
|
|
fd_screen_lock(ctx->screen);
|
2019-02-19 14:29:49 +00:00
|
|
|
fd_batch_reference_locked(&write_batch, rsc->write_batch);
|
2020-10-27 23:44:38 +00:00
|
|
|
fd_screen_unlock(ctx->screen);
|
2016-07-19 23:24:57 +01:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if ((usage & PIPE_MAP_WRITE) && write_batch &&
|
2016-07-19 23:24:57 +01:00
|
|
|
write_batch->back_blit) {
|
2016-07-14 15:32:02 +01:00
|
|
|
/* if only thing pending is a back-blit, we can discard it: */
|
2016-07-19 23:24:57 +01:00
|
|
|
fd_batch_reset(write_batch);
|
2016-07-14 15:32:02 +01:00
|
|
|
}
|
|
|
|
|
2015-04-03 03:28:21 +01:00
|
|
|
/* If the GPU is writing to the resource, or if it is reading from the
|
|
|
|
* resource and we're trying to write to it, flush the renders.
|
|
|
|
*/
|
2020-04-24 21:56:09 +01:00
|
|
|
bool busy = needs_flush || fd_resource_busy(rsc, op);
|
2016-06-29 18:51:26 +01:00
|
|
|
|
|
|
|
/* if we need to flush/stall, see if we can make a shadow buffer
|
|
|
|
* to avoid this:
|
|
|
|
*
|
|
|
|
* TODO we could go down this path !reorder && !busy_for_read
|
|
|
|
* ie. we only *don't* want to go down this path if the blit
|
|
|
|
* will trigger a flush!
|
|
|
|
*/
|
2020-07-01 13:16:12 +01:00
|
|
|
if (ctx->screen->reorder && busy && !(usage & PIPE_MAP_READ) &&
|
|
|
|
(usage & PIPE_MAP_DISCARD_RANGE)) {
|
2017-11-20 20:34:40 +00:00
|
|
|
/* try shadowing only if it avoids a flush, otherwise staging would
|
|
|
|
* be better:
|
|
|
|
*/
|
2019-06-07 17:23:16 +01:00
|
|
|
if (needs_flush && fd_try_shadow_resource(ctx, rsc, level,
|
|
|
|
box, DRM_FORMAT_MOD_LINEAR)) {
|
2016-06-29 18:51:26 +01:00
|
|
|
needs_flush = busy = false;
|
2017-11-21 18:20:53 +00:00
|
|
|
ctx->stats.shadow_uploads++;
|
2017-11-20 20:34:40 +00:00
|
|
|
} else {
|
|
|
|
struct fd_resource *staging_rsc;
|
2016-06-29 18:51:26 +01:00
|
|
|
|
2017-11-20 20:34:40 +00:00
|
|
|
if (needs_flush) {
|
|
|
|
flush_resource(ctx, rsc, usage);
|
|
|
|
needs_flush = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* in this case, we don't need to shadow the whole resource,
|
|
|
|
* since any draw that references the previous contents has
|
|
|
|
* already had rendering flushed for all tiles. So we can
|
|
|
|
* use a staging buffer to do the upload.
|
2017-11-20 14:52:04 +00:00
|
|
|
*/
|
2017-11-20 20:34:40 +00:00
|
|
|
staging_rsc = fd_alloc_staging(ctx, rsc, level, box);
|
|
|
|
if (staging_rsc) {
|
|
|
|
trans->staging_prsc = &staging_rsc->base;
|
2020-07-07 18:38:18 +01:00
|
|
|
trans->base.stride = fd_resource_pitch(staging_rsc, 0);
|
2019-11-20 20:55:56 +00:00
|
|
|
trans->base.layer_stride =
|
|
|
|
fd_resource_layer_stride(staging_rsc, 0);
|
2017-11-20 20:34:40 +00:00
|
|
|
trans->staging_box = *box;
|
|
|
|
trans->staging_box.x = 0;
|
|
|
|
trans->staging_box.y = 0;
|
|
|
|
trans->staging_box.z = 0;
|
|
|
|
buf = fd_bo_map(staging_rsc->bo);
|
|
|
|
offset = 0;
|
|
|
|
|
|
|
|
*pptrans = ptrans;
|
|
|
|
|
|
|
|
fd_batch_reference(&write_batch, NULL);
|
|
|
|
|
2017-11-21 18:20:53 +00:00
|
|
|
ctx->stats.staging_uploads++;
|
|
|
|
|
2017-11-20 20:34:40 +00:00
|
|
|
return buf;
|
2016-07-13 14:49:53 +01:00
|
|
|
}
|
2016-06-27 14:44:15 +01:00
|
|
|
}
|
2017-11-20 20:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (needs_flush) {
|
|
|
|
flush_resource(ctx, rsc, usage);
|
|
|
|
needs_flush = false;
|
2016-06-27 14:44:15 +01:00
|
|
|
}
|
2015-04-03 03:28:21 +01:00
|
|
|
|
2016-07-19 23:24:57 +01:00
|
|
|
fd_batch_reference(&write_batch, NULL);
|
|
|
|
|
2015-04-03 03:28:21 +01:00
|
|
|
/* The GPU keeps track of how the various bo's are being used, and
|
|
|
|
* will wait if necessary for the proper operation to have
|
|
|
|
* completed.
|
|
|
|
*/
|
2016-06-29 18:51:26 +01:00
|
|
|
if (busy) {
|
2017-08-24 14:34:48 +01:00
|
|
|
ret = fd_bo_cpu_prep(rsc->bo, ctx->pipe, op);
|
2016-06-29 18:51:26 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-09-11 15:08:08 +01:00
|
|
|
}
|
2013-05-26 22:13:27 +01:00
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
buf = fd_bo_map(rsc->bo);
|
2018-12-18 15:27:10 +00:00
|
|
|
offset =
|
2015-11-08 03:13:16 +00:00
|
|
|
box->y / util_format_get_blockheight(format) * ptrans->stride +
|
2019-05-05 18:59:37 +01:00
|
|
|
box->x / util_format_get_blockwidth(format) * rsc->layout.cpp +
|
2018-12-18 15:27:10 +00:00
|
|
|
fd_resource_offset(rsc, level, box->z);
|
2014-12-12 18:38:05 +00:00
|
|
|
|
2020-07-01 13:16:12 +01:00
|
|
|
if (usage & PIPE_MAP_WRITE)
|
2017-11-20 20:34:40 +00:00
|
|
|
rsc->valid = true;
|
|
|
|
|
2015-04-22 19:35:00 +01:00
|
|
|
*pptrans = ptrans;
|
|
|
|
|
2014-12-12 18:38:05 +00:00
|
|
|
return buf + offset;
|
2013-09-11 15:08:08 +01:00
|
|
|
|
|
|
|
fail:
|
|
|
|
fd_resource_transfer_unmap(pctx, ptrans);
|
|
|
|
return NULL;
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fd_resource_destroy(struct pipe_screen *pscreen,
|
|
|
|
struct pipe_resource *prsc)
|
|
|
|
{
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
2016-06-27 14:44:15 +01:00
|
|
|
fd_bc_invalidate_resource(rsc, true);
|
2013-09-27 20:35:19 +01:00
|
|
|
if (rsc->bo)
|
|
|
|
fd_bo_del(rsc->bo);
|
2020-09-29 18:00:13 +01:00
|
|
|
if (rsc->lrz)
|
|
|
|
fd_bo_del(rsc->lrz);
|
2019-01-16 15:22:53 +00:00
|
|
|
if (rsc->scanout)
|
|
|
|
renderonly_scanout_destroy(rsc->scanout, fd_screen(pscreen)->ro);
|
|
|
|
|
2015-04-03 07:15:17 +01:00
|
|
|
util_range_destroy(&rsc->valid_buffer_range);
|
2020-04-24 22:45:04 +01:00
|
|
|
simple_mtx_destroy(&rsc->lock);
|
2012-10-27 17:07:34 +01:00
|
|
|
FREE(rsc);
|
|
|
|
}
|
|
|
|
|
freedreno: set modifier when exporting buffer
Fixes an assert we start hitting with kms/gbm:
#0 0x0000007fbf3d6e3c in raise () from /lib64/libc.so.6
#1 0x0000007fbf3c4a68 in abort () from /lib64/libc.so.6
#2 0x0000007fbf3d04e8 in __assert_fail_base () from /lib64/libc.so.6
#3 0x0000007fbf3d0550 in __assert_fail () from /lib64/libc.so.6
#4 0x0000007fbf5a73c4 in gbm_dri_bo_create (gbm=0x5820f0, width=2160, height=1440, format=875713112, usage=0, modifiers=0x695e00, count=1) at ../src/gbm/backends/dri/gbm_dri.c:1150
#5 0x0000007fbf5a49c4 in gbm_bo_create_with_modifiers (gbm=0x5820f0, width=2160, height=1440, format=875713112, modifiers=0x695e00, count=1) at ../src/gbm/main/gbm.c:491
#6 0x0000007fbbac3d64 in get_back_bo (dri2_surf=0x6f4cc0) at ../src/egl/drivers/dri2/platform_drm.c:258
#7 0x0000007fbbac4318 in dri2_drm_image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x6f4cc0, buffer_mask=1, buffers=0x7fffffe210) at ../src/egl/drivers/dri2/platform_drm.c:409
#8 0x0000007fbf5a5318 in image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x70e150, buffer_mask=1, buffers=0x7fffffe210) at ../src/gbm/backends/dri/gbm_dri.c:135
#9 0x0000007fbe4308c4 in dri_image_drawable_get_buffers (drawable=0x6fc730, images=0x7fffffe210, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:339
#10 0x0000007fbe430c44 in dri2_allocate_textures (ctx=0x614b30, drawable=0x6fc730, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:466
#11 0x0000007fbe435580 in dri_st_framebuffer_validate (stctx=0x714160, stfbi=0x6fc730, statts=0x6f2660, count=1, out=0x7fffffe3b8) at ../src/gallium/state_trackers/dri/dri_drawable.c:85
#12 0x0000007fbe7b2c84 in st_framebuffer_validate (stfb=0x6f2190, st=0x714160) at ../src/mesa/state_tracker/st_manager.c:222
#13 0x0000007fbe7b4884 in st_api_make_current (stapi=0x7fbf0430d8 <st_gl_api>, stctxi=0x714160, stdrawi=0x6fc730, streadi=0x6fc730) at ../src/mesa/state_tracker/st_manager.c:1074
#14 0x0000007fbe434f44 in dri_make_current (cPriv=0x703c20, driDrawPriv=0x704490, driReadPriv=0x704490) at ../src/gallium/state_trackers/dri/dri_context.c:301
#15 0x0000007fbe42c910 in driBindContext (pcp=0x703c20, pdp=0x704490, prp=0x704490) at ../src/mesa/drivers/dri/common/dri_util.c:579
#16 0x0000007fbbabab40 in dri2_make_current (drv=0x69d170, disp=0x69c6e0, dsurf=0x6f4cc0, rsurf=0x6f4cc0, ctx=0x70cb40) at ../src/egl/drivers/dri2/egl_dri2.c:1456
#17 0x0000007fbbaa8ef4 in eglMakeCurrent (dpy=0x69c6e0, draw=0x6f4cc0, read=0x6f4cc0, ctx=0x70cb40) at ../src/egl/main/eglapi.c:862
#18 0x0000007fbf5736ac in InternalMakeCurrentVendor (dpy=dpy@entry=0x614fb0, draw=draw@entry=0x6f4cc0, read=read@entry=0x6f4cc0, context=context@entry=0x70cb40, apiState=apiState@entry=0x6fc940, vendor=0x6975f0) at libegl.c:861
#19 0x0000007fbf573764 in InternalMakeCurrentDispatch (dpy=0x614fb0, draw=0x6f4cc0, read=0x6f4cc0, context=0x70cb40, vendor=0x6975f0) at libegl.c:630
#20 0x0000000000403640 in init_egl (egl=0x5805a8 <gl>, gbm=0x580528 <gbm>, samples=0) at ../common.c:263
#21 0x0000000000403c1c in init_cube_smooth (gbm=0x580528 <gbm>, samples=0) at ../cube-smooth.c:225
#22 0x0000000000408618 in main (argc=1, argv=0x7fffffe8d8) at ../kmscube.c:145
Fixes: 1ce5d757d04 freedreno: core buffer modifier support
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-23 14:42:42 +00:00
|
|
|
static uint64_t
|
|
|
|
fd_resource_modifier(struct fd_resource *rsc)
|
|
|
|
{
|
2019-05-05 18:59:37 +01:00
|
|
|
if (!rsc->layout.tile_mode)
|
freedreno: set modifier when exporting buffer
Fixes an assert we start hitting with kms/gbm:
#0 0x0000007fbf3d6e3c in raise () from /lib64/libc.so.6
#1 0x0000007fbf3c4a68 in abort () from /lib64/libc.so.6
#2 0x0000007fbf3d04e8 in __assert_fail_base () from /lib64/libc.so.6
#3 0x0000007fbf3d0550 in __assert_fail () from /lib64/libc.so.6
#4 0x0000007fbf5a73c4 in gbm_dri_bo_create (gbm=0x5820f0, width=2160, height=1440, format=875713112, usage=0, modifiers=0x695e00, count=1) at ../src/gbm/backends/dri/gbm_dri.c:1150
#5 0x0000007fbf5a49c4 in gbm_bo_create_with_modifiers (gbm=0x5820f0, width=2160, height=1440, format=875713112, modifiers=0x695e00, count=1) at ../src/gbm/main/gbm.c:491
#6 0x0000007fbbac3d64 in get_back_bo (dri2_surf=0x6f4cc0) at ../src/egl/drivers/dri2/platform_drm.c:258
#7 0x0000007fbbac4318 in dri2_drm_image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x6f4cc0, buffer_mask=1, buffers=0x7fffffe210) at ../src/egl/drivers/dri2/platform_drm.c:409
#8 0x0000007fbf5a5318 in image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x70e150, buffer_mask=1, buffers=0x7fffffe210) at ../src/gbm/backends/dri/gbm_dri.c:135
#9 0x0000007fbe4308c4 in dri_image_drawable_get_buffers (drawable=0x6fc730, images=0x7fffffe210, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:339
#10 0x0000007fbe430c44 in dri2_allocate_textures (ctx=0x614b30, drawable=0x6fc730, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:466
#11 0x0000007fbe435580 in dri_st_framebuffer_validate (stctx=0x714160, stfbi=0x6fc730, statts=0x6f2660, count=1, out=0x7fffffe3b8) at ../src/gallium/state_trackers/dri/dri_drawable.c:85
#12 0x0000007fbe7b2c84 in st_framebuffer_validate (stfb=0x6f2190, st=0x714160) at ../src/mesa/state_tracker/st_manager.c:222
#13 0x0000007fbe7b4884 in st_api_make_current (stapi=0x7fbf0430d8 <st_gl_api>, stctxi=0x714160, stdrawi=0x6fc730, streadi=0x6fc730) at ../src/mesa/state_tracker/st_manager.c:1074
#14 0x0000007fbe434f44 in dri_make_current (cPriv=0x703c20, driDrawPriv=0x704490, driReadPriv=0x704490) at ../src/gallium/state_trackers/dri/dri_context.c:301
#15 0x0000007fbe42c910 in driBindContext (pcp=0x703c20, pdp=0x704490, prp=0x704490) at ../src/mesa/drivers/dri/common/dri_util.c:579
#16 0x0000007fbbabab40 in dri2_make_current (drv=0x69d170, disp=0x69c6e0, dsurf=0x6f4cc0, rsurf=0x6f4cc0, ctx=0x70cb40) at ../src/egl/drivers/dri2/egl_dri2.c:1456
#17 0x0000007fbbaa8ef4 in eglMakeCurrent (dpy=0x69c6e0, draw=0x6f4cc0, read=0x6f4cc0, ctx=0x70cb40) at ../src/egl/main/eglapi.c:862
#18 0x0000007fbf5736ac in InternalMakeCurrentVendor (dpy=dpy@entry=0x614fb0, draw=draw@entry=0x6f4cc0, read=read@entry=0x6f4cc0, context=context@entry=0x70cb40, apiState=apiState@entry=0x6fc940, vendor=0x6975f0) at libegl.c:861
#19 0x0000007fbf573764 in InternalMakeCurrentDispatch (dpy=0x614fb0, draw=0x6f4cc0, read=0x6f4cc0, context=0x70cb40, vendor=0x6975f0) at libegl.c:630
#20 0x0000000000403640 in init_egl (egl=0x5805a8 <gl>, gbm=0x580528 <gbm>, samples=0) at ../common.c:263
#21 0x0000000000403c1c in init_cube_smooth (gbm=0x580528 <gbm>, samples=0) at ../cube-smooth.c:225
#22 0x0000000000408618 in main (argc=1, argv=0x7fffffe8d8) at ../kmscube.c:145
Fixes: 1ce5d757d04 freedreno: core buffer modifier support
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-23 14:42:42 +00:00
|
|
|
return DRM_FORMAT_MOD_LINEAR;
|
|
|
|
|
2019-11-25 19:49:05 +00:00
|
|
|
if (rsc->layout.ubwc_layer_size)
|
2019-06-07 17:12:52 +01:00
|
|
|
return DRM_FORMAT_MOD_QCOM_COMPRESSED;
|
|
|
|
|
freedreno: set modifier when exporting buffer
Fixes an assert we start hitting with kms/gbm:
#0 0x0000007fbf3d6e3c in raise () from /lib64/libc.so.6
#1 0x0000007fbf3c4a68 in abort () from /lib64/libc.so.6
#2 0x0000007fbf3d04e8 in __assert_fail_base () from /lib64/libc.so.6
#3 0x0000007fbf3d0550 in __assert_fail () from /lib64/libc.so.6
#4 0x0000007fbf5a73c4 in gbm_dri_bo_create (gbm=0x5820f0, width=2160, height=1440, format=875713112, usage=0, modifiers=0x695e00, count=1) at ../src/gbm/backends/dri/gbm_dri.c:1150
#5 0x0000007fbf5a49c4 in gbm_bo_create_with_modifiers (gbm=0x5820f0, width=2160, height=1440, format=875713112, modifiers=0x695e00, count=1) at ../src/gbm/main/gbm.c:491
#6 0x0000007fbbac3d64 in get_back_bo (dri2_surf=0x6f4cc0) at ../src/egl/drivers/dri2/platform_drm.c:258
#7 0x0000007fbbac4318 in dri2_drm_image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x6f4cc0, buffer_mask=1, buffers=0x7fffffe210) at ../src/egl/drivers/dri2/platform_drm.c:409
#8 0x0000007fbf5a5318 in image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x70e150, buffer_mask=1, buffers=0x7fffffe210) at ../src/gbm/backends/dri/gbm_dri.c:135
#9 0x0000007fbe4308c4 in dri_image_drawable_get_buffers (drawable=0x6fc730, images=0x7fffffe210, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:339
#10 0x0000007fbe430c44 in dri2_allocate_textures (ctx=0x614b30, drawable=0x6fc730, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:466
#11 0x0000007fbe435580 in dri_st_framebuffer_validate (stctx=0x714160, stfbi=0x6fc730, statts=0x6f2660, count=1, out=0x7fffffe3b8) at ../src/gallium/state_trackers/dri/dri_drawable.c:85
#12 0x0000007fbe7b2c84 in st_framebuffer_validate (stfb=0x6f2190, st=0x714160) at ../src/mesa/state_tracker/st_manager.c:222
#13 0x0000007fbe7b4884 in st_api_make_current (stapi=0x7fbf0430d8 <st_gl_api>, stctxi=0x714160, stdrawi=0x6fc730, streadi=0x6fc730) at ../src/mesa/state_tracker/st_manager.c:1074
#14 0x0000007fbe434f44 in dri_make_current (cPriv=0x703c20, driDrawPriv=0x704490, driReadPriv=0x704490) at ../src/gallium/state_trackers/dri/dri_context.c:301
#15 0x0000007fbe42c910 in driBindContext (pcp=0x703c20, pdp=0x704490, prp=0x704490) at ../src/mesa/drivers/dri/common/dri_util.c:579
#16 0x0000007fbbabab40 in dri2_make_current (drv=0x69d170, disp=0x69c6e0, dsurf=0x6f4cc0, rsurf=0x6f4cc0, ctx=0x70cb40) at ../src/egl/drivers/dri2/egl_dri2.c:1456
#17 0x0000007fbbaa8ef4 in eglMakeCurrent (dpy=0x69c6e0, draw=0x6f4cc0, read=0x6f4cc0, ctx=0x70cb40) at ../src/egl/main/eglapi.c:862
#18 0x0000007fbf5736ac in InternalMakeCurrentVendor (dpy=dpy@entry=0x614fb0, draw=draw@entry=0x6f4cc0, read=read@entry=0x6f4cc0, context=context@entry=0x70cb40, apiState=apiState@entry=0x6fc940, vendor=0x6975f0) at libegl.c:861
#19 0x0000007fbf573764 in InternalMakeCurrentDispatch (dpy=0x614fb0, draw=0x6f4cc0, read=0x6f4cc0, context=0x70cb40, vendor=0x6975f0) at libegl.c:630
#20 0x0000000000403640 in init_egl (egl=0x5805a8 <gl>, gbm=0x580528 <gbm>, samples=0) at ../common.c:263
#21 0x0000000000403c1c in init_cube_smooth (gbm=0x580528 <gbm>, samples=0) at ../cube-smooth.c:225
#22 0x0000000000408618 in main (argc=1, argv=0x7fffffe8d8) at ../kmscube.c:145
Fixes: 1ce5d757d04 freedreno: core buffer modifier support
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-23 14:42:42 +00:00
|
|
|
/* TODO invent a modifier for tiled but not UBWC buffers: */
|
|
|
|
return DRM_FORMAT_MOD_INVALID;
|
|
|
|
}
|
|
|
|
|
2019-07-04 16:41:41 +01:00
|
|
|
static bool
|
2012-10-27 17:07:34 +01:00
|
|
|
fd_resource_get_handle(struct pipe_screen *pscreen,
|
2017-12-04 14:02:07 +00:00
|
|
|
struct pipe_context *pctx,
|
2012-10-27 17:07:34 +01:00
|
|
|
struct pipe_resource *prsc,
|
2017-12-04 14:02:07 +00:00
|
|
|
struct winsys_handle *handle,
|
|
|
|
unsigned usage)
|
2012-10-27 17:07:34 +01:00
|
|
|
{
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
|
|
|
|
freedreno: set modifier when exporting buffer
Fixes an assert we start hitting with kms/gbm:
#0 0x0000007fbf3d6e3c in raise () from /lib64/libc.so.6
#1 0x0000007fbf3c4a68 in abort () from /lib64/libc.so.6
#2 0x0000007fbf3d04e8 in __assert_fail_base () from /lib64/libc.so.6
#3 0x0000007fbf3d0550 in __assert_fail () from /lib64/libc.so.6
#4 0x0000007fbf5a73c4 in gbm_dri_bo_create (gbm=0x5820f0, width=2160, height=1440, format=875713112, usage=0, modifiers=0x695e00, count=1) at ../src/gbm/backends/dri/gbm_dri.c:1150
#5 0x0000007fbf5a49c4 in gbm_bo_create_with_modifiers (gbm=0x5820f0, width=2160, height=1440, format=875713112, modifiers=0x695e00, count=1) at ../src/gbm/main/gbm.c:491
#6 0x0000007fbbac3d64 in get_back_bo (dri2_surf=0x6f4cc0) at ../src/egl/drivers/dri2/platform_drm.c:258
#7 0x0000007fbbac4318 in dri2_drm_image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x6f4cc0, buffer_mask=1, buffers=0x7fffffe210) at ../src/egl/drivers/dri2/platform_drm.c:409
#8 0x0000007fbf5a5318 in image_get_buffers (driDrawable=0x704490, format=4098, stamp=0x6fc730, loaderPrivate=0x70e150, buffer_mask=1, buffers=0x7fffffe210) at ../src/gbm/backends/dri/gbm_dri.c:135
#9 0x0000007fbe4308c4 in dri_image_drawable_get_buffers (drawable=0x6fc730, images=0x7fffffe210, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:339
#10 0x0000007fbe430c44 in dri2_allocate_textures (ctx=0x614b30, drawable=0x6fc730, statts=0x6f2660, statts_count=1) at ../src/gallium/state_trackers/dri/dri2.c:466
#11 0x0000007fbe435580 in dri_st_framebuffer_validate (stctx=0x714160, stfbi=0x6fc730, statts=0x6f2660, count=1, out=0x7fffffe3b8) at ../src/gallium/state_trackers/dri/dri_drawable.c:85
#12 0x0000007fbe7b2c84 in st_framebuffer_validate (stfb=0x6f2190, st=0x714160) at ../src/mesa/state_tracker/st_manager.c:222
#13 0x0000007fbe7b4884 in st_api_make_current (stapi=0x7fbf0430d8 <st_gl_api>, stctxi=0x714160, stdrawi=0x6fc730, streadi=0x6fc730) at ../src/mesa/state_tracker/st_manager.c:1074
#14 0x0000007fbe434f44 in dri_make_current (cPriv=0x703c20, driDrawPriv=0x704490, driReadPriv=0x704490) at ../src/gallium/state_trackers/dri/dri_context.c:301
#15 0x0000007fbe42c910 in driBindContext (pcp=0x703c20, pdp=0x704490, prp=0x704490) at ../src/mesa/drivers/dri/common/dri_util.c:579
#16 0x0000007fbbabab40 in dri2_make_current (drv=0x69d170, disp=0x69c6e0, dsurf=0x6f4cc0, rsurf=0x6f4cc0, ctx=0x70cb40) at ../src/egl/drivers/dri2/egl_dri2.c:1456
#17 0x0000007fbbaa8ef4 in eglMakeCurrent (dpy=0x69c6e0, draw=0x6f4cc0, read=0x6f4cc0, ctx=0x70cb40) at ../src/egl/main/eglapi.c:862
#18 0x0000007fbf5736ac in InternalMakeCurrentVendor (dpy=dpy@entry=0x614fb0, draw=draw@entry=0x6f4cc0, read=read@entry=0x6f4cc0, context=context@entry=0x70cb40, apiState=apiState@entry=0x6fc940, vendor=0x6975f0) at libegl.c:861
#19 0x0000007fbf573764 in InternalMakeCurrentDispatch (dpy=0x614fb0, draw=0x6f4cc0, read=0x6f4cc0, context=0x70cb40, vendor=0x6975f0) at libegl.c:630
#20 0x0000000000403640 in init_egl (egl=0x5805a8 <gl>, gbm=0x580528 <gbm>, samples=0) at ../common.c:263
#21 0x0000000000403c1c in init_cube_smooth (gbm=0x580528 <gbm>, samples=0) at ../cube-smooth.c:225
#22 0x0000000000408618 in main (argc=1, argv=0x7fffffe8d8) at ../kmscube.c:145
Fixes: 1ce5d757d04 freedreno: core buffer modifier support
Signed-off-by: Rob Clark <robdclark@gmail.com>
2019-01-23 14:42:42 +00:00
|
|
|
handle->modifier = fd_resource_modifier(rsc);
|
|
|
|
|
2021-01-22 16:42:29 +00:00
|
|
|
DBG("%"PRSC_FMT", modifier=%"PRIx64, PRSC_ARGS(prsc), handle->modifier);
|
2020-10-25 20:07:23 +00:00
|
|
|
|
2019-01-16 15:22:53 +00:00
|
|
|
return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->scanout,
|
2020-07-07 18:38:18 +01:00
|
|
|
fd_resource_pitch(rsc, 0), handle);
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
2016-07-11 22:36:45 +01:00
|
|
|
/* special case to resize query buf after allocated.. */
|
|
|
|
void
|
|
|
|
fd_resource_resize(struct pipe_resource *prsc, uint32_t sz)
|
|
|
|
{
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
|
|
|
|
|
|
|
debug_assert(prsc->width0 == 0);
|
|
|
|
debug_assert(prsc->target == PIPE_BUFFER);
|
|
|
|
debug_assert(prsc->bind == PIPE_BIND_QUERY_BUFFER);
|
|
|
|
|
|
|
|
prsc->width0 = sz;
|
2018-01-14 13:57:29 +00:00
|
|
|
realloc_bo(rsc, fd_screen(prsc->screen)->setup_slices(rsc));
|
2016-07-11 22:36:45 +01:00
|
|
|
}
|
|
|
|
|
2019-05-05 18:59:37 +01:00
|
|
|
static void
|
|
|
|
fd_resource_layout_init(struct pipe_resource *prsc)
|
|
|
|
{
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
|
|
|
struct fdl_layout *layout = &rsc->layout;
|
|
|
|
|
2020-07-07 23:27:32 +01:00
|
|
|
layout->format = prsc->format;
|
|
|
|
|
2019-05-05 18:59:37 +01:00
|
|
|
layout->width0 = prsc->width0;
|
|
|
|
layout->height0 = prsc->height0;
|
|
|
|
layout->depth0 = prsc->depth0;
|
|
|
|
|
|
|
|
layout->cpp = util_format_get_blocksize(prsc->format);
|
|
|
|
layout->cpp *= fd_resource_nr_samples(prsc);
|
2020-04-14 22:35:05 +01:00
|
|
|
layout->cpp_shift = ffs(layout->cpp) - 1;
|
2019-05-05 18:59:37 +01:00
|
|
|
}
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
/**
|
2020-08-18 09:04:02 +01:00
|
|
|
* Helper that allocates a resource and resolves its layout (but doesn't
|
|
|
|
* allocate its bo).
|
|
|
|
*
|
|
|
|
* It returns a pipe_resource (as fd_resource_create_with_modifiers()
|
|
|
|
* would do), and also bo's minimum required size as an output argument.
|
2012-10-27 17:07:34 +01:00
|
|
|
*/
|
|
|
|
static struct pipe_resource *
|
2020-08-18 09:04:02 +01:00
|
|
|
fd_resource_allocate_and_resolve(struct pipe_screen *pscreen,
|
2019-01-21 15:50:13 +00:00
|
|
|
const struct pipe_resource *tmpl,
|
2020-08-18 09:04:02 +01:00
|
|
|
const uint64_t *modifiers, int count, uint32_t *psize)
|
2012-10-27 17:07:34 +01:00
|
|
|
{
|
2017-06-03 18:36:25 +01:00
|
|
|
struct fd_screen *screen = fd_screen(pscreen);
|
2019-01-16 15:22:53 +00:00
|
|
|
struct fd_resource *rsc;
|
|
|
|
struct pipe_resource *prsc;
|
2015-11-08 03:13:16 +00:00
|
|
|
enum pipe_format format = tmpl->format;
|
2018-01-14 13:57:29 +00:00
|
|
|
uint32_t size;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2019-01-16 15:22:53 +00:00
|
|
|
rsc = CALLOC_STRUCT(fd_resource);
|
|
|
|
prsc = &rsc->base;
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*prsc = *tmpl;
|
2021-01-22 16:42:29 +00:00
|
|
|
|
|
|
|
DBG("%"PRSC_FMT, PRSC_ARGS(prsc));
|
|
|
|
|
2019-05-05 18:59:37 +01:00
|
|
|
fd_resource_layout_init(prsc);
|
2012-10-27 17:07:34 +01:00
|
|
|
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
#define LINEAR \
|
|
|
|
(PIPE_BIND_SCANOUT | \
|
|
|
|
PIPE_BIND_LINEAR | \
|
|
|
|
PIPE_BIND_DISPLAY_TARGET)
|
|
|
|
|
2019-03-14 04:14:37 +00:00
|
|
|
bool linear = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
|
2021-01-22 17:19:09 +00:00
|
|
|
if (linear) {
|
|
|
|
perf_debug("%"PRSC_FMT": linear: DRM_FORMAT_MOD_LINEAR requested!", PRSC_ARGS(prsc));
|
|
|
|
} else if (tmpl->bind & LINEAR) {
|
|
|
|
if (tmpl->usage != PIPE_USAGE_STAGING)
|
|
|
|
perf_debug("%"PRSC_FMT": linear: LINEAR bind requested!", PRSC_ARGS(prsc));
|
2019-01-21 15:50:13 +00:00
|
|
|
linear = true;
|
2021-01-22 17:19:09 +00:00
|
|
|
}
|
2019-01-21 15:50:13 +00:00
|
|
|
|
2019-11-26 05:14:31 +00:00
|
|
|
if (fd_mesa_debug & FD_DBG_NOTILE)
|
|
|
|
linear = true;
|
|
|
|
|
2019-01-21 15:50:13 +00:00
|
|
|
/* Normally, for non-shared buffers, allow buffer compression if
|
|
|
|
* not shared, otherwise only allow if QCOM_COMPRESSED modifier
|
|
|
|
* is requested:
|
|
|
|
*
|
|
|
|
* TODO we should probably also limit tiled in a similar way,
|
|
|
|
* except we don't have a format modifier for tiled. (We probably
|
|
|
|
* should.)
|
|
|
|
*/
|
2021-01-22 17:19:09 +00:00
|
|
|
bool allow_ubwc = false;
|
|
|
|
if (!linear) {
|
|
|
|
allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count);
|
2020-10-25 21:13:38 +00:00
|
|
|
if (!allow_ubwc) {
|
2021-01-22 17:19:09 +00:00
|
|
|
perf_debug("%"PRSC_FMT": not UBWC: DRM_FORMAT_MOD_INVALID not requested!",
|
|
|
|
PRSC_ARGS(prsc));
|
|
|
|
}
|
|
|
|
if (tmpl->bind & PIPE_BIND_SHARED) {
|
|
|
|
allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count);
|
|
|
|
if (!allow_ubwc) {
|
|
|
|
perf_debug("%"PRSC_FMT": not UBWC: shared and DRM_FORMAT_MOD_QCOM_COMPRESSED not requested!",
|
|
|
|
PRSC_ARGS(prsc));
|
|
|
|
linear = true;
|
|
|
|
}
|
2020-10-25 21:13:38 +00:00
|
|
|
}
|
|
|
|
}
|
2019-01-21 15:50:13 +00:00
|
|
|
|
2019-06-11 00:12:12 +01:00
|
|
|
allow_ubwc &= !(fd_mesa_debug & FD_DBG_NOUBWC);
|
2019-02-27 02:31:38 +00:00
|
|
|
|
2019-09-10 00:19:40 +01:00
|
|
|
pipe_reference_init(&prsc->reference, 1);
|
|
|
|
|
|
|
|
prsc->screen = pscreen;
|
|
|
|
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
if (screen->tile_mode &&
|
|
|
|
(tmpl->target != PIPE_BUFFER) &&
|
2019-01-21 15:50:13 +00:00
|
|
|
!linear) {
|
2019-05-05 18:59:37 +01:00
|
|
|
rsc->layout.tile_mode = screen->tile_mode(prsc);
|
freedreno/a5xx: texture tiling
Overall a nice 5-10% gain for most games. And more for things like
glmark2 texture benchmark.
There are some rough edges. In particular, the hardware seems to only
support tiling or component swap. (Ie. from hw PoV, ARGB/ABGR/RGBA/
BGRA are all the same format but with different component swap.) For
tiled formats, only ARGB is possible. This isn't a big problem for
*sampling* since we also have swizzle state there (and since
util_format_compose_swizzles() already takes into account the component
order, we didn't use COLOR_SWAP for sampling). But it is a problem if
you try to render to a tiled BGRA (for example) surface.
The next patch introduces a workaround for blitter, so we can generate
tiled textures in ABGR/RGBA/BGRA, but that doesn't help the render-
target case. To handle that, I think we'd need to keep track that the
tiled format is different from the linear format, which seems like it
would get extra fun with sampler views/etc.
So for now, disabled by default, enable with FD_MESA_DEBUG=ttile. In
practice it works fine for all the games I've tried, but makes piglit
grumpy.
Signed-off-by: Rob Clark <robdclark@gmail.com>
2017-12-31 20:01:51 +00:00
|
|
|
}
|
|
|
|
|
2015-04-03 07:15:17 +01:00
|
|
|
util_range_init(&rsc->valid_buffer_range);
|
|
|
|
|
2020-04-24 22:45:04 +01:00
|
|
|
simple_mtx_init(&rsc->lock, mtx_plain);
|
|
|
|
|
2015-11-20 23:34:03 +00:00
|
|
|
rsc->internal_format = format;
|
2013-05-26 22:13:27 +01:00
|
|
|
|
2019-11-21 23:09:02 +00:00
|
|
|
rsc->layout.ubwc = rsc->layout.tile_mode && is_a6xx(screen) && allow_ubwc;
|
|
|
|
|
2019-11-26 20:02:34 +00:00
|
|
|
if (prsc->target == PIPE_BUFFER) {
|
|
|
|
assert(prsc->format == PIPE_FORMAT_R8_UNORM);
|
|
|
|
size = prsc->width0;
|
|
|
|
fdl_layout_buffer(&rsc->layout, size);
|
|
|
|
} else {
|
|
|
|
size = screen->setup_slices(rsc);
|
|
|
|
}
|
2013-08-31 14:14:27 +01:00
|
|
|
|
2016-07-11 22:36:45 +01:00
|
|
|
/* special case for hw-query buffer, which we need to allocate before we
|
|
|
|
* know the size:
|
|
|
|
*/
|
|
|
|
if (size == 0) {
|
|
|
|
/* note, semi-intention == instead of & */
|
|
|
|
debug_assert(prsc->bind == PIPE_BIND_QUERY_BUFFER);
|
2020-11-17 20:40:26 +00:00
|
|
|
*psize = 0;
|
2016-07-11 22:36:45 +01:00
|
|
|
return prsc;
|
|
|
|
}
|
|
|
|
|
2019-12-12 00:30:43 +00:00
|
|
|
/* Set the layer size if the (non-a6xx) backend hasn't done so. */
|
|
|
|
if (rsc->layout.layer_first && !rsc->layout.layer_size) {
|
2019-05-05 18:59:37 +01:00
|
|
|
rsc->layout.layer_size = align(size, 4096);
|
|
|
|
size = rsc->layout.layer_size * prsc->array_size;
|
2014-12-12 18:38:05 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 21:48:31 +00:00
|
|
|
if (fd_mesa_debug & FD_DBG_LAYOUT)
|
|
|
|
fdl_dump_layout(&rsc->layout);
|
|
|
|
|
2020-08-18 09:04:02 +01:00
|
|
|
/* Hand out the resolved size. */
|
|
|
|
if (psize)
|
|
|
|
*psize = size;
|
|
|
|
|
|
|
|
return prsc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new texture object, using the given template info.
|
|
|
|
*/
|
|
|
|
static struct pipe_resource *
|
|
|
|
fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
|
|
|
const struct pipe_resource *tmpl,
|
|
|
|
const uint64_t *modifiers, int count)
|
|
|
|
{
|
|
|
|
struct fd_screen *screen = fd_screen(pscreen);
|
|
|
|
struct fd_resource *rsc;
|
|
|
|
struct pipe_resource *prsc;
|
|
|
|
uint32_t size;
|
|
|
|
|
|
|
|
/* when using kmsro, scanout buffers are allocated on the display device
|
|
|
|
* create_with_modifiers() doesn't give us usage flags, so we have to
|
|
|
|
* assume that all calls with modifiers are scanout-possible
|
|
|
|
*/
|
|
|
|
if (screen->ro &&
|
|
|
|
((tmpl->bind & PIPE_BIND_SCANOUT) ||
|
|
|
|
!(count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID))) {
|
|
|
|
struct pipe_resource scanout_templat = *tmpl;
|
|
|
|
struct renderonly_scanout *scanout;
|
|
|
|
struct winsys_handle handle;
|
|
|
|
|
|
|
|
/* note: alignment is wrong for a6xx */
|
2020-10-29 10:08:30 +00:00
|
|
|
scanout_templat.width0 = align(tmpl->width0, screen->info.gmem_align_w);
|
2020-08-18 09:04:02 +01:00
|
|
|
|
|
|
|
scanout = renderonly_scanout_for_resource(&scanout_templat,
|
|
|
|
screen->ro, &handle);
|
|
|
|
if (!scanout)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
renderonly_scanout_destroy(scanout, screen->ro);
|
|
|
|
|
|
|
|
assert(handle.type == WINSYS_HANDLE_TYPE_FD);
|
|
|
|
rsc = fd_resource(pscreen->resource_from_handle(pscreen, tmpl,
|
|
|
|
&handle,
|
|
|
|
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
|
|
|
|
close(handle.handle);
|
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &rsc->base;
|
|
|
|
}
|
|
|
|
|
|
|
|
prsc = fd_resource_allocate_and_resolve(pscreen, tmpl, modifiers, count, &size);
|
|
|
|
if (!prsc)
|
|
|
|
return NULL;
|
|
|
|
rsc = fd_resource(prsc);
|
|
|
|
|
2013-09-11 15:08:08 +01:00
|
|
|
realloc_bo(rsc, size);
|
2013-09-27 20:35:19 +01:00
|
|
|
if (!rsc->bo)
|
|
|
|
goto fail;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
|
|
|
return prsc;
|
2013-09-27 20:35:19 +01:00
|
|
|
fail:
|
|
|
|
fd_resource_destroy(pscreen, prsc);
|
|
|
|
return NULL;
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
2019-01-21 15:50:13 +00:00
|
|
|
static struct pipe_resource *
|
|
|
|
fd_resource_create(struct pipe_screen *pscreen,
|
|
|
|
const struct pipe_resource *tmpl)
|
|
|
|
{
|
|
|
|
const uint64_t mod = DRM_FORMAT_MOD_INVALID;
|
|
|
|
return fd_resource_create_with_modifiers(pscreen, tmpl, &mod, 1);
|
|
|
|
}
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
/**
|
|
|
|
* Create a texture from a winsys_handle. The handle is often created in
|
|
|
|
* another process by first creating a pipe texture and then calling
|
|
|
|
* resource_get_handle.
|
|
|
|
*/
|
|
|
|
static struct pipe_resource *
|
|
|
|
fd_resource_from_handle(struct pipe_screen *pscreen,
|
|
|
|
const struct pipe_resource *tmpl,
|
2016-04-25 16:47:21 +01:00
|
|
|
struct winsys_handle *handle, unsigned usage)
|
2012-10-27 17:07:34 +01:00
|
|
|
{
|
2019-01-21 15:50:13 +00:00
|
|
|
struct fd_screen *screen = fd_screen(pscreen);
|
2012-10-27 17:07:34 +01:00
|
|
|
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
|
2020-09-29 00:16:37 +01:00
|
|
|
|
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
|
2019-11-20 20:40:25 +00:00
|
|
|
struct fdl_slice *slice = fd_resource_slice(rsc, 0);
|
2017-12-04 14:02:07 +00:00
|
|
|
struct pipe_resource *prsc = &rsc->base;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
|
|
|
*prsc = *tmpl;
|
2021-01-22 16:42:29 +00:00
|
|
|
|
|
|
|
DBG("%"PRSC_FMT", modifier=%"PRIx64, PRSC_ARGS(prsc), handle->modifier);
|
|
|
|
|
2019-05-05 18:59:37 +01:00
|
|
|
fd_resource_layout_init(prsc);
|
2012-10-27 17:07:34 +01:00
|
|
|
|
|
|
|
pipe_reference_init(&prsc->reference, 1);
|
2016-06-27 14:44:15 +01:00
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
prsc->screen = pscreen;
|
|
|
|
|
2015-04-03 07:15:17 +01:00
|
|
|
util_range_init(&rsc->valid_buffer_range);
|
|
|
|
|
2020-04-24 22:45:04 +01:00
|
|
|
simple_mtx_init(&rsc->lock, mtx_plain);
|
|
|
|
|
2020-09-01 19:23:49 +01:00
|
|
|
struct fd_bo *bo = fd_screen_bo_from_handle(pscreen, handle);
|
|
|
|
if (!bo)
|
2013-09-27 20:35:19 +01:00
|
|
|
goto fail;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2020-09-01 19:23:49 +01:00
|
|
|
fd_resource_set_bo(rsc, bo);
|
|
|
|
|
2017-12-22 05:27:50 +00:00
|
|
|
rsc->internal_format = tmpl->format;
|
2020-07-07 23:27:32 +01:00
|
|
|
rsc->layout.pitch0 = handle->stride;
|
2016-04-25 16:47:21 +01:00
|
|
|
slice->offset = handle->offset;
|
2016-11-21 15:23:04 +00:00
|
|
|
slice->size0 = handle->stride * prsc->height0;
|
2013-05-26 22:13:27 +01:00
|
|
|
|
2020-10-29 10:08:30 +00:00
|
|
|
/* use a pitchalign of gmem_align_w pixels, because GMEM resolve for
|
2020-07-11 18:49:51 +01:00
|
|
|
* lower alignments is not implemented (but possible for a6xx at least)
|
|
|
|
*
|
|
|
|
* for UBWC-enabled resources, layout_resource_for_modifier will further
|
|
|
|
* validate the pitch and set the right pitchalign
|
2020-06-09 23:48:34 +01:00
|
|
|
*/
|
2020-07-11 18:49:51 +01:00
|
|
|
rsc->layout.pitchalign =
|
2020-10-29 10:08:30 +00:00
|
|
|
fdl_cpp_shift(&rsc->layout) + util_logbase2(screen->info.gmem_align_w);
|
2020-07-11 18:49:51 +01:00
|
|
|
|
|
|
|
/* apply the minimum pitchalign (note: actually 4 for a3xx but doesn't matter) */
|
|
|
|
if (is_a6xx(screen) || is_a5xx(screen))
|
|
|
|
rsc->layout.pitchalign = MAX2(rsc->layout.pitchalign, 6);
|
|
|
|
else
|
|
|
|
rsc->layout.pitchalign = MAX2(rsc->layout.pitchalign, 5);
|
2020-05-13 02:31:52 +01:00
|
|
|
|
2020-07-11 18:49:51 +01:00
|
|
|
if (rsc->layout.pitch0 < (prsc->width0 * rsc->layout.cpp) ||
|
|
|
|
fd_resource_pitch(rsc, 0) != rsc->layout.pitch0)
|
2016-09-03 17:57:50 +01:00
|
|
|
goto fail;
|
|
|
|
|
2019-05-05 18:59:37 +01:00
|
|
|
assert(rsc->layout.cpp);
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2020-02-05 01:46:10 +00:00
|
|
|
if (screen->layout_resource_for_modifier(rsc, handle->modifier) < 0)
|
|
|
|
goto fail;
|
|
|
|
|
2019-01-16 15:22:53 +00:00
|
|
|
if (screen->ro) {
|
|
|
|
rsc->scanout =
|
|
|
|
renderonly_create_gpu_import_for_resource(prsc, screen->ro, NULL);
|
|
|
|
/* failure is expected in some cases.. */
|
|
|
|
}
|
|
|
|
|
2019-05-04 13:06:50 +01:00
|
|
|
rsc->valid = true;
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
return prsc;
|
2013-09-27 20:35:19 +01:00
|
|
|
|
|
|
|
fail:
|
|
|
|
fd_resource_destroy(pscreen, prsc);
|
|
|
|
return NULL;
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
2015-11-08 04:20:31 +00:00
|
|
|
bool
|
|
|
|
fd_render_condition_check(struct pipe_context *pctx)
|
|
|
|
{
|
|
|
|
struct fd_context *ctx = fd_context(pctx);
|
|
|
|
|
|
|
|
if (!ctx->cond_query)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
union pipe_query_result res = { 0 };
|
|
|
|
bool wait =
|
|
|
|
ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT &&
|
|
|
|
ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
|
|
|
|
|
|
|
|
if (pctx->get_query_result(pctx, ctx->cond_query, wait, &res))
|
|
|
|
return (bool)res.u64 != ctx->cond_cond;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-11 15:57:34 +01:00
|
|
|
static void
|
|
|
|
fd_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
|
2021-02-12 20:42:01 +00:00
|
|
|
in_dt
|
2017-10-11 15:57:34 +01:00
|
|
|
{
|
2019-01-21 16:32:30 +00:00
|
|
|
struct fd_context *ctx = fd_context(pctx);
|
2017-10-11 15:57:34 +01:00
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO I guess we could track that the resource is invalidated and
|
|
|
|
* use that as a hint to realloc rather than stall in _transfer_map(),
|
|
|
|
* even in the non-DISCARD_WHOLE_RESOURCE case?
|
2019-01-21 16:32:30 +00:00
|
|
|
*
|
|
|
|
* Note: we set dirty bits to trigger invalidate logic fd_draw_vbo
|
2017-10-11 15:57:34 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (rsc->write_batch) {
|
|
|
|
struct fd_batch *batch = rsc->write_batch;
|
|
|
|
struct pipe_framebuffer_state *pfb = &batch->framebuffer;
|
|
|
|
|
2019-01-21 16:32:30 +00:00
|
|
|
if (pfb->zsbuf && pfb->zsbuf->texture == prsc) {
|
2017-10-11 15:57:34 +01:00
|
|
|
batch->resolve &= ~(FD_BUFFER_DEPTH | FD_BUFFER_STENCIL);
|
2019-01-21 16:32:30 +00:00
|
|
|
ctx->dirty |= FD_DIRTY_ZSA;
|
|
|
|
}
|
2017-10-11 15:57:34 +01:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
|
|
|
|
if (pfb->cbufs[i] && pfb->cbufs[i]->texture == prsc) {
|
|
|
|
batch->resolve &= ~(PIPE_CLEAR_COLOR0 << i);
|
2019-01-21 16:32:30 +00:00
|
|
|
ctx->dirty |= FD_DIRTY_FRAMEBUFFER;
|
2017-10-11 15:57:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-19 17:50:50 +00:00
|
|
|
|
|
|
|
rsc->valid = false;
|
2017-10-11 15:57:34 +01:00
|
|
|
}
|
|
|
|
|
2017-12-04 14:15:27 +00:00
|
|
|
static enum pipe_format
|
|
|
|
fd_resource_get_internal_format(struct pipe_resource *prsc)
|
|
|
|
{
|
|
|
|
return fd_resource(prsc)->internal_format;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fd_resource_set_stencil(struct pipe_resource *prsc,
|
|
|
|
struct pipe_resource *stencil)
|
|
|
|
{
|
|
|
|
fd_resource(prsc)->stencil = fd_resource(stencil);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct pipe_resource *
|
|
|
|
fd_resource_get_stencil(struct pipe_resource *prsc)
|
|
|
|
{
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
|
|
|
if (rsc->stencil)
|
|
|
|
return &rsc->stencil->base;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct u_transfer_vtbl transfer_vtbl = {
|
|
|
|
.resource_create = fd_resource_create,
|
|
|
|
.resource_destroy = fd_resource_destroy,
|
|
|
|
.transfer_map = fd_resource_transfer_map,
|
|
|
|
.transfer_flush_region = fd_resource_transfer_flush_region,
|
|
|
|
.transfer_unmap = fd_resource_transfer_unmap,
|
|
|
|
.get_internal_format = fd_resource_get_internal_format,
|
|
|
|
.set_stencil = fd_resource_set_stencil,
|
|
|
|
.get_stencil = fd_resource_get_stencil,
|
|
|
|
};
|
|
|
|
|
2020-02-05 01:41:27 +00:00
|
|
|
static const uint64_t supported_modifiers[] = {
|
|
|
|
DRM_FORMAT_MOD_LINEAR,
|
|
|
|
};
|
|
|
|
|
2020-02-05 01:46:10 +00:00
|
|
|
static int
|
|
|
|
fd_layout_resource_for_modifier(struct fd_resource *rsc, uint64_t modifier)
|
|
|
|
{
|
|
|
|
switch (modifier) {
|
|
|
|
case DRM_FORMAT_MOD_LINEAR:
|
2020-06-23 18:39:14 +01:00
|
|
|
/* The dri gallium frontend will pass DRM_FORMAT_MOD_INVALID to us
|
|
|
|
* when it's called through any of the non-modifier BO create entry
|
|
|
|
* points. Other drivers will determine tiling from the kernel or
|
|
|
|
* other legacy backchannels, but for freedreno it just means
|
|
|
|
* LINEAR. */
|
|
|
|
case DRM_FORMAT_MOD_INVALID:
|
2020-02-05 01:46:10 +00:00
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 12:59:48 +01:00
|
|
|
static struct pipe_resource *
|
|
|
|
fd_resource_from_memobj(struct pipe_screen *pscreen,
|
|
|
|
const struct pipe_resource *tmpl,
|
|
|
|
struct pipe_memory_object *pmemobj,
|
|
|
|
uint64_t offset)
|
|
|
|
{
|
|
|
|
struct fd_screen *screen = fd_screen(pscreen);
|
|
|
|
struct fd_memory_object *memobj = fd_memory_object(pmemobj);
|
|
|
|
struct pipe_resource *prsc;
|
|
|
|
struct fd_resource *rsc;
|
|
|
|
uint32_t size;
|
|
|
|
assert(memobj->bo);
|
|
|
|
|
|
|
|
/* We shouldn't get a scanout buffer here. */
|
|
|
|
assert(!(tmpl->bind & PIPE_BIND_SCANOUT));
|
|
|
|
|
|
|
|
uint64_t modifiers = DRM_FORMAT_MOD_INVALID;
|
|
|
|
if (tmpl->bind & PIPE_BIND_LINEAR) {
|
|
|
|
modifiers = DRM_FORMAT_MOD_LINEAR;
|
|
|
|
} else if (is_a6xx(screen) && tmpl->width0 >= FDL_MIN_UBWC_WIDTH) {
|
|
|
|
modifiers = DRM_FORMAT_MOD_QCOM_COMPRESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate new pipe resource. */
|
|
|
|
prsc = fd_resource_allocate_and_resolve(pscreen, tmpl, &modifiers, 1, &size);
|
|
|
|
if (!prsc)
|
|
|
|
return NULL;
|
|
|
|
rsc = fd_resource(prsc);
|
|
|
|
|
|
|
|
/* bo's size has to be large enough, otherwise cleanup resource and fail
|
|
|
|
* gracefully.
|
|
|
|
*/
|
|
|
|
if (fd_bo_size(memobj->bo) < size) {
|
|
|
|
fd_resource_destroy(pscreen, prsc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Share the bo with the memory object. */
|
2020-09-01 19:23:49 +01:00
|
|
|
fd_resource_set_bo(rsc, fd_bo_ref(memobj->bo));
|
2020-04-08 12:59:48 +01:00
|
|
|
|
|
|
|
return prsc;
|
|
|
|
}
|
|
|
|
|
2020-04-07 07:52:25 +01:00
|
|
|
static struct pipe_memory_object *
|
|
|
|
fd_memobj_create_from_handle(struct pipe_screen *pscreen,
|
|
|
|
struct winsys_handle *whandle,
|
|
|
|
bool dedicated)
|
|
|
|
{
|
|
|
|
struct fd_memory_object *memobj = CALLOC_STRUCT(fd_memory_object);
|
|
|
|
if (!memobj)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
struct fd_bo *bo = fd_screen_bo_from_handle(pscreen, whandle);
|
|
|
|
if (!bo) {
|
|
|
|
free(memobj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memobj->b.dedicated = dedicated;
|
|
|
|
memobj->bo = bo;
|
|
|
|
|
|
|
|
return &memobj->b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fd_memobj_destroy(struct pipe_screen *pscreen,
|
|
|
|
struct pipe_memory_object *pmemobj)
|
|
|
|
{
|
|
|
|
struct fd_memory_object *memobj = fd_memory_object(pmemobj);
|
|
|
|
|
|
|
|
assert(memobj->bo);
|
|
|
|
fd_bo_del(memobj->bo);
|
|
|
|
|
|
|
|
free(pmemobj);
|
|
|
|
}
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
void
|
|
|
|
fd_resource_screen_init(struct pipe_screen *pscreen)
|
|
|
|
{
|
2018-01-14 13:57:29 +00:00
|
|
|
struct fd_screen *screen = fd_screen(pscreen);
|
|
|
|
bool fake_rgtc = screen->gpu_id < 400;
|
2017-12-04 14:15:27 +00:00
|
|
|
|
|
|
|
pscreen->resource_create = u_transfer_helper_resource_create;
|
2019-01-21 15:50:13 +00:00
|
|
|
/* NOTE: u_transfer_helper does not yet support the _with_modifiers()
|
|
|
|
* variant:
|
|
|
|
*/
|
|
|
|
pscreen->resource_create_with_modifiers = fd_resource_create_with_modifiers;
|
2012-10-27 17:07:34 +01:00
|
|
|
pscreen->resource_from_handle = fd_resource_from_handle;
|
2017-12-04 14:02:07 +00:00
|
|
|
pscreen->resource_get_handle = fd_resource_get_handle;
|
2017-12-04 14:15:27 +00:00
|
|
|
pscreen->resource_destroy = u_transfer_helper_resource_destroy;
|
|
|
|
|
|
|
|
pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
|
2018-07-30 23:20:00 +01:00
|
|
|
true, false, fake_rgtc, true);
|
2018-01-14 13:57:29 +00:00
|
|
|
|
2020-02-05 01:46:10 +00:00
|
|
|
if (!screen->layout_resource_for_modifier)
|
|
|
|
screen->layout_resource_for_modifier = fd_layout_resource_for_modifier;
|
2020-02-05 01:41:27 +00:00
|
|
|
if (!screen->supported_modifiers) {
|
|
|
|
screen->supported_modifiers = supported_modifiers;
|
|
|
|
screen->num_supported_modifiers = ARRAY_SIZE(supported_modifiers);
|
|
|
|
}
|
2020-04-07 07:52:25 +01:00
|
|
|
|
|
|
|
/* GL_EXT_memory_object */
|
|
|
|
pscreen->memobj_create_from_handle = fd_memobj_create_from_handle;
|
|
|
|
pscreen->memobj_destroy = fd_memobj_destroy;
|
2020-04-08 12:59:48 +01:00
|
|
|
pscreen->resource_from_memobj = fd_resource_from_memobj;
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
2018-11-07 02:30:31 +00:00
|
|
|
static void
|
|
|
|
fd_get_sample_position(struct pipe_context *context,
|
|
|
|
unsigned sample_count, unsigned sample_index,
|
|
|
|
float *pos_out)
|
|
|
|
{
|
|
|
|
/* The following is copied from nouveau/nv50 except for position
|
|
|
|
* values, which are taken from blob driver */
|
|
|
|
static const uint8_t pos1[1][2] = { { 0x8, 0x8 } };
|
|
|
|
static const uint8_t pos2[2][2] = {
|
|
|
|
{ 0xc, 0xc }, { 0x4, 0x4 } };
|
|
|
|
static const uint8_t pos4[4][2] = {
|
|
|
|
{ 0x6, 0x2 }, { 0xe, 0x6 },
|
|
|
|
{ 0x2, 0xa }, { 0xa, 0xe } };
|
|
|
|
/* TODO needs to be verified on supported hw */
|
|
|
|
static const uint8_t pos8[8][2] = {
|
|
|
|
{ 0x9, 0x5 }, { 0x7, 0xb },
|
|
|
|
{ 0xd, 0x9 }, { 0x5, 0x3 },
|
|
|
|
{ 0x3, 0xd }, { 0x1, 0x7 },
|
|
|
|
{ 0xb, 0xf }, { 0xf, 0x1 } };
|
|
|
|
|
|
|
|
const uint8_t (*ptr)[2];
|
|
|
|
|
|
|
|
switch (sample_count) {
|
|
|
|
case 1:
|
|
|
|
ptr = pos1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ptr = pos2;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
ptr = pos4;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
ptr = pos8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos_out[0] = ptr[sample_index][0] / 16.0f;
|
|
|
|
pos_out[1] = ptr[sample_index][1] / 16.0f;
|
|
|
|
}
|
|
|
|
|
2019-02-26 16:54:56 +00:00
|
|
|
static void
|
|
|
|
fd_blit_pipe(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
|
2021-02-12 20:42:01 +00:00
|
|
|
in_dt
|
2019-02-26 16:54:56 +00:00
|
|
|
{
|
|
|
|
/* wrap fd_blit to return void */
|
|
|
|
fd_blit(pctx, blit_info);
|
|
|
|
}
|
|
|
|
|
2012-10-27 17:07:34 +01:00
|
|
|
void
|
|
|
|
fd_resource_context_init(struct pipe_context *pctx)
|
|
|
|
{
|
2017-12-04 14:15:27 +00:00
|
|
|
pctx->transfer_map = u_transfer_helper_transfer_map;
|
|
|
|
pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region;
|
|
|
|
pctx->transfer_unmap = u_transfer_helper_transfer_unmap;
|
gallium: split transfer_inline_write into buffer and texture callbacks
to reduce the call indirections with u_resource_vtbl.
The worst call tree you could get was:
- u_transfer_inline_write_vtbl
- u_default_transfer_inline_write
- u_transfer_map_vtbl
- driver_transfer_map
- u_transfer_unmap_vtbl
- driver_transfer_unmap
That's 6 indirect calls. Some drivers only had 5. The goal is to have
1 indirect call for drivers that care. The resource type can be determined
statically at most call sites.
The new interface is:
pipe_context::buffer_subdata(ctx, resource, usage, offset, size, data)
pipe_context::texture_subdata(ctx, resource, level, usage, box, data,
stride, layer_stride)
v2: fix whitespace, correct ilo's behavior
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Acked-by: Roland Scheidegger <sroland@vmware.com>
2016-07-16 20:19:48 +01:00
|
|
|
pctx->buffer_subdata = u_default_buffer_subdata;
|
2016-12-03 17:34:10 +00:00
|
|
|
pctx->texture_subdata = u_default_texture_subdata;
|
2012-10-27 17:07:34 +01:00
|
|
|
pctx->create_surface = fd_create_surface;
|
|
|
|
pctx->surface_destroy = fd_surface_destroy;
|
|
|
|
pctx->resource_copy_region = fd_resource_copy_region;
|
2019-02-26 16:54:56 +00:00
|
|
|
pctx->blit = fd_blit_pipe;
|
2013-09-20 14:08:29 +01:00
|
|
|
pctx->flush_resource = fd_flush_resource;
|
2017-10-11 15:57:34 +01:00
|
|
|
pctx->invalidate_resource = fd_invalidate_resource;
|
2018-11-07 02:30:31 +00:00
|
|
|
pctx->get_sample_position = fd_get_sample_position;
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|