[Mesa-dev] [PATCH 10/10] r600g, radeonsi: consolidate buffer code, add handling of DISCARD_RANGE for SI

Marek Olšák maraeo at gmail.com
Fri Nov 29 09:55:29 PST 2013


From: Marek Olšák <marek.olsak at amd.com>

This adds 2 optimizations for radeonsi:
- handling of DISCARD_RANGE
- mapping an uninitialized buffer range is automatically UNSYNCHRONIZED
---
 src/gallium/drivers/r600/Makefile.sources     |   1 -
 src/gallium/drivers/r600/r600_buffer.c        | 202 --------------------------
 src/gallium/drivers/r600/r600_pipe.c          |  14 --
 src/gallium/drivers/r600/r600_pipe.h          |  10 --
 src/gallium/drivers/r600/r600_state_common.c  |  10 +-
 src/gallium/drivers/radeon/r600_buffer.c      | 174 ++++++++++++++++++++++
 src/gallium/drivers/radeon/r600_pipe_common.c |  17 +++
 src/gallium/drivers/radeon/r600_pipe_common.h |   8 +
 src/gallium/drivers/radeonsi/r600_buffer.c    | 101 +------------
 src/gallium/drivers/radeonsi/r600_resource.c  |   4 +-
 src/gallium/drivers/radeonsi/r600_translate.c |   2 +-
 src/gallium/drivers/radeonsi/radeonsi_pipe.c  |  15 --
 src/gallium/drivers/radeonsi/radeonsi_pipe.h  |   5 -
 13 files changed, 210 insertions(+), 353 deletions(-)
 delete mode 100644 src/gallium/drivers/r600/r600_buffer.c

diff --git a/src/gallium/drivers/r600/Makefile.sources b/src/gallium/drivers/r600/Makefile.sources
index 76fd164..d96d98b 100644
--- a/src/gallium/drivers/r600/Makefile.sources
+++ b/src/gallium/drivers/r600/Makefile.sources
@@ -1,7 +1,6 @@
 C_SOURCES = \
 	r600_asm.c \
 	r600_blit.c \
