[Mesa-dev] [PATCH v2] gallium: Implement APPLE_object_purgeable (iris, freedeno, vc4)
Chris Wilson
chris at chris-wilson.co.uk
Tue Feb 26 21:52:07 UTC 2019
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.
v2: Refactor the repeated resource purging.
Cc: Eric Anholt <eric at anholt.net>
Cc: Kenneth Graunke <kenneth at whitecape.org>
Cc: Rob Clark <robdclark at 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 | 141 ++++++++++++++++++
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, 260 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
+ * 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..49bba040566
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_objectpurge.c
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * 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 gl_context *ctx,
+ struct pipe_resource *res,
+ boolean dontneed)
+{
+ struct pipe_screen *screen = st_context(ctx)->pipe->screen;
+ return screen->resource_madvise(screen, res, dontneed);
+}
+
+static GLenum
+st_resource_purgeable(struct gl_context *ctx,
+ struct pipe_resource *res,
+ GLenum option)
+{
+ if (res && pipe_resource_madvise(ctx, res, true))
+ return GL_VOLATILE_APPLE;
+ else
+ return GL_RELEASED_APPLE;
+}
+
+static GLenum
+st_buffer_object_purgeable(struct gl_context *ctx,
+ struct gl_buffer_object *obj,
+ GLenum option)
+{
+ struct st_buffer_object *stobj = st_buffer_object(obj);
+ return st_resource_purgeable(ctx, stobj->buffer, option);
+}
+
+static GLenum
+st_render_object_purgeable(struct gl_context *ctx,
+ struct gl_renderbuffer *obj,
+ GLenum option)
+{
+ struct st_renderbuffer *stobj = st_renderbuffer(obj);
+ return st_resource_purgeable(ctx, stobj->texture, option);
+}
+
+static GLenum
+st_texture_object_purgeable(struct gl_context *ctx,
+ struct gl_texture_object *obj,
+ GLenum option)
+{
+ struct st_texture_object *stobj = st_texture_object(obj);
+ return st_resource_purgeable(ctx, stobj->pt, option);
+}
+
+static GLenum
+st_resource_unpurgeable(struct gl_context *ctx,
+ struct pipe_resource **res,
+ GLenum option)
+{
+ if (!*res)
+ return GL_UNDEFINED_APPLE;
+
+ if (option == GL_UNDEFINED_APPLE ||
+ !pipe_resource_madvise(ctx, *res, false)) {
+ pipe_resource_reference(res, NULL);
+ return GL_UNDEFINED_APPLE;
+ }
+
+ return GL_RETAINED_APPLE;
+}
+
+static GLenum
+st_buffer_object_unpurgeable(struct gl_context *ctx,
+ struct gl_buffer_object *obj,
+ GLenum option)
+{
+ struct st_buffer_object *stobj = st_buffer_object(obj);
+ return st_resource_unpurgeable(ctx, &stobj->buffer, option);
+}
+
+static GLenum
+st_render_object_unpurgeable(struct gl_context * ctx,
+ struct gl_renderbuffer *obj,
+ GLenum option)
+{
+ struct st_renderbuffer *stobj = st_renderbuffer(obj);
+ return st_resource_unpurgeable(ctx, &stobj->texture, option);
+}
+
+static GLenum
+st_texture_object_unpurgeable(struct gl_context * ctx,
+ struct gl_texture_object *obj,
+ GLenum option)
+{
+ struct st_texture_object *stobj = st_texture_object(obj);
+ return st_resource_unpurgeable(ctx, &stobj->pt, option);
+}
+
+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
More information about the mesa-dev
mailing list