I attached an updated patch that applies to latest CVS and includes a
fix along the lines of the one I just committed to texmem.c.

I havn't heard any feedback in over a week. If no one objects I'll
commit this tomorrow.

Regards,
  Felix

Am Mittwoch, den 26.01.2005, 00:26 +0100 schrieb Felix Kühling:
> Hi,
> 
> The attached patch is my first cut at implementing a fair strategy for
> using all texture heaps. This solves my texture trashing problems with
> Torcs on Savage4 and ProSavageDDR. Testing and comments are welcome. I'm
> especially interested if anyone sees any performance regressions with
> this.
> 
> Heaps are now weighted by their sizes. That is, the bigger a heap, the
> more data will be kicked from/uploaded to it. If upload performance
> differs greatly then it would be quite easy to multiply a heap-specific
> factor to that weight in order to introduce a heap preference. This
> could be done either directly in the driver just after allocating a
> texture heap (heap->weight *= factor) or by adding a new parameter to
> driCreateTextureHeap.
> 
> Note that the new code in my patch will not be active as long as there
> is enough free space on any texture heap. So in order to see any
> performance difference you will either have to test with a very
> texture-hungry application or artificially reduce the amount of texture
> memory on one or both heaps. Also note that you need at least two
> texture heaps, so r200 is a bad candidate. ;-)
> 
> Regards,
>   Felix
> 
-- 
| Felix Kühling <[EMAIL PROTECTED]>                     http://fxk.de.vu |
| PGP Fingerprint: 6A3C 9566 5B30 DDED 73C3  B152 151C 5CC1 D888 E595 |
Index: texmem.c
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/common/texmem.c,v
retrieving revision 1.8
diff -u -r1.8 texmem.c
--- texmem.c	2 Feb 2005 15:52:29 -0000	1.8
+++ texmem.c	2 Feb 2005 16:34:56 -0000
@@ -477,6 +477,8 @@
 
 
 
+#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps */
+
 /**
  * Allocate memory from a texture heap to hold a texture object.  This
  * routine will attempt to allocate memory for the texture from the heaps
@@ -528,39 +530,91 @@
     */
 
    if ( t->memBlock == NULL ) {
-      for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
+      unsigned index[INDEX_ARRAY_SIZE];
+      unsigned nrGoodHeaps = 0;
+
+      /* Trying to avoid dynamic memory allocation. If you have more
+       * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any
+       * drivers with more than 2 tex heaps. */
+      assert( nr_neaps < INDEX_ARRAY_SIZE );
+
+      /* Sort large enough heaps by duty. Insertion sort should be
+       * fast enough for such a short array. */
+      for ( id = 0 ; id < nr_heaps ; id++ ) {
 	 heap = heap_array[ id ];
 
-	 if ( heap == NULL )
-	    continue;
+	 if ( heap != NULL && t->totalSize <= heap->size ) {
+	    unsigned j;
 
-	 if ( t->totalSize <= heap->size ) { 
+	    for ( j = 0 ; j < nrGoodHeaps; j++ ) {
+	       if ( heap->duty > heap_array[ index[ j ] ]->duty )
+		  break;
+	    }
 
-	    for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
-		  cursor != &heap->texture_objects ; 
-		  cursor = temp, temp = cursor->prev ) {
-	       
-	       /* The the LRU element.  If the texture is bound to one of
-		* the texture units, then we cannot kick it out.
-		*/
-	       if ( cursor->bound /* || cursor->reserved */ ) {
-		  continue;
-	       }
+	    if ( j < nrGoodHeaps ) {
+	       memmove( &index[ j+1 ], &index[ j ],
+			sizeof(index[ 0 ]) * (nrGoodHeaps - j) );
+	    }
 
-	       /* If this is a placeholder, there's no need to keep it */
-	       if (cursor->tObj)
-		   driSwapOutTextureObject( cursor );
-	       else
-		   driDestroyTextureObject( cursor );
+	    index[ j ] = id;
 
-	       t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, 
-					 heap->alignmentShift, 0 );
+	    nrGoodHeaps++;
+	 }
+      }
 
-	       if (t->memBlock)
-		  break;
+      for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) {
+	 heap = heap_array[ index[ id ] ];
+
+	 for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
+	       cursor != &heap->texture_objects ; 
+	       cursor = temp, temp = cursor->prev ) {
+	       
+	    /* The the LRU element.  If the texture is bound to one of
+	     * the texture units, then we cannot kick it out.
+	     */
+	    if ( cursor->bound /* || cursor->reserved */ ) {
+	       continue;
 	    }
-	 }     /* if ( t->totalSize <= heap->size ) ... */
+
+	    if ( cursor->memBlock )
+	       heap->duty -= cursor->memBlock->size;
+
+	    /* If this is a placeholder, there's no need to keep it */
+	    if (cursor->tObj)
+	       driSwapOutTextureObject( cursor );
+	    else
+	       driDestroyTextureObject( cursor );
+
+	    t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, 
+				      heap->alignmentShift, 0 );
+
+	    if (t->memBlock)
+	       break;
+	 }
       }
+
+      /* Rebalance duties. If a heap kicked more data than its duty,
+       * then all other heaps get that amount multiplied with their
+       * relative weight added to their duty. The negative duty is
+       * reset to 0. In the end all heaps have a duty >= 0.
+       *
+       * CAUTION: we must not change the heap pointer here, because it
+       * is used below to update the texture object.
+       */
+      for ( id = 0 ; id < nr_heaps ; id++ )
+	 if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) {
+	    int duty = -heap_array[ id ]->duty;
+	    double weight = heap_array[ id ]->weight;
+	    unsigned j;
+
+	    for ( j = 0 ; j < nr_heaps ; j++ )
+	       if ( j != id && heap_array[ j ] != NULL ) {
+		  heap_array[ j ]->duty += (double) duty *
+		     heap_array[ j ]->weight / weight;
+	       }
+
+	    heap_array[ id ]->duty = 0;
+	 }
    }
 
 
@@ -679,6 +733,9 @@
 
 	 make_empty_list( & heap->texture_objects );
 	 driSetTextureSwapCounterLocation( heap, NULL );
+
+	 heap->weight = heap->size;
+	 heap->duty = 0;
       }
       else {
 	 FREE( heap );
Index: texmem.h
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/common/texmem.h,v
retrieving revision 1.5
diff -u -r1.5 texmem.h
--- texmem.h	19 Jun 2004 17:44:23 -0000	1.5
+++ texmem.h	2 Feb 2005 16:34:56 -0000
@@ -216,6 +216,23 @@
 	 * framebuffer.  
 	 */
         unsigned timestamp;
+
+	/** \brief Kick/upload weight
+	 *
+	 * When not enough free space is available this weight
+	 * influences the choice of the heap from which textures are
+	 * kicked. By default the weight is equal to the heap size.
+	 */
+	double weight;
+
+	/** \brief Kick/upload duty
+	 *
+	 * The heap with the highest duty will be chosen for kicking
+	 * textures if not enough free space is available. The duty is
+	 * reduced by the amount of data kicked. Rebalancing of
+	 * negative duties takes the weights into account.
+	 */
+	int duty;
 };
 
 

Reply via email to