[Mesa-dev] [PATCH v3 09/25] panfrost: Rework the panfrost_bo API
Boris Brezillon
boris.brezillon at collabora.com
Thu Sep 5 19:41:34 UTC 2019
* BO related functions/structs are now exposed in pan_bo.h instead of
being spread in pan_screen.h/pan_resource.h
* cache related functions are no longer exposed
* panfrost_bo now has a ->screen field to avoid passing screen around
* the function names are made consistent (all BO related functions are
prefixed with panfrost_bo_)
* release functions are no longer exposed, existing users are converted
to use panfrost_bo_unreference() instead
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
---
src/gallium/drivers/panfrost/pan_allocate.c | 5 +-
src/gallium/drivers/panfrost/pan_allocate.h | 20 --
src/gallium/drivers/panfrost/pan_assemble.c | 3 +-
src/gallium/drivers/panfrost/pan_blend_cso.c | 5 +-
src/gallium/drivers/panfrost/pan_bo.c | 236 +++++++++++++++++-
src/gallium/drivers/panfrost/pan_bo.h | 78 ++++++
src/gallium/drivers/panfrost/pan_context.c | 16 +-
src/gallium/drivers/panfrost/pan_drm.c | 187 +-------------
src/gallium/drivers/panfrost/pan_instancing.c | 1 +
src/gallium/drivers/panfrost/pan_job.c | 7 +-
src/gallium/drivers/panfrost/pan_mfbd.c | 1 +
src/gallium/drivers/panfrost/pan_resource.c | 38 +--
src/gallium/drivers/panfrost/pan_resource.h | 8 +-
src/gallium/drivers/panfrost/pan_screen.c | 1 +
src/gallium/drivers/panfrost/pan_screen.h | 24 --
src/gallium/drivers/panfrost/pan_sfbd.c | 1 +
src/gallium/drivers/panfrost/pan_varyings.c | 1 +
17 files changed, 338 insertions(+), 294 deletions(-)
create mode 100644 src/gallium/drivers/panfrost/pan_bo.h
diff --git a/src/gallium/drivers/panfrost/pan_allocate.c b/src/gallium/drivers/panfrost/pan_allocate.c
index a22b1a5a88d6..beebb0bc6d7e 100644
--- a/src/gallium/drivers/panfrost/pan_allocate.c
+++ b/src/gallium/drivers/panfrost/pan_allocate.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <panfrost-misc.h>
#include <panfrost-job.h>
+#include "pan_bo.h"
#include "pan_context.h"
/* TODO: What does this actually have to be? */
@@ -66,12 +67,12 @@ panfrost_allocate_transient(struct panfrost_context *ctx, size_t sz)
TRANSIENT_SLAB_SIZE : ALIGN_POT(sz, 4096);
/* We can't reuse the current BO, but we can create a new one. */
- bo = panfrost_drm_create_bo(screen, bo_sz, 0);
+ bo = panfrost_bo_create(screen, bo_sz, 0);
panfrost_batch_add_bo(batch, bo);
/* Creating a BO adds a reference, and then the job adds a
* second one. So we need to pop back one reference */
- panfrost_bo_unreference(&screen->base, bo);
+ panfrost_bo_unreference(bo);
if (sz < TRANSIENT_SLAB_SIZE) {
batch->transient_bo = bo;
diff --git a/src/gallium/drivers/panfrost/pan_allocate.h b/src/gallium/drivers/panfrost/pan_allocate.h
index c0aff62df4a1..91c2af9c4f17 100644
--- a/src/gallium/drivers/panfrost/pan_allocate.h
+++ b/src/gallium/drivers/panfrost/pan_allocate.h
@@ -43,26 +43,6 @@ struct panfrost_transfer {
mali_ptr gpu;
};
-struct panfrost_bo {
- /* Must be first for casting */
- struct list_head link;
-
- struct pipe_reference reference;
-
- /* Mapping for the entire object (all levels) */
- uint8_t *cpu;
-
- /* GPU address for the object */
- mali_ptr gpu;
-
- /* Size of all entire trees */
- size_t size;
-
- int gem_handle;
-
- uint32_t flags;
-};
-
struct panfrost_transfer
panfrost_allocate_transient(struct panfrost_context *ctx, size_t sz);
diff --git a/src/gallium/drivers/panfrost/pan_assemble.c b/src/gallium/drivers/panfrost/pan_assemble.c
index b57cd5ef6ad2..79c000367632 100644
--- a/src/gallium/drivers/panfrost/pan_assemble.c
+++ b/src/gallium/drivers/panfrost/pan_assemble.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "pan_bo.h"
#include "pan_context.h"
#include "compiler/nir/nir.h"
@@ -82,7 +83,7 @@ panfrost_shader_compile(
* I bet someone just thought that would be a cute pun. At least,
* that's how I'd do it. */
- state->bo = panfrost_drm_create_bo(screen, size, PAN_ALLOCATE_EXECUTE);
+ state->bo = panfrost_bo_create(screen, size, PAN_ALLOCATE_EXECUTE);
memcpy(state->bo->cpu, dst, size);
meta->shader = state->bo->gpu | program.first_tag;
diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.c b/src/gallium/drivers/panfrost/pan_blend_cso.c
index ab49772f3ba3..69897be4f007 100644
--- a/src/gallium/drivers/panfrost/pan_blend_cso.c
+++ b/src/gallium/drivers/panfrost/pan_blend_cso.c
@@ -29,6 +29,7 @@
#include "util/u_memory.h"
#include "pan_blend_shaders.h"
#include "pan_blending.h"
+#include "pan_bo.h"
/* A given Gallium blend state can be encoded to the hardware in numerous,
* dramatically divergent ways due to the interactions of blending with
@@ -272,12 +273,12 @@ panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti)
final.shader.first_tag = shader->first_tag;
/* Upload the shader */
- final.shader.bo = panfrost_drm_create_bo(screen, shader->size, PAN_ALLOCATE_EXECUTE);
+ final.shader.bo = panfrost_bo_create(screen, shader->size, PAN_ALLOCATE_EXECUTE);
memcpy(final.shader.bo->cpu, shader->buffer, shader->size);
/* Pass BO ownership to job */
panfrost_batch_add_bo(batch, final.shader.bo);
- panfrost_bo_unreference(ctx->base.screen, final.shader.bo);
+ panfrost_bo_unreference(final.shader.bo);
if (shader->patch_index) {
/* We have to specialize the blend shader to use constants, so
diff --git a/src/gallium/drivers/panfrost/pan_bo.c b/src/gallium/drivers/panfrost/pan_bo.c
index f2f49437a89f..1f87c18e9ad5 100644
--- a/src/gallium/drivers/panfrost/pan_bo.c
+++ b/src/gallium/drivers/panfrost/pan_bo.c
@@ -23,11 +23,20 @@
* Authors (Collabora):
* Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
*/
+#include <stdio.h>
+#include <fcntl.h>
#include <xf86drm.h>
#include <pthread.h>
#include "drm-uapi/panfrost_drm.h"
+#include "pan_bo.h"
#include "pan_screen.h"
+#include "pan_util.h"
+#include "pandecode/decode.h"
+
+#include "os/os_mman.h"
+
+#include "util/u_inlines.h"
#include "util/u_math.h"
/* This file implements a userspace BO cache. Allocating and freeing
@@ -45,6 +54,51 @@
* around the linked list.
*/
+static struct panfrost_bo *
+panfrost_bo_alloc(struct panfrost_screen *screen, size_t size,
+ uint32_t flags)
+{
+ struct drm_panfrost_create_bo create_bo = { .size = size };
+ struct panfrost_bo *bo;
+ int ret;
+
+ if (screen->kernel_version->version_major > 1 ||
+ screen->kernel_version->version_minor >= 1) {
+ if (flags & PAN_ALLOCATE_GROWABLE)
+ create_bo.flags |= PANFROST_BO_HEAP;
+ if (!(flags & PAN_ALLOCATE_EXECUTE))
+ create_bo.flags |= PANFROST_BO_NOEXEC;
+ }
+
+ ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_CREATE_BO, &create_bo);
+ if (ret)
+ return NULL;
+
+ bo = rzalloc(screen, struct panfrost_bo);
+ assert(bo);
+ bo->size = create_bo.size;
+ bo->gpu = create_bo.offset;
+ bo->gem_handle = create_bo.handle;
+ bo->flags = flags;
+ bo->screen = screen;
+ return bo;
+}
+
+static void
+panfrost_bo_free(struct panfrost_bo *bo)
+{
+ struct drm_gem_close gem_close = { .handle = bo->gem_handle };
+ int ret;
+
+ ret = drmIoctl(bo->screen->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret) {
+ fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %m\n");
+ assert(0);
+ }
+
+ ralloc_free(bo);
+}
+
/* Helper to calculate the bucket index of a BO */
static unsigned
@@ -80,10 +134,9 @@ pan_bucket(struct panfrost_screen *screen, unsigned size)
* cache. If it fails, it returns NULL signaling the caller to allocate a new
* BO. */
-struct panfrost_bo *
-panfrost_bo_cache_fetch(
- struct panfrost_screen *screen,
- size_t size, uint32_t flags)
+static struct panfrost_bo *
+panfrost_bo_cache_fetch(struct panfrost_screen *screen,
+ size_t size, uint32_t flags)
{
pthread_mutex_lock(&screen->bo_cache_lock);
struct list_head *bucket = pan_bucket(screen, size);
@@ -105,7 +158,7 @@ panfrost_bo_cache_fetch(
ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
if (!ret && !madv.retained) {
- panfrost_drm_release_bo(screen, entry, false);
+ panfrost_bo_free(entry);
continue;
}
/* Let's go! */
@@ -121,11 +174,14 @@ panfrost_bo_cache_fetch(
/* Tries to add a BO to the cache. Returns if it was
* successful */
-bool
-panfrost_bo_cache_put(
- struct panfrost_screen *screen,
- struct panfrost_bo *bo)
+static bool
+panfrost_bo_cache_put(struct panfrost_bo *bo)
{
+ struct panfrost_screen *screen = bo->screen;
+
+ if (bo->dont_reuse)
+ return false;
+
pthread_mutex_lock(&screen->bo_cache_lock);
struct list_head *bucket = pan_bucket(screen, bo->size);
struct drm_panfrost_madvise madv;
@@ -150,8 +206,7 @@ panfrost_bo_cache_put(
* OS) */
void
-panfrost_bo_cache_evict_all(
- struct panfrost_screen *screen)
+panfrost_bo_cache_evict_all(struct panfrost_screen *screen)
{
pthread_mutex_lock(&screen->bo_cache_lock);
for (unsigned i = 0; i < ARRAY_SIZE(screen->bo_cache); ++i) {
@@ -159,9 +214,166 @@ panfrost_bo_cache_evict_all(
list_for_each_entry_safe(struct panfrost_bo, entry, bucket, link) {
list_del(&entry->link);
- panfrost_drm_release_bo(screen, entry, false);
+ panfrost_bo_free(entry);
}
}
pthread_mutex_unlock(&screen->bo_cache_lock);
}
+void
+panfrost_bo_mmap(struct panfrost_bo *bo)
+{
+ struct drm_panfrost_mmap_bo mmap_bo = { .handle = bo->gem_handle };
+ int ret;
+
+ if (bo->cpu)
+ return;
+
+ ret = drmIoctl(bo->screen->fd, DRM_IOCTL_PANFROST_MMAP_BO, &mmap_bo);
+ if (ret) {
+ fprintf(stderr, "DRM_IOCTL_PANFROST_MMAP_BO failed: %m\n");
+ assert(0);
+ }
+
+ bo->cpu = os_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ bo->screen->fd, mmap_bo.offset);
+ if (bo->cpu == MAP_FAILED) {
+ fprintf(stderr, "mmap failed: %p %m\n", bo->cpu);
+ assert(0);
+ }
+
+ /* Record the mmap if we're tracing */
+ if (pan_debug & PAN_DBG_TRACE)
+ pandecode_inject_mmap(bo->gpu, bo->cpu, bo->size, NULL);
+}
+
+void
+panfrost_bo_munmap(struct panfrost_bo *bo)
+{
+ if (!bo->cpu)
+ return;
+
+ if (os_munmap((void *) (uintptr_t)bo->cpu, bo->size)) {
+ perror("munmap");
+ abort();
+ }
+
+ bo->cpu = NULL;
+}
+
+struct panfrost_bo *
+panfrost_bo_create(struct panfrost_screen *screen, size_t size,
+ uint32_t flags)
+{
+ struct panfrost_bo *bo;
+
+ /* Kernel will fail (confusingly) with EPERM otherwise */
+ assert(size > 0);
+
+ /* To maximize BO cache usage, don't allocate tiny BOs */
+ size = MAX2(size, 4096);
+
+ /* GROWABLE BOs cannot be mmapped */
+ if (flags & PAN_ALLOCATE_GROWABLE)
+ assert(flags & PAN_ALLOCATE_INVISIBLE);
+
+ /* Before creating a BO, we first want to check the cache, otherwise,
+ * the cache misses and we need to allocate a BO fresh from the kernel
+ */
+ bo = panfrost_bo_cache_fetch(screen, size, flags);
+ if (!bo)
+ bo = panfrost_bo_alloc(screen, size, flags);
+
+ assert(bo);
+
+ /* Only mmap now if we know we need to. For CPU-invisible buffers, we
+ * never map since we don't care about their contents; they're purely
+ * for GPU-internal use. But we do trace them anyway.
+ */
+ if (!(flags & (PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_DELAY_MMAP)))
+ panfrost_bo_mmap(bo);
+ else if ((flags & PAN_ALLOCATE_INVISIBLE) && (pan_debug & PAN_DBG_TRACE))
+ pandecode_inject_mmap(bo->gpu, NULL, bo->size, NULL);
+
+ pipe_reference_init(&bo->reference, 1);
+ return bo;
+}
+
+static void
+panfrost_bo_release(struct panfrost_bo *bo)
+{
+ if (!bo)
+ return;
+
+ /* Rather than freeing the BO now, we'll cache the BO for later
+ * allocations if we're allowed to */
+
+ panfrost_bo_munmap(bo);
+
+ if (panfrost_bo_cache_put(bo))
+ return;
+
+ panfrost_bo_free(bo);
+}
+
+void
+panfrost_bo_reference(struct panfrost_bo *bo)
+{
+ if (bo)
+ pipe_reference(NULL, &bo->reference);
+}
+
+void
+panfrost_bo_unreference(struct panfrost_bo *bo)
+{
+ if (!bo)
+ return;
+
+ /* When the reference count goes to zero, we need to cleanup */
+ if (pipe_reference(&bo->reference, NULL))
+ panfrost_bo_release(bo);
+}
+
+struct panfrost_bo *
+panfrost_bo_import(struct panfrost_screen *screen, int fd)
+{
+ struct panfrost_bo *bo = rzalloc(screen, struct panfrost_bo);
+ struct drm_panfrost_get_bo_offset get_bo_offset = {0,};
+ ASSERTED int ret;
+ unsigned gem_handle;
+
+ ret = drmPrimeFDToHandle(screen->fd, fd, &gem_handle);
+ assert(!ret);
+
+ get_bo_offset.handle = gem_handle;
+ ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_GET_BO_OFFSET, &get_bo_offset);
+ assert(!ret);
+
+ bo->screen = screen;
+ bo->gem_handle = gem_handle;
+ bo->gpu = (mali_ptr)get_bo_offset.offset;
+ bo->size = lseek(fd, 0, SEEK_END);
+ bo->dont_reuse = true;
+ assert(bo->size > 0);
+ pipe_reference_init(&bo->reference, 1);
+
+ // TODO map and unmap on demand?
+ panfrost_bo_mmap(bo);
+ return bo;
+}
+
+int
+panfrost_bo_export(struct panfrost_bo *bo)
+{
+ struct drm_prime_handle args = {
+ .handle = bo->gem_handle,
+ .flags = DRM_CLOEXEC,
+ };
+
+ int ret = drmIoctl(bo->screen->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ if (ret == -1)
+ return -1;
+
+ bo->dont_reuse = true;
+ return args.fd;
+}
diff --git a/src/gallium/drivers/panfrost/pan_bo.h b/src/gallium/drivers/panfrost/pan_bo.h
new file mode 100644
index 000000000000..b4bff645e257
--- /dev/null
+++ b/src/gallium/drivers/panfrost/pan_bo.h
@@ -0,0 +1,78 @@
+/*
+ * © Copyright 2019 Alyssa Rosenzweig
+ * © Copyright 2019 Collabora, Ltd.
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 __PAN_BO_H__
+#define __PAN_BO_H__
+
+#include <panfrost-misc.h>
+#include "pipe/p_state.h"
+#include "util/list.h"
+
+struct panfrost_bo {
+ /* Must be first for casting */
+ struct list_head link;
+
+ struct pipe_reference reference;
+
+ struct panfrost_screen *screen;
+
+ /* Mapping for the entire object (all levels) */
+ uint8_t *cpu;
+
+ /* GPU address for the object */
+ mali_ptr gpu;
+
+ /* Size of all entire trees */
+ size_t size;
+
+ int gem_handle;
+
+ /* The BO should not be added to the re-use cache when released. Should
+ * be true for imported/exported BOs.
+ */
+ bool dont_reuse;
+
+ uint32_t flags;
+};
+
+void
+panfrost_bo_mmap(struct panfrost_bo *bo);
+void
+panfrost_bo_munmap(struct panfrost_bo *bo);
+void
+panfrost_bo_reference(struct panfrost_bo *bo);
+void
+panfrost_bo_unreference(struct panfrost_bo *bo);
+struct panfrost_bo *
+panfrost_bo_create(struct panfrost_screen *screen, size_t size,
+ uint32_t flags);
+struct panfrost_bo *
+panfrost_bo_import(struct panfrost_screen *screen, int fd);
+int
+panfrost_bo_export(struct panfrost_bo *bo);
+void
+panfrost_bo_cache_evict_all(struct panfrost_screen *screen);
+
+#endif /* __PAN_BO_H__ */
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 0fb4c2584e40..f0cd8cdb12ea 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -27,6 +27,7 @@
#include <sys/poll.h>
#include <errno.h>
+#include "pan_bo.h"
#include "pan_context.h"
#include "pan_format.h"
@@ -1889,7 +1890,7 @@ panfrost_delete_shader_state(
for (unsigned i = 0; i < cso->variant_count; ++i) {
struct panfrost_shader_state *shader_state = &cso->variants[i];
- panfrost_bo_unreference(pctx->screen, shader_state->bo);
+ panfrost_bo_unreference(shader_state->bo);
shader_state->bo = NULL;
}
@@ -2556,7 +2557,6 @@ static void
panfrost_destroy(struct pipe_context *pipe)
{
struct panfrost_context *panfrost = pan_context(pipe);
- struct panfrost_screen *screen = pan_screen(pipe->screen);
if (panfrost->blitter)
util_blitter_destroy(panfrost->blitter);
@@ -2564,9 +2564,9 @@ panfrost_destroy(struct pipe_context *pipe)
if (panfrost->blitter_wallpaper)
util_blitter_destroy(panfrost->blitter_wallpaper);
- panfrost_drm_release_bo(screen, panfrost->scratchpad, false);
- panfrost_drm_release_bo(screen, panfrost->tiler_heap, false);
- panfrost_drm_release_bo(screen, panfrost->tiler_dummy, false);
+ panfrost_bo_unreference(panfrost->scratchpad);
+ panfrost_bo_unreference(panfrost->tiler_heap);
+ panfrost_bo_unreference(panfrost->tiler_dummy);
ralloc_free(pipe);
}
@@ -2749,11 +2749,11 @@ panfrost_setup_hardware(struct panfrost_context *ctx)
struct pipe_context *gallium = (struct pipe_context *) ctx;
struct panfrost_screen *screen = pan_screen(gallium->screen);
- ctx->scratchpad = panfrost_drm_create_bo(screen, 64 * 4 * 4096, 0);
- ctx->tiler_heap = panfrost_drm_create_bo(screen, 4096 * 4096,
+ ctx->scratchpad = panfrost_bo_create(screen, 64 * 4 * 4096, 0);
+ ctx->tiler_heap = panfrost_bo_create(screen, 4096 * 4096,
PAN_ALLOCATE_INVISIBLE |
PAN_ALLOCATE_GROWABLE);
- ctx->tiler_dummy = panfrost_drm_create_bo(screen, 4096,
+ ctx->tiler_dummy = panfrost_bo_create(screen, 4096,
PAN_ALLOCATE_INVISIBLE);
assert(ctx->scratchpad && ctx->tiler_heap && ctx->tiler_dummy);
}
diff --git a/src/gallium/drivers/panfrost/pan_drm.c b/src/gallium/drivers/panfrost/pan_drm.c
index e7dcd2e58751..e4b75fad4078 100644
--- a/src/gallium/drivers/panfrost/pan_drm.c
+++ b/src/gallium/drivers/panfrost/pan_drm.c
@@ -32,198 +32,13 @@
#include "util/os_time.h"
#include "os/os_mman.h"
+#include "pan_bo.h"
#include "pan_screen.h"
#include "pan_resource.h"
#include "pan_context.h"
#include "pan_util.h"
#include "pandecode/decode.h"
-void
-panfrost_drm_mmap_bo(struct panfrost_screen *screen, struct panfrost_bo *bo)
-{
- struct drm_panfrost_mmap_bo mmap_bo = { .handle = bo->gem_handle };
- int ret;
-
- if (bo->cpu)
- return;
-
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MMAP_BO, &mmap_bo);
- if (ret) {
- fprintf(stderr, "DRM_IOCTL_PANFROST_MMAP_BO failed: %m\n");
- assert(0);
- }
-
- bo->cpu = os_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
- screen->fd, mmap_bo.offset);
- if (bo->cpu == MAP_FAILED) {
- fprintf(stderr, "mmap failed: %p %m\n", bo->cpu);
- assert(0);
- }
-
- /* Record the mmap if we're tracing */
- if (pan_debug & PAN_DBG_TRACE)
- pandecode_inject_mmap(bo->gpu, bo->cpu, bo->size, NULL);
-}
-
-static void
-panfrost_drm_munmap_bo(struct panfrost_screen *screen, struct panfrost_bo *bo)
-{
- if (!bo->cpu)
- return;
-
- if (os_munmap((void *) (uintptr_t)bo->cpu, bo->size)) {
- perror("munmap");
- abort();
- }
-
- bo->cpu = NULL;
-}
-
-struct panfrost_bo *
-panfrost_drm_create_bo(struct panfrost_screen *screen, size_t size,
- uint32_t flags)
-{
- struct panfrost_bo *bo;
-
- /* Kernel will fail (confusingly) with EPERM otherwise */
- assert(size > 0);
-
- /* To maximize BO cache usage, don't allocate tiny BOs */
- size = MAX2(size, 4096);
-
- /* GROWABLE BOs cannot be mmapped */
- if (flags & PAN_ALLOCATE_GROWABLE)
- assert(flags & PAN_ALLOCATE_INVISIBLE);
-
- unsigned translated_flags = 0;
-
- if (screen->kernel_version->version_major > 1 ||
- screen->kernel_version->version_minor >= 1) {
- if (flags & PAN_ALLOCATE_GROWABLE)
- translated_flags |= PANFROST_BO_HEAP;
- if (!(flags & PAN_ALLOCATE_EXECUTE))
- translated_flags |= PANFROST_BO_NOEXEC;
- }
-
- struct drm_panfrost_create_bo create_bo = {
- .size = size,
- .flags = translated_flags,
- };
-
- /* Before creating a BO, we first want to check the cache */
-
- bo = panfrost_bo_cache_fetch(screen, size, flags);
-
- if (bo == NULL) {
- /* Otherwise, the cache misses and we need to allocate a BO fresh from
- * the kernel */
-
- int ret;
-
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_CREATE_BO, &create_bo);
- if (ret) {
- fprintf(stderr, "DRM_IOCTL_PANFROST_CREATE_BO failed: %m\n");
- assert(0);
- }
-
- /* We have a BO allocated from the kernel; fill in the userspace
- * version */
-
- bo = rzalloc(screen, struct panfrost_bo);
- bo->size = create_bo.size;
- bo->gpu = create_bo.offset;
- bo->gem_handle = create_bo.handle;
- bo->flags = flags;
- }
-
- /* Only mmap now if we know we need to. For CPU-invisible buffers, we
- * never map since we don't care about their contents; they're purely
- * for GPU-internal use. But we do trace them anyway. */
-
- if (!(flags & (PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_DELAY_MMAP)))
- panfrost_drm_mmap_bo(screen, bo);
- else if (flags & PAN_ALLOCATE_INVISIBLE) {
- if (pan_debug & PAN_DBG_TRACE)
- pandecode_inject_mmap(bo->gpu, NULL, bo->size, NULL);
- }
-
- pipe_reference_init(&bo->reference, 1);
- return bo;
-}
-
-void
-panfrost_drm_release_bo(struct panfrost_screen *screen, struct panfrost_bo *bo, bool cacheable)
-{
- if (!bo)
- return;
-
- struct drm_gem_close gem_close = { .handle = bo->gem_handle };
- int ret;
-
- /* Rather than freeing the BO now, we'll cache the BO for later
- * allocations if we're allowed to */
-
- panfrost_drm_munmap_bo(screen, bo);
-
- if (cacheable) {
- bool cached = panfrost_bo_cache_put(screen, bo);
-
- if (cached)
- return;
- }
-
- /* Otherwise, if the BO wasn't cached, we'll legitimately free the BO */
-
- ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
- if (ret) {
- fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %m\n");
- assert(0);
- }
-
- ralloc_free(bo);
-}
-
-struct panfrost_bo *
-panfrost_drm_import_bo(struct panfrost_screen *screen, int fd)
-{
- struct panfrost_bo *bo = rzalloc(screen, struct panfrost_bo);
- struct drm_panfrost_get_bo_offset get_bo_offset = {0,};
- ASSERTED int ret;
- unsigned gem_handle;
-
- ret = drmPrimeFDToHandle(screen->fd, fd, &gem_handle);
- assert(!ret);
-
- get_bo_offset.handle = gem_handle;
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_GET_BO_OFFSET, &get_bo_offset);
- assert(!ret);
-
- bo->gem_handle = gem_handle;
- bo->gpu = (mali_ptr) get_bo_offset.offset;
- bo->size = lseek(fd, 0, SEEK_END);
- assert(bo->size > 0);
- pipe_reference_init(&bo->reference, 1);
-
- // TODO map and unmap on demand?
- panfrost_drm_mmap_bo(screen, bo);
- return bo;
-}
-
-int
-panfrost_drm_export_bo(struct panfrost_screen *screen, const struct panfrost_bo *bo)
-{
- struct drm_prime_handle args = {
- .handle = bo->gem_handle,
- .flags = DRM_CLOEXEC,
- };
-
- int ret = drmIoctl(screen->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
- if (ret == -1)
- return -1;
-
- return args.fd;
-}
-
static int
panfrost_drm_submit_batch(struct panfrost_batch *batch, u64 first_job_desc,
int reqs)
diff --git a/src/gallium/drivers/panfrost/pan_instancing.c b/src/gallium/drivers/panfrost/pan_instancing.c
index 44fe0a344aab..bcdcbe429394 100644
--- a/src/gallium/drivers/panfrost/pan_instancing.c
+++ b/src/gallium/drivers/panfrost/pan_instancing.c
@@ -23,6 +23,7 @@
*
*/
+#include "pan_bo.h"
#include "pan_context.h"
/* See mali_job for notes on how this works. But basically, for small vertex
diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index 58b494108e2d..7c40bcee0fca 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -25,6 +25,7 @@
#include <assert.h>
+#include "pan_bo.h"
#include "pan_context.h"
#include "util/hash_table.h"
#include "util/ralloc.h"
@@ -62,11 +63,11 @@ panfrost_free_batch(struct panfrost_batch *batch)
set_foreach(batch->bos, entry) {
struct panfrost_bo *bo = (struct panfrost_bo *)entry->key;
- panfrost_bo_unreference(ctx->base.screen, bo);
+ panfrost_bo_unreference(bo);
}
/* Unreference the polygon list */
- panfrost_bo_unreference(ctx->base.screen, batch->polygon_list);
+ panfrost_bo_unreference(batch->polygon_list);
_mesa_hash_table_remove_key(ctx->batches, &batch->key);
@@ -170,7 +171,7 @@ panfrost_batch_get_polygon_list(struct panfrost_batch *batch, unsigned size)
/* Create the BO as invisible, as there's no reason to map */
- batch->polygon_list = panfrost_drm_create_bo(screen,
+ batch->polygon_list = panfrost_bo_create(screen,
size, PAN_ALLOCATE_INVISIBLE);
}
diff --git a/src/gallium/drivers/panfrost/pan_mfbd.c b/src/gallium/drivers/panfrost/pan_mfbd.c
index 3ad22f82c4ab..618ebd3c4a19 100644
--- a/src/gallium/drivers/panfrost/pan_mfbd.c
+++ b/src/gallium/drivers/panfrost/pan_mfbd.c
@@ -22,6 +22,7 @@
*
*/
+#include "pan_bo.h"
#include "pan_context.h"
#include "pan_util.h"
#include "pan_format.h"
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index 0be6b2b1c330..a5869768f9de 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -41,6 +41,7 @@
#include "util/u_transfer_helper.h"
#include "util/u_gen_mipmap.h"
+#include "pan_bo.h"
#include "pan_context.h"
#include "pan_screen.h"
#include "pan_resource.h"
@@ -81,7 +82,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
pipe_reference_init(&prsc->reference, 1);
prsc->screen = pscreen;
- rsc->bo = panfrost_drm_import_bo(screen, whandle->handle);
+ rsc->bo = panfrost_bo_import(screen, whandle->handle);
rsc->slices[0].stride = whandle->stride;
rsc->slices[0].initialized = true;
panfrost_resource_reset_damage(rsc);
@@ -133,7 +134,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
return true;
} else {
- int fd = panfrost_drm_export_bo(screen, rsrc->bo);
+ int fd = panfrost_bo_export(rsrc->bo);
if (fd < 0)
return false;
@@ -412,7 +413,7 @@ panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_reso
/* We create a BO immediately but don't bother mapping, since we don't
* care to map e.g. FBOs which the CPU probably won't touch */
- pres->bo = panfrost_drm_create_bo(screen, bo_size, PAN_ALLOCATE_DELAY_MMAP);
+ pres->bo = panfrost_bo_create(screen, bo_size, PAN_ALLOCATE_DELAY_MMAP);
}
void
@@ -521,25 +522,6 @@ panfrost_resource_create(struct pipe_screen *screen,
return (struct pipe_resource *)so;
}
-void
-panfrost_bo_reference(struct panfrost_bo *bo)
-{
- if (bo)
- pipe_reference(NULL, &bo->reference);
-}
-
-void
-panfrost_bo_unreference(struct pipe_screen *screen, struct panfrost_bo *bo)
-{
- if (!bo)
- return;
-
- /* When the reference count goes to zero, we need to cleanup */
-
- if (pipe_reference(&bo->reference, NULL))
- panfrost_drm_release_bo(pan_screen(screen), bo, true);
-}
-
static void
panfrost_resource_destroy(struct pipe_screen *screen,
struct pipe_resource *pt)
@@ -551,7 +533,7 @@ panfrost_resource_destroy(struct pipe_screen *screen,
renderonly_scanout_destroy(rsrc->scanout, pscreen->ro);
if (rsrc->bo)
- panfrost_bo_unreference(screen, rsrc->bo);
+ panfrost_bo_unreference(rsrc->bo);
util_range_destroy(&rsrc->valid_buffer_range);
ralloc_free(rsrc);
@@ -579,11 +561,7 @@ panfrost_transfer_map(struct pipe_context *pctx,
*out_transfer = &transfer->base;
/* If we haven't already mmaped, now's the time */
-
- if (!bo->cpu) {
- struct panfrost_screen *screen = pan_screen(pctx->screen);
- panfrost_drm_mmap_bo(screen, bo);
- }
+ panfrost_bo_mmap(bo);
/* Check if we're bound for rendering and this is a read pixels. If so,
* we need to flush */
@@ -861,8 +839,8 @@ panfrost_resource_hint_layout(
/* If we grew in size, reallocate the BO */
if (new_size > rsrc->bo->size) {
- panfrost_drm_release_bo(screen, rsrc->bo, true);
- rsrc->bo = panfrost_drm_create_bo(screen, new_size, PAN_ALLOCATE_DELAY_MMAP);
+ panfrost_bo_unreference(rsrc->bo);
+ rsrc->bo = panfrost_bo_create(screen, new_size, PAN_ALLOCATE_DELAY_MMAP);
}
}
diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h
index 6ed3d1fd60e8..aca3c70952b1 100644
--- a/src/gallium/drivers/panfrost/pan_resource.h
+++ b/src/gallium/drivers/panfrost/pan_resource.h
@@ -32,6 +32,8 @@
#include "drm-uapi/drm.h"
#include "util/u_range.h"
+struct panfrost_bo;
+
/* Describes the memory layout of a BO */
enum panfrost_memory_layout {
@@ -57,12 +59,6 @@ struct panfrost_slice {
bool initialized;
};
-void
-panfrost_bo_reference(struct panfrost_bo *bo);
-
-void
-panfrost_bo_unreference(struct pipe_screen *screen, struct panfrost_bo *bo);
-
struct panfrost_resource {
struct pipe_resource base;
struct {
diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c
index 5dcceac370d5..50a27bad1767 100644
--- a/src/gallium/drivers/panfrost/pan_screen.c
+++ b/src/gallium/drivers/panfrost/pan_screen.c
@@ -42,6 +42,7 @@
#include "drm-uapi/drm_fourcc.h"
+#include "pan_bo.h"
#include "pan_screen.h"
#include "pan_resource.h"
#include "pan_public.h"
diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h
index 96044b8c8b90..aab141a563c2 100644
--- a/src/gallium/drivers/panfrost/pan_screen.h
+++ b/src/gallium/drivers/panfrost/pan_screen.h
@@ -120,17 +120,6 @@ pan_screen(struct pipe_screen *p)
return (struct panfrost_screen *)p;
}
-struct panfrost_bo *
-panfrost_drm_create_bo(struct panfrost_screen *screen, size_t size,
- uint32_t flags);
-void
-panfrost_drm_mmap_bo(struct panfrost_screen *screen, struct panfrost_bo *bo);
-void
-panfrost_drm_release_bo(struct panfrost_screen *screen, struct panfrost_bo *bo, bool cacheable);
-struct panfrost_bo *
-panfrost_drm_import_bo(struct panfrost_screen *screen, int fd);
-int
-panfrost_drm_export_bo(struct panfrost_screen *screen, const struct panfrost_bo *bo);
int
panfrost_drm_submit_vs_fs_batch(struct panfrost_batch *batch, bool has_draws);
void
@@ -149,18 +138,5 @@ panfrost_drm_fence_finish(struct pipe_screen *pscreen,
struct pipe_context *ctx,
struct pipe_fence_handle *fence,
uint64_t timeout);
-struct panfrost_bo *
-panfrost_bo_cache_fetch(
- struct panfrost_screen *screen,
- size_t size, uint32_t flags);
-
-bool
-panfrost_bo_cache_put(
- struct panfrost_screen *screen,
- struct panfrost_bo *bo);
-
-void
-panfrost_bo_cache_evict_all(
- struct panfrost_screen *screen);
#endif /* PAN_SCREEN_H */
diff --git a/src/gallium/drivers/panfrost/pan_sfbd.c b/src/gallium/drivers/panfrost/pan_sfbd.c
index f58c054c8f24..2d12904e9393 100644
--- a/src/gallium/drivers/panfrost/pan_sfbd.c
+++ b/src/gallium/drivers/panfrost/pan_sfbd.c
@@ -22,6 +22,7 @@
*
*/
+#include "pan_bo.h"
#include "pan_context.h"
#include "pan_util.h"
#include "pan_format.h"
diff --git a/src/gallium/drivers/panfrost/pan_varyings.c b/src/gallium/drivers/panfrost/pan_varyings.c
index 12760109b7cb..02f2e670eaf6 100644
--- a/src/gallium/drivers/panfrost/pan_varyings.c
+++ b/src/gallium/drivers/panfrost/pan_varyings.c
@@ -23,6 +23,7 @@
*
*/
+#include "pan_bo.h"
#include "pan_context.h"
#include "util/u_prim.h"
--
2.21.0
More information about the mesa-dev
mailing list