1 /* 2 * Copyright (c) 2008-2024 Broadcom. All Rights Reserved. 3 * The term “Broadcom” refers to Broadcom Inc. 4 * and/or its subsidiaries. 5 * SPDX-License-Identifier: MIT 6 */ 7 8 #ifndef SVGA_SCREEN_CACHE_H_ 9 #define SVGA_SCREEN_CACHE_H_ 10 11 #include "svga_reg.h" 12 #include "svga3d_reg.h" 13 14 #include "util/u_thread.h" 15 16 #include "util/list.h" 17 18 19 /* Guess the storage size of cached surfaces and try and keep it under 20 * this amount: 21 */ 22 #define SVGA_HOST_SURFACE_CACHE_BYTES (16 * 1024 * 1024) 23 24 /* Maximum number of discrete surfaces in the cache: 25 */ 26 #define SVGA_HOST_SURFACE_CACHE_SIZE 1024 27 28 /* Number of hash buckets: 29 */ 30 #define SVGA_HOST_SURFACE_CACHE_BUCKETS 256 31 32 33 struct svga_winsys_surface; 34 struct svga_screen; 35 struct svga_context; 36 37 /** 38 * Same as svga_winsys_screen::surface_create. 39 */ 40 struct svga_host_surface_cache_key 41 { 42 SVGA3dSurfaceAllFlags flags; 43 SVGA3dSurfaceFormat format; 44 SVGA3dSize size; 45 uint32_t numFaces:3; 46 uint32_t arraySize:16; 47 uint32_t numMipLevels:6; 48 uint32_t cachable:1; /* False if this is a shared surface */ 49 uint32_t sampleCount:5; 50 uint32_t scanout:1; 51 uint32_t coherent:1; 52 uint32_t persistent:1; 53 }; 54 55 56 struct svga_host_surface_cache_entry 57 { 58 /** 59 * Head for the LRU list, svga_host_surface_cache::unused, and 60 * svga_host_surface_cache::empty 61 */ 62 struct list_head head; 63 64 /** Head for the bucket lists. */ 65 struct list_head bucket_head; 66 67 struct svga_host_surface_cache_key key; 68 struct svga_winsys_surface *handle; 69 70 struct pipe_fence_handle *fence; 71 }; 72 73 74 /** 75 * Cache of the host surfaces. 76 * 77 * A cache entry can be in the following stages: 78 * 1. empty (entry->handle = NULL) 79 * 2. holding a buffer in a validate list 80 * 3. holding a buffer in an invalidate list 81 * 4. holding a flushed buffer (not in any validate list) with an active fence 82 * 5. holding a flushed buffer with an expired fence 83 * 84 * An entry progresses from 1 -> 2 -> 3 -> 4 -> 5. When we need an entry to put a 85 * buffer into we preferentially take from 1, or from the least recently used 86 * buffer from 4/5. 87 */ 88 struct svga_host_surface_cache 89 { 90 mtx_t mutex; 91 92 /* Unused buffers are put in buckets to speed up lookups */ 93 struct list_head bucket[SVGA_HOST_SURFACE_CACHE_BUCKETS]; 94 95 /* Entries with unused buffers, ordered from most to least recently used 96 * (3 and 4) */ 97 struct list_head unused; 98 99 /* Entries with buffers still in validate list (2) */ 100 struct list_head validated; 101 102 /* Entries with buffers still in invalidate list (3) */ 103 struct list_head invalidated; 104 105 /** Empty entries (1) */ 106 struct list_head empty; 107 108 /** The actual storage for the entries */ 109 struct svga_host_surface_cache_entry entries[SVGA_HOST_SURFACE_CACHE_SIZE]; 110 111 /** Sum of sizes of all surfaces (in bytes) */ 112 unsigned total_size; 113 }; 114 115 116 void 117 svga_screen_cache_cleanup(struct svga_screen *svgascreen); 118 119 void 120 svga_screen_cache_flush(struct svga_screen *svgascreen, 121 struct svga_context *svga, 122 struct pipe_fence_handle *fence); 123 124 enum pipe_error 125 svga_screen_cache_init(struct svga_screen *svgascreen); 126 127 128 struct svga_winsys_surface * 129 svga_screen_surface_create(struct svga_screen *svgascreen, 130 unsigned bind_flags, enum pipe_resource_usage usage, 131 bool *invalidated, 132 struct svga_host_surface_cache_key *key); 133 134 void 135 svga_screen_surface_destroy(struct svga_screen *svgascreen, 136 const struct svga_host_surface_cache_key *key, 137 bool to_invalidate, 138 struct svga_winsys_surface **handle); 139 140 void 141 svga_screen_cache_dump(const struct svga_screen *svgascreen); 142 143 unsigned 144 svga_surface_size(const struct svga_host_surface_cache_key *key); 145 146 147 #endif /* SVGA_SCREEN_CACHE_H_ */ 148