1/* 2 * Copyright © 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#ifndef DISK_CACHE_H 25#define DISK_CACHE_H 26 27#ifdef HAVE_DLFCN_H 28#include <dlfcn.h> 29#include <stdio.h> 30#include "util/build_id.h" 31#endif 32#include <assert.h> 33#include <stdint.h> 34#include <stdbool.h> 35#include <sys/stat.h> 36#include "util/mesa-sha1.h" 37#include "util/detect_os.h" 38 39#ifdef __cplusplus 40extern "C" { 41#endif 42 43/* Size of cache keys in bytes. */ 44#define CACHE_KEY_SIZE 20 45 46#define CACHE_DIR_NAME "mesa_shader_cache" 47#define CACHE_DIR_NAME_SF "mesa_shader_cache_sf" 48 49typedef uint8_t cache_key[CACHE_KEY_SIZE]; 50 51/* WARNING: 3rd party applications might be reading the cache item metadata. 52 * Do not change these values without making the change widely known. 53 * Please contact Valve developers and make them aware of this change. 54 */ 55#define CACHE_ITEM_TYPE_UNKNOWN 0x0 56#define CACHE_ITEM_TYPE_GLSL 0x1 57 58typedef void 59(*disk_cache_put_cb) (const void *key, signed long keySize, 60 const void *value, signed long valueSize); 61 62typedef signed long 63(*disk_cache_get_cb) (const void *key, signed long keySize, 64 void *value, signed long valueSize); 65 66struct cache_item_metadata { 67 /** 68 * The cache item type. This could be used to identify a GLSL cache item, 69 * a certain type of IR (tgsi, nir, etc), or signal that it is the final 70 * binary form of the shader. 71 */ 72 uint32_t type; 73 74 /** GLSL cache item metadata */ 75 cache_key *keys; /* sha1 list of shaders that make up the cache item */ 76 uint32_t num_keys; 77}; 78 79struct disk_cache; 80 81static inline char * 82disk_cache_format_hex_id(char *buf, const uint8_t *hex_id, unsigned size) 83{ 84 static const char hex_digits[] = "0123456789abcdef"; 85 unsigned i; 86 87 for (i = 0; i < size; i += 2) { 88 buf[i] = hex_digits[hex_id[i >> 1] >> 4]; 89 buf[i + 1] = hex_digits[hex_id[i >> 1] & 0x0f]; 90 } 91 buf[i] = '\0'; 92 93 return buf; 94} 95 96#ifdef HAVE_DLADDR 97static inline bool 98disk_cache_get_function_timestamp(void *ptr, uint32_t* timestamp) 99{ 100 Dl_info info; 101 struct stat st; 102 if (!dladdr(ptr, &info) || !info.dli_fname) { 103 return false; 104 } 105 if (stat(info.dli_fname, &st)) { 106 return false; 107 } 108 109 if (!st.st_mtime) { 110 fprintf(stderr, "Mesa: The provided filesystem timestamp for the cache " 111 "is bogus! Disabling On-disk cache.\n"); 112 return false; 113 } 114 115 *timestamp = st.st_mtime; 116 117 return true; 118} 119 120static inline bool 121disk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx) 122{ 123 uint32_t timestamp; 124 125#ifdef HAVE_DL_ITERATE_PHDR 126 const struct build_id_note *note = NULL; 127 if ((note = build_id_find_nhdr_for_addr(ptr))) { 128 _mesa_sha1_update(ctx, build_id_data(note), build_id_length(note)); 129 } else 130#endif 131 if (disk_cache_get_function_timestamp(ptr, ×tamp)) { 132 _mesa_sha1_update(ctx, ×tamp, sizeof(timestamp)); 133 } else 134 return false; 135 return true; 136} 137#elif DETECT_OS_WINDOWS 138bool 139disk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx); 140#else 141static inline bool 142disk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx) 143{ 144 return false; 145} 146#endif 147 148/* Provide inlined stub functions if the shader cache is disabled. */ 149 150#ifdef ENABLE_SHADER_CACHE 151 152/** 153 * Create a new cache object. 154 * 155 * This function creates the handle necessary for all subsequent cache_* 156 * functions. 157 * 158 * This cache provides two distinct operations: 159 * 160 * o Storage and retrieval of arbitrary objects by cryptographic 161 * name (or "key"). This is provided via disk_cache_put() and 162 * disk_cache_get(). 163 * 164 * o The ability to store a key alone and check later whether the 165 * key was previously stored. This is provided via disk_cache_put_key() 166 * and disk_cache_has_key(). 167 * 168 * The put_key()/has_key() operations are conceptually identical to 169 * put()/get() with no data, but are provided separately to allow for 170 * a more efficient implementation. 171 * 172 * In all cases, the keys are sequences of 20 bytes. It is anticipated 173 * that callers will compute appropriate SHA-1 signatures for keys, 174 * (though nothing in this implementation directly relies on how the 175 * names are computed). See mesa-sha1.h and _mesa_sha1_compute for 176 * assistance in computing SHA-1 signatures. 177 */ 178struct disk_cache * 179disk_cache_create(const char *gpu_name, const char *timestamp, 180 uint64_t driver_flags); 181 182/** 183 * Destroy a cache object, (freeing all associated resources). 184 */ 185void 186disk_cache_destroy(struct disk_cache *cache); 187 188/* Wait for all previous disk_cache_put() calls to be processed (used for unit 189 * testing). 190 */ 191void 192disk_cache_wait_for_idle(struct disk_cache *cache); 193 194/** 195 * Remove the item in the cache under the name \key. 196 */ 197void 198disk_cache_remove(struct disk_cache *cache, const cache_key key); 199 200/** 201 * Store an item in the cache under the name \key. 202 * 203 * The item can be retrieved later with disk_cache_get(), (unless the item has 204 * been evicted in the interim). 205 * 206 * Any call to disk_cache_put() may cause an existing, random item to be 207 * evicted from the cache. 208 */ 209void 210disk_cache_put(struct disk_cache *cache, const cache_key key, 211 const void *data, size_t size, 212 struct cache_item_metadata *cache_item_metadata); 213 214/** 215 * Store an item in the cache under the name \key without copying the data param. 216 * 217 * The item can be retrieved later with disk_cache_get(), (unless the item has 218 * been evicted in the interim). 219 * 220 * Any call to disk_cache_put() may cause an existing, random item to be 221 * evicted from the cache. 222 * 223 * @p data will be freed 224 */ 225void 226disk_cache_put_nocopy(struct disk_cache *cache, const cache_key key, 227 void *data, size_t size, 228 struct cache_item_metadata *cache_item_metadata); 229 230/** 231 * Retrieve an item previously stored in the cache with the name <key>. 232 * 233 * The item must have been previously stored with a call to disk_cache_put(). 234 * 235 * If \size is non-NULL, then, on successful return, it will be set to the 236 * size of the object. 237 * 238 * \return A pointer to the stored object if found. NULL if the object 239 * is not found, or if any error occurs, (memory allocation failure, 240 * filesystem error, etc.). The returned data is malloc'ed so the 241 * caller should call free() it when finished. 242 */ 243void * 244disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size); 245 246/** 247 * Store the name \key within the cache, (without any associated data). 248 * 249 * Later this key can be checked with disk_cache_has_key(), (unless the key 250 * has been evicted in the interim). 251 * 252 * Any call to disk_cache_put_key() may cause an existing, random key to be 253 * evicted from the cache. 254 */ 255void 256disk_cache_put_key(struct disk_cache *cache, const cache_key key); 257 258/** 259 * Test whether the name \key was previously recorded in the cache. 260 * 261 * Return value: True if disk_cache_put_key() was previously called with 262 * \key, (and the key was not evicted in the interim). 263 * 264 * Note: disk_cache_has_key() will only return true for keys passed to 265 * disk_cache_put_key(). Specifically, a call to disk_cache_put() will not cause 266 * disk_cache_has_key() to return true for the same key. 267 */ 268bool 269disk_cache_has_key(struct disk_cache *cache, const cache_key key); 270 271/** 272 * Compute the name \key from \data of given \size. 273 */ 274void 275disk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size, 276 cache_key key); 277 278void 279disk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put, 280 disk_cache_get_cb get); 281 282#else 283 284static inline struct disk_cache * 285disk_cache_create(const char *gpu_name, const char *timestamp, 286 uint64_t driver_flags) 287{ 288 return NULL; 289} 290 291static inline void 292disk_cache_destroy(struct disk_cache *cache) { 293 return; 294} 295 296static inline void 297disk_cache_put(struct disk_cache *cache, const cache_key key, 298 const void *data, size_t size, 299 struct cache_item_metadata *cache_item_metadata) 300{ 301 return; 302} 303 304static inline void 305disk_cache_put_nocopy(struct disk_cache *cache, const cache_key key, 306 void *data, size_t size, 307 struct cache_item_metadata *cache_item_metadata) 308{ 309 return; 310} 311 312static inline void 313disk_cache_remove(struct disk_cache *cache, const cache_key key) 314{ 315 return; 316} 317 318static inline uint8_t * 319disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size) 320{ 321 return NULL; 322} 323 324static inline void 325disk_cache_put_key(struct disk_cache *cache, const cache_key key) 326{ 327 return; 328} 329 330static inline bool 331disk_cache_has_key(struct disk_cache *cache, const cache_key key) 332{ 333 return false; 334} 335 336static inline void 337disk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size, 338 const cache_key key) 339{ 340 return; 341} 342 343static inline void 344disk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put, 345 disk_cache_get_cb get) 346{ 347 return; 348} 349 350#endif /* ENABLE_SHADER_CACHE */ 351 352#ifdef __cplusplus 353} 354#endif 355 356#endif /* CACHE_H */ 357