-	r600_buffer.c \
 	r600_hw_context.c \
 	r600_isa.c \
 	r600_pipe.c \
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
deleted file mode 100644
index 969803f..0000000
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse at freedesktop.org>
- *
- * 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
- * on 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
- * THE AUTHOR(S) AND/OR THEIR 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.
- *
- * Authors:
- *      Jerome Glisse
- *      Corbin Simpson <MostAwesomeDude at gmail.com>
- */
-#include "r600_pipe.h"
-#include "util/u_upload_mgr.h"
-#include "util/u_memory.h"
-#include "util/u_surface.h"
-
-static void r600_buffer_destroy(struct pipe_screen *screen,
-				struct pipe_resource *buf)
-{
-	struct r600_resource *rbuffer = r600_resource(buf);
-
-	util_range_destroy(&rbuffer->valid_buffer_range);
-	pb_reference(&rbuffer->buf, NULL);
-	FREE(rbuffer);
-}
-
-static void *r600_buffer_get_transfer(struct pipe_context *ctx,
-				      struct pipe_resource *resource,
-                                      unsigned level,
-                                      unsigned usage,
-                                      const struct pipe_box *box,
-				      struct pipe_transfer **ptransfer,
-				      void *data, struct r600_resource *staging,
-				      unsigned offset)
-{
-	struct r600_context *rctx = (struct r600_context*)ctx;
-	struct r600_transfer *transfer = util_slab_alloc(&rctx->pool_transfers);
-
-	transfer->transfer.resource = resource;
-	transfer->transfer.level = level;
-	transfer->transfer.usage = usage;
-	transfer->transfer.box = *box;
-	transfer->transfer.stride = 0;
-	transfer->transfer.layer_stride = 0;
-	transfer->offset = offset;
-	transfer->staging = staging;
-	*ptransfer = &transfer->transfer;
-	return data;
-}
-
-static void *r600_buffer_transfer_map(struct pipe_context *ctx,
-					struct pipe_resource *resource,
-					unsigned level,
-					unsigned usage,
-					const struct pipe_box *box,
-					struct pipe_transfer **ptransfer)
-{
-	struct r600_context *rctx = (struct r600_context*)ctx;
-	struct r600_resource *rbuffer = r600_resource(resource);
-	uint8_t *data;
-
-	assert(box->x + box->width <= resource->width0);
-
-	/* See if the buffer range being mapped has never been initialized,
-	 * in which case it can be mapped unsynchronized. */
-	if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
-	    usage & PIPE_TRANSFER_WRITE &&
-	    !util_ranges_intersect(&rbuffer->valid_buffer_range, box->x, box->x + box->width)) {
-		usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
-	}
-
-	if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE &&
-	    !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
-		assert(usage & PIPE_TRANSFER_WRITE);
-
-		/* Check if mapping this buffer would cause waiting for the GPU. */
-		if (r600_rings_is_buffer_referenced(&rctx->b, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
-		    rctx->b.ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
-			rctx->b.invalidate_buffer(&rctx->b.b, &rbuffer->b.b);
-		}
-	}
-	else if ((usage & PIPE_TRANSFER_DISCARD_RANGE) &&
-		 !(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
-		 !(rctx->screen->b.debug_flags & DBG_NO_DISCARD_RANGE) &&
-		 (rctx->screen->b.has_cp_dma ||
-		  (rctx->screen->b.has_streamout &&
-		   /* The buffer range must be aligned to 4 with streamout. */
-		   box->x % 4 == 0 && box->width % 4 == 0))) {
-		assert(usage & PIPE_TRANSFER_WRITE);
-
-		/* Check if mapping this buffer would cause waiting for the GPU. */
-		if (r600_rings_is_buffer_referenced(&rctx->b, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
-		    rctx->b.ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
-			/* Do a wait-free write-only transfer using a temporary buffer. */
-			unsigned offset;
-			struct r600_resource *staging = NULL;
-
-			u_upload_alloc(rctx->uploader, 0, box->width + (box->x % R600_MAP_BUFFER_ALIGNMENT),
-				       &offset, (struct pipe_resource**)&staging, (void**)&data);
-
-			if (staging) {
-				data += box->x % R600_MAP_BUFFER_ALIGNMENT;
-				return r600_buffer_get_transfer(ctx, resource, level, usage, box,
-								ptransfer, data, staging, offset);
-			}
-		}
-	}
-
-	/* mmap and synchronize with rings */
-	data = r600_buffer_map_sync_with_rings(&rctx->b, rbuffer, usage);
-	if (!data) {
-		return NULL;
-	}
-	data += box->x;
-
-	return r600_buffer_get_transfer(ctx, resource, level, usage, box,
-					ptransfer, data, NULL, 0);
-}
-
-static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
-					struct pipe_transfer *transfer)
-{
-	struct r600_context *rctx = (struct r600_context*)pipe;
-	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
-	struct r600_resource *rbuffer = r600_resource(transfer->resource);
-
-	if (rtransfer->staging) {
-		struct pipe_resource *dst, *src;
-		unsigned soffset, doffset, size;
-		struct pipe_box box;
-
-		dst = transfer->resource;
-		src = &rtransfer->staging->b.b;
-		size = transfer->box.width;
-		doffset = transfer->box.x;
-		soffset = rtransfer->offset + transfer->box.x % R600_MAP_BUFFER_ALIGNMENT;
-
-		u_box_1d(soffset, size, &box);
-
-		/* Copy the staging buffer into the original one. */
-		if (!(size % 4) && !(doffset % 4) && !(soffset % 4) &&
-		    rctx->b.dma_copy(pipe, dst, 0, doffset, 0, 0, src, 0, &box)) {
-			/* DONE. */
-		} else {
-			pipe->resource_copy_region(pipe, dst, 0, doffset, 0, 0, src, 0, &box);
-		}
-		pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
-	}
-
-	if (transfer->usage & PIPE_TRANSFER_WRITE) {
-		util_range_add(&rbuffer->valid_buffer_range, transfer->box.x,
-			       transfer->box.x + transfer->box.width);
-	}
-	util_slab_free(&rctx->pool_transfers, transfer);
-}
-
-static const struct u_resource_vtbl r600_buffer_vtbl =
-{
-	u_default_resource_get_handle,		/* get_handle */
-	r600_buffer_destroy,			/* resource_destroy */
-	r600_buffer_transfer_map,		/* transfer_map */
-	NULL,					/* transfer_flush_region */
-	r600_buffer_transfer_unmap,		/* transfer_unmap */
-	NULL					/* transfer_inline_write */
-};
-
-struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
-					 const struct pipe_resource *templ,
-					 unsigned alignment)
-{
-	struct r600_screen *rscreen = (struct r600_screen*)screen;
-	struct r600_resource *rbuffer;
-
-	rbuffer = MALLOC_STRUCT(r600_resource);
-
-	rbuffer->b.b = *templ;
-	pipe_reference_init(&rbuffer->b.b.reference, 1);
-	rbuffer->b.b.screen = screen;
-	rbuffer->b.vtbl = &r600_buffer_vtbl;
-	util_range_init(&rbuffer->valid_buffer_range);
-
-	if (!r600_init_resource(&rscreen->b, rbuffer, templ->width0, alignment, TRUE, templ->usage)) {
-		FREE(rbuffer);
-		return NULL;
-	}
-	return &rbuffer->b.b;
-}
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 296d466..4016bbe 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -179,13 +179,9 @@ static void r600_destroy_context(struct pipe_context *context)
 	if (rctx->blitter) {
 		util_blitter_destroy(rctx->blitter);
 	}
