glsl: make use of on disk shader cache
authorTimothy Arceri <timothy.arceri@collabora.com>
Mon, 23 Jan 2017 21:39:13 +0000 (08:39 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Fri, 17 Feb 2017 00:18:42 +0000 (11:18 +1100)
The hash key for glsl metadata is a hash of the hashes of each GLSL
source string.

This commit uses the put_key/get_key support in the cache put the SHA-1
hash of the source string for each successfully compiled shader into the
cache. This allows for early, optimistic returns from glCompileShader
(if the identical source string had been successfully compiled in the past),
in the hope that the final, linked shader will be found in the cache.

This is based on the intial patch by Carl.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/compiler/glsl/glsl_parser_extras.cpp
src/compiler/glsl/linker.cpp
src/mesa/program/ir_to_mesa.cpp

index f6a9c9a051dd711d6ca34f44b449e60b0889c1f1..833b5fefa18882455796f74c279da1df911f3fae 100644 (file)
@@ -33,6 +33,8 @@
 #include "main/shaderobj.h"
 #include "util/u_atomic.h" /* for p_atomic_cmpxchg */
 #include "util/ralloc.h"
+#include "util/disk_cache.h"
+#include "util/mesa-sha1.h"
 #include "ast.h"
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
@@ -1934,6 +1936,20 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
    state->error = glcpp_preprocess(state, &source, &state->info_log,
                              add_builtin_defines, state, ctx);
 
+   if (!force_recompile) {
+      char buf[41];
+      _mesa_sha1_compute(source, strlen(source), shader->sha1);
+      if (ctx->Cache && disk_cache_has_key(ctx->Cache, shader->sha1)) {
+         /* We've seen this shader before and know it compiles */
+         if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
+            fprintf(stderr, "deferring compile of shader: %s\n",
+                    _mesa_sha1_format(buf, shader->sha1));
+         }
+         shader->CompileStatus = true;
+         return;
+      }
+   }
+
    if (!state->error) {
      _mesa_glsl_lexer_ctor(state, source);
      _mesa_glsl_parse(state);
index b3c7d2c14569855788f8963aadf42f966fda4c0a..80d83141f9a5b6aead4418ffc7e503b72fea7188 100644 (file)
@@ -73,6 +73,7 @@
 #include "program.h"
 #include "program/prog_instruction.h"
 #include "program/program.h"
+#include "util/mesa-sha1.h"
 #include "util/set.h"
 #include "util/string_to_uint_map.h"
 #include "linker.h"
@@ -81,6 +82,7 @@
 #include "ir_rvalue_visitor.h"
 #include "ir_uniform.h"
 #include "builtin_functions.h"
+#include "shader_cache.h"
 
 #include "main/shaderobj.h"
 #include "main/enums.h"
@@ -4619,6 +4621,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       return;
    }
 
+   if (shader_cache_read_program_metadata(ctx, prog))
+      return;
+
    void *mem_ctx = ralloc_context(NULL); // temporary linker context
 
    prog->ARB_fragment_coord_conventions_enable = false;
index ce58fbbd4604231187478333a51b79476e2b4126..67c9267ac09a686a68b9a03a672096d381812eba 100644 (file)
@@ -46,6 +46,7 @@
 #include "compiler/glsl_types.h"
 #include "compiler/glsl/linker.h"
 #include "compiler/glsl/program.h"
+#include "compiler/glsl/shader_cache.h"
 #include "program/prog_instruction.h"
 #include "program/prog_optimize.h"
 #include "program/prog_print.h"
@@ -3114,6 +3115,10 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       }
    }
 
+   /* Return early if we are loading the shader from on-disk cache */
+   if (prog->data->LinkStatus == linking_skipped)
+      return;
+
    if (ctx->_Shader->Flags & GLSL_DUMP) {
       if (!prog->data->LinkStatus) {
         fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name);
@@ -3124,6 +3129,9 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
          fprintf(stderr, "%s\n", prog->data->InfoLog);
       }
    }
+
+   if (prog->data->LinkStatus)
+      shader_cache_write_program_metadata(ctx, prog);
 }
 
 } /* extern "C" */