ttn: Implement disk cache
ttn is slow, let's disk cache it. Signed-off-by: Axel Davy <davyaxel0@gmail.com> Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4993>
This commit is contained in:
@@ -22,12 +22,16 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "util/blob.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/ralloc.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#include "compiler/nir/nir.h"
|
||||
#include "compiler/nir/nir_control_flow.h"
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
#include "compiler/nir/nir_serialize.h"
|
||||
#include "compiler/shader_enums.h"
|
||||
|
||||
#include "tgsi_to_nir.h"
|
||||
@@ -2580,21 +2584,97 @@ ttn_finalize_nir(struct ttn_compile *c, struct pipe_screen *screen)
|
||||
nir_validate_shader(nir, "TTN: after all optimizations");
|
||||
}
|
||||
|
||||
static void save_nir_to_disk_cache(struct disk_cache *cache,
|
||||
uint8_t key[CACHE_KEY_SIZE],
|
||||
const nir_shader *s)
|
||||
{
|
||||
struct blob blob = {0};
|
||||
|
||||
blob_init(&blob);
|
||||
/* Because we cannot fully trust disk_cache_put
|
||||
* (EGL_ANDROID_blob_cache) we add the shader size,
|
||||
* which we'll check after disk_cache_get().
|
||||
*/
|
||||
if (blob_reserve_uint32(&blob) != 0) {
|
||||
blob_finish(&blob);
|
||||
return;
|
||||
}
|
||||
|
||||
nir_serialize(&blob, s, true);
|
||||
*(uint32_t *)blob.data = blob.size;
|
||||
|
||||
disk_cache_put(cache, key, blob.data, blob.size, NULL);
|
||||
blob_finish(&blob);
|
||||
}
|
||||
|
||||
static nir_shader *
|
||||
load_nir_from_disk_cache(struct disk_cache *cache,
|
||||
struct pipe_screen *screen,
|
||||
uint8_t key[CACHE_KEY_SIZE],
|
||||
unsigned processor)
|
||||
{
|
||||
const nir_shader_compiler_options *options =
|
||||
screen->get_compiler_options(screen, PIPE_SHADER_IR_NIR, processor);
|
||||
struct blob_reader blob_reader;
|
||||
size_t size;
|
||||
nir_shader *s;
|
||||
|
||||
uint32_t *buffer = (uint32_t *)disk_cache_get(cache, key, &size);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
/* Match found. No need to check crc32 or other things.
|
||||
* disk_cache_get is supposed to do that for us.
|
||||
* However we do still check if the first element is indeed the size,
|
||||
* as we cannot fully trust disk_cache_get (EGL_ANDROID_blob_cache) */
|
||||
if (buffer[0] != size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size -= 4;
|
||||
blob_reader_init(&blob_reader, buffer + 1, size);
|
||||
s = nir_deserialize(NULL, options, &blob_reader);
|
||||
free(buffer); /* buffer was malloc-ed */
|
||||
return s;
|
||||
}
|
||||
|
||||
struct nir_shader *
|
||||
tgsi_to_nir(const void *tgsi_tokens,
|
||||
struct pipe_screen *screen,
|
||||
bool allow_disk_cache)
|
||||
{
|
||||
struct disk_cache *cache = NULL;
|
||||
struct ttn_compile *c;
|
||||
struct nir_shader *s;
|
||||
struct nir_shader *s = NULL;
|
||||
uint8_t key[CACHE_KEY_SIZE];
|
||||
unsigned processor;
|
||||
|
||||
(void)allow_disk_cache;
|
||||
if (allow_disk_cache)
|
||||
cache = screen->get_disk_shader_cache(screen);
|
||||
|
||||
/* Look first in the cache */
|
||||
if (cache) {
|
||||
disk_cache_compute_key(cache,
|
||||
tgsi_tokens,
|
||||
tgsi_num_tokens(tgsi_tokens) * sizeof(struct tgsi_token),
|
||||
key);
|
||||
processor = tgsi_get_processor_type(tgsi_tokens);
|
||||
s = load_nir_from_disk_cache(cache, screen, key, processor);
|
||||
}
|
||||
|
||||
if (s)
|
||||
return s;
|
||||
|
||||
/* Not in the cache */
|
||||
|
||||
c = ttn_compile_init(tgsi_tokens, NULL, screen);
|
||||
s = c->build.shader;
|
||||
ttn_finalize_nir(c, screen);
|
||||
ralloc_free(c);
|
||||
|
||||
if (cache)
|
||||
save_nir_to_disk_cache(cache, key, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user