-	if (rctx->uploader) {
-		u_upload_destroy(rctx->uploader);
-	}
 	if (rctx->allocator_fetch_shader) {
 		u_suballocator_destroy(rctx->allocator_fetch_shader);
 	}
-	util_slab_destroy(&rctx->pool_transfers);
 
 	r600_release_command_buffer(&rctx->start_cs_cmd);
 
@@ -208,10 +204,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 	if (rctx == NULL)
 		return NULL;
 
-	util_slab_create(&rctx->pool_transfers,
-			 sizeof(struct r600_transfer), 64,
-			 UTIL_SLAB_SINGLETHREADED);
-
 	rctx->b.b.screen = screen;
 	rctx->b.b.priv = priv;
 	rctx->b.b.destroy = r600_destroy_context;
@@ -295,12 +287,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 		rctx->b.rings.dma.flushing = false;
 	}
 
-	rctx->uploader = u_upload_create(&rctx->b.b, 1024 * 1024, 256,
-					PIPE_BIND_INDEX_BUFFER |
-					PIPE_BIND_CONSTANT_BUFFER);
-	if (!rctx->uploader)
-		goto fail;
-
 	rctx->allocator_fetch_shader = u_suballocator_create(&rctx->b.b, 64 * 1024, 256,
 							     0, PIPE_USAGE_STATIC, FALSE);
 	if (!rctx->allocator_fetch_shader)
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 15e89a0..7350479 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -34,7 +34,6 @@
 #include "r600_resource.h"
 
 #include "util/u_blitter.h"
-#include "util/u_slab.h"
 #include "util/u_suballoc.h"
 #include "util/u_double_list.h"
 #include "util/u_transfer.h"
@@ -63,8 +62,6 @@
 #define R600_BIG_ENDIAN 0
 #endif
 
-#define R600_MAP_BUFFER_ALIGNMENT 64
-
 #define R600_QUERY_DRAW_CALLS		(PIPE_QUERY_DRIVER_SPECIFIC + 0)
 #define R600_QUERY_REQUESTED_VRAM	(PIPE_QUERY_DRIVER_SPECIFIC + 1)
 #define R600_QUERY_REQUESTED_GTT	(PIPE_QUERY_DRIVER_SPECIFIC + 2)
@@ -399,9 +396,7 @@ struct r600_context {
 	struct r600_common_context	b;
 	struct r600_screen		*screen;
 	struct blitter_context		*blitter;
-	struct u_upload_mgr		*uploader;
 	struct u_suballocator		*allocator_fetch_shader;
-	struct util_slab_mempool	pool_transfers;
 	unsigned			initial_gfx_cs_size;
 
 	/* Hardware info. */
@@ -601,11 +596,6 @@ void r600_decompress_depth_textures(struct r600_context *rctx,
 void r600_decompress_color_textures(struct r600_context *rctx,
 				    struct r600_samplerview_state *textures);
 
-/* r600_buffer.c */
-struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
-					 const struct pipe_resource *templ,
-					 unsigned alignment);
-
 /* r600_pipe.c */
 const char * r600_llvm_gpu_string(enum radeon_family family);
 
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 3c7bfe9..3dc7991 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -953,10 +953,10 @@ static void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint
 				tmpPtr[i] = util_bswap32(((uint32_t *)ptr)[i]);
 			}
 
-			u_upload_data(rctx->uploader, 0, size, tmpPtr, &cb->buffer_offset, &cb->buffer);
+			u_upload_data(rctx->b.uploader, 0, size, tmpPtr, &cb->buffer_offset, &cb->buffer);
 			free(tmpPtr);
 		} else {
-			u_upload_data(rctx->uploader, 0, input->buffer_size, ptr, &cb->buffer_offset, &cb->buffer);
+			u_upload_data(rctx->b.uploader, 0, input->buffer_size, ptr, &cb->buffer_offset, &cb->buffer);
 		}
 		/* account it in gtt */
 		rctx->b.gtt += input->buffer_size;
@@ -1257,7 +1257,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 			unsigned out_offset;
 			void *ptr;
 
-			u_upload_alloc(rctx->uploader, 0, info.count * 2,
+			u_upload_alloc(rctx->b.uploader, 0, info.count * 2,
 				       &out_offset, &out_buffer, &ptr);
 
 			util_shorten_ubyte_elts_to_userptr(
@@ -1276,7 +1276,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 		 * Note: Instanced rendering in combination with immediate indices hangs. */
 		if (ib.user_buffer && (R600_BIG_ENDIAN || info.instance_count > 1 ||
 				       info.count*ib.index_size > 20)) {
-			u_upload_data(rctx->uploader, 0, info.count * ib.index_size,
+			u_upload_data(rctx->b.uploader, 0, info.count * ib.index_size,
 				      ib.user_buffer, &ib.offset, &ib.buffer);
 			ib.user_buffer = NULL;
 		}
@@ -1452,7 +1452,7 @@ void r600_draw_rectangle(struct blitter_context *blitter,
 	/* Upload vertices. The hw rectangle has only 3 vertices,
 	 * I guess the 4th one is derived from the first 3.
 	 * The vertex specification should match u_blitter's vertex element state. */
-	u_upload_alloc(rctx->uploader, 0, sizeof(float) * 24, &offset, &buf, (void**)&vb);
+	u_upload_alloc(rctx->b.uploader, 0, sizeof(float) * 24, &offset, &buf, (void**)&vb);
 	vb[0] = x1;
 	vb[1] = y1;
 	vb[2] = depth;
diff --git a/src/gallium/drivers/radeon/r600_buffer.c b/src/gallium/drivers/radeon/r600_buffer.c
index 8158234..b67a2af 100644
--- a/src/gallium/drivers/radeon/r600_buffer.c
+++ b/src/gallium/drivers/radeon/r600_buffer.c
@@ -25,6 +25,8 @@
  */
 
 #include "r600_cs.h"
+#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
 
 boolean r600_rings_is_buffer_referenced(struct r600_common_context *ctx,
 					struct radeon_winsys_cs_handle *buf,
@@ -145,3 +147,175 @@ bool r600_init_resource(struct r600_common_screen *rscreen,
 	}
 	return true;
 }
+
+static void r600_buffer_destroy(struct pipe_screen *screen,
+				struct pipe_resource *buf)
+{
+	struct r600_resource *rbuffer = r600_resource(buf);
+
+	util_range_destroy(&rbuffer->valid_buffer_range);
+	pb_reference(&rbuffer->buf, NULL);
+	FREE(rbuffer);
+}
+
+static void *r600_buffer_get_transfer(struct pipe_context *ctx,
+				      struct pipe_resource *resource,
+                                      unsigned level,
+                                      unsigned usage,
+                                      const struct pipe_box *box,
+				      struct pipe_transfer **ptransfer,
+				      void *data, struct r600_resource *staging,
+				      unsigned offset)
+{
+	struct r600_common_context *rctx = (struct r600_common_context*)ctx;
+	struct r600_transfer *transfer = util_slab_alloc(&rctx->pool_transfers);
+
+	transfer->transfer.resource = resource;
+	transfer->transfer.level = level;
+	transfer->transfer.usage = usage;
+	transfer->transfer.box = *box;
+	transfer->transfer.stride = 0;
+	transfer->transfer.layer_stride = 0;
+	transfer->offset = offset;
+	transfer->staging = staging;
+	*ptransfer = &transfer->transfer;
+	return data;
+}
+
+static void *r600_buffer_transfer_map(struct pipe_context *ctx,
+                                      struct pipe_resource *resource,
+                                      unsigned level,
+                                      unsigned usage,
+                                      const struct pipe_box *box,
+                                      struct pipe_transfer **ptransfer)
+{
+	struct r600_common_context *rctx = (struct r600_common_context*)ctx;
+	struct r600_common_screen *rscreen = (struct r600_common_screen*)ctx->screen;
+        struct r600_resource *rbuffer = r600_resource(resource);
+        uint8_t *data;
+
+	assert(box->x + box->width <= resource->width0);
+
+	/* See if the buffer range being mapped has never been initialized,
+	 * in which case it can be mapped unsynchronized. */
+	if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
+	    usage & PIPE_TRANSFER_WRITE &&
+	    !util_ranges_intersect(&rbuffer->valid_buffer_range, box->x, box->x + box->width)) {
+		usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
+	}
+
+	if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE &&
+	    !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+		assert(usage & PIPE_TRANSFER_WRITE);
+
+		/* Check if mapping this buffer would cause waiting for the GPU. */
+		if (r600_rings_is_buffer_referenced(rctx, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
+		    rctx->ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
+			rctx->invalidate_buffer(&rctx->b, &rbuffer->b.b);
+		}
+	}
+	else if ((usage & PIPE_TRANSFER_DISCARD_RANGE) &&
+		 !(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
+		 !(rscreen->debug_flags & DBG_NO_DISCARD_RANGE) &&
+		 (rscreen->has_cp_dma ||
+		  (rscreen->has_streamout &&
+		   /* The buffer range must be aligned to 4 with streamout. */
+		   box->x % 4 == 0 && box->width % 4 == 0))) {
+		assert(usage & PIPE_TRANSFER_WRITE);
+
+		/* Check if mapping this buffer would cause waiting for the GPU. */
+		if (r600_rings_is_buffer_referenced(rctx, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
+		    rctx->ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
+			/* Do a wait-free write-only transfer using a temporary buffer. */
+			unsigned offset;
+			struct r600_resource *staging = NULL;
+
+			u_upload_alloc(rctx->uploader, 0, box->width + (box->x % R600_MAP_BUFFER_ALIGNMENT),
+				       &offset, (struct pipe_resource**)&staging, (void**)&data);
+
+			if (staging) {
+				data += box->x % R600_MAP_BUFFER_ALIGNMENT;
+				return r600_buffer_get_transfer(ctx, resource, level, usage, box,
+								ptransfer, data, staging, offset);
+			}
+		}
+	}
+
+	data = r600_buffer_map_sync_with_rings(rctx, rbuffer, usage);
+	if (!data) {
+		return NULL;
+	}
+	data += box->x;
+
+	return r600_buffer_get_transfer(ctx, resource, level, usage, box,
+					ptransfer, data, NULL, 0);
+}
+
+static void r600_buffer_transfer_unmap(struct pipe_context *ctx,
+				       struct pipe_transfer *transfer)
+{
+	struct r600_common_context *rctx = (struct r600_common_context*)ctx;
+	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
+	struct r600_resource *rbuffer = r600_resource(transfer->resource);
+
+	if (rtransfer->staging) {
+		struct pipe_resource *dst, *src;
+		unsigned soffset, doffset, size;
+		struct pipe_box box;
+
+		dst = transfer->resource;
+		src = &rtransfer->staging->b.b;
+		size = transfer->box.width;
+		doffset = transfer->box.x;
+		soffset = rtransfer->offset + transfer->box.x % R600_MAP_BUFFER_ALIGNMENT;
+
+		u_box_1d(soffset, size, &box);
+
+		/* Copy the staging buffer into the original one. */
+		if (!(size % 4) && !(doffset % 4) && !(soffset % 4) &&
+		    rctx->dma_copy(ctx, dst, 0, doffset, 0, 0, src, 0, &box)) {
+			/* DONE. */
+		} else {
+			ctx->resource_copy_region(ctx, dst, 0, doffset, 0, 0, src, 0, &box);
+		}
+		pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
+	}
+
+	if (transfer->usage & PIPE_TRANSFER_WRITE) {
+		util_range_add(&rbuffer->valid_buffer_range, transfer->box.x,
+			       transfer->box.x + transfer->box.width);
+	}
+	util_slab_free(&rctx->pool_transfers, transfer);
+}
+
+static const struct u_resource_vtbl r600_buffer_vtbl =
+{
+	NULL,				/* get_handle */
+	r600_buffer_destroy,		/* resource_destroy */
+	r600_buffer_transfer_map,	/* transfer_map */
+	NULL,				/* transfer_flush_region */
+	r600_buffer_transfer_unmap,	/* transfer_unmap */
+	NULL				/* transfer_inline_write */
+};
+
+struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
+					 const struct pipe_resource *templ,
+					 unsigned alignment)
+{
+	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
+	struct r600_resource *rbuffer;
+
+	rbuffer = MALLOC_STRUCT(r600_resource);
+
+	rbuffer->b.b = *templ;
+	pipe_reference_init(&rbuffer->b.b.reference, 1);
+	rbuffer->b.b.screen = screen;
+	rbuffer->b.vtbl = &r600_buffer_vtbl;
+	util_range_init(&rbuffer->valid_buffer_range);
+
+	if (!r600_init_resource(rscreen, rbuffer, templ->width0, alignment, TRUE, templ->usage)) {
+		FREE(rbuffer);
+		return NULL;
+	}
+	return &rbuffer->b.b;
+}
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index 3a96aea..44061ab 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -28,6 +28,7 @@
 #include "r600_cs.h"
 #include "tgsi/tgsi_parse.h"
 #include "util/u_format_s3tc.h"
+#include "util/u_upload_mgr.h"
 
 static const struct debug_named_value common_debug_options[] = {
 	/* logging */
@@ -222,6 +223,10 @@ void r600_common_screen_cleanup(struct r600_common_screen *rscreen)
 bool r600_common_context_init(struct r600_common_context *rctx,
 			      struct r600_common_screen *rscreen)
 {
+	util_slab_create(&rctx->pool_transfers,
+			 sizeof(struct r600_transfer), 64,
+			 UTIL_SLAB_SINGLETHREADED);
+
 	rctx->ws = rscreen->ws;
 	rctx->family = rscreen->family;
 	rctx->chip_class = rscreen->chip_class;
@@ -233,11 +238,23 @@ bool r600_common_context_init(struct r600_common_context *rctx,
 	if (!rctx->allocator_so_filled_size)
 		return false;
 
+	rctx->uploader = u_upload_create(&rctx->b, 1024 * 1024, 256,
+					PIPE_BIND_INDEX_BUFFER |
+					PIPE_BIND_CONSTANT_BUFFER);
+	if (!rctx->uploader)
+		return false;
+
 	return true;
 }
 
 void r600_common_context_cleanup(struct r600_common_context *rctx)
 {
+	if (rctx->uploader) {
+		u_upload_destroy(rctx->uploader);
+	}
+
+	util_slab_destroy(&rctx->pool_transfers);
+
 	if (rctx->allocator_so_filled_size) {
 		u_suballocator_destroy(rctx->allocator_so_filled_size);
 	}
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index 172dd93..0814482 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -35,6 +35,7 @@
 #include "../../winsys/radeon/drm/radeon_winsys.h"
 
 #include "util/u_range.h"
+#include "util/u_slab.h"
 #include "util/u_suballoc.h"
 #include "util/u_transfer.h"
 
@@ -77,6 +78,8 @@
 #define DBG_NO_DISCARD_RANGE	(1 << 14)
 /* The maximum allowed bit is 15. */
 
+#define R600_MAP_BUFFER_ALIGNMENT 64
+
 struct r600_common_context;
 
 struct r600_resource {
@@ -225,7 +228,9 @@ struct r600_common_context {
 	enum chip_class			chip_class;
 	struct r600_rings		rings;
 
+	struct u_upload_mgr		*uploader;
 	struct u_suballocator		*allocator_so_filled_size;
+	struct util_slab_mempool	pool_transfers;
 
 	/* Current unaccounted memory usage. */
 	uint64_t			vram;
@@ -273,6 +278,9 @@ bool r600_init_resource(struct r600_common_screen *rscreen,
 			struct r600_resource *res,
 			unsigned size, unsigned alignment,
 			bool use_reusable_pool, unsigned usage);
+struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
+					 const struct pipe_resource *templ,
+					 unsigned alignment);
 
 /* r600_common_pipe.c */
 bool r600_common_screen_init(struct r600_common_screen *rscreen,
diff --git a/src/gallium/drivers/radeonsi/r600_buffer.c b/src/gallium/drivers/radeonsi/r600_buffer.c
index c952fe0..e64683d 100644
--- a/src/gallium/drivers/radeonsi/r600_buffer.c
+++ b/src/gallium/drivers/radeonsi/r600_buffer.c
@@ -35,105 +35,10 @@
 #include "r600.h"
 #include "radeonsi_pipe.h"
 
-static void r600_buffer_destroy(struct pipe_screen *screen,
-				struct pipe_resource *buf)
-{
-	struct r600_resource *rbuffer = r600_resource(buf);
-
-	pb_reference(&rbuffer->buf, NULL);
-	FREE(rbuffer);
-}
-
-static void *r600_buffer_transfer_map(struct pipe_context *ctx,
-                                      struct pipe_resource *resource,
-                                      unsigned level,
-                                      unsigned usage,
-                                      const struct pipe_box *box,
-                                      struct pipe_transfer **ptransfer)
-{
-	struct r600_context *rctx = (struct r600_context*)ctx;
-	struct pipe_transfer *transfer;
-        struct r600_resource *rbuffer = r600_resource(resource);
-        uint8_t *data;
-
-	if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE &&
-	    !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
-		assert(usage & PIPE_TRANSFER_WRITE);
-
-		/* Check if mapping this buffer would cause waiting for the GPU. */
-		if (r600_rings_is_buffer_referenced(&rctx->b, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
-		    rctx->b.ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
-			rctx->b.invalidate_buffer(&rctx->b.b, &rbuffer->b.b);
-		}
-	}
-
-	data = rctx->b.ws->buffer_map(rbuffer->cs_buf, rctx->b.rings.gfx.cs, usage);
-        if (!data) {
-		return NULL;
-        }
-
-	transfer = util_slab_alloc(&rctx->pool_transfers);
-	transfer->resource = resource;
-	transfer->level = level;
-	transfer->usage = usage;
-	transfer->box = *box;
-	transfer->stride = 0;
-	transfer->layer_stride = 0;
-        *ptransfer = transfer;
-
-	return (uint8_t*)data + transfer->box.x;
-}
-
-static void r600_buffer_transfer_unmap(struct pipe_context *ctx,
-					struct pipe_transfer *transfer)
-{
-	struct r600_context *rctx = (struct r600_context*)ctx;
-	util_slab_free(&rctx->pool_transfers, transfer);
-}
-
-static void r600_buffer_transfer_flush_region(struct pipe_context *pipe,
-						struct pipe_transfer *transfer,
-						const struct pipe_box *box)
-{
-}
-
-static const struct u_resource_vtbl r600_buffer_vtbl =
-{
-	u_default_resource_get_handle,		/* get_handle */
-	r600_buffer_destroy,			/* resource_destroy */
-	r600_buffer_transfer_map,		/* transfer_map */
-	r600_buffer_transfer_flush_region,	/* transfer_flush_region */
-	r600_buffer_transfer_unmap,		/* transfer_unmap */
-	NULL	/* transfer_inline_write */
-};
-
-struct pipe_resource *si_buffer_create(struct pipe_screen *screen,
-				       const struct pipe_resource *templ)
-{
-	struct r600_screen *rscreen = (struct r600_screen*)screen;
-	struct r600_resource *rbuffer;
-	/* XXX We probably want a different alignment for buffers and textures. */
-	unsigned alignment = 4096;
-
-	rbuffer = MALLOC_STRUCT(r600_resource);
-
-	rbuffer->b.b = *templ;
-	pipe_reference_init(&rbuffer->b.b.reference, 1);
-	rbuffer->b.b.screen = screen;
-	rbuffer->b.vtbl = &r600_buffer_vtbl;
-	util_range_init(&rbuffer->valid_buffer_range);
-
-	if (!r600_init_resource(&rscreen->b, rbuffer, templ->width0, alignment, TRUE, templ->usage)) {
-		FREE(rbuffer);
-		return NULL;
-	}
-	return &rbuffer->b.b;
-}
-
 void r600_upload_index_buffer(struct r600_context *rctx,
 			      struct pipe_index_buffer *ib, unsigned count)
 {
-	u_upload_data(rctx->uploader, 0, count * ib->index_size,
+	u_upload_data(rctx->b.uploader, 0, count * ib->index_size,
 		      ib->user_buffer, &ib->offset, &ib->buffer);
 }
 
@@ -154,12 +59,12 @@ void r600_upload_const_buffer(struct r600_context *rctx, struct r600_resource **
 			tmpPtr[i] = util_bswap32(((uint32_t *)ptr)[i]);
 		}
 
-		u_upload_data(rctx->uploader, 0, size, tmpPtr, const_offset,
+		u_upload_data(rctx->b.uploader, 0, size, tmpPtr, const_offset,
 				(struct pipe_resource**)rbuffer);
 
 		free(tmpPtr);
 	} else {
-		u_upload_data(rctx->uploader, 0, size, ptr, const_offset,
+		u_upload_data(rctx->b.uploader, 0, size, ptr, const_offset,
 					(struct pipe_resource**)rbuffer);
 	}
 }
diff --git a/src/gallium/drivers/radeonsi/r600_resource.c b/src/gallium/drivers/radeonsi/r600_resource.c
index 745d3ba..9a0fde4 100644
--- a/src/gallium/drivers/radeonsi/r600_resource.c
+++ b/src/gallium/drivers/radeonsi/r600_resource.c
@@ -27,7 +27,7 @@ static struct pipe_resource *r600_resource_create(struct pipe_screen *screen,
 						const struct pipe_resource *templ)
 {
 	if (templ->target == PIPE_BUFFER) {
-		return si_buffer_create(screen, templ);
+		return r600_buffer_create(screen, templ, 4096);
 	} else {
 		return r600_texture_create(screen, templ);
 	}
@@ -55,7 +55,7 @@ void r600_init_screen_resource_functions(struct pipe_screen *screen)
 void r600_init_context_resource_functions(struct r600_context *r600)
 {
 	r600->b.b.transfer_map = u_transfer_map_vtbl;
-	r600->b.b.transfer_flush_region = u_transfer_flush_region_vtbl;
+	r600->b.b.transfer_flush_region = u_default_transfer_flush_region;
 	r600->b.b.transfer_unmap = u_transfer_unmap_vtbl;
 	r600->b.b.transfer_inline_write = u_default_transfer_inline_write;
 }
diff --git a/src/gallium/drivers/radeonsi/r600_translate.c b/src/gallium/drivers/radeonsi/r600_translate.c
index ccb72d5..177a9dd 100644
--- a/src/gallium/drivers/radeonsi/r600_translate.c
+++ b/src/gallium/drivers/radeonsi/r600_translate.c
@@ -38,7 +38,7 @@ void r600_translate_index_buffer(struct r600_context *r600,
 
 	switch (ib->index_size) {
 	case 1:
-		u_upload_alloc(r600->uploader, 0, count * 2,
+		u_upload_alloc(r600->b.uploader, 0, count * 2,
 			       &out_offset, &out_buffer, &ptr);
 
 		util_shorten_ubyte_elts_to_userptr(
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
index fe860a9..3b25aef 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
@@ -119,11 +119,6 @@ static void r600_destroy_context(struct pipe_context *context)
 
 	util_blitter_destroy(rctx->blitter);
 
-	if (rctx->uploader) {
-		u_upload_destroy(rctx->uploader);
-	}
-	util_slab_destroy(&rctx->pool_transfers);
-
 	r600_common_context_cleanup(&rctx->b);
 	FREE(rctx);
 }
@@ -187,16 +182,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 
 	rctx->b.ws->cs_set_flush_callback(rctx->b.rings.gfx.cs, r600_flush_from_winsys, rctx);
 
-	util_slab_create(&rctx->pool_transfers,
-			 sizeof(struct pipe_transfer), 64,
-			 UTIL_SLAB_SINGLETHREADED);
-
-        rctx->uploader = u_upload_create(&rctx->b.b, 1024 * 1024, 256,
-                                         PIPE_BIND_INDEX_BUFFER |
-                                         PIPE_BIND_CONSTANT_BUFFER);
-        if (!rctx->uploader)
-		goto fail;
-
 	rctx->blitter = util_blitter_create(&rctx->b.b);
 	if (rctx->blitter == NULL)
 		goto fail;
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
index de613e0..e84088f 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.h
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
@@ -142,9 +142,6 @@ struct r600_context {
 	struct r600_resource		*border_color_table;
 	unsigned			border_color_offset;
 
-	struct u_upload_mgr	        *uploader;
-	struct util_slab_mempool	pool_transfers;
-
 	unsigned default_ps_gprs, default_vs_gprs;
 
 	/* Below are variables from the old r600_context.
@@ -186,8 +183,6 @@ void r600_decompress_color_textures(struct r600_context *rctx,
 				    struct r600_textures_info *textures);
 
 /* r600_buffer.c */
-struct pipe_resource *si_buffer_create(struct pipe_screen *screen,
-				       const struct pipe_resource *templ);
 void r600_upload_index_buffer(struct r600_context *rctx,
 			      struct pipe_index_buffer *ib, unsigned count);
 
-- 
1.8.3.2



More information about the mesa-dev mailing list