--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>
Wed, 27 Sep 2017 16:03:00 +0000 (18:03 +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.

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

index 790c8051ace72d92cbcd81dcd84a8ef987fd64f7..80a8f750d204aa47be8777fab491e874e4b071f3 100644 (file)
@@ -128,10 +128,11 @@ enum {
        G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11),  /* single threaded depsgraph */
        G_DEBUG_GPU =        (1 << 12), /* gpu debug */
        G_DEBUG_IO = (1 << 13),   /* IO Debugging (for Collada, ...)*/
        G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11),  /* single threaded depsgraph */
        G_DEBUG_GPU =        (1 << 12), /* gpu debug */
        G_DEBUG_IO = (1 << 13),   /* IO Debugging (for Collada, ...)*/
+       G_DEBUG_GPU_SHADERS = (1 << 14),   /* GLSL shaders */
 };
 
 #define G_DEBUG_ALL  (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
 };
 
 #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 */
 
 
 /* G.fileflags */
index 5d5be2ec4ef382c4a857ec7bba60703fe9e0cf3e..7e0848ec071a0acd712e76142848643a882db822 100644 (file)
 #include "BLI_utildefines.h"
 #include "BLI_math_base.h"
 #include "BLI_math_vector.h"
 #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 "BKE_global.h"
 
+#include "DNA_space_types.h"
+
 #include "GPU_compositing.h"
 #include "GPU_extensions.h"
 #include "GPU_matrix.h"
 #include "GPU_compositing.h"
 #include "GPU_extensions.h"
 #include "GPU_matrix.h"
@@ -267,6 +271,53 @@ GPUShader *GPU_shader_create(const char *vertexcode,
                                    GPU_SHADER_FLAGS_NONE);
 }
 
                                    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,
 GPUShader *GPU_shader_create_ex(const char *vertexcode,
                                 const char *fragcode,
                                 const char *geocode,
@@ -288,6 +339,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
        char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
 
        shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
        char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
 
        shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+       gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
 
        if (vertexcode)
                shader->vertex = glCreateShader(GL_VERTEX_SHADER);
 
        if (vertexcode)
                shader->vertex = glCreateShader(GL_VERTEX_SHADER);
@@ -325,6 +377,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (defines) source[num_source++] = defines;
                source[num_source++] = 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);
 
                glAttachShader(shader->program, shader->vertex);
                glShaderSource(shader->vertex, num_source, source, NULL);
 
@@ -364,6 +418,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (libcode) source[num_source++] = libcode;
                source[num_source++] = fragcode;
 
                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);
 
                glAttachShader(shader->program, shader->fragment);
                glShaderSource(shader->fragment, num_source, source, NULL);
 
@@ -390,6 +446,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
                if (defines) source[num_source++] = defines;
                source[num_source++] = geocode;
 
                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);
 
                glAttachShader(shader->program, shader->geometry);
                glShaderSource(shader->geometry, num_source, source, NULL);
 
@@ -452,6 +510,11 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
        return shader;
 }
 
        return shader;
 }
 
+#undef DEBUG_SHADER_GEOMETRY
+#undef DEBUG_SHADER_FRAGMENT
+#undef DEBUG_SHADER_VERTEX
+#undef DEBUG_SHADER_NONE
+
 void GPU_shader_bind(GPUShader *shader)
 {
        BLI_assert(shader && shader->program);
 void GPU_shader_bind(GPUShader *shader)
 {
        BLI_assert(shader && shader->program);
index 52a9165bbcb38efda03087ba0077797dc5cd096a..c38f19397c344c0d4aa45a3d136e94145ba32701 100644 (file)
@@ -548,6 +548,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-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");
        BLI_argsPrintArgDoc(ba, "--debug-wm");
        BLI_argsPrintArgDoc(ba, "--debug-all");
        BLI_argsPrintArgDoc(ba, "--debug-io");
@@ -1805,6 +1806,8 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
                    CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
        BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
                    CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
                    CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
        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, "--verbose", CB(arg_handle_verbosity_set), NULL);
 
 
        BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);