[Mesa-dev] [PATCH shaderdb] run: shader program file created via GetProgramBinary (v4)

Dongwon Kim dongwon.kim at intel.com
Fri Mar 16 22:30:45 UTC 2018


With optin '-b', shader-db now generates a shader program binary file
using GetProgramBinary(). This shader program binary can be loaded via
ProgramBinary() to be executed by an application later.

v2: 1. define MAX_LOG_LEN and use it as the size of gl log
    2. define MAX_PROG_SIZE and use it as the max size of extracted
       shader_program
    3. out_file is now pointer allocated by strdup for the file name

v3: 1. automatically using original shader test file's name +  ".bin"
       as a filename for program binary - better way to cover the case
       with batch compilation of many shader test files in the same
       directory
    2. remove --out=<file name> since it is now unnecessary (due to v3-1.)
       to provide custom file name. Instead, option, "--bin", which is
       basically a flag that enables getting program binary as a file.
    3. Now it tries to get the length of binary by reading program's
       GL_PROGRAM_BINARY_LENGTH_OES parameter

v4: 1. '--bin' -> '-b'
    2. stop generating binary program when failing to retrieve the binary
       size
    3. error checking after malloc for binary program
    4. changed some of variable names
    5. several consecutive fprintfs are consolidated
    6. removed MAX_LOG_LEN and MAX_PROG_SIZE

Signed-off-by: Dongwon Kim <dongwon.kim at intel.com>
---
 run.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 78 insertions(+), 3 deletions(-)

diff --git a/run.c b/run.c
index 69e64c7..bcec5ca 100644
--- a/run.c
+++ b/run.c
@@ -356,7 +356,8 @@ const struct platform platforms[] = {
 void print_usage(const char *prog_name)
 {
     fprintf(stderr,
-            "Usage: %s [-d <device>] [-j <max_threads>] [-o <driver>] [-p <platform>] <directories and *.shader_test files>\n",
+            "Usage: %s [-d <device>] [-j <max_threads>] [-o <driver>] "
+            "[-p <platform>] [-b] <directories and *.shader_test files>\n",
             prog_name);
 }
 
@@ -435,10 +436,11 @@ main(int argc, char **argv)
     char device_path[64];
     int device_id = 0;
     int opt;
+    bool generate_prog_bin = 0;
 
     max_threads = omp_get_max_threads();
 
-    while ((opt = getopt(argc, argv, "d:j:o:p:")) != -1) {
+    while ((opt = getopt(argc, argv, "d:j:o:p:b")) != -1) {
         switch(opt) {
         case 'd': {
             char *endptr;
@@ -478,6 +480,9 @@ main(int argc, char **argv)
         case 'j':
             max_threads = atoi(optarg);
             break;
+        case 'b':
+            generate_prog_bin = 1;
+            break;
         default:
             fprintf(stderr, "Unknown option: %x\n", opt);
             print_usage(argv[0]);
@@ -813,18 +818,24 @@ main(int argc, char **argv)
                     const_text = text;
                     GLuint prog = glCreateShaderProgramv(shader[i].type, 1,
                                                          &const_text);
+
+                    if (generate_prog_bin)
+                        fprintf(stderr,
+                                "Currently, program binary generation "
+                                "doesn't support SSO.\n");
+
                     glDeleteProgram(prog);
                     free(text);
                 }
             } else if (type == TYPE_CORE || type == TYPE_COMPAT || type == TYPE_ES) {
                 GLuint prog = glCreateProgram();
+                GLint param;
 
                 for (unsigned i = 0; i < num_shaders; i++) {
                     GLuint s = glCreateShader(shader[i].type);
                     glShaderSource(s, 1, &shader[i].text, &shader[i].length);
                     glCompileShader(s);
 
-                    GLint param;
                     glGetShaderiv(s, GL_COMPILE_STATUS, &param);
                     if (unlikely(!param)) {
                         GLchar log[4096];
@@ -839,6 +850,70 @@ main(int argc, char **argv)
                 }
 
                 glLinkProgram(prog);
+
+                glGetProgramiv(prog, GL_LINK_STATUS, &param);
+                if (unlikely(!param)) {
+                    GLchar log[4096];
+                    GLsizei length;
+                    glGetProgramInfoLog(prog, sizeof(log), &length, log);
+
+                    fprintf(stderr, "ERROR: failed to link progam:\n%s\n",
+                           log);
+                } else if (generate_prog_bin) {
+                    /* generating shader program binary */
+                    char *prog_buf;
+                    GLenum format;
+                    GLsizei length = 0;
+                    FILE *fp;
+
+                    glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &length);
+
+                    if (glGetError() != GL_NO_ERROR) {
+                        fprintf(stderr,
+                                "ERROR: failed to generate a program binary "
+                                "(invalid program size).\n");
+                        continue;
+                    }
+
+                    prog_buf = (char *)malloc(length);
+
+                    if (!prog_buf) {
+                        fprintf(stderr,
+                                "ERROR: failed to generate a program binary "
+                                "(malloc failed)\n");
+                        continue;
+                    }
+
+                    glGetProgramBinary(prog, length, &length, &format, prog_buf);
+                    if (glGetError() != GL_NO_ERROR) {
+                        fprintf(stderr,
+                                "ERROR: failed to generate a program binary "
+                                "(GetProgramBinary failed)\n");
+                        free(prog_buf);
+                        continue;
+                    }
+
+                    char *out_filename = malloc(strlen(current_shader_name) + 4);
+
+                    strncpy(out_filename, current_shader_name,
+                            strlen(current_shader_name) + 1);
+                    out_filename = strcat(out_filename, ".bin");
+
+                    fp = fopen(out_filename, "wb");
+                    fprintf(stdout,
+                            "\nBinary program has been successfully generated for %s.\n"
+                            "\nWriting it to the file.....\n"
+                            "===============================================\n"
+                            "File Name : %s\nFormat : %d\nSize : %d Byte\n"
+                            "===============================================\n\n",
+                            current_shader_name, out_filename, format, length);
+
+                    fwrite(prog_buf, sizeof(char), length, fp);
+                    fclose(fp);
+                    free(out_filename);
+                    free(prog_buf);
+                }
+
                 glDeleteProgram(prog);
             } else {
                 for (unsigned i = 0; i < num_shaders; i++) {
-- 
2.16.2



More information about the mesa-dev mailing list