Mesa (main): mesa/shaderapi: add an optional shader override mechanism

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jun 28 09:30:52 UTC 2021


Module: Mesa
Branch: main
Commit: 11528b621ccdfe40b10d3a9841a7f71f3fd6d848
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=11528b621ccdfe40b10d3a9841a7f71f3fd6d848

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Thu May 27 16:06:15 2021 +0200

mesa/shaderapi: add an optional shader override mechanism

MESA_SHADER_READ_PATH is handy but it's not usable in
all cases.

This commit allows to implement an alternative mechanism
without assuming too much about how it's done, nor where/how
the shaders are stored.

When this is enabled MESA_SHADER_DUMP_PATH,
MESA_SHADER_CAPTURE_PATH and MESA_GLSL env var handling is
disabled.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11621>

---

 meson.build                   |  6 ++++
 meson_options.txt             |  6 ++++
 src/mesa/main/shaderapi.c     | 66 +++++++++++++++++++++++++++++++++++++++++--
 src/mesa/program/prog_print.c |  2 ++
 4 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/meson.build b/meson.build
index 0c0f71ae06a..8d74b96a27b 100644
--- a/meson.build
+++ b/meson.build
@@ -2006,6 +2006,12 @@ else
   dep_lmsensors = null_dep
 endif
 
+_shader_replacement = get_option('custom-shader-replacement')
+if _shader_replacement == ''
+else
+  pre_args += '-DCUSTOM_SHADER_REPLACEMENT'
+endif
+
 with_perfetto = get_option('perfetto')
 with_datasources = get_option('datasources')
 with_any_datasource = with_datasources.length() != 0
diff --git a/meson_options.txt b/meson_options.txt
index 42ea224c95a..9fd9c8a2fd9 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -502,3 +502,9 @@ option(
   choices : ['auto', 'panfrost', 'intel', 'freedreno'],
   description: 'List of Perfetto datasources to build. If this is set to `auto`, datasources that can not be build are skipped. Default: [`auto`]'
 )
+option(
+  'custom-shader-replacement',
+  type : 'string',
+  value : '',
+  description : 'Enable a custom shader replacement mechanism. Note that enabling this option requires adding/generating a shader_replacement.h file that can be included (see shaderapi.c).'
+)
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index dab12e7a1ef..d6d42bd8d5c 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -64,8 +64,47 @@
 #include "util/crc32.h"
 #include "util/os_file.h"
 #include "util/simple_list.h"
+#include "util/u_process.h"
 #include "util/u_string.h"
 
+#ifdef ENABLE_SHADER_CACHE
+#if CUSTOM_SHADER_REPLACEMENT
+#include "shader_replacement.h"
+/* shader_replacement.h must declare a variable like this:
+
+   struct _shader_replacement {
+      // process name. If null, only sha1 is used to match
+      const char *app;
+      // original glsl shader sha1
+      const char *sha1;
+      // shader stage
+      gl_shader_stage stage;
+      ... any other information ...
+   };
+   struct _shader_replacement shader_replacements[...];
+
+   And a method to load a given replacement and return the new
+   glsl source:
+
+   char* load_shader_replacement(struct _shader_replacement *repl);
+
+   shader_replacement.h can be generated at build time, or copied
+   from an external folder, or any other method.
+*/
+#else
+struct _shader_replacement {
+   const char *app;
+   const char *sha1;
+   gl_shader_stage stage;
+};
+struct _shader_replacement shader_replacements[0];
+static char* load_shader_replacement(struct _shader_replacement *repl)
+{
+   return NULL;
+}
+#endif
+#endif
+
 /**
  * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
  */
@@ -78,10 +117,12 @@ _mesa_get_shader_flags(void)
    if (env) {
       if (strstr(env, "dump_on_error"))
          flags |= GLSL_DUMP_ON_ERROR;
+#ifndef CUSTOM_SHADER_REPLACEMENT
       else if (strstr(env, "dump"))
          flags |= GLSL_DUMP;
       if (strstr(env, "log"))
          flags |= GLSL_LOG;
+#endif
       if (strstr(env, "cache_fb"))
          flags |= GLSL_CACHE_FALLBACK;
       if (strstr(env, "cache_info"))
@@ -1342,6 +1383,7 @@ link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
       }
    }
 
+#ifndef CUSTOM_SHADER_REPLACEMENT
    /* Capture .shader_test files. */
    const char *capture_path = _mesa_get_shader_capture_path();
    if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
@@ -1386,6 +1428,7 @@ link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
 
       ralloc_free(filename);
    }
+#endif
 
    if (shProg->data->LinkStatus == LINKING_FAILURE &&
        (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
@@ -1953,6 +1996,7 @@ construct_name(const gl_shader_stage stage, const char *sha,
 void
 _mesa_dump_shader_source(const gl_shader_stage stage, const char *source)
 {
+#ifndef CUSTOM_SHADER_REPLACEMENT
    static bool path_exists = true;
    char *dump_path;
    FILE *f;
@@ -1980,6 +2024,7 @@ _mesa_dump_shader_source(const gl_shader_stage stage, const char *source)
                     strerror(errno));
    }
    ralloc_free(name);
+#endif
 }
 
 /**
@@ -1996,6 +2041,24 @@ _mesa_read_shader_source(const gl_shader_stage stage, const char *source)
    FILE *f;
    char sha[64];
 
+   generate_sha1(source, sha);
+
+   const char *process_name =
+      ARRAY_SIZE(shader_replacements) ? util_get_process_name() : NULL;
+   for (size_t i = 0; i < ARRAY_SIZE(shader_replacements); i++) {
+      if (stage != shader_replacements[i].stage)
+         continue;
+
+      if (shader_replacements[i].app &&
+          strcmp(process_name, shader_replacements[i].app) != 0)
+         continue;
+
+      if (memcmp(sha, shader_replacements[i].sha1, 40) != 0)
+         continue;
+
+      return load_shader_replacement(&shader_replacements[i]);
+   }
+
    if (!path_exists)
       return NULL;
 
@@ -2005,8 +2068,7 @@ _mesa_read_shader_source(const gl_shader_stage stage, const char *source)
       return NULL;
    }
 
-   char *name = construct_name(stage, generate_sha1(source, sha),
-                               source, read_path);
+   char *name = construct_name(stage, sha, source, read_path);
    f = fopen(name, "r");
    ralloc_free(name);
    if (!f)
diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
index 8e9b1def253..6d67eb42f1b 100644
--- a/src/mesa/program/prog_print.c
+++ b/src/mesa/program/prog_print.c
@@ -962,6 +962,7 @@ _mesa_print_parameter_list(const struct gl_program_parameter_list *list)
 void
 _mesa_write_shader_to_file(const struct gl_shader *shader)
 {
+#ifndef CUSTOM_SHADER_REPLACEMENT
    const char *type = "????";
    char filename[100];
    FILE *f;
@@ -1012,6 +1013,7 @@ _mesa_write_shader_to_file(const struct gl_shader *shader)
    }
 
    fclose(f);
+#endif
 }
 
 



More information about the mesa-commit mailing list