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
|
|
|
|
|
|
|
#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' */
|
|
|
|
#include "state_tracker/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
|
|
|
|
* called on realloc_bo to ensure the neccessary state is re-
|
|
|
|
* emitted so the GPU looks at the new backing bo.
|
|
|
|
*/
|
2015-04-04 03:29:44 +01:00
|
|
|
static void
|
2017-10-05 22:07:27 +01:00
|
|
|
rebind_resource(struct fd_context *ctx, struct pipe_resource *prsc)
|
2015-04-04 03:29:44 +01:00
|
|
|
{
|
|
|
|
/* VBOs */
|
2017-04-15 15:04:55 +01:00
|
|
|
for (unsigned i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) {
|
2017-04-02 13:30:16 +01:00
|
|
|
if (ctx->vtx.vertexbuf.vb[i].buffer.resource == prsc)
|
2015-04-04 03:29:44 +01:00
|
|
|
ctx->dirty |= FD_DIRTY_VTXBUF;
|
|
|
|
}
|
|
|
|
|
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..
|
|
|
|
*/
|
|
|
|
const unsigned num_ubos = util_last_bit(ctx->constbuf[stage].enabled_mask);
|
|
|
|
for (unsigned i = 1; i < num_ubos; i++) {
|
|
|
|
if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_CONST)
|
|
|
|
break;
|
|
|
|
if (ctx->constbuf[stage].cb[i].buffer == prsc)
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_CONST;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Textures */
|
|
|
|
for (unsigned i = 0; i < ctx->tex[stage].num_textures; i++) {
|
|
|
|
if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_TEX)
|
|
|
|
break;
|
|
|
|
if (ctx->tex[stage].textures[i] && (ctx->tex[stage].textures[i]->texture == prsc))
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_TEX;
|
|
|
|
}
|
2017-04-17 15:56:20 +01:00
|
|
|
|
2019-06-07 19:20:11 +01:00
|
|
|
/* Images */
|
|
|
|
const unsigned num_images = util_last_bit(ctx->shaderimg[stage].enabled_mask);
|
|
|
|
for (unsigned i = 0; i < num_images; i++) {
|
|
|
|
if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_IMAGE)
|
|
|
|
break;
|
|
|
|
if (ctx->shaderimg[stage].si[i].resource == prsc)
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_IMAGE;
|
|
|
|
}
|
|
|
|
|
2017-04-17 15:56:20 +01:00
|
|
|
/* SSBOs */
|
|
|
|
const unsigned num_ssbos = util_last_bit(ctx->shaderbuf[stage].enabled_mask);
|
|
|
|
for (unsigned i = 0; i < num_ssbos; i++) {
|
|
|
|
if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_SSBO)
|
|
|
|
break;
|
|
|
|
if (ctx->shaderbuf[stage].sb[i].buffer == prsc)
|
|
|
|
ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_SSBO;
|
|
|
|
}
|
2015-04-04 03:29:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2018-11-30 13:29:51 +00:00
|
|
|
rsc->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-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) {
|
|
|
|
void *buf = fd_bo_map(rsc->bo);
|
|
|
|
memset(buf, 0, rsc->layout.slices[0].offset);
|
|
|
|
}
|
|
|
|
|
2018-10-12 14:24:21 +01:00
|
|
|
rsc->seqno = p_atomic_inc_return(&screen->rsc_seqno);
|
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)
|
|
|
|
{
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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)
|
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;
|
|
|
|
|
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);
|
|
|
|
|
2017-03-05 01:12:30 +00:00
|
|
|
mtx_lock(&ctx->screen->lock);
|
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);
|
|
|
|
|
2017-03-05 01:32:06 +00:00
|
|
|
mtx_unlock(&ctx->screen->lock);
|
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)
|
|
|
|
|
|
|
|
/* 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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
* appears to the state tracker as if nothing changed.
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO what if rsc is used in other contexts, we don't currently
|
|
|
|
* have a good way to rebind_resource() in other contexts. And an
|
|
|
|
* app that is reading one resource in multiple contexts, isn't
|
|
|
|
* going to expect that the resource is modified.
|
|
|
|
*
|
|
|
|
* Hopefully the edge cases where we need to uncompress are rare
|
|
|
|
* enough that they mostly only show up in deqp.
|
|
|
|
*/
|
|
|
|
|
|
|
|
rebind_resource(ctx, &rsc->base);
|
|
|
|
}
|
|
|
|
|
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;
|
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)
|
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)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
struct fd_batch *write_batch = NULL;
|
|
|
|
|
2019-02-19 14:29:49 +00:00
|
|
|
mtx_lock(&ctx->screen->lock);
|
|
|
|
fd_batch_reference_locked(&write_batch, rsc->write_batch);
|
|
|
|
mtx_unlock(&ctx->screen->lock);
|
2017-11-20 20:34:40 +00:00
|
|
|
|
|
|
|
if (usage & PIPE_TRANSFER_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.
|
|
|
|
*/
|
|
|
|
mtx_lock(&ctx->screen->lock);
|
|
|
|
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);
|
2017-11-20 20:34:40 +00:00
|
|
|
mtx_unlock(&ctx->screen->lock);
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
flush_resource(fd_context(pctx), fd_resource(prsc), PIPE_TRANSFER_READ);
|
|
|
|
}
|
|
|
|
|
2013-05-26 22:13:27 +01:00
|
|
|
static void
|
|
|
|
fd_resource_transfer_unmap(struct pipe_context *pctx,
|
|
|
|
struct pipe_transfer *ptrans)
|
|
|
|
{
|
|
|
|
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) {
|
|
|
|
if (ptrans->usage & PIPE_TRANSFER_WRITE)
|
|
|
|
fd_blit_from_staging(ctx, trans);
|
|
|
|
pipe_resource_reference(&trans->staging_prsc, NULL);
|
|
|
|
}
|
2015-04-22 19:35:00 +01:00
|
|
|
|
|
|
|
if (!(ptrans->usage & PIPE_TRANSFER_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)
|
|
|
|
{
|
|
|
|
struct fd_context *ctx = fd_context(pctx);
|
|
|
|
struct fd_resource *rsc = fd_resource(prsc);
|
2019-11-20 20:40:25 +00:00
|
|
|
struct fdl_slice *slice = fd_resource_slice(rsc, level);
|
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
|
|
|
|
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-04-14 19:14:31 +01:00
|
|
|
ptrans->stride = slice->pitch;
|
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) {
|
2019-11-20 20:40:25 +00:00
|
|
|
struct fdl_slice *staging_slice =
|
2019-05-05 16:10:24 +01:00
|
|
|
fd_resource_slice(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
|
|
|
// TODO for PIPE_TRANSFER_READ, need to do untiling blit..
|
|
|
|
trans->staging_prsc = &staging_rsc->base;
|
2020-04-14 19:14:31 +01:00
|
|
|
trans->base.stride = staging_slice->pitch;
|
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;
|
|
|
|
|
|
|
|
if (usage & PIPE_TRANSFER_READ) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-29 18:51:26 +01:00
|
|
|
if (ctx->in_shadow && !(usage & PIPE_TRANSFER_READ))
|
|
|
|
usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
|
|
|
|
|
2013-09-11 15:08:08 +01:00
|
|
|
if (usage & PIPE_TRANSFER_READ)
|
|
|
|
op |= DRM_FREEDRENO_PREP_READ;
|
|
|
|
|
|
|
|
if (usage & PIPE_TRANSFER_WRITE)
|
|
|
|
op |= DRM_FREEDRENO_PREP_WRITE;
|
|
|
|
|
2020-04-24 21:56:09 +01:00
|
|
|
bool needs_flush = pending(rsc, !!(usage & PIPE_TRANSFER_WRITE));
|
|
|
|
|
2014-10-22 21:36:24 +01:00
|
|
|
if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
|
2020-04-24 21:56:09 +01:00
|
|
|
if (needs_flush || fd_resource_busy(rsc, op)) {
|
|
|
|
realloc_bo(rsc, fd_bo_size(rsc->bo));
|
|
|
|
rebind_resource(ctx, prsc);
|
|
|
|
}
|
2015-04-03 07:15:17 +01:00
|
|
|
} else if ((usage & PIPE_TRANSFER_WRITE) &&
|
|
|
|
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.
|
|
|
|
*/
|
2014-10-22 21:36:24 +01:00
|
|
|
} else if (!(usage & PIPE_TRANSFER_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: */
|
2019-02-19 14:29:49 +00:00
|
|
|
fd_context_lock(ctx);
|
|
|
|
fd_batch_reference_locked(&write_batch, rsc->write_batch);
|
|
|
|
fd_context_unlock(ctx);
|
2016-07-19 23:24:57 +01:00
|
|
|
|
|
|
|
if ((usage & PIPE_TRANSFER_WRITE) && write_batch &&
|
|
|
|
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!
|
|
|
|
*/
|
2017-11-20 20:33:54 +00:00
|
|
|
if (ctx->screen->reorder && busy && !(usage & PIPE_TRANSFER_READ) &&
|
|
|
|
(usage & PIPE_TRANSFER_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-10-05 22:07:27 +01:00
|
|
|
rebind_resource(ctx, prsc);
|
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) {
|
2019-11-20 20:40:25 +00:00
|
|
|
struct fdl_slice *staging_slice =
|
2019-05-05 16:10:24 +01:00
|
|
|
fd_resource_slice(staging_rsc, 0);
|
2017-11-20 20:34:40 +00:00
|
|
|
trans->staging_prsc = &staging_rsc->base;
|
2020-04-14 19:14:31 +01:00
|
|
|
trans->base.stride = staging_slice->pitch;
|
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
|
|
|
|
2017-11-20 20:34:40 +00:00
|
|
|
if (usage & PIPE_TRANSFER_WRITE)
|
|
|
|
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);
|
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);
|
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);
|
|
|
|
|
2019-01-16 15:22:53 +00:00
|
|
|
return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->scanout,
|
2020-04-14 19:14:31 +01:00
|
|
|
fd_resource_slice(rsc, 0)->pitch, handle);
|
2012-10-27 17:07:34 +01:00
|
|
|
}
|
|
|
|
|
2013-08-31 14:14:27 +01:00
|
|
|
static uint32_t
|
2015-11-08 03:13:16 +00:00
|
|
|
setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format format)
|
2013-08-31 14:14:27 +01:00
|
|
|
{
|
2017-12-04 14:02:07 +00:00
|
|
|
struct pipe_resource *prsc = &rsc->base;
|
2017-09-14 20:03:11 +01:00
|
|
|
struct fd_screen *screen = fd_screen(prsc->screen);
|
2015-11-21 16:49:03 +00:00
|
|
|
enum util_format_layout layout = util_format_description(format)->layout;
|
2017-09-14 20:03:11 +01:00
|
|
|
uint32_t pitchalign = screen->gmem_alignw;
|
2013-08-31 14:14:27 +01:00
|
|
|
uint32_t level, size = 0;
|
|
|
|
uint32_t width = prsc->width0;
|
|
|
|
uint32_t height = prsc->height0;
|
|
|
|
uint32_t depth = prsc->depth0;
|
2014-12-12 18:38:05 +00:00
|
|
|
/* in layer_first layout, the level (slice) contains just one
|
|
|
|
* layer (since in fact the layer contains the slices)
|
|
|
|
*/
|
2019-05-05 18:59:37 +01:00
|
|
|
uint32_t layers_in_level = rsc->layout.layer_first ? 1 : prsc->array_size;
|
2013-08-31 14:14:27 +01:00
|
|
|
|
|
|
|
for (level = 0; level <= prsc->last_level; level++) {
|
2019-11-20 20:40:25 +00:00
|
|
|
struct fdl_slice *slice = fd_resource_slice(rsc, level);
|
2015-08-16 18:15:55 +01:00
|
|
|
uint32_t blocks;
|
2013-08-31 14:14:27 +01:00
|
|
|
|
2015-11-21 16:49:03 +00:00
|
|
|
if (layout == UTIL_FORMAT_LAYOUT_ASTC)
|
2020-04-14 19:14:31 +01:00
|
|
|
width = util_align_npot(width, pitchalign * util_format_get_blockwidth(format));
|
2015-11-21 16:49:03 +00:00
|
|
|
else
|
2020-04-14 19:14:31 +01:00
|
|
|
width = align(width, pitchalign);
|
|
|
|
slice->pitch = util_format_get_nblocksx(format, width) * rsc->layout.cpp;
|
2013-08-31 14:14:27 +01:00
|
|
|
slice->offset = size;
|
2015-11-08 03:13:16 +00:00
|
|
|
blocks = util_format_get_nblocks(format, width, height);
|
2015-03-15 20:38:42 +00:00
|
|
|
/* 1d array and 2d array textures must all have the same layer size
|
|
|
|
* for each miplevel on a3xx. 3d textures can have different layer
|
|
|
|
* sizes for high levels, but the hw auto-sizer is buggy (or at least
|
|
|
|
* different than what this code does), so as soon as the layer size
|
|
|
|
* range gets into range, we stop reducing it.
|
2015-03-13 04:53:49 +00:00
|
|
|
*/
|
2015-03-15 20:38:42 +00:00
|
|
|
if (prsc->target == PIPE_TEXTURE_3D && (
|
|
|
|
level == 1 ||
|
2019-05-05 16:10:24 +01:00
|
|
|
(level > 1 && fd_resource_slice(rsc, level - 1)->size0 > 0xf000)))
|
2019-05-05 18:59:37 +01:00
|
|
|
slice->size0 = align(blocks * rsc->layout.cpp, alignment);
|
|
|
|
else if (level == 0 || rsc->layout.layer_first || alignment == 1)
|
|
|
|
slice->size0 = align(blocks * rsc->layout.cpp, alignment);
|
2015-03-13 04:53:49 +00:00
|
|
|
else
|
2019-05-05 16:10:24 +01:00
|
|
|
slice->size0 = fd_resource_slice(rsc, level - 1)->size0;
|
2013-08-31 14:14:27 +01:00
|
|
|
|
2014-12-12 18:38:05 +00:00
|
|
|
size += slice->size0 * depth * layers_in_level;
|
2013-08-31 14:14:27 +01:00
|
|
|
|
|
|
|
width = u_minify(width, 1);
|
|
|
|
height = u_minify(height, 1);
|
|
|
|
depth = u_minify(depth, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2014-09-13 13:25:51 +01:00
|
|
|
static uint32_t
|
2018-01-14 13:57:29 +00:00
|
|
|
slice_alignment(enum pipe_texture_target target)
|
2014-09-13 13:25:51 +01:00
|
|
|
{
|
2014-12-04 21:56:33 +00:00
|
|
|
/* on a3xx, 2d array and 3d textures seem to want their
|
|
|
|
* layers aligned to page boundaries:
|
|
|
|
*/
|
2018-01-14 13:57:29 +00:00
|
|
|
switch (target) {
|
2014-12-04 21:56:33 +00:00
|
|
|
case PIPE_TEXTURE_3D:
|
|
|
|
case PIPE_TEXTURE_1D_ARRAY:
|
|
|
|
case PIPE_TEXTURE_2D_ARRAY:
|
|
|
|
return 4096;
|
|
|
|
default:
|
|
|
|
return 1;
|
2014-09-13 13:25:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-14 13:57:29 +00:00
|
|
|
/* cross generation texture layout to plug in to screen->setup_slices()..
|
|
|
|
* replace with generation specific one as-needed.
|
|
|
|
*
|
|
|
|
* TODO for a4xx probably can extract out the a4xx specific logic int
|
|
|
|
* a small fd4_setup_slices() wrapper that sets up layer_first, and then
|
|
|
|
* calls this.
|
|
|
|
*/
|
|
|
|
uint32_t
|
|
|
|
fd_setup_slices(struct fd_resource *rsc)
|
|
|
|
{
|
|
|
|
uint32_t alignment;
|
|
|
|
|
|
|
|
alignment = slice_alignment(rsc->base.target);
|
|
|
|
|
|
|
|
struct fd_screen *screen = fd_screen(rsc->base.screen);
|
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 (is_a4xx(screen)) {
|
2018-01-14 13:57:29 +00:00
|
|
|
switch (rsc->base.target) {
|
|
|
|
case PIPE_TEXTURE_3D:
|
2019-05-05 18:59:37 +01:00
|
|
|
rsc->layout.layer_first = false;
|
2018-01-14 13:57:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
2019-05-05 18:59:37 +01:00
|
|
|
rsc->layout.layer_first = true;
|
2018-01-14 13:57:29 +00:00
|
|
|
alignment = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return setup_slices(rsc, alignment, rsc->base.format);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
/**
|
|
|
|
* Create a new texture object, using the given template info.
|
|
|
|
*/
|
|
|
|
static struct pipe_resource *
|
2019-01-21 15:50:13 +00:00
|
|
|
fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
|
|
|
const struct pipe_resource *tmpl,
|
|
|
|
const uint64_t *modifiers, int count)
|
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-02-20 10:50:47 +00:00
|
|
|
/* 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))) {
|
2019-01-16 15:22:53 +00:00
|
|
|
struct pipe_resource scanout_templat = *tmpl;
|
|
|
|
struct renderonly_scanout *scanout;
|
|
|
|
struct winsys_handle handle;
|
|
|
|
|
2019-08-01 17:42:33 +01:00
|
|
|
/* apply freedreno alignment requirement */
|
|
|
|
scanout_templat.width0 = align(tmpl->width0, screen->gmem_alignw);
|
|
|
|
|
2019-01-16 15:22:53 +00: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;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsc = CALLOC_STRUCT(fd_resource);
|
|
|
|
prsc = &rsc->base;
|
|
|
|
|
2016-06-28 12:53:34 +01:00
|
|
|
DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
|
|
|
|
"nr_samples=%u, usage=%u, bind=%x, flags=%x", prsc,
|
2015-11-08 03:13:16 +00:00
|
|
|
tmpl->target, util_format_name(format),
|
2012-10-27 17:07:34 +01:00
|
|
|
tmpl->width0, tmpl->height0, tmpl->depth0,
|
|
|
|
tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
|
|
|
|
tmpl->usage, tmpl->bind, tmpl->flags);
|
|
|
|
|
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*prsc = *tmpl;
|
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);
|
2019-01-21 15:50:13 +00:00
|
|
|
if (tmpl->bind & LINEAR)
|
|
|
|
linear = true;
|
|
|
|
|
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.)
|
|
|
|
*/
|
2019-03-14 04:14:37 +00:00
|
|
|
bool allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count);
|
2019-01-21 15:50:13 +00:00
|
|
|
if (tmpl->bind & PIPE_BIND_SHARED)
|
2019-03-14 04:14:37 +00:00
|
|
|
allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count);
|
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);
|
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
|
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);
|
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;
|
2020-04-14 19:14:31 +01:00
|
|
|
uint32_t pitchalign = fd_screen(pscreen)->gmem_alignw * rsc->layout.cpp;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2013-08-31 14:14:27 +01:00
|
|
|
DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
|
2012-10-27 17:07:34 +01:00
|
|
|
"nr_samples=%u, usage=%u, bind=%x, flags=%x",
|
|
|
|
tmpl->target, util_format_name(tmpl->format),
|
|
|
|
tmpl->width0, tmpl->height0, tmpl->depth0,
|
|
|
|
tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
|
|
|
|
tmpl->usage, tmpl->bind, tmpl->flags);
|
|
|
|
|
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*prsc = *tmpl;
|
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);
|
|
|
|
|
2016-09-03 17:57:50 +01:00
|
|
|
rsc->bo = fd_screen_bo_from_handle(pscreen, handle);
|
2013-09-27 20:35:19 +01:00
|
|
|
if (!rsc->bo)
|
|
|
|
goto fail;
|
2012-10-27 17:07:34 +01:00
|
|
|
|
2017-12-22 05:27:50 +00:00
|
|
|
rsc->internal_format = tmpl->format;
|
2020-04-14 19:14:31 +01:00
|
|
|
slice->pitch = 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-04-14 19:14:31 +01:00
|
|
|
if ((slice->pitch < align(prsc->width0 * rsc->layout.cpp, pitchalign)) ||
|
2016-12-03 17:34:10 +00:00
|
|
|
(slice->pitch & (pitchalign - 1)))
|
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)
|
|
|
|
{
|
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:
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
if (!screen->setup_slices)
|
|
|
|
screen->setup_slices = fd_setup_slices;
|
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);
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
/* 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
|
|
|
}
|