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 }