Mesa (master): radeon: Fix dma buffer object pool to scale object sizes.

Alex Deucher agd5f at kemper.freedesktop.org
Wed Aug 19 16:03:52 UTC 2009


Module: Mesa
Branch: master
Commit: 66e019c6c91e6ae3fb9e26a12d7b7782a0095a8d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=66e019c6c91e6ae3fb9e26a12d7b7782a0095a8d

Author: Pauli Nieminen <suokkos at gmail.com>
Date:   Wed Aug 19 14:47:25 2009 +0300

radeon: Fix dma buffer object pool to scale object sizes.

This fixes problems when application is using large vertex arrays for drawing.

Signed-off-by: Pauli Nieminen <suokkos at gmail.com>

---

 .../drivers/dri/radeon/radeon_common_context.h     |    5 +-
 src/mesa/drivers/dri/radeon/radeon_dma.c           |   48 ++++++++++++++++----
 2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 39fab66..9e9c356 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -313,8 +313,9 @@ struct radeon_dma {
 	struct radeon_dma_bo free;
 	struct radeon_dma_bo wait;
 	struct radeon_dma_bo reserved;
-        int current_used; /** Number of bytes allocated and forgotten about */
-        int current_vertexptr; /** End of active vertex region */
+        size_t current_used; /** Number of bytes allocated and forgotten about */
+        size_t current_vertexptr; /** End of active vertex region */
+        size_t minimum_size;
 
         /**
          * If current_vertexptr != current_used then flush must be non-zero.
diff --git a/src/mesa/drivers/dri/radeon/radeon_dma.c b/src/mesa/drivers/dri/radeon/radeon_dma.c
index 3019184..edf9ea0 100644
--- a/src/mesa/drivers/dri/radeon/radeon_dma.c
+++ b/src/mesa/drivers/dri/radeon/radeon_dma.c
@@ -164,14 +164,18 @@ void rcommon_emit_vector(GLcontext * ctx, struct radeon_aos *aos,
 
 void radeon_init_dma(radeonContextPtr rmesa)
 {
-   make_empty_list(&rmesa->dma.free);
-   make_empty_list(&rmesa->dma.wait);
-   make_empty_list(&rmesa->dma.reserved);
+	make_empty_list(&rmesa->dma.free);
+	make_empty_list(&rmesa->dma.wait);
+	make_empty_list(&rmesa->dma.reserved);
+	rmesa->dma.minimum_size = MAX_DMA_BUF_SZ;
 }
 
 void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
 {
-	size = MAX2(size, MAX_DMA_BUF_SZ);
+	/* we set minimum sizes to at least requested size
+	   aligned to next 16 bytes. */
+	if (size > rmesa->dma.minimum_size)
+		rmesa->dma.minimum_size = (size + 15) & (~15);
 
 	if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
 		fprintf(stderr, "%s\n", __FUNCTION__);
@@ -184,14 +188,15 @@ void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
 	if (!is_empty_list(&rmesa->dma.reserved))
 		radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo);
 
-	if (is_empty_list(&rmesa->dma.free)) {
+	if (is_empty_list(&rmesa->dma.free)
+	      || last_elem(&rmesa->dma.free)->bo->size < size) {
 		struct radeon_dma_bo *dma_bo = CALLOC(sizeof(struct radeon_dma_bo));
 		assert(dma_bo);
 
 again_alloc:
 		dma_bo->bo = radeon_bo_open(rmesa->radeonScreen->bom,
-					    0, size, 4, RADEON_GEM_DOMAIN_GTT,
-					    0);
+					    0, rmesa->dma.minimum_size, 4,
+					    RADEON_GEM_DOMAIN_GTT, 0);
 
 		if (!dma_bo->bo) {
 			rcommonFlushCmdBuf(rmesa, __FUNCTION__);
@@ -241,7 +246,7 @@ void radeonAllocDmaRegion(radeonContextPtr rmesa,
 
 	if (is_empty_list(&rmesa->dma.reserved)
 		|| rmesa->dma.current_used + bytes > first_elem(&rmesa->dma.reserved)->bo->size)
-		radeonRefillCurrentDmaRegion(rmesa, (bytes + 15) & ~15);
+		radeonRefillCurrentDmaRegion(rmesa, bytes);
 
 	*poffset = rmesa->dma.current_used;
 	*pbo = first_elem(&rmesa->dma.reserved)->bo;
@@ -267,6 +272,12 @@ void radeonFreeDmaRegions(radeonContextPtr rmesa)
 		FREE(dma_bo);
 	}
 
+	foreach_s(dma_bo, temp, &rmesa->dma.free) {
+		remove_from_list(dma_bo);
+	        radeon_bo_unref(dma_bo->bo);
+		FREE(dma_bo);
+	}
+
 	foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
 		remove_from_list(dma_bo);
 		radeon_bo_unmap(dma_bo->bo);
@@ -286,6 +297,11 @@ void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes)
 	rmesa->dma.current_vertexptr = rmesa->dma.current_used;
 }
 
+static int radeon_bo_is_idle(struct radeon_bo* bo)
+{
+	return bo->cref == 1;
+}
+
 void radeonReleaseDmaRegions(radeonContextPtr rmesa)
 {
 	struct radeon_dma_bo *dma_bo;
@@ -305,7 +321,14 @@ void radeonReleaseDmaRegions(radeonContextPtr rmesa)
 			FREE(dma_bo);
 			continue;
 		}
-		if (dma_bo->bo->cref > 1)
+		/* free objects that are too small to be used because of large request */
+		if (dma_bo->bo->size < rmesa->dma.minimum_size) {
+		   radeon_bo_unref(dma_bo->bo);
+		   remove_from_list(dma_bo);
+		   FREE(dma_bo);
+		   continue;
+		}
+		if (!radeon_bo_is_idle(dma_bo->bo))
 			continue;
 		remove_from_list(dma_bo);
 		dma_bo->expire_counter = expire_at;
@@ -317,6 +340,13 @@ void radeonReleaseDmaRegions(radeonContextPtr rmesa)
 		radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo);
 	/* move reserved to wait list */
 	foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
+		/* free objects that are too small to be used because of large request */
+		if (dma_bo->bo->size < rmesa->dma.minimum_size) {
+		   radeon_bo_unref(dma_bo->bo);
+		   remove_from_list(dma_bo);
+		   FREE(dma_bo);
+		   continue;
+		}
 		remove_from_list(dma_bo);
 		dma_bo->expire_counter = expire_at;
 		insert_at_tail(&rmesa->dma.wait, dma_bo);




More information about the mesa-commit mailing list