radeon: Fix dma buffer object pool to scale object sizes.
authorPauli Nieminen <suokkos@gmail.com>
Wed, 19 Aug 2009 11:47:25 +0000 (14:47 +0300)
committerAlex Deucher <alexdeucher@gmail.com>
Wed, 19 Aug 2009 15:59:34 +0000 (11:59 -0400)
This fixes problems when application is using large vertex arrays for drawing.

Signed-off-by: Pauli Nieminen <suokkos@gmail.com>
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_dma.c

index 39fab66ca763c46b48c456e5456bbf2bf896c34b..9e9c35650d416e044f2c333b701bf322cac6b420 100644 (file)
@@ -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.
index 30191845b98b54accbaad07369fc38844fe0d151..edf9ea0f01b2e94d103ea746fae74a97c6742646 100644 (file)
@@ -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);