panfrost: Handle context_init errors correctly

This fix OpenCL CTS "multiple_device_context/test_multiples" failures.

Also improve create_context/destroy error management a bit.

Signed-off-by: Mary Guillemard <mary.guillemard@collabora.com>
Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30150>
This commit is contained in:
Mary Guillemard
2024-07-08 12:38:54 +02:00
committed by Marge Bot
parent 668bde4421
commit 71a24a0c5e
5 changed files with 86 additions and 26 deletions

View File

@@ -551,21 +551,25 @@ panfrost_destroy(struct pipe_context *pipe)
pan_screen(pipe->screen)->vtbl.context_cleanup(panfrost);
_mesa_hash_table_destroy(panfrost->writers, NULL);
if (panfrost->writers)
_mesa_hash_table_destroy(panfrost->writers, NULL);
if (panfrost->blitter)
util_blitter_destroy(panfrost->blitter);
util_unreference_framebuffer_state(&panfrost->pipe_framebuffer);
u_upload_destroy(pipe->stream_uploader);
if (pipe->stream_uploader)
u_upload_destroy(pipe->stream_uploader);
panfrost_pool_cleanup(&panfrost->descs);
panfrost_pool_cleanup(&panfrost->shaders);
panfrost_afbc_context_destroy(panfrost);
drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->in_sync_obj);
if (panfrost->in_sync_fd != -1)
if (panfrost->in_sync_fd != -1) {
close(panfrost->in_sync_fd);
panfrost->in_sync_fd = -1;
}
drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->syncobj);
ralloc_free(pipe);
@@ -872,9 +876,25 @@ struct pipe_context *
panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
{
struct panfrost_context *ctx = rzalloc(NULL, struct panfrost_context);
if (!ctx)
return NULL;
struct pipe_context *gallium = (struct pipe_context *)ctx;
struct panfrost_device *dev = pan_device(screen);
int ret;
/* Create a syncobj in a signaled state. Will be updated to point to the
* last queued job out_sync every time we submit a new job.
*/
ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED,
&ctx->syncobj);
if (ret) {
ralloc_free(ctx);
return NULL;
}
gallium->screen = screen;
gallium->destroy = panfrost_destroy;
@@ -969,21 +989,17 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
ctx->sample_mask = ~0;
ctx->active_queries = true;
int ASSERTED ret;
/* Create a syncobj in a signaled state. Will be updated to point to the
* last queued job out_sync every time we submit a new job.
*/
ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED,
&ctx->syncobj);
assert(!ret && ctx->syncobj);
/* Sync object/FD used for NATIVE_FENCE_FD. */
ctx->in_sync_fd = -1;
ret = drmSyncobjCreate(panfrost_device_fd(dev), 0, &ctx->in_sync_obj);
assert(!ret);
pan_screen(screen)->vtbl.context_init(ctx);
ret = pan_screen(screen)->vtbl.context_init(ctx);
if (ret) {
gallium->destroy(gallium);
return NULL;
}
return gallium;
}
@@ -992,5 +1008,6 @@ void
panfrost_context_reinit(struct panfrost_context *ctx)
{
pan_screen(ctx->base.screen)->vtbl.context_cleanup(ctx);
pan_screen(ctx->base.screen)->vtbl.context_init(ctx);
ASSERTED int ret = pan_screen(ctx->base.screen)->vtbl.context_init(ctx);
assert(!ret);
}

View File

@@ -945,7 +945,7 @@ GENX(csf_launch_draw)(struct panfrost_batch *batch,
#define POSITION_FIFO_SIZE (64 * 1024)
void
int
GENX(csf_init_context)(struct panfrost_context *ctx)
{
struct panfrost_device *dev = pan_device(ctx->base.screen);
@@ -969,27 +969,42 @@ GENX(csf_init_context)(struct panfrost_context *ctx)
int ret =
drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_GROUP_CREATE, &gc);
assert(!ret);
if (ret)
goto err_group_create;
ctx->csf.group_handle = gc.group_handle;
struct drm_panthor_group_destroy gd = {
.group_handle = ctx->csf.group_handle,
};
/* Get tiler heap */
struct drm_panthor_tiler_heap_create thc = {
.vm_id = pan_kmod_vm_handle(dev->kmod.vm),
.chunk_size = pan_screen(ctx->base.screen)->csf_tiler_heap.chunk_size,
.initial_chunk_count = pan_screen(ctx->base.screen)->csf_tiler_heap.initial_chunks,
.initial_chunk_count =
pan_screen(ctx->base.screen)->csf_tiler_heap.initial_chunks,
.max_chunks = pan_screen(ctx->base.screen)->csf_tiler_heap.max_chunks,
.target_in_flight = 65535,
};
ret = drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE,
&thc);
assert(!ret);
if (ret)
goto err_tiler_heap;
ctx->csf.heap.handle = thc.handle;
struct drm_panthor_tiler_heap_destroy thd = {
.handle = ctx->csf.heap.handle,
};
ctx->csf.heap.desc_bo =
panfrost_bo_create(dev, pan_size(TILER_HEAP), 0, "Tiler Heap");
if (ctx->csf.heap.desc_bo == NULL)
goto err_tiler_heap_desc_bo;
pan_pack(ctx->csf.heap.desc_bo->ptr.cpu, TILER_HEAP, heap) {
heap.size = pan_screen(ctx->base.screen)->csf_tiler_heap.chunk_size;
heap.base = thc.first_heap_chunk_gpu_va;
@@ -999,12 +1014,16 @@ GENX(csf_init_context)(struct panfrost_context *ctx)
ctx->csf.tmp_geom_bo = panfrost_bo_create(
dev, POSITION_FIFO_SIZE, PAN_BO_INVISIBLE, "Temporary Geometry buffer");
assert(ctx->csf.tmp_geom_bo);
if (ctx->csf.tmp_geom_bo == NULL)
goto err_tiler_heap_tmp_geom_bo;
/* Setup the tiler heap */
struct panfrost_bo *cs_bo =
panfrost_bo_create(dev, 4096, 0, "Temporary CS buffer");
assert(cs_bo);
if (cs_bo == NULL)
goto err_tiler_heap_cs_bo;
struct cs_buffer init_buffer = {
.cpu = cs_bo->ptr.cpu,
@@ -1039,19 +1058,40 @@ GENX(csf_init_context)(struct panfrost_context *ctx)
csf_prepare_qsubmit(ctx, &qsubmit, 0, cs_start, cs_size, &sync, 1);
csf_prepare_gsubmit(ctx, &gsubmit, &qsubmit, 1);
ret = csf_submit_gsubmit(ctx, &gsubmit);
assert(!ret);
if (ret)
goto err_g_submit;
/* Wait before freeing the buffer. */
ret = drmSyncobjWait(panfrost_device_fd(dev), &ctx->syncobj, 1, INT64_MAX,
0, NULL);
ret = drmSyncobjWait(panfrost_device_fd(dev), &ctx->syncobj, 1, INT64_MAX, 0,
NULL);
assert(!ret);
panfrost_bo_unreference(cs_bo);
ctx->csf.is_init = true;
return 0;
err_g_submit:
panfrost_bo_unreference(cs_bo);
err_tiler_heap_cs_bo:
panfrost_bo_unreference(ctx->csf.tmp_geom_bo);
err_tiler_heap_tmp_geom_bo:
panfrost_bo_unreference(ctx->csf.heap.desc_bo);
err_tiler_heap_desc_bo:
drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY,
&thd);
err_tiler_heap:
drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_GROUP_DESTROY, &gd);
err_group_create:
return -1;
}
void
GENX(csf_cleanup_context)(struct panfrost_context *ctx)
{
if (!ctx->csf.is_init)
return;
struct panfrost_device *dev = pan_device(ctx->base.screen);
struct drm_panthor_tiler_heap_destroy thd = {
.handle = ctx->csf.heap.handle,
@@ -1076,4 +1116,5 @@ GENX(csf_cleanup_context)(struct panfrost_context *ctx)
assert(!ret);
panfrost_bo_unreference(ctx->csf.heap.desc_bo);
ctx->csf.is_init = false;
}

View File

@@ -48,6 +48,7 @@ struct panfrost_csf_batch {
};
struct panfrost_csf_context {
bool is_init;
uint32_t group_handle;
struct {
@@ -70,7 +71,7 @@ struct pipe_draw_info;
struct pipe_grid_info;
struct pipe_draw_start_count_bias;
void GENX(csf_init_context)(struct panfrost_context *ctx);
int GENX(csf_init_context)(struct panfrost_context *ctx);
void GENX(csf_cleanup_context)(struct panfrost_context *ctx);
void GENX(csf_init_batch)(struct panfrost_batch *batch);

View File

@@ -49,9 +49,10 @@ struct pipe_draw_info;
struct pipe_grid_info;
struct pipe_draw_start_count_bias;
static inline void
static inline int
GENX(jm_init_context)(struct panfrost_context *ctx)
{
return 0;
}
static inline void

View File

@@ -71,7 +71,7 @@ struct panfrost_vtable {
void (*context_populate_vtbl)(struct pipe_context *pipe);
/* Initialize/cleanup a Gallium context */
void (*context_init)(struct panfrost_context *ctx);
int (*context_init)(struct panfrost_context *ctx);
void (*context_cleanup)(struct panfrost_context *ctx);
/* Device-dependent initialization/cleanup of a panfrost_batch */