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;
};