Home | History | Annotate | Download | only in svga
      1 /**********************************************************
      2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 #include "util/u_math.h"
     27 #include "util/u_memory.h"
     28 #include "util/crc32.h"
     29 
     30 #include "svga_debug.h"
     31 #include "svga_format.h"
     32 #include "svga_winsys.h"
     33 #include "svga_screen.h"
     34 #include "svga_screen_cache.h"
     35 
     36 
     37 #define SVGA_SURFACE_CACHE_ENABLED 1
     38 
     39 
     40 /**
     41  * Return the size of the surface described by the key (in bytes).
     42  */
     43 static unsigned
     44 surface_size(const struct svga_host_surface_cache_key *key)
     45 {
     46    unsigned bw, bh, bpb, total_size, i;
     47 
     48    assert(key->numMipLevels > 0);
     49    assert(key->numFaces > 0);
     50 
     51    if (key->format == SVGA3D_BUFFER) {
     52       /* Special case: we don't want to count vertex/index buffers
     53        * against the cache size limit, so view them as zero-sized.
     54        */
     55       return 0;
     56    }
     57 
     58    svga_format_size(key->format, &bw, &bh, &bpb);
     59 
     60    total_size = 0;
     61 
     62    for (i = 0; i < key->numMipLevels; i++) {
     63       unsigned w = u_minify(key->size.width, i);
     64       unsigned h = u_minify(key->size.height, i);
     65       unsigned d = u_minify(key->size.depth, i);
     66       unsigned img_size = ((w + bw - 1) / bw) * ((h + bh - 1) / bh) * d * bpb;
     67       total_size += img_size;
     68    }
     69 
     70    total_size *= key->numFaces;
     71 
     72    return total_size;
     73 }
     74 
     75 
     76 /**
     77  * Compute the bucket for this key.
     78  */
     79 static inline unsigned
     80 svga_screen_cache_bucket(const struct svga_host_surface_cache_key *key)
     81 {
     82    return util_hash_crc32(key, sizeof *key) % SVGA_HOST_SURFACE_CACHE_BUCKETS;
     83 }
     84 
     85 
     86 /**
     87  * Search the cache for a surface that matches the key.  If a match is
     88  * found, remove it from the cache and return the surface pointer.
     89  * Return NULL otherwise.
     90  */
     91 static struct svga_winsys_surface *
     92 svga_screen_cache_lookup(struct svga_screen *svgascreen,
     93                          const struct svga_host_surface_cache_key *key)
     94 {
     95    struct svga_host_surface_cache *cache = &svgascreen->cache;
     96    struct svga_winsys_screen *sws = svgascreen->sws;
     97    struct svga_host_surface_cache_entry *entry;
     98    struct svga_winsys_surface *handle = NULL;
     99    struct list_head *curr, *next;
    100    unsigned bucket;
    101    unsigned tries = 0;
    102 
    103    assert(key->cachable);
    104 
    105    bucket = svga_screen_cache_bucket(key);
    106 
    107    pipe_mutex_lock(cache->mutex);
    108 
    109    curr = cache->bucket[bucket].next;
    110    next = curr->next;
    111    while (curr != &cache->bucket[bucket]) {
    112       ++tries;
    113 
    114       entry = LIST_ENTRY(struct svga_host_surface_cache_entry, curr, bucket_head);
    115 
    116       assert(entry->handle);
    117 
    118       /* If the key matches and the fence is signalled (the surface is no
    119        * longer needed) the lookup was successful.  We found a surface that
    120        * can be reused.
    121        * We unlink the surface from the cache entry and we add the entry to
    122        * the 'empty' list.
    123        */
    124       if (memcmp(&entry->key, key, sizeof *key) == 0 &&
    125           sws->fence_signalled(sws, entry->fence, 0) == 0) {
    126          unsigned surf_size;
    127 
    128          assert(sws->surface_is_flushed(sws, entry->handle));
    129 
    130          handle = entry->handle; /* Reference is transfered here. */
    131          entry->handle = NULL;
    132 
    133          /* Remove from hash table */
    134          LIST_DEL(&entry->bucket_head);
    135 
    136          /* remove from LRU list */
    137          LIST_DEL(&entry->head);
    138 
    139          /* Add the cache entry (but not the surface!) to the empty list */
    140          LIST_ADD(&entry->head, &cache->empty);
    141 
    142          /* update the cache size */
    143          surf_size = surface_size(&entry->key);
    144          assert(surf_size <= cache->total_size);
    145          if (surf_size > cache->total_size)
    146             cache->total_size = 0; /* should never happen, but be safe */
    147          else
    148             cache->total_size -= surf_size;
    149 
    150          break;
    151       }
    152 
    153       curr = next;
    154       next = curr->next;
    155    }
    156 
    157    pipe_mutex_unlock(cache->mutex);
    158 
    159    if (SVGA_DEBUG & DEBUG_DMA)
    160       debug_printf("%s: cache %s after %u tries (bucket %d)\n", __FUNCTION__,
    161                    handle ? "hit" : "miss", tries, bucket);
    162 
    163    return handle;
    164 }
    165 
    166 
    167 /**
    168  * Free the least recently used entries in the surface cache until the
    169  * cache size is <= the target size OR there are no unused entries left
    170  * to discard.  We don't do any flushing to try to free up additional
    171  * surfaces.
    172  */
    173 static void
    174 svga_screen_cache_shrink(struct svga_screen *svgascreen,
    175                          unsigned target_size)
    176 {
    177    struct svga_host_surface_cache *cache = &svgascreen->cache;
    178    struct svga_winsys_screen *sws = svgascreen->sws;
    179    struct svga_host_surface_cache_entry *entry = NULL, *next_entry;
    180 
    181    /* Walk over the list of unused buffers in reverse order: from oldest
    182     * to newest.
    183     */
    184    LIST_FOR_EACH_ENTRY_SAFE_REV(entry, next_entry, &cache->unused, head) {
    185       if (entry->key.format != SVGA3D_BUFFER) {
    186          /* we don't want to discard vertex/index buffers */
    187 
    188          cache->total_size -= surface_size(&entry->key);
    189 
    190          assert(entry->handle);
    191          sws->surface_reference(sws, &entry->handle, NULL);
    192 
    193          LIST_DEL(&entry->bucket_head);
    194          LIST_DEL(&entry->head);
    195          LIST_ADD(&entry->head, &cache->empty);
    196 
    197          if (cache->total_size <= target_size) {
    198             /* all done */
    199             break;
    200          }
    201       }
    202    }
    203 }
    204 
    205 
    206 /**
    207  * Add a surface to the cache.  This is done when the driver deletes
    208  * the surface.  Note: transfers a handle reference.
    209  */
    210 static void
    211 svga_screen_cache_add(struct svga_screen *svgascreen,
    212                       const struct svga_host_surface_cache_key *key,
    213                       struct svga_winsys_surface **p_handle)
    214 {
    215    struct svga_host_surface_cache *cache = &svgascreen->cache;
    216    struct svga_winsys_screen *sws = svgascreen->sws;
    217    struct svga_host_surface_cache_entry *entry = NULL;
    218    struct svga_winsys_surface *handle = *p_handle;
    219    unsigned surf_size;
    220 
    221    assert(key->cachable);
    222 
    223    if (!handle)
    224       return;
    225 
    226    surf_size = surface_size(key);
    227 
    228    *p_handle = NULL;
    229    pipe_mutex_lock(cache->mutex);
    230 
    231    if (surf_size >= SVGA_HOST_SURFACE_CACHE_BYTES) {
    232       /* this surface is too large to cache, just free it */
    233       sws->surface_reference(sws, &handle, NULL);
    234       pipe_mutex_unlock(cache->mutex);
    235       return;
    236    }
    237 
    238    if (cache->total_size + surf_size > SVGA_HOST_SURFACE_CACHE_BYTES) {
    239       /* Adding this surface would exceed the cache size.
    240        * Try to discard least recently used entries until we hit the
    241        * new target cache size.
    242        */
    243       unsigned target_size = SVGA_HOST_SURFACE_CACHE_BYTES - surf_size;
    244 
    245       svga_screen_cache_shrink(svgascreen, target_size);
    246 
    247       if (cache->total_size > target_size) {
    248          /* we weren't able to shrink the cache as much as we wanted so
    249           * just discard this surface.
    250           */
    251          sws->surface_reference(sws, &handle, NULL);
    252          pipe_mutex_unlock(cache->mutex);
    253          return;
    254       }
    255    }
    256 
    257    if (!LIST_IS_EMPTY(&cache->empty)) {
    258       /* An empty entry has no surface associated with it.
    259        * Use the first empty entry.
    260        */
    261       entry = LIST_ENTRY(struct svga_host_surface_cache_entry,
    262                          cache->empty.next, head);
    263 
    264       /* Remove from LRU list */
    265       LIST_DEL(&entry->head);
    266    }
    267    else if (!LIST_IS_EMPTY(&cache->unused)) {
    268       /* free the last used buffer and reuse its entry */
    269       entry = LIST_ENTRY(struct svga_host_surface_cache_entry,
    270                          cache->unused.prev, head);
    271       SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    272                "unref sid %p (make space)\n", entry->handle);
    273 
    274       cache->total_size -= surface_size(&entry->key);
    275 
    276       sws->surface_reference(sws, &entry->handle, NULL);
    277 
    278       /* Remove from hash table */
    279       LIST_DEL(&entry->bucket_head);
    280 
    281       /* Remove from LRU list */
    282       LIST_DEL(&entry->head);
    283    }
    284 
    285    if (entry) {
    286       assert(entry->handle == NULL);
    287       entry->handle = handle;
    288       memcpy(&entry->key, key, sizeof entry->key);
    289 
    290       SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    291                "cache sid %p\n", entry->handle);
    292       LIST_ADD(&entry->head, &cache->validated);
    293 
    294       cache->total_size += surf_size;
    295    }
    296    else {
    297       /* Couldn't cache the buffer -- this really shouldn't happen */
    298       SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    299                "unref sid %p (couldn't find space)\n", handle);
    300       sws->surface_reference(sws, &handle, NULL);
    301    }
    302 
    303    pipe_mutex_unlock(cache->mutex);
    304 }
    305 
    306 
    307 /**
    308  * Called during the screen flush to move all buffers not in a validate list
    309  * into the unused list.
    310  */
    311 void
    312 svga_screen_cache_flush(struct svga_screen *svgascreen,
    313                         struct pipe_fence_handle *fence)
    314 {
    315    struct svga_host_surface_cache *cache = &svgascreen->cache;
    316    struct svga_winsys_screen *sws = svgascreen->sws;
    317    struct svga_host_surface_cache_entry *entry;
    318    struct list_head *curr, *next;
    319    unsigned bucket;
    320 
    321    pipe_mutex_lock(cache->mutex);
    322 
    323    /* Loop over entries in the invalidated list */
    324    curr = cache->invalidated.next;
    325    next = curr->next;
    326    while (curr != &cache->invalidated) {
    327       entry = LIST_ENTRY(struct svga_host_surface_cache_entry, curr, head);
    328 
    329       assert(entry->handle);
    330 
    331       if (sws->surface_is_flushed(sws, entry->handle)) {
    332          /* remove entry from the invalidated list */
    333          LIST_DEL(&entry->head);
    334 
    335          sws->fence_reference(sws, &entry->fence, fence);
    336 
    337          /* Add entry to the unused list */
    338          LIST_ADD(&entry->head, &cache->unused);
    339 
    340          /* Add entry to the hash table bucket */
    341          bucket = svga_screen_cache_bucket(&entry->key);
    342          LIST_ADD(&entry->bucket_head, &cache->bucket[bucket]);
    343       }
    344 
    345       curr = next;
    346       next = curr->next;
    347    }
    348 
    349    curr = cache->validated.next;
    350    next = curr->next;
    351    while (curr != &cache->validated) {
    352       entry = LIST_ENTRY(struct svga_host_surface_cache_entry, curr, head);
    353 
    354       assert(entry->handle);
    355 
    356       if (sws->surface_is_flushed(sws, entry->handle)) {
    357          /* remove entry from the validated list */
    358          LIST_DEL(&entry->head);
    359 
    360          /* it is now safe to invalidate the surface content. */
    361          sws->surface_invalidate(sws, entry->handle);
    362 
    363          /* add the entry to the invalidated list */
    364          LIST_ADD(&entry->head, &cache->invalidated);
    365       }
    366 
    367       curr = next;
    368       next = curr->next;
    369    }
    370 
    371    pipe_mutex_unlock(cache->mutex);
    372 }
    373 
    374 
    375 /**
    376  * Free all the surfaces in the cache.
    377  * Called when destroying the svga screen object.
    378  */
    379 void
    380 svga_screen_cache_cleanup(struct svga_screen *svgascreen)
    381 {
    382    struct svga_host_surface_cache *cache = &svgascreen->cache;
    383    struct svga_winsys_screen *sws = svgascreen->sws;
    384    unsigned i;
    385 
    386    for (i = 0; i < SVGA_HOST_SURFACE_CACHE_SIZE; ++i) {
    387       if (cache->entries[i].handle) {
    388 	 SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    389                   "unref sid %p (shutdown)\n", cache->entries[i].handle);
    390 	 sws->surface_reference(sws, &cache->entries[i].handle, NULL);
    391 
    392          cache->total_size -= surface_size(&cache->entries[i].key);
    393       }
    394 
    395       if (cache->entries[i].fence)
    396          sws->fence_reference(sws, &cache->entries[i].fence, NULL);
    397    }
    398 
    399    pipe_mutex_destroy(cache->mutex);
    400 }
    401 
    402 
    403 enum pipe_error
    404 svga_screen_cache_init(struct svga_screen *svgascreen)
    405 {
    406    struct svga_host_surface_cache *cache = &svgascreen->cache;
    407    unsigned i;
    408 
    409    assert(cache->total_size == 0);
    410 
    411    pipe_mutex_init(cache->mutex);
    412 
    413    for (i = 0; i < SVGA_HOST_SURFACE_CACHE_BUCKETS; ++i)
    414       LIST_INITHEAD(&cache->bucket[i]);
    415 
    416    LIST_INITHEAD(&cache->unused);
    417 
    418    LIST_INITHEAD(&cache->validated);
    419 
    420    LIST_INITHEAD(&cache->invalidated);
    421 
    422    LIST_INITHEAD(&cache->empty);
    423    for (i = 0; i < SVGA_HOST_SURFACE_CACHE_SIZE; ++i)
    424       LIST_ADDTAIL(&cache->entries[i].head, &cache->empty);
    425 
    426    return PIPE_OK;
    427 }
    428 
    429 
    430 /**
    431  * Allocate a new host-side surface.  If the surface is marked as cachable,
    432  * first try re-using a surface in the cache of freed surfaces.  Otherwise,
    433  * allocate a new surface.
    434  * \param bind_flags  bitmask of PIPE_BIND_x flags
    435  * \param usage  one of PIPE_USAGE_x values
    436  * \param validated return True if the surface is a reused surface
    437  */
    438 struct svga_winsys_surface *
    439 svga_screen_surface_create(struct svga_screen *svgascreen,
    440                            unsigned bind_flags, enum pipe_resource_usage usage,
    441                            boolean *validated,
    442                            struct svga_host_surface_cache_key *key)
    443 {
    444    struct svga_winsys_screen *sws = svgascreen->sws;
    445    struct svga_winsys_surface *handle = NULL;
    446    boolean cachable = SVGA_SURFACE_CACHE_ENABLED && key->cachable;
    447 
    448    SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    449             "%s sz %dx%dx%d mips %d faces %d arraySize %d cachable %d\n",
    450             __FUNCTION__,
    451             key->size.width,
    452             key->size.height,
    453             key->size.depth,
    454             key->numMipLevels,
    455             key->numFaces,
    456             key->arraySize,
    457             key->cachable);
    458 
    459    if (cachable) {
    460       if (key->format == SVGA3D_BUFFER) {
    461          SVGA3dSurfaceFlags hint_flag;
    462 
    463          /* For buffers, round the buffer size up to the nearest power
    464           * of two to increase the probability of cache hits.  Keep
    465           * texture surface dimensions unchanged.
    466           */
    467          uint32_t size = 1;
    468          while (size < key->size.width)
    469             size <<= 1;
    470          key->size.width = size;
    471 
    472          /* Determine whether the buffer is static or dynamic.
    473           * This is a bit of a heuristic which can be tuned as needed.
    474           */
    475          if (usage == PIPE_USAGE_DEFAULT ||
    476              usage == PIPE_USAGE_IMMUTABLE) {
    477             hint_flag = SVGA3D_SURFACE_HINT_STATIC;
    478          }
    479          else if (bind_flags & PIPE_BIND_INDEX_BUFFER) {
    480             /* Index buffers don't change too often.  Mark them as static.
    481              */
    482             hint_flag = SVGA3D_SURFACE_HINT_STATIC;
    483          }
    484          else {
    485             /* Since we're reusing buffers we're effectively transforming all
    486              * of them into dynamic buffers.
    487              *
    488              * It would be nice to not cache long lived static buffers. But there
    489              * is no way to detect the long lived from short lived ones yet. A
    490              * good heuristic would be buffer size.
    491              */
    492             hint_flag = SVGA3D_SURFACE_HINT_DYNAMIC;
    493          }
    494 
    495          key->flags &= ~(SVGA3D_SURFACE_HINT_STATIC |
    496                          SVGA3D_SURFACE_HINT_DYNAMIC);
    497          key->flags |= hint_flag;
    498       }
    499 
    500       handle = svga_screen_cache_lookup(svgascreen, key);
    501       if (handle) {
    502          if (key->format == SVGA3D_BUFFER)
    503             SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    504                      "reuse sid %p sz %d (buffer)\n", handle,
    505                      key->size.width);
    506          else
    507             SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    508                      "reuse sid %p sz %dx%dx%d mips %d faces %d arraySize %d\n", handle,
    509                      key->size.width,
    510                      key->size.height,
    511                      key->size.depth,
    512                      key->numMipLevels,
    513                      key->numFaces,
    514                      key->arraySize);
    515          *validated = TRUE;
    516       }
    517    }
    518 
    519    if (!handle) {
    520       unsigned usage = 0;
    521 
    522       if (!key->cachable)
    523          usage |= SVGA_SURFACE_USAGE_SHARED;
    524       if (key->scanout)
    525          usage |= SVGA_SURFACE_USAGE_SCANOUT;
    526 
    527       handle = sws->surface_create(sws,
    528                                    key->flags,
    529                                    key->format,
    530                                    usage,
    531                                    key->size,
    532                                    key->numFaces * key->arraySize,
    533                                    key->numMipLevels,
    534                                    key->sampleCount);
    535       if (handle)
    536          SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
    537                   "  CREATE sid %p sz %dx%dx%d\n",
    538                   handle,
    539                   key->size.width,
    540                   key->size.height,
    541                   key->size.depth);
    542 
    543       *validated = FALSE;
    544    }
    545 
    546    return handle;
    547 }
    548 
    549 
    550 /**
    551  * Release a surface.  We don't actually free the surface- we put
    552  * it into the cache of freed surfaces (if it's cachable).
    553  */
    554 void
    555 svga_screen_surface_destroy(struct svga_screen *svgascreen,
    556                             const struct svga_host_surface_cache_key *key,
    557                             struct svga_winsys_surface **p_handle)
    558 {
    559    struct svga_winsys_screen *sws = svgascreen->sws;
    560 
    561    /* We only set the cachable flag for surfaces of which we are the
    562     * exclusive owner.  So just hold onto our existing reference in
    563     * that case.
    564     */
    565    if (SVGA_SURFACE_CACHE_ENABLED && key->cachable) {
    566       svga_screen_cache_add(svgascreen, key, p_handle);
    567    }
    568    else {
    569       SVGA_DBG(DEBUG_DMA,
    570                "unref sid %p (uncachable)\n", *p_handle);
    571       sws->surface_reference(sws, p_handle, NULL);
    572    }
    573 }
    574 
    575 
    576 /**
    577  * Print/dump the contents of the screen cache.  For debugging.
    578  */
    579 void
    580 svga_screen_cache_dump(const struct svga_screen *svgascreen)
    581 {
    582    const struct svga_host_surface_cache *cache = &svgascreen->cache;
    583    unsigned bucket;
    584    unsigned count = 0;
    585 
    586    debug_printf("svga3d surface cache:\n");
    587    for (bucket = 0; bucket < SVGA_HOST_SURFACE_CACHE_BUCKETS; bucket++) {
    588       struct list_head *curr;
    589       curr = cache->bucket[bucket].next;
    590       while (curr && curr != &cache->bucket[bucket]) {
    591          struct svga_host_surface_cache_entry *entry =
    592             LIST_ENTRY(struct svga_host_surface_cache_entry,
    593                        curr, bucket_head);
    594          if (entry->key.format == SVGA3D_BUFFER) {
    595             debug_printf("  %p: buffer %u bytes\n",
    596                          entry->handle,
    597                          entry->key.size.width);
    598          }
    599          else {
    600             debug_printf("  %p: %u x %u x %u format %u\n",
    601                          entry->handle,
    602                          entry->key.size.width,
    603                          entry->key.size.height,
    604                          entry->key.size.depth,
    605                          entry->key.format);
    606          }
    607          curr = curr->next;
    608          count++;
    609       }
    610    }
    611 
    612    debug_printf("%u surfaces, %u bytes\n", count, cache->total_size);
    613 }
    614