On Tue, Feb 26, 2019 at 4:39 PM Chris Wilson <ch...@chris-wilson.co.uk> wrote:
> A few of the GEM drivers provide matching ioctls to allow control of > their bo caches. Hook these up to APPLE_object_purgeable to allow > clients to discard video memory under pressure where they are able to > fallback to restoring content themselves, e.g. from their own (presumably > compressed, on disk) caches. > > Cc: Eric Anholt <e...@anholt.net> > Cc: Kenneth Graunke <kenn...@whitecape.org> > Cc: Rob Clark <robdcl...@gmail.com> > --- > .../drivers/freedreno/freedreno_resource.c | 10 ++ > .../drivers/freedreno/freedreno_screen.c | 1 + > src/gallium/drivers/iris/iris_resource.c | 10 ++ > src/gallium/drivers/iris/iris_screen.c | 1 + > src/gallium/drivers/vc4/vc4_bufmgr.c | 15 ++ > src/gallium/drivers/vc4/vc4_bufmgr.h | 3 + > src/gallium/drivers/vc4/vc4_resource.c | 10 ++ > src/gallium/drivers/vc4/vc4_screen.c | 3 + > src/gallium/include/pipe/p_defines.h | 1 + > src/gallium/include/pipe/p_screen.h | 20 +++ > src/mesa/Makefile.sources | 2 + > src/mesa/meson.build | 2 + > src/mesa/state_tracker/st_cb_objectpurge.c | 161 ++++++++++++++++++ > src/mesa/state_tracker/st_cb_objectpurge.h | 38 +++++ > src/mesa/state_tracker/st_context.c | 2 + > src/mesa/state_tracker/st_extensions.c | 1 + > 16 files changed, 280 insertions(+) > create mode 100644 src/mesa/state_tracker/st_cb_objectpurge.c > create mode 100644 src/mesa/state_tracker/st_cb_objectpurge.h > > diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c > b/src/gallium/drivers/freedreno/freedreno_resource.c > index 163fa70312a..5638d8efe33 100644 > --- a/src/gallium/drivers/freedreno/freedreno_resource.c > +++ b/src/gallium/drivers/freedreno/freedreno_resource.c > @@ -702,6 +702,15 @@ fd_resource_get_handle(struct pipe_screen *pscreen, > rsc->slices[0].pitch * rsc->cpp, handle); > } > > +static boolean > +fd_resource_madvise(struct pipe_screen *pscreen, > + struct pipe_resource *resource, > + boolean dontneed) > +{ > + struct fd_resource *rsc = fd_resource(prsc); > + return rsc->bo->madvise(rsc->bo, !dontneed); > +} > + > static uint32_t > setup_slices(struct fd_resource *rsc, uint32_t alignment, enum > pipe_format format) > { > @@ -1196,6 +1205,7 @@ fd_resource_screen_init(struct pipe_screen *pscreen) > pscreen->resource_create_with_modifiers = > fd_resource_create_with_modifiers; > pscreen->resource_from_handle = fd_resource_from_handle; > pscreen->resource_get_handle = fd_resource_get_handle; > + pscreen->resource_madvise = fd_resource_madvise; > pscreen->resource_destroy = u_transfer_helper_resource_destroy; > > pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, > diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c > b/src/gallium/drivers/freedreno/freedreno_screen.c > index 5b107b87ba8..909cfecd6f9 100644 > --- a/src/gallium/drivers/freedreno/freedreno_screen.c > +++ b/src/gallium/drivers/freedreno/freedreno_screen.c > @@ -194,6 +194,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum > pipe_cap param) > case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: > case PIPE_CAP_TEXTURE_BARRIER: > case PIPE_CAP_INVALIDATE_BUFFER: > + case PIPE_CAP_RESOURCE_MADVISE: > return 1; > > case PIPE_CAP_VERTEXID_NOBASE: > diff --git a/src/gallium/drivers/iris/iris_resource.c > b/src/gallium/drivers/iris/iris_resource.c > index b5829e94b36..d681dca7321 100644 > --- a/src/gallium/drivers/iris/iris_resource.c > +++ b/src/gallium/drivers/iris/iris_resource.c > @@ -1199,6 +1199,15 @@ iris_flush_resource(struct pipe_context *ctx, > struct pipe_resource *resource) > { > } > > +static boolean > +iris_resource_madvise(struct pipe_screen *pscreen, > + struct pipe_resource *resource, > + boolean dontneed) > +{ > + struct iris_resource *res = (struct iris_resource *)resource; > + return iris_bo_madvise(res->bo, dontneed); > +} > + > void > iris_flush_and_dirty_for_history(struct iris_context *ice, > struct iris_batch *batch, > @@ -1269,6 +1278,7 @@ iris_init_screen_resource_functions(struct > pipe_screen *pscreen) > pscreen->resource_create = u_transfer_helper_resource_create; > pscreen->resource_from_user_memory = iris_resource_from_user_memory; > pscreen->resource_from_handle = iris_resource_from_handle; > + pscreen->resource_madvise = iris_resource_madvise; > pscreen->resource_get_handle = iris_resource_get_handle; > pscreen->resource_destroy = u_transfer_helper_resource_destroy; > pscreen->transfer_helper = > diff --git a/src/gallium/drivers/iris/iris_screen.c > b/src/gallium/drivers/iris/iris_screen.c > index d831ffbc0a2..ecccf6af5e2 100644 > --- a/src/gallium/drivers/iris/iris_screen.c > +++ b/src/gallium/drivers/iris/iris_screen.c > @@ -172,6 +172,7 @@ iris_get_param(struct pipe_screen *pscreen, enum > pipe_cap param) > case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS: > case PIPE_CAP_LOAD_CONSTBUF: > case PIPE_CAP_NIR_COMPACT_ARRAYS: > + case PIPE_CAP_RESOURCE_MADVISE: > return true; > case PIPE_CAP_TGSI_FS_FBFETCH: > case PIPE_CAP_POST_DEPTH_COVERAGE: > diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c > b/src/gallium/drivers/vc4/vc4_bufmgr.c > index 716ca50ea06..de0d3fcafeb 100644 > --- a/src/gallium/drivers/vc4/vc4_bufmgr.c > +++ b/src/gallium/drivers/vc4/vc4_bufmgr.c > @@ -663,6 +663,21 @@ vc4_bo_map(struct vc4_bo *bo) > return map; > } > > +bool > +vc4_bo_madvise(struct vc4_bo *bo, bool dontneed) > +{ > + struct drm_vc4_gem_madvise arg = { > + .handle = bo->handle, > + .madv = dontneed ? VC4_MADV_DONTNEED : VC4_MADV_WILLNEED, > + .retained = true; > + }; > + > + if (bo->screen->has_madvise) > + vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg); > + > + return arg.retained; > +} > + > void > vc4_bufmgr_destroy(struct pipe_screen *pscreen) > { > diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.h > b/src/gallium/drivers/vc4/vc4_bufmgr.h > index 30a388ee599..dfb3aa65160 100644 > --- a/src/gallium/drivers/vc4/vc4_bufmgr.h > +++ b/src/gallium/drivers/vc4/vc4_bufmgr.h > @@ -143,6 +143,9 @@ vc4_wait_seqno(struct vc4_screen *screen, uint64_t > seqno, uint64_t timeout_ns, > void > vc4_bo_label(struct vc4_screen *screen, struct vc4_bo *bo, const char > *fmt, ...); > > +bool > +vc4_bo_madvise(struct vc4_bo *bo, bool dontneed); > + > void > vc4_bufmgr_destroy(struct pipe_screen *pscreen); > > diff --git a/src/gallium/drivers/vc4/vc4_resource.c > b/src/gallium/drivers/vc4/vc4_resource.c > index c12187d7872..d844c5d888a 100644 > --- a/src/gallium/drivers/vc4/vc4_resource.c > +++ b/src/gallium/drivers/vc4/vc4_resource.c > @@ -269,6 +269,15 @@ vc4_texture_subdata(struct pipe_context *pctx, > box); > } > > +static boolean > +vc4_resource_madvise(struct pipe_screen *pscreen, > + struct pipe_resource *prsc, > + boolean dontneed) > +{ > + struct vc4_resource *rsc = vc4_resource(prsc); > + return vc4_bo_madvise(rsc->bo, dontneed); > +} > + > static void > vc4_resource_destroy(struct pipe_screen *pscreen, > struct pipe_resource *prsc) > @@ -1136,6 +1145,7 @@ vc4_resource_screen_init(struct pipe_screen *pscreen) > pscreen->resource_from_handle = vc4_resource_from_handle; > pscreen->resource_destroy = u_resource_destroy_vtbl; > pscreen->resource_get_handle = vc4_resource_get_handle; > + pscreen->resource_madvise = vc4_resource_madvise; > pscreen->resource_destroy = vc4_resource_destroy; > pscreen->transfer_helper = > u_transfer_helper_create(&transfer_vtbl, > false, false, > diff --git a/src/gallium/drivers/vc4/vc4_screen.c > b/src/gallium/drivers/vc4/vc4_screen.c > index 5fc8c35f8a9..3b725b791bd 100644 > --- a/src/gallium/drivers/vc4/vc4_screen.c > +++ b/src/gallium/drivers/vc4/vc4_screen.c > @@ -150,6 +150,9 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum > pipe_cap param) > case PIPE_CAP_TEXTURE_BARRIER: > return 1; > > + case PIPE_CAP_RESOURCE_MADVISE: > + return screen->has_madvise; > + > case PIPE_CAP_NATIVE_FENCE_FD: > return screen->has_syncobj; > > diff --git a/src/gallium/include/pipe/p_defines.h > b/src/gallium/include/pipe/p_defines.h > index e2b0104ce43..edf733f70a8 100644 > --- a/src/gallium/include/pipe/p_defines.h > +++ b/src/gallium/include/pipe/p_defines.h > @@ -858,6 +858,7 @@ enum pipe_cap > PIPE_CAP_DEST_SURFACE_SRGB_CONTROL, > PIPE_CAP_NIR_COMPACT_ARRAYS, > PIPE_CAP_MAX_VARYINGS, > + PIPE_CAP_RESOURCE_MADVISE, > }; > > /** > diff --git a/src/gallium/include/pipe/p_screen.h > b/src/gallium/include/pipe/p_screen.h > index c4d6e1cc94f..8c5fa06d0bc 100644 > --- a/src/gallium/include/pipe/p_screen.h > +++ b/src/gallium/include/pipe/p_screen.h > @@ -222,6 +222,26 @@ struct pipe_screen { > const struct > pipe_resource *t, > void *user_memory); > > + /** > + * Mark the resource as either being unneeded or needed for the near > future. > + * > + * If the resource is marked as dontneed, then the backend is at > liberty > + * to free it as it chooses. Prior to future use, the client must call > + * with willneed, at which point it will be told whether the resource > "willneed" doesn't occur in the interface. Marek > + * is still available. The backend is only allowed to discard the > + * contents (and recover the memory used by the resource) while the > + * resource is marked as dontneed. > + * > + * Used by APPLE_object_purgeable. > + * > + * Returns true if the resource is still available (with its contents > + * retained), or false if the backend has freed it and discarded its > contents > + * in the meantime. > + */ > + boolean (*resource_madvise)(struct pipe_screen *screen, > + struct pipe_resource *resource, > + boolean dontneed); > + > /** > * Unlike pipe_resource::bind, which describes what state trackers > want, > * resources can have much greater capabilities in practice, often > implied > diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources > index 1e25f47e509..2804b3475e9 100644 > --- a/src/mesa/Makefile.sources > +++ b/src/mesa/Makefile.sources > @@ -481,6 +481,8 @@ STATETRACKER_FILES = \ > state_tracker/st_cb_memoryobjects.h \ > state_tracker/st_cb_msaa.c \ > state_tracker/st_cb_msaa.h \ > + state_tracker/st_cb_objectpurge.c \ > + state_tracker/st_cb_objectpurge.h \ > state_tracker/st_cb_perfmon.c \ > state_tracker/st_cb_perfmon.h \ > state_tracker/st_cb_program.c \ > diff --git a/src/mesa/meson.build b/src/mesa/meson.build > index d8a5682f6a0..ea69a5e5ef2 100644 > --- a/src/mesa/meson.build > +++ b/src/mesa/meson.build > @@ -525,6 +525,8 @@ files_libmesa_gallium = files( > 'state_tracker/st_cb_memoryobjects.h', > 'state_tracker/st_cb_msaa.c', > 'state_tracker/st_cb_msaa.h', > + 'state_tracker/st_cb_objectpurge.c', > + 'state_tracker/st_cb_objectpurge.h', > 'state_tracker/st_cb_perfmon.c', > 'state_tracker/st_cb_perfmon.h', > 'state_tracker/st_cb_program.c', > diff --git a/src/mesa/state_tracker/st_cb_objectpurge.c > b/src/mesa/state_tracker/st_cb_objectpurge.c > new file mode 100644 > index 00000000000..c8c777481fe > --- /dev/null > +++ b/src/mesa/state_tracker/st_cb_objectpurge.c > @@ -0,0 +1,161 @@ > > +/************************************************************************** > + * > + * Copyright 2019 Intel Corporation > + * All Rights Reserved. > + * > + * 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, sub license, 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 NON-INFRINGEMENT. > + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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. > + * > + > **************************************************************************/ > + > +#include "st_cb_bufferobjects.h" > +#include "st_cb_fbo.h" > +#include "st_cb_objectpurge.h" > +#include "st_context.h" > +#include "st_texture.h" > + > +#include "pipe/p_screen.h" > + > +static boolean > +pipe_resource_madvise(struct st_context *st, > + struct pipe_resource *res, > + boolean dontneed) > +{ > + struct pipe_screen *screen = st->pipe->screen; > + return screen->resource_madvise(screen, res, dontneed); > +} > + > +static GLenum > +st_buffer_object_purgeable(struct gl_context *ctx, > + struct gl_buffer_object *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_buffer_object *stobj = st_buffer_object(obj); > + > + if (stobj->buffer && pipe_resource_madvise(st, stobj->buffer, true)) > + return GL_VOLATILE_APPLE; > + else > + return GL_RELEASED_APPLE; > +} > + > +static GLenum > +st_render_object_purgeable(struct gl_context *ctx, > + struct gl_renderbuffer *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_renderbuffer *stobj = st_renderbuffer(obj); > + > + if (stobj->texture && pipe_resource_madvise(st, stobj->texture, true)) > + return GL_VOLATILE_APPLE; > + else > + return GL_RELEASED_APPLE; > +} > + > +static GLenum > +st_texture_object_purgeable(struct gl_context *ctx, > + struct gl_texture_object *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_texture_object *stobj = st_texture_object(obj); > + > + if (stobj->pt && pipe_resource_madvise(st, stobj->pt, true)) > + return GL_VOLATILE_APPLE; > + else > + return GL_RELEASED_APPLE; > +} > + > +static GLenum > +st_buffer_object_unpurgeable(struct gl_context * ctx, > + struct gl_buffer_object *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_buffer_object *stobj = st_buffer_object(obj); > + > + if (!stobj->buffer) > + return GL_UNDEFINED_APPLE; > + > + if (option == GL_UNDEFINED_APPLE || > + !pipe_resource_madvise(st, stobj->buffer, false)) { > + pipe_resource_reference(&stobj->buffer, NULL); > + return GL_UNDEFINED_APPLE; > + } > + > + return GL_RETAINED_APPLE; > +} > + > +static GLenum > +st_render_object_unpurgeable(struct gl_context * ctx, > + struct gl_renderbuffer *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_renderbuffer *stobj = st_renderbuffer(obj); > + > + if (!stobj->texture) > + return GL_UNDEFINED_APPLE; > + > + if (option == GL_UNDEFINED_APPLE || > + !pipe_resource_madvise(st, stobj->texture, false)) { > + pipe_resource_reference(&stobj->texture, NULL); > + return GL_UNDEFINED_APPLE; > + } > + > + return GL_RETAINED_APPLE; > +} > + > +static GLenum > +st_texture_object_unpurgeable(struct gl_context * ctx, > + struct gl_texture_object *obj, > + GLenum option) > +{ > + struct st_context *st = st_context(ctx); > + struct st_texture_object *stobj = st_texture_object(obj); > + > + if (!stobj->pt) > + return GL_UNDEFINED_APPLE; > + > + if (option == GL_UNDEFINED_APPLE || > + !pipe_resource_madvise(st, stobj->pt, false)) { > + pipe_resource_reference(&stobj->pt, NULL); > + return GL_UNDEFINED_APPLE; > + } > + > + return GL_RETAINED_APPLE; > +} > + > +void > +st_init_objectpurge_functions(struct pipe_screen *screen, > + struct dd_function_table *functions) > +{ > + if (!screen->get_param(screen, PIPE_CAP_RESOURCE_MADVISE)) > + return; > + > + functions->BufferObjectPurgeable = st_buffer_object_purgeable; > + functions->RenderObjectPurgeable = st_render_object_purgeable; > + functions->TextureObjectPurgeable = st_texture_object_purgeable; > + > + functions->BufferObjectUnpurgeable = st_buffer_object_unpurgeable; > + functions->RenderObjectUnpurgeable = st_render_object_unpurgeable; > + functions->TextureObjectUnpurgeable = st_texture_object_unpurgeable; > +} > diff --git a/src/mesa/state_tracker/st_cb_objectpurge.h > b/src/mesa/state_tracker/st_cb_objectpurge.h > new file mode 100644 > index 00000000000..4bdc1881211 > --- /dev/null > +++ b/src/mesa/state_tracker/st_cb_objectpurge.h > @@ -0,0 +1,38 @@ > > +/************************************************************************** > + * > + * Copyright 2019 Intel Corporation > + * All Rights Reserved. > + * > + * 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, sub license, 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 NON-INFRINGEMENT. > + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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. > + * > + > **************************************************************************/ > + > +#ifndef ST_CB_OBJECT_PURGE_H > +#define ST_CB_OBJECT_PURGE_H > + > +struct dd_function_table; > +struct pipe_screen; > + > +extern void > +st_init_objectpurge_functions(struct pipe_screen *screen, > + struct dd_function_table *functions); > + > +#endif /* ST_CB_OBJECT_PURGE_H */ > diff --git a/src/mesa/state_tracker/st_context.c > b/src/mesa/state_tracker/st_context.c > index 45451531df9..647bb5a9325 100644 > --- a/src/mesa/state_tracker/st_context.c > +++ b/src/mesa/state_tracker/st_context.c > @@ -56,6 +56,7 @@ > #include "st_cb_feedback.h" > #include "st_cb_memoryobjects.h" > #include "st_cb_msaa.h" > +#include "st_cb_objectpurge.h" > #include "st_cb_perfmon.h" > #include "st_cb_program.h" > #include "st_cb_queryobj.h" > @@ -727,6 +728,7 @@ st_init_driver_functions(struct pipe_screen *screen, > st_init_draw_functions(functions); > st_init_blit_functions(functions); > st_init_bufferobject_functions(screen, functions); > + st_init_objectpurge_functions(screen, functions); > st_init_clear_functions(functions); > st_init_bitmap_functions(functions); > st_init_copy_image_functions(functions); > diff --git a/src/mesa/state_tracker/st_extensions.c > b/src/mesa/state_tracker/st_extensions.c > index 528e6b74a54..7e5e056dd3e 100644 > --- a/src/mesa/state_tracker/st_extensions.c > +++ b/src/mesa/state_tracker/st_extensions.c > @@ -765,6 +765,7 @@ void st_init_extensions(struct pipe_screen *screen, > { o(ATI_meminfo), PIPE_CAP_QUERY_MEMORY_INFO > }, > { o(AMD_seamless_cubemap_per_texture), > PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE }, > { o(ATI_texture_mirror_once), > PIPE_CAP_TEXTURE_MIRROR_CLAMP }, > + { o(APPLE_object_purgeable), PIPE_CAP_RESOURCE_MADVISE > }, > { o(MESA_tile_raster_order), PIPE_CAP_TILE_RASTER_ORDER > }, > { o(NV_conditional_render), PIPE_CAP_CONDITIONAL_RENDER > }, > { o(NV_fill_rectangle), > PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE }, > -- > 2.20.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev