From 84bc7e4a1809600b6349738557b410ce8e796605 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Wed, 1 Mar 2017 15:48:11 +0000 Subject: [PATCH] wip: report GL_OUT_OF_MEMORY when DRM_RADEON_CS ioctl returns ENOMEM --- src/gallium/auxiliary/util/u_blitter.c | 6 ++++-- src/gallium/drivers/r600/r600_hw_context.c | 5 +++++ src/gallium/drivers/radeon/r600_cs.h | 8 ++++++-- src/gallium/drivers/radeon/radeon_winsys.h | 2 ++ src/gallium/drivers/radeonsi/si_descriptors.c | 2 ++ src/gallium/drivers/radeonsi/si_hw_context.c | 4 ++++ src/gallium/include/pipe/p_context.h | 2 ++ src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 9 ++++++--- src/mesa/main/errors.c | 3 ++- src/mesa/state_tracker/st_cb_flush.c | 5 +++++ src/mesa/state_tracker/st_cb_texture.c | 6 ++++++ 11 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 447d8d2..8f3efe6 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -1814,8 +1814,10 @@ void util_blitter_blit_generic(struct blitter_context *blitter, blitter_set_common_draw_rect_state(ctx, scissor != NULL, FALSE); - do_blits(ctx, dst, dstbox, src, src_width0, src_height0, - srcbox, blit_depth || blit_stencil); + if (pipe->status == PIPE_OK) { + do_blits(ctx, dst, dstbox, src, src_width0, src_height0, + srcbox, blit_depth || blit_stencil); + } util_blitter_restore_vertex_states(blitter); util_blitter_restore_fragment_states(blitter); diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index 4663d99..0e8ec52 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -281,6 +281,11 @@ void r600_context_gfx_flush(void *context, unsigned flags, /* Flush the CS. */ ws->cs_flush(cs, flags, &ctx->b.last_gfx_fence); + if (cs->status == PIPE_ERROR_OUT_OF_MEMORY) { + ctx->b.b.status = cs->status; + return; + } + if (fence) ws->fence_reference(fence, ctx->b.last_gfx_fence); ctx->b.num_gfx_cs_flushes++; diff --git a/src/gallium/drivers/radeon/r600_cs.h b/src/gallium/drivers/radeon/r600_cs.h index 28bdf15..faeaa4c 100644 --- a/src/gallium/drivers/radeon/r600_cs.h +++ b/src/gallium/drivers/radeon/r600_cs.h @@ -107,8 +107,12 @@ radeon_add_to_buffer_list_check_mem(struct r600_common_context *rctx, if (check_mem && !radeon_cs_memory_below_limit(rctx->screen, ring->cs, rctx->vram + rbo->vram_usage, - rctx->gtt + rbo->gart_usage)) - ring->flush(rctx, RADEON_FLUSH_ASYNC, NULL); + rctx->gtt + rbo->gart_usage)) { + /* The following call will block until completion of a previous call. */ + ring->flush(rctx, RADEON_FLUSH_ASYNC, NULL); + if (rctx->b.status == PIPE_ERROR_OUT_OF_MEMORY) + return 0; + } return radeon_add_to_buffer_list(rctx, ring, rbo, usage, priority); } diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h index 812c036..f137998 100644 --- a/src/gallium/drivers/radeon/radeon_winsys.h +++ b/src/gallium/drivers/radeon/radeon_winsys.h @@ -170,6 +170,8 @@ struct radeon_winsys_cs { * IBs. */ uint64_t used_vram; uint64_t used_gart; + + enum pipe_error status; }; struct radeon_info { diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index a41b243..5b99025 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -535,6 +535,8 @@ static void si_set_sampler_views(struct pipe_context *ctx, } si_set_sampler_view(sctx, shader, slot, views[i], false); + if (ctx->status == PIPE_ERROR_OUT_OF_MEMORY) + return; if (views[i]->texture && views[i]->texture->target != PIPE_BUFFER) { struct r600_texture *rtex = diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c index c80b884..69ada5e 100644 --- a/src/gallium/drivers/radeonsi/si_hw_context.c +++ b/src/gallium/drivers/radeonsi/si_hw_context.c @@ -145,6 +145,10 @@ void si_context_gfx_flush(void *context, unsigned flags, /* Flush the CS. */ ws->cs_flush(cs, flags, &ctx->b.last_gfx_fence); + if (cs->status == PIPE_ERROR_OUT_OF_MEMORY) { + ctx->b.b.status = cs->status; + return; + } if (fence) ws->fence_reference(fence, ctx->b.last_gfx_fence); ctx->b.num_gfx_cs_flushes++; diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 49e366a..00eaa04 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -757,6 +757,8 @@ struct pipe_context { unsigned last_level, unsigned first_layer, unsigned last_layer); + + enum pipe_error status; }; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index fb6a6bb..45dec4a 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -447,15 +447,18 @@ static unsigned radeon_drm_cs_get_buffer_list(struct radeon_winsys_cs *rcs, void radeon_drm_cs_emit_ioctl_oneshot(void *job, int thread_index) { - struct radeon_cs_context *csc = ((struct radeon_drm_cs*)job)->cst; + struct radeon_drm_cs *cs = (struct radeon_drm_cs*)job; + struct radeon_cs_context *csc = cs->cst; unsigned i; int r; r = drmCommandWriteRead(csc->fd, DRM_RADEON_CS, &csc->cs, sizeof(struct drm_radeon_cs)); if (r) { - if (r == -ENOMEM) - fprintf(stderr, "radeon: Not enough memory for command submission.\n"); + if (r == -ENOMEM) { + fprintf(stderr, "radeon: Not enough memory for command submission.\n"); + cs->base.status = PIPE_ERROR_OUT_OF_MEMORY; + } else if (debug_get_bool_option("RADEON_DUMP_CS", false)) { unsigned i; diff --git a/src/mesa/main/errors.c b/src/mesa/main/errors.c index 3a40c74..d02b92e 100644 --- a/src/mesa/main/errors.c +++ b/src/mesa/main/errors.c @@ -334,7 +334,8 @@ void _mesa_error_no_memory(const char *caller) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller); + if (ctx && ctx->ErrorValue == GL_NO_ERROR) + _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller); } /** diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 6442fc9..8269dc2 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -85,6 +85,11 @@ void st_flush(struct st_context *st, st_flush_bitmap_cache(st); st->pipe->flush(st->pipe, fence, flags); + + if (st->pipe && st->pipe->status == PIPE_ERROR_OUT_OF_MEMORY) {; + _mesa_error_no_memory(__func__); + st->pipe->status = PIPE_OK; + } } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index bc6f108..03d094a 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -1599,6 +1599,12 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, st->pipe->blit(st->pipe, &blit); pipe_resource_reference(&src, NULL); + + if (pipe->status == PIPE_ERROR_OUT_OF_MEMORY) { + _mesa_error_no_memory(__func__); + pipe->status = PIPE_OK; + } + return; fallback: -- 2.7.4