/** * Given a set of flags, determine whether a shader with these flags exists within the GL_shader vector. If no shader with the requested flags exists, attempt to compile one. * * @param shader_t shader_type variable, a reference to the shader program needed * @param flags Integer variable, holding a combination of SDR_* flags * @return Index into GL_shader, referencing a valid shader, or -1 if shader compilation failed */ int gr_opengl_maybe_create_shader(shader_type shader_t, unsigned int flags) { size_t idx = opengl_get_shader_idx(shader_t, flags); if (idx < GL_shader.size()) return (int)idx; // If we are here, it means we need to compile a new shader return opengl_compile_shader(shader_t, flags); }
/** * Given a set of flags, determine whether a shader with these flags exists within the GL_shader vector. If no shader with the requested flags exists, attempt to compile one. * * @param shader_t shader_type variable, a reference to the shader program needed * @param flags Integer variable, holding a combination of SDR_* flags * @return Index into GL_shader, referencing a valid shader, or -1 if shader compilation failed */ int gr_opengl_maybe_create_shader(shader_type shader_t, unsigned int flags) { size_t idx; size_t max = GL_shader.size(); for (idx = 0; idx < max; idx++) { if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) { return (int)idx; } } // If we are here, it means we need to compile a new shader return opengl_compile_shader(shader_t, flags); }
int opengl_shader_binary_generator(const GLchar ** opengl_vertex_source, const GLchar ** opengl_fragment_source, const GLchar ** opengl_tessellation_control_source, const GLchar ** opengl_tessellation_evaluation_source, const GLchar ** opengl_geometry_source, const char *outputfile) { int i; void *bin_buffer; FILE *f; GLuint opengl_vertex_shader_id = 0; GLuint opengl_tessellation_control_shader_id = 0; GLuint opengl_tessellation_evaluation_shader_id = 0; GLuint opengl_geometry_shader_id = 0; GLuint opengl_fragment_shader_id = 0; GLint status; GLint formats; GLint logLen; GLsizei written; GLint bin_length; if (!opengl_vertex_source || !opengl_fragment_source) return -1; /* Compile shaders */ opengl_vertex_shader_id = opengl_compile_shader(opengl_vertex_source, GL_VERTEX_SHADER); if (opengl_tessellation_control_source) opengl_tessellation_control_shader_id = opengl_compile_shader (opengl_tessellation_control_source, GL_TESS_CONTROL_SHADER); if (opengl_tessellation_evaluation_source) opengl_tessellation_evaluation_shader_id = opengl_compile_shader (opengl_tessellation_evaluation_source, GL_TESS_EVALUATION_SHADER); if (opengl_geometry_source) opengl_geometry_shader_id = opengl_compile_shader(opengl_geometry_source, GL_GEOMETRY_SHADER); opengl_fragment_shader_id = opengl_compile_shader(opengl_fragment_source, GL_FRAGMENT_SHADER); /* Create GL program */ GLuint glprogram = glCreateProgram(); if (glprogram == 0) { fprintf(stderr, "Error creating program object.\n"); exit(1); } /* Attach shaders to program */ glAttachShader(glprogram, opengl_vertex_shader_id); if (opengl_tessellation_control_shader_id != 0) glAttachShader(glprogram, opengl_tessellation_control_shader_id); if (opengl_tessellation_evaluation_shader_id != 0) glAttachShader(glprogram, opengl_tessellation_evaluation_shader_id); if (opengl_geometry_shader_id != 0) glAttachShader(glprogram, opengl_geometry_shader_id); glAttachShader(glprogram, opengl_fragment_shader_id); /* Link */ glProgramParameteri(glprogram, PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); glLinkProgram(glprogram); glGetProgramiv(glprogram, GL_LINK_STATUS, &status); if (status == GL_FALSE) { fprintf(stderr, "Failed to link shader program!\n"); glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char *log = (char *) xmalloc(logLen); glGetProgramInfoLog(glprogram, logLen, &written, log); fprintf(stderr, "Program log: \n%s", log); free(log); exit(1); } } else glUseProgram(glprogram); /* Dump binary */ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats); GLint *binaryFormats = xcalloc(formats, sizeof(GLint)); glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats); for (i = 0; i < formats; i++) printf("Format[%d]=%d\n", i, binaryFormats[i]); glGetProgramiv(glprogram, GL_PROGRAM_BINARY_LENGTH, &bin_length); printf("Shader binary has %d bytes\n", bin_length); bin_buffer = xmalloc(bin_length); f = fopen(outputfile, "wb"); fwrite(bin_buffer, bin_length, 1, f); fclose(f); /* Process generated binary */ if (dump_intermediate) opengl_shader_binary_analyze(outputfile); free(bin_buffer); return 0; }