* 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"
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;
+
+ 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);
+ }
- (void)allow_disk_cache;
+ 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;
}