diff options
author | Kenneth Graunke <[email protected]> | 2014-09-06 20:26:51 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2016-06-05 13:48:57 -0700 |
commit | c417c0c9c37f6cdea679e12d84cfc2ab51667cf6 (patch) | |
tree | 678a74b6744ff6e4a992dacab4d120c0aac07d11 /src/mesa | |
parent | 092ec3920f7f9a57fcc1c859a477e891752f5c1f (diff) |
mesa: Add MESA_SHADER_CAPTURE_PATH for writing .shader_test files.
This writes linked shader programs to .shader_test files to
$MESA_SHADER_CAPTURE_PATH in the format used by shader-db
(http://cgit.freedesktop.org/mesa/shader-db).
It supports both GLSL shaders and ARB programs. All stages that
are linked together are written in a single .shader_test file.
This eliminates the need for shader-db's split-to-files.py, as Mesa
produces the desired format directly. It's much more reliable than
parsing stdout/stderr, as those may contain extraneous messages, or
simply be closed by the application and unavailable.
We have many similar features already, but this is a bit different:
- MESA_GLSL=dump writes to stdout, not files.
- MESA_GLSL=log writes each stage to separate files (rather than
all linked shaders in one file), at draw time (not link time),
with uniform data and state flag info.
- Tapani's shader replacement mechanism (MESA_SHADER_DUMP_PATH and
MESA_SHADER_READ_PATH) also uses separate files per shader stage,
but allows reading in files to replace an app's shader code.
v2: Dump ARB programs too, not just GLSL.
v3: Don't dump bogus 0.shader_test file.
v4: Add "GL_ARB_separate_shader_objects" to the [require] block.
v5: Print "GLSL 4.00" instead of "GLSL 4.0" in the [require] block.
v6: Don't hardcode /tmp/mesa.
v7: Fix memoization of getenv().
v8: Also print "SSO ENABLED" (suggested by Timothy).
v9: Also handle ES shaders (suggested by Ilia).
v10: Guard against MESA_SHADER_CAPTURE_PATH being too long; add
_mesa_warning calls on error handling (suggested by Ben).
v11: Fix crash when variable is unset introduced in v10.
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/main/arbprogram.c | 22 | ||||
-rw-r--r-- | src/mesa/main/shaderapi.c | 52 | ||||
-rw-r--r-- | src/mesa/main/shaderapi.h | 3 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/mesa/main/arbprogram.c b/src/mesa/main/arbprogram.c index 3f7acda9f32..c0786d4230d 100644 --- a/src/mesa/main/arbprogram.c +++ b/src/mesa/main/arbprogram.c @@ -36,6 +36,7 @@ #include "main/macros.h" #include "main/mtypes.h" #include "main/arbprogram.h" +#include "main/shaderapi.h" #include "program/arbprogparse.h" #include "program/program.h" #include "program/prog_print.h" @@ -378,6 +379,27 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, } fflush(stderr); } + + /* Capture vp-*.shader_test/fp-*.shader_test files. */ + const char *capture_path = _mesa_get_shader_capture_path(); + if (capture_path != NULL) { + FILE *file; + char filename[PATH_MAX]; + const char *shader_type = + target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; + + _mesa_snprintf(filename, sizeof(filename), "%s/%cp-%u.shader_test", + capture_path, shader_type[0], base->Id); + file = fopen(filename, "w"); + if (file) { + fprintf(file, + "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n", + shader_type, shader_type, (const char *) string); + fclose(file); + } else { + _mesa_warning(ctx, "Failed to open %s", filename); + } + } } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 167e06f3d4f..eb6b1f5a7e8 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -96,6 +96,29 @@ _mesa_get_shader_flags(void) return flags; } +/** + * Memoized version of getenv("MESA_SHADER_CAPTURE_PATH"). + */ +const char * +_mesa_get_shader_capture_path(void) +{ + static bool read_env_var = false; + static const char *path = NULL; + + if (!read_env_var) { + path = getenv("MESA_SHADER_CAPTURE_PATH"); + read_env_var = true; + if (path && + strlen(path) > PATH_MAX - strlen("/fp-4294967295.shader_test")) { + GET_CURRENT_CONTEXT(ctx); + _mesa_warning(ctx, "MESA_SHADER_CAPTURE_PATH too long; ignoring " + "request to capture shaders"); + path = NULL; + } + } + + return path; +} /** * Initialize context's shader state. @@ -1046,6 +1069,35 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg) _mesa_glsl_link_shader(ctx, shProg); + /* Capture .shader_test files. */ + const char *capture_path = _mesa_get_shader_capture_path(); + if (shProg->Name != 0 && capture_path != NULL) { + FILE *file; + char filename[PATH_MAX]; + + _mesa_snprintf(filename, sizeof(filename), "%s/%u.shader_test", + capture_path, shProg->Name); + + file = fopen(filename, "w"); + if (file) { + fprintf(file, "[require]\nGLSL%s >= %u.%02u\n", + shProg->IsES ? " ES" : "", + shProg->Version / 100, shProg->Version % 100); + if (shProg->SeparateShader) + fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n"); + fprintf(file, "\n"); + + for (unsigned i = 0; i < shProg->NumShaders; i++) { + fprintf(file, "[%s shader]\n%s\n", + _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage), + shProg->Shaders[i]->Source); + } + fclose(file); + } else { + _mesa_warning(ctx, "Failed to open %s", filename); + } + } + if (shProg->LinkStatus == GL_FALSE && (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) { _mesa_debug(ctx, "Error linking program %u:\n%s\n", diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index d2d7f16ec7c..09b9525e402 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -43,6 +43,9 @@ struct gl_shader_program; extern GLbitfield _mesa_get_shader_flags(void); +extern const char * +_mesa_get_shader_capture_path(void); + extern void _mesa_copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src); |