X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fcommon%2Ftexmem.c;h=b0e8c4c1c2824c871168bfbfd8862c21fd1b586b;hb=6ee6b2dcd96fafae8d924d617e54e32a2aa8c5ea;hp=48a8f5c74e9459c61dfeab63af2687baf882c45d;hpb=f252f64430ccb957698fcf85e84c9d64008147eb;p=mesa.git diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c index 48a8f5c74e9..b0e8c4c1c28 100644 --- a/src/mesa/drivers/dri/common/texmem.c +++ b/src/mesa/drivers/dri/common/texmem.c @@ -188,7 +188,7 @@ static void printLocalLRU( driTexHeap * heap, const char *callername ) static void printGlobalLRU( driTexHeap * heap, const char *callername ) { drmTextureRegionPtr list = heap->global_regions; - int i, j; + unsigned int i, j; fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n", __FUNCTION__, callername, heap->heapId, (void *)list ); @@ -410,11 +410,12 @@ static void driTexturesGone( driTexHeap * heap, int offset, int size, fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId, (int)size, (int)offset ); mmDumpMemInfo( heap->memory_heap ); + FREE(t); return; } t->heap = heap; if (in_use) - t->bound = 99; + t->reserved = 1; insert_at_head( & heap->texture_objects, t ); } } @@ -477,6 +478,8 @@ void driAgeTextures( driTexHeap * heap ) +#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,35 +531,91 @@ driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps, */ if ( t->memBlock == NULL ) { - for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) { - heap = heap_array[ id ]; - if ( t->totalSize <= heap->size ) { + unsigned index[INDEX_ARRAY_SIZE]; + unsigned nrGoodHeaps = 0; - 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; - } + /* 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_heaps < INDEX_ARRAY_SIZE ); - /* If this is a placeholder, there's no need to keep it */ - if (cursor->tObj) - driSwapOutTextureObject( cursor ); - else - driDestroyTextureObject( cursor ); + /* 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 ]; - t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, - heap->alignmentShift, 0 ); + if ( heap != NULL && t->totalSize <= heap->size ) { + unsigned j; - if (t->memBlock) + for ( j = 0 ; j < nrGoodHeaps; j++ ) { + if ( heap->duty > heap_array[ index[ j ] ]->duty ) break; } - } /* if ( t->totalSize <= heap->size ) ... */ + + if ( j < nrGoodHeaps ) { + memmove( &index[ j+1 ], &index[ j ], + sizeof(index[ 0 ]) * (nrGoodHeaps - j) ); + } + + index[ j ] = id; + + nrGoodHeaps++; + } } + + 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 ( 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; + } } @@ -675,6 +734,9 @@ driCreateTextureHeap( unsigned heap_id, void * context, unsigned size, make_empty_list( & heap->texture_objects ); driSetTextureSwapCounterLocation( heap, NULL ); + + heap->weight = heap->size; + heap->duty = 0; } else { FREE( heap ); @@ -884,7 +946,7 @@ get_max_size( unsigned nr_heaps, do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 ) #define SET_MAX_RECT(f,v) \ - do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << max_sizes[v]; } } while( 0 ) + do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << (max_sizes[v] - 1); } } while( 0 ) /** @@ -910,19 +972,22 @@ get_max_size( unsigned nr_heaps, * For hardware that does not support mipmapping, this will be 1. * \param all_textures_one_heap True if the hardware requires that all * textures be in a single texture heap for multitexturing. + * \param allow_larger_textures 0 conservative, 1 calculate limits + * so at least one worst-case texture can fit, 2 just use hw limits. */ void driCalculateMaxTextureLevels( driTexHeap * const * heaps, unsigned nr_heaps, struct gl_constants * limits, - unsigned max_bytes_per_texel, + unsigned max_bytes_per_texel, unsigned max_2D_size, unsigned max_3D_size, unsigned max_cube_size, unsigned max_rect_size, unsigned mipmaps_at_once, - int all_textures_one_heap ) + int all_textures_one_heap, + int allow_larger_textures ) { struct maps_per_heap max_textures[8]; unsigned i; @@ -939,8 +1004,8 @@ driCalculateMaxTextureLevels( driTexHeap * const * heaps, mipmaps[0] = mipmaps_at_once; mipmaps[1] = mipmaps_at_once; - mipmaps[2] = 1; - mipmaps[3] = mipmaps_at_once; + mipmaps[2] = mipmaps_at_once; + mipmaps[3] = 1; /* Calculate the maximum number of texture levels in two passes. The @@ -951,18 +1016,22 @@ driCalculateMaxTextureLevels( driTexHeap * const * heaps, */ for ( i = 0 ; i < 4 ; i++ ) { - if ( max_sizes[ i ] != 0 ) { - fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel, + if ( (allow_larger_textures != 2) && (max_sizes[ i ] != 0) ) { + fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel, max_sizes[ i ], mipmaps[ i ], dimensions[ i ], faces[ i ], max_textures ); - max_sizes[ i ] = get_max_size( nr_heaps, - limits->MaxTextureUnits, + max_sizes[ i ] = get_max_size( nr_heaps, + allow_larger_textures == 1 ? + 1 : limits->MaxTextureUnits, max_sizes[ i ], all_textures_one_heap, max_textures ); } + else if (max_sizes[ i ] != 0) { + max_sizes[ i ] += 1; + } } SET_MAX( MaxTextureLevels, 0 ); @@ -1077,7 +1146,7 @@ driValidateTextureHeaps( driTexHeap * const * texture_heaps, unsigned textures_in_heap = 0; unsigned blocks_in_mempool = 0; const driTexHeap * heap = texture_heaps[i]; - const memHeap_t * p = heap->memory_heap; + const struct mem_block *p = heap->memory_heap; /* Check each texture object has a MemBlock, and is linked into * the correct heap.