asahi: Make agx_flush_resource reallocate non-shareable resources
It's not legal to share a resource that isn't PIPE_BIND_SHARED, but flush_resource needs to prepare a resource for potential sharing. Let's allocate a new resource and blit it over when this happens. See also: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13154 Signed-off-by: Asahi Lina <lina@asahilina.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21620>
This commit is contained in:
@@ -940,9 +940,64 @@ agx_clear(struct pipe_context *pctx, unsigned buffers,
|
||||
}
|
||||
|
||||
static void
|
||||
agx_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
|
||||
agx_flush_resource(struct pipe_context *pctx, struct pipe_resource *pres)
|
||||
{
|
||||
agx_flush_writer(agx_context(ctx), agx_resource(resource), "flush_resource");
|
||||
struct agx_resource *rsrc = agx_resource(pres);
|
||||
|
||||
/* flush_resource is used to prepare resources for sharing, so if this is not
|
||||
* already a shareabe resource, make it so
|
||||
*/
|
||||
struct agx_bo *old = rsrc->bo;
|
||||
if (!(old->flags & AGX_BO_SHAREABLE)) {
|
||||
assert(rsrc->layout.levels == 1 &&
|
||||
"Shared resources must not be mipmapped");
|
||||
assert(rsrc->layout.sample_count_sa == 1 &&
|
||||
"Shared resources must not be multisampled");
|
||||
assert(rsrc->bo);
|
||||
assert(!(pres->bind & PIPE_BIND_SHARED));
|
||||
|
||||
struct pipe_resource templ = *pres;
|
||||
templ.bind |= PIPE_BIND_SHARED;
|
||||
|
||||
/* Create a new shareable resource */
|
||||
struct agx_resource *new_res =
|
||||
agx_resource(pctx->screen->resource_create(pctx->screen, &templ));
|
||||
|
||||
assert(new_res);
|
||||
|
||||
/* Blit it over */
|
||||
struct pipe_blit_info blit = {0};
|
||||
|
||||
u_box_3d(0, 0, 0, rsrc->layout.width_px, rsrc->layout.height_px,
|
||||
rsrc->layout.depth_px, &blit.dst.box);
|
||||
blit.src.box = blit.dst.box;
|
||||
|
||||
blit.dst.resource = &new_res->base;
|
||||
blit.dst.format = new_res->base.format;
|
||||
blit.dst.level = 0;
|
||||
blit.src.resource = pres;
|
||||
blit.src.format = pres->format;
|
||||
blit.src.level = 0;
|
||||
blit.mask = util_format_get_mask(blit.src.format);
|
||||
blit.filter = PIPE_TEX_FILTER_NEAREST;
|
||||
agx_blit(pctx, &blit);
|
||||
|
||||
/* Flush the blit out, to make sure the old resource is no longer used */
|
||||
agx_flush_writer(agx_context(pctx), new_res, "flush_resource");
|
||||
|
||||
/* Copy the bind flags and swap the BOs */
|
||||
rsrc->base.bind = new_res->base.bind;
|
||||
rsrc->bo = new_res->bo;
|
||||
new_res->bo = old;
|
||||
|
||||
/* Free the new resource, which now owns the old BO */
|
||||
pipe_resource_reference((struct pipe_resource **)&new_res, NULL);
|
||||
} else {
|
||||
/* Otherwise just claim it's already shared */
|
||||
pres->bind |= PIPE_BIND_SHARED;
|
||||
agx_flush_writer(agx_context(pctx), rsrc, "flush_resource");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user