[Mesa-dev] [RFC PATCH] mesa: Add MESA_SHADER_CAPTURE_PATH for writing .shader_test files.
Kenneth Graunke
kenneth at whitecape.org
Mon Jan 18 07:05:21 PST 2016
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.
Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
src/mesa/main/arbprogram.c | 20 ++++++++++++++++++++
src/mesa/main/mtypes.h | 1 -
src/mesa/main/shaderapi.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/mesa/main/shaderapi.h | 3 +++
4 files changed, 63 insertions(+), 1 deletion(-)
Hi Felix,
Nothing nearly as cool as apitrace :) It's just a simple patch to write
.shader_test files for any shader programs an application asks us to compile.
My workflow is basically:
$ mkdir /tmp/mesa
$ MESA_SHADER_CAPTURE_PATH=/tmp/mesa <some application>
(this writes a /tmp/mesa
$ cd ~/Projects/shader-db/shaders/...
$ find-duplicates /tmp/mesa/* | grep ^rm | sh
$ mv /tmp/mesa/* .
$ git add .
$ git commit -m 'Import shaders for ...'
where find-duplicates is http://whitecape.org/stuff/find-duplicates
To do this with Steam, you can right click on the game in the library,
click "Properties", then "Set Launch Options", and enter:
MESA_SHADER_CAPTURE_PATH=/tmp/mesa %command%
--Ken
diff --git a/src/mesa/main/arbprogram.c b/src/mesa/main/arbprogram.c
index f474951..f78598c 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"
@@ -373,6 +374,25 @@ _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);
+ }
+ }
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 0992d4d..6d35e41 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2856,7 +2856,6 @@ struct gl_shader_program
#define GLSL_REPORT_ERRORS 0x100 /**< Print compilation errors */
#define GLSL_DUMP_ON_ERROR 0x200 /**< Dump shaders to stderr on compile error */
-
/**
* Context state for GLSL vertex/fragment shaders.
* Extended to support pipeline object
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 126786c..030d9a1 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -96,6 +96,20 @@ _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");
+
+ return path;
+}
/**
* Initialize context's shader state.
@@ -1047,6 +1061,32 @@ link_program(struct gl_context *ctx, GLuint program)
_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 >= %u.%02u\n",
+ shProg->Version / 100, shProg->Version % 100);
+ if (shProg->SeparateShader)
+ fprintf(file, "GL_ARB_separate_shader_objects\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);
+ }
+ }
+
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 fba767b..2ac25d0 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);
--
2.7.0
More information about the mesa-dev
mailing list