[Mesa-dev] [PATCH 4/4] radeon: cache the last used userptr

Christian König deathsimple at vodafone.de
Tue Aug 5 10:31:36 PDT 2014


From: Christian König <christian.koenig at amd.com>

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 src/gallium/drivers/radeon/r600_pipe_common.c |  9 ++++++
 src/gallium/drivers/radeon/r600_pipe_common.h | 11 +++++++
 src/gallium/drivers/radeon/r600_texture.c     | 41 +++++++++++++++++++++++++--
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index 69d344e..f745311 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -770,11 +770,20 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen,
 		}
 	}
 
+	pipe_mutex_init(rscreen->userptr_lock);
+
 	return true;
 }
 
 void r600_destroy_common_screen(struct r600_common_screen *rscreen)
 {
+	unsigned i;
+
+	for (i = 0; i < R600_USERPTR_CACHE; ++i)
+		pipe_resource_reference((struct pipe_resource **)&rscreen->userptr[i].tex, NULL);
+
+	pipe_mutex_destroy(rscreen->userptr_lock);
+
 	pipe_mutex_destroy(rscreen->aux_context_lock);
 	rscreen->aux_context->destroy(rscreen->aux_context);
 
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index dcec2bb..88dbaf8 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -97,6 +97,8 @@
 
 #define R600_MAP_BUFFER_ALIGNMENT 64
 
+#define R600_USERPTR_CACHE 32
+
 struct r600_common_context;
 
 struct radeon_shader_binary {
@@ -258,6 +260,15 @@ struct r600_common_screen {
 	struct r600_resource		*trace_bo;
 	uint32_t			*trace_ptr;
 	unsigned			cs_count;
+
+	struct {
+		struct r600_texture	*tex;
+		void			*pointer;
+		unsigned		offset;
+		unsigned		size;
+	}				userptr[R600_USERPTR_CACHE];
+	unsigned			userptr_idx;
+	pipe_mutex			userptr_lock;
 };
 
 /* This encapsulates a state or an operation which can emitted into the GPU
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 89b3b55..c3ff96c 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -855,10 +855,11 @@ static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
 {
 	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
 	struct radeon_surface surface = {};
+	struct pipe_resource *res = NULL;
 	struct r600_texture *tex;
 	unsigned offset, size;
 	struct pb_buffer *buf;
-	int r;
+	int r, i;
 
 	/* Support only 2D textures without mipmaps */
 	if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
@@ -877,16 +878,52 @@ static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
 	if (size < 64*1024)
 		return NULL;
 
+	pipe_mutex_lock(rscreen->userptr_lock);
+	for (i = 0; i < R600_USERPTR_CACHE; ++i) {
+
+		if (rscreen->userptr[i].pointer != pointer ||
+		    rscreen->userptr[i].offset != offset ||
+		    rscreen->userptr[i].size != size ||
+		    !rscreen->userptr[i].tex)
+			continue;
+
+		tex = rscreen->userptr[i].tex;
+		if (tex->resource.b.b.width0 != templ->width0 &&
+		    tex->resource.b.b.height0 != templ->height0 &&
+		    tex->resource.b.b.target != templ->target &&
+		    tex->resource.b.b.format != templ->format)
+			continue;
+
+		pipe_resource_reference(&res, (struct pipe_resource *)tex);
+		pipe_mutex_unlock(rscreen->userptr_lock);
+		return (struct r600_texture *)res;
+	}
+	pipe_mutex_unlock(rscreen->userptr_lock);
+
 	buf = rscreen->ws->buffer_from_ptr(rscreen->ws, pointer, size);
 	if (!buf)
 		return NULL;
 
-	r = r600_init_surface(rscreen, &surface, templ, RADEON_SURF_MODE_LINEAR_ALIGNED, false);
+	r = r600_init_surface(rscreen, &surface, templ, RADEON_SURF_MODE_LINEAR, false);
 	if (r)
 		return NULL;
 
 	tex = r600_texture_create_object(screen, templ, stride, buf, &surface);
 	tex->surface.level[0].offset += offset;
+
+	pipe_mutex_lock(rscreen->userptr_lock);
+	++rscreen->userptr_idx;
+	rscreen->userptr_idx %= R600_USERPTR_CACHE;
+
+	i = rscreen->userptr_idx;
+	pipe_resource_reference((struct pipe_resource **)&rscreen->userptr[i].tex,
+				(struct pipe_resource *)tex);
+	rscreen->userptr[i].pointer = pointer;
+	rscreen->userptr[i].offset = offset;
+	rscreen->userptr[i].size = size;
+
+	pipe_mutex_unlock(rscreen->userptr_lock);
+
 	return tex;
 }
 
-- 
1.9.1



More information about the mesa-dev mailing list