--debug-gpu-shader: Dump GLSL shaders to disk
authorDalai Felinto <dfelinto@gmail.com>
Wed, 27 Sep 2017 16:03:00 +0000 (18:03 +0200)
committerDalai Felinto <dfelinto@gmail.com>
Sat, 2 Jun 2018 18:29:27 +0000 (20:29 +0200)
This is really convenient for development. Either for profiling the
generated shaders or to check if the generated code is correct.

It writes the shaders to the temporary blender session folder.

(ported over from blender2.8)

source/blender/blenkernel/BKE_global.h
source/blender/gpu/intern/gpu_shader.c
source/creator/creator_args.c

index ce8de456697403fb9c9dd133ec6b29ab46e9fb4b..45a0a765ce163e3ab3f9f974a300546fcadb8c45 100644 (file)
@@ -143,10 +143,11 @@ enum {
        G_DEBUG_GPU_MEM =   (1 << 15), /* gpu memory in status bar */
        G_DEBUG_GPU =       (1 << 16), /* gpu debug */
        G_DEBUG_IO = (1 << 17),   /* IO Debugging (for Collada, ...)*/
+       G_DEBUG_GPU_SHADERS = (1 << 18),   /* GLSL shaders */
 };
 
 #define G_DEBUG_ALL  (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
-                      G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO)
+                      G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS)
 
 
 /* G.fileflags */
index b579f87698c98d747921f529d587c510bdb2cb2a..d43b2f257e82692beea9ceb8c2c0a41009aabaa9 100644 (file)
@@ -30,7 +30,9 @@
 #include "BLI_utildefines.h"
 #include "BLI_math_base.h"
 #include "BLI_math_vector.h"
+#include "BLI_path_util.h"
 
+#include "BKE_appdir.h"
 #include "BKE_global.h"
 
 #include "GPU_compositing.h"
@@ -259,6 +261,53 @@ GPUShader *GPU_shader_create(const char *vertexcode,
                                    GPU_SHADER_FLAGS_NONE);
 }
 
+#define DEBUG_SHADER_NONE ""
+#define DEBUG_SHADER_VERTEX "vert"
+#define DEBUG_SHADER_FRAGMENT "frag"
+#define DEBUG_SHADER_GEOMETRY "geom"
+
+/**
+ * Dump GLSL shaders to disk
+ *
+ * This is used for profiling shader performance externally and debug if shader code is correct.
+ * If called with no code, it simply bumps the shader index, so different shaders for the same
+ * program share the same index.
+ */
+static void gpu_dump_shaders(const char **code, const int num_shaders, const char *extension)
+{
+       if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) {
+               return;
+       }
+
+       /* We use the same shader index for shaders in the same program.
+        * So we call this function once before calling for the invidual shaders. */
+       static int shader_index = 0;
+       if (code == NULL) {
+               shader_index++;
+               BLI_assert(STREQ(DEBUG_SHADER_NONE, extension));
+               return;
+       }
+
+       /* Determine the full path of the new shader. */
+       char shader_path[FILE_MAX];
+
+       char file_name[512] = {'\0'};
+       sprintf(file_name, "%04d.%s", shader_index, extension);
+
+       BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name);
+
+       /* Write shader to disk. */
+       FILE *f = fopen(shader_path, "w");
+       if (f == NULL) {
+               printf("Error writing to file: %s\n", shader_path);
+       }
+       for (int j = 0; j < num_shaders; j++) {
+               fprintf(f, "%s", code[j]);
+       }
+       fclose(f);
+       printf("Shader file written to disk: %s\n", shader_path);
+}
+
 GPUShader *GPU_shader_create_ex(const char *vertexcode,
                                 const char *fragcode,
                                 const char *geocode,
@@ -290,6 +339,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                return NULL;
 
        shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+       gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
 
        if (vertexcode)
                shader->vertex = glCreateShader(GL_VERTEX_SHADER);
@@ -327,6 +377,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (defines) source[num_source++] = defines;
                source[num_source++] = vertexcode;
 
+               gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX);
+
                glAttachShader(shader->program, shader->vertex);
                glShaderSource(shader->vertex, num_source, source, NULL);
 
@@ -366,6 +418,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (libcode) source[num_source++] = libcode;
                source[num_source++] = fragcode;
 
+               gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT);
+
                glAttachShader(shader->program, shader->fragment);
                glShaderSource(shader->fragment, num_source, source, NULL);
 
@@ -392,6 +446,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (defines) source[num_source++] = defines;
                source[num_source++] = geocode;
 
+               gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY);
+
                glAttachShader(shader->program, shader->geometry);
                glShaderSource(shader->geometry, num_source, source, NULL);
 
@@ -452,6 +508,11 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
        return shader;
 }
 
+#undef DEBUG_SHADER_GEOMETRY
+#undef DEBUG_SHADER_FRAGMENT
+#undef DEBUG_SHADER_VERTEX
+#undef DEBUG_SHADER_NONE
+
 void GPU_shader_bind(GPUShader *shader)
 {
        GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
index 971c2e84780340e8846c9d2f3166dad4a15b9a62..4f2185cae96453c8e25491b1cea847feeee69a24 100644 (file)
@@ -567,6 +567,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
        BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
 
        BLI_argsPrintArgDoc(ba, "--debug-gpumem");
+       BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
        BLI_argsPrintArgDoc(ba, "--debug-wm");
        BLI_argsPrintArgDoc(ba, "--debug-all");
        BLI_argsPrintArgDoc(ba, "--debug-io");
@@ -2022,6 +2023,8 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
                    CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY);
        BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
                    CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
+       BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
+                   CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_SHADERS);
 
        BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", CB(arg_handle_depsgraph_use_new), NULL);
        BLI_argsAdd(ba, 1, NULL, "--enable-new-basic-shader-glsl", CB(arg_handle_basic_shader_glsl_use_new), NULL);