101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2014 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#ifndef DISK_CACHE_H
2501e04c3fSmrg#define DISK_CACHE_H
2601e04c3fSmrg
2701e04c3fSmrg#ifdef HAVE_DLFCN_H
2801e04c3fSmrg#include <dlfcn.h>
2901e04c3fSmrg#include <stdio.h>
3001e04c3fSmrg#include "util/build_id.h"
3101e04c3fSmrg#endif
3201e04c3fSmrg#include <assert.h>
3301e04c3fSmrg#include <stdint.h>
3401e04c3fSmrg#include <stdbool.h>
3501e04c3fSmrg#include <sys/stat.h>
3601e04c3fSmrg#include "util/mesa-sha1.h"
3701e04c3fSmrg
3801e04c3fSmrg#ifdef __cplusplus
3901e04c3fSmrgextern "C" {
4001e04c3fSmrg#endif
4101e04c3fSmrg
4201e04c3fSmrg/* Size of cache keys in bytes. */
4301e04c3fSmrg#define CACHE_KEY_SIZE 20
4401e04c3fSmrg
4501e04c3fSmrg#define CACHE_DIR_NAME "mesa_shader_cache"
467ec681f3Smrg#define CACHE_DIR_NAME_SF "mesa_shader_cache_sf"
4701e04c3fSmrg
4801e04c3fSmrgtypedef uint8_t cache_key[CACHE_KEY_SIZE];
4901e04c3fSmrg
5001e04c3fSmrg/* WARNING: 3rd party applications might be reading the cache item metadata.
5101e04c3fSmrg * Do not change these values without making the change widely known.
5201e04c3fSmrg * Please contact Valve developers and make them aware of this change.
5301e04c3fSmrg */
5401e04c3fSmrg#define CACHE_ITEM_TYPE_UNKNOWN  0x0
5501e04c3fSmrg#define CACHE_ITEM_TYPE_GLSL     0x1
5601e04c3fSmrg
5701e04c3fSmrgtypedef void
5801e04c3fSmrg(*disk_cache_put_cb) (const void *key, signed long keySize,
5901e04c3fSmrg                      const void *value, signed long valueSize);
6001e04c3fSmrg
6101e04c3fSmrgtypedef signed long
6201e04c3fSmrg(*disk_cache_get_cb) (const void *key, signed long keySize,
6301e04c3fSmrg                      void *value, signed long valueSize);
6401e04c3fSmrg
6501e04c3fSmrgstruct cache_item_metadata {
6601e04c3fSmrg   /**
6701e04c3fSmrg    * The cache item type. This could be used to identify a GLSL cache item,
6801e04c3fSmrg    * a certain type of IR (tgsi, nir, etc), or signal that it is the final
6901e04c3fSmrg    * binary form of the shader.
7001e04c3fSmrg    */
7101e04c3fSmrg   uint32_t type;
7201e04c3fSmrg
7301e04c3fSmrg   /** GLSL cache item metadata */
7401e04c3fSmrg   cache_key *keys;   /* sha1 list of shaders that make up the cache item */
7501e04c3fSmrg   uint32_t num_keys;
7601e04c3fSmrg};
7701e04c3fSmrg
7801e04c3fSmrgstruct disk_cache;
7901e04c3fSmrg
8001e04c3fSmrgstatic inline char *
8101e04c3fSmrgdisk_cache_format_hex_id(char *buf, const uint8_t *hex_id, unsigned size)
8201e04c3fSmrg{
8301e04c3fSmrg   static const char hex_digits[] = "0123456789abcdef";
8401e04c3fSmrg   unsigned i;
8501e04c3fSmrg
8601e04c3fSmrg   for (i = 0; i < size; i += 2) {
8701e04c3fSmrg      buf[i] = hex_digits[hex_id[i >> 1] >> 4];
8801e04c3fSmrg      buf[i + 1] = hex_digits[hex_id[i >> 1] & 0x0f];
8901e04c3fSmrg   }
9001e04c3fSmrg   buf[i] = '\0';
9101e04c3fSmrg
9201e04c3fSmrg   return buf;
9301e04c3fSmrg}
9401e04c3fSmrg
957ec681f3Smrg#ifdef HAVE_DLADDR
9601e04c3fSmrgstatic inline bool
9701e04c3fSmrgdisk_cache_get_function_timestamp(void *ptr, uint32_t* timestamp)
9801e04c3fSmrg{
9901e04c3fSmrg   Dl_info info;
10001e04c3fSmrg   struct stat st;
10101e04c3fSmrg   if (!dladdr(ptr, &info) || !info.dli_fname) {
10201e04c3fSmrg      return false;
10301e04c3fSmrg   }
10401e04c3fSmrg   if (stat(info.dli_fname, &st)) {
10501e04c3fSmrg      return false;
10601e04c3fSmrg   }
10701e04c3fSmrg
10801e04c3fSmrg   if (!st.st_mtime) {
10901e04c3fSmrg      fprintf(stderr, "Mesa: The provided filesystem timestamp for the cache "
11001e04c3fSmrg              "is bogus! Disabling On-disk cache.\n");
11101e04c3fSmrg      return false;
11201e04c3fSmrg   }
11301e04c3fSmrg
11401e04c3fSmrg   *timestamp = st.st_mtime;
11501e04c3fSmrg
11601e04c3fSmrg   return true;
11701e04c3fSmrg}
11801e04c3fSmrg
11901e04c3fSmrgstatic inline bool
12001e04c3fSmrgdisk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx)
12101e04c3fSmrg{
12201e04c3fSmrg   uint32_t timestamp;
12301e04c3fSmrg
12401e04c3fSmrg#ifdef HAVE_DL_ITERATE_PHDR
12501e04c3fSmrg   const struct build_id_note *note = NULL;
12601e04c3fSmrg   if ((note = build_id_find_nhdr_for_addr(ptr))) {
12701e04c3fSmrg      _mesa_sha1_update(ctx, build_id_data(note), build_id_length(note));
12801e04c3fSmrg   } else
12901e04c3fSmrg#endif
13001e04c3fSmrg   if (disk_cache_get_function_timestamp(ptr, &timestamp)) {
13101e04c3fSmrg      _mesa_sha1_update(ctx, &timestamp, sizeof(timestamp));
13201e04c3fSmrg   } else
13301e04c3fSmrg      return false;
13401e04c3fSmrg   return true;
13501e04c3fSmrg}
1367ec681f3Smrg#else
1377ec681f3Smrgstatic inline bool
1387ec681f3Smrgdisk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx)
1397ec681f3Smrg{
1407ec681f3Smrg   return false;
1417ec681f3Smrg}
14201e04c3fSmrg#endif
14301e04c3fSmrg
14401e04c3fSmrg/* Provide inlined stub functions if the shader cache is disabled. */
14501e04c3fSmrg
14601e04c3fSmrg#ifdef ENABLE_SHADER_CACHE
14701e04c3fSmrg
14801e04c3fSmrg/**
14901e04c3fSmrg * Create a new cache object.
15001e04c3fSmrg *
15101e04c3fSmrg * This function creates the handle necessary for all subsequent cache_*
15201e04c3fSmrg * functions.
15301e04c3fSmrg *
15401e04c3fSmrg * This cache provides two distinct operations:
15501e04c3fSmrg *
15601e04c3fSmrg *   o Storage and retrieval of arbitrary objects by cryptographic
15701e04c3fSmrg *     name (or "key").  This is provided via disk_cache_put() and
15801e04c3fSmrg *     disk_cache_get().
15901e04c3fSmrg *
16001e04c3fSmrg *   o The ability to store a key alone and check later whether the
16101e04c3fSmrg *     key was previously stored. This is provided via disk_cache_put_key()
16201e04c3fSmrg *     and disk_cache_has_key().
16301e04c3fSmrg *
16401e04c3fSmrg * The put_key()/has_key() operations are conceptually identical to
16501e04c3fSmrg * put()/get() with no data, but are provided separately to allow for
16601e04c3fSmrg * a more efficient implementation.
16701e04c3fSmrg *
16801e04c3fSmrg * In all cases, the keys are sequences of 20 bytes. It is anticipated
16901e04c3fSmrg * that callers will compute appropriate SHA-1 signatures for keys,
17001e04c3fSmrg * (though nothing in this implementation directly relies on how the
17101e04c3fSmrg * names are computed). See mesa-sha1.h and _mesa_sha1_compute for
17201e04c3fSmrg * assistance in computing SHA-1 signatures.
17301e04c3fSmrg */
17401e04c3fSmrgstruct disk_cache *
17501e04c3fSmrgdisk_cache_create(const char *gpu_name, const char *timestamp,
17601e04c3fSmrg                  uint64_t driver_flags);
17701e04c3fSmrg
17801e04c3fSmrg/**
17901e04c3fSmrg * Destroy a cache object, (freeing all associated resources).
18001e04c3fSmrg */
18101e04c3fSmrgvoid
18201e04c3fSmrgdisk_cache_destroy(struct disk_cache *cache);
18301e04c3fSmrg
1847ec681f3Smrg/* Wait for all previous disk_cache_put() calls to be processed (used for unit
1857ec681f3Smrg * testing).
1867ec681f3Smrg */
1877ec681f3Smrgvoid
1887ec681f3Smrgdisk_cache_wait_for_idle(struct disk_cache *cache);
1897ec681f3Smrg
19001e04c3fSmrg/**
19101e04c3fSmrg * Remove the item in the cache under the name \key.
19201e04c3fSmrg */
19301e04c3fSmrgvoid
19401e04c3fSmrgdisk_cache_remove(struct disk_cache *cache, const cache_key key);
19501e04c3fSmrg
19601e04c3fSmrg/**
19701e04c3fSmrg * Store an item in the cache under the name \key.
19801e04c3fSmrg *
19901e04c3fSmrg * The item can be retrieved later with disk_cache_get(), (unless the item has
20001e04c3fSmrg * been evicted in the interim).
20101e04c3fSmrg *
20201e04c3fSmrg * Any call to disk_cache_put() may cause an existing, random item to be
20301e04c3fSmrg * evicted from the cache.
20401e04c3fSmrg */
20501e04c3fSmrgvoid
20601e04c3fSmrgdisk_cache_put(struct disk_cache *cache, const cache_key key,
20701e04c3fSmrg               const void *data, size_t size,
20801e04c3fSmrg               struct cache_item_metadata *cache_item_metadata);
20901e04c3fSmrg
2107ec681f3Smrg/**
2117ec681f3Smrg * Store an item in the cache under the name \key without copying the data param.
2127ec681f3Smrg *
2137ec681f3Smrg * The item can be retrieved later with disk_cache_get(), (unless the item has
2147ec681f3Smrg * been evicted in the interim).
2157ec681f3Smrg *
2167ec681f3Smrg * Any call to disk_cache_put() may cause an existing, random item to be
2177ec681f3Smrg * evicted from the cache.
2187ec681f3Smrg *
2197ec681f3Smrg * @p data will be freed
2207ec681f3Smrg */
2217ec681f3Smrgvoid
2227ec681f3Smrgdisk_cache_put_nocopy(struct disk_cache *cache, const cache_key key,
2237ec681f3Smrg                      void *data, size_t size,
2247ec681f3Smrg                      struct cache_item_metadata *cache_item_metadata);
2257ec681f3Smrg
22601e04c3fSmrg/**
22701e04c3fSmrg * Retrieve an item previously stored in the cache with the name <key>.
22801e04c3fSmrg *
22901e04c3fSmrg * The item must have been previously stored with a call to disk_cache_put().
23001e04c3fSmrg *
23101e04c3fSmrg * If \size is non-NULL, then, on successful return, it will be set to the
23201e04c3fSmrg * size of the object.
23301e04c3fSmrg *
23401e04c3fSmrg * \return A pointer to the stored object if found. NULL if the object
23501e04c3fSmrg * is not found, or if any error occurs, (memory allocation failure,
23601e04c3fSmrg * filesystem error, etc.). The returned data is malloc'ed so the
23701e04c3fSmrg * caller should call free() it when finished.
23801e04c3fSmrg */
23901e04c3fSmrgvoid *
24001e04c3fSmrgdisk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size);
24101e04c3fSmrg
24201e04c3fSmrg/**
24301e04c3fSmrg * Store the name \key within the cache, (without any associated data).
24401e04c3fSmrg *
24501e04c3fSmrg * Later this key can be checked with disk_cache_has_key(), (unless the key
24601e04c3fSmrg * has been evicted in the interim).
24701e04c3fSmrg *
24801e04c3fSmrg * Any call to disk_cache_put_key() may cause an existing, random key to be
24901e04c3fSmrg * evicted from the cache.
25001e04c3fSmrg */
25101e04c3fSmrgvoid
25201e04c3fSmrgdisk_cache_put_key(struct disk_cache *cache, const cache_key key);
25301e04c3fSmrg
25401e04c3fSmrg/**
25501e04c3fSmrg * Test whether the name \key was previously recorded in the cache.
25601e04c3fSmrg *
25701e04c3fSmrg * Return value: True if disk_cache_put_key() was previously called with
25801e04c3fSmrg * \key, (and the key was not evicted in the interim).
25901e04c3fSmrg *
26001e04c3fSmrg * Note: disk_cache_has_key() will only return true for keys passed to
26101e04c3fSmrg * disk_cache_put_key(). Specifically, a call to disk_cache_put() will not cause
26201e04c3fSmrg * disk_cache_has_key() to return true for the same key.
26301e04c3fSmrg */
26401e04c3fSmrgbool
26501e04c3fSmrgdisk_cache_has_key(struct disk_cache *cache, const cache_key key);
26601e04c3fSmrg
26701e04c3fSmrg/**
26801e04c3fSmrg * Compute the name \key from \data of given \size.
26901e04c3fSmrg */
27001e04c3fSmrgvoid
27101e04c3fSmrgdisk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
27201e04c3fSmrg                       cache_key key);
27301e04c3fSmrg
27401e04c3fSmrgvoid
27501e04c3fSmrgdisk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
27601e04c3fSmrg                         disk_cache_get_cb get);
27701e04c3fSmrg
27801e04c3fSmrg#else
27901e04c3fSmrg
28001e04c3fSmrgstatic inline struct disk_cache *
28101e04c3fSmrgdisk_cache_create(const char *gpu_name, const char *timestamp,
28201e04c3fSmrg                  uint64_t driver_flags)
28301e04c3fSmrg{
28401e04c3fSmrg   return NULL;
28501e04c3fSmrg}
28601e04c3fSmrg
28701e04c3fSmrgstatic inline void
28801e04c3fSmrgdisk_cache_destroy(struct disk_cache *cache) {
28901e04c3fSmrg   return;
29001e04c3fSmrg}
29101e04c3fSmrg
29201e04c3fSmrgstatic inline void
29301e04c3fSmrgdisk_cache_put(struct disk_cache *cache, const cache_key key,
29401e04c3fSmrg               const void *data, size_t size,
29501e04c3fSmrg               struct cache_item_metadata *cache_item_metadata)
29601e04c3fSmrg{
29701e04c3fSmrg   return;
29801e04c3fSmrg}
29901e04c3fSmrg
3007ec681f3Smrgstatic inline void
3017ec681f3Smrgdisk_cache_put_nocopy(struct disk_cache *cache, const cache_key key,
3027ec681f3Smrg                      void *data, size_t size,
3037ec681f3Smrg                      struct cache_item_metadata *cache_item_metadata)
3047ec681f3Smrg{
3057ec681f3Smrg   return;
3067ec681f3Smrg}
3077ec681f3Smrg
30801e04c3fSmrgstatic inline void
30901e04c3fSmrgdisk_cache_remove(struct disk_cache *cache, const cache_key key)
31001e04c3fSmrg{
31101e04c3fSmrg   return;
31201e04c3fSmrg}
31301e04c3fSmrg
31401e04c3fSmrgstatic inline uint8_t *
31501e04c3fSmrgdisk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
31601e04c3fSmrg{
31701e04c3fSmrg   return NULL;
31801e04c3fSmrg}
31901e04c3fSmrg
32001e04c3fSmrgstatic inline void
32101e04c3fSmrgdisk_cache_put_key(struct disk_cache *cache, const cache_key key)
32201e04c3fSmrg{
32301e04c3fSmrg   return;
32401e04c3fSmrg}
32501e04c3fSmrg
32601e04c3fSmrgstatic inline bool
32701e04c3fSmrgdisk_cache_has_key(struct disk_cache *cache, const cache_key key)
32801e04c3fSmrg{
32901e04c3fSmrg   return false;
33001e04c3fSmrg}
33101e04c3fSmrg
33201e04c3fSmrgstatic inline void
33301e04c3fSmrgdisk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
33401e04c3fSmrg                       const cache_key key)
33501e04c3fSmrg{
33601e04c3fSmrg   return;
33701e04c3fSmrg}
33801e04c3fSmrg
33901e04c3fSmrgstatic inline void
34001e04c3fSmrgdisk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
34101e04c3fSmrg                         disk_cache_get_cb get)
34201e04c3fSmrg{
34301e04c3fSmrg   return;
34401e04c3fSmrg}
34501e04c3fSmrg
34601e04c3fSmrg#endif /* ENABLE_SHADER_CACHE */
34701e04c3fSmrg
34801e04c3fSmrg#ifdef __cplusplus
34901e04c3fSmrg}
35001e04c3fSmrg#endif
35101e04c3fSmrg
35201e04c3fSmrg#endif /* CACHE_H */
353