CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/GPU/OpenGL/GLSLProgram.cpp
Views: 1401
#include <set>12#include <cstdio>3#include <cstring>4#include <sys/stat.h>56#include "Common/File/VFS/VFS.h"7#include "Common/File/FileUtil.h"8#include "Common/GPU/OpenGL/GLSLProgram.h"910#include "Common/Log.h"1112static std::set<GLSLProgram *> active_programs;1314bool CompileShader(const char *source, GLuint shader, const char *filename, std::string *error_message) {15glShaderSource(shader, 1, &source, NULL);16glCompileShader(shader);17GLint success;18glGetShaderiv(shader, GL_COMPILE_STATUS, &success);19if (!success) {20#define MAX_INFO_LOG_SIZE 204821GLchar infoLog[MAX_INFO_LOG_SIZE];22GLsizei len;23glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);24infoLog[len] = '\0';25ERROR_LOG(Log::G3D, "Error in shader compilation of %s!\n", filename);26ERROR_LOG(Log::G3D, "Info log: %s\n", infoLog);27ERROR_LOG(Log::G3D, "Shader source:\n%s\n", (const char *)source);28if (error_message)29*error_message = infoLog;30return false;31}32return true;33}3435GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src, std::string *error_message) {36GLSLProgram *program = new GLSLProgram();37program->program_ = 0;38program->vsh_ = 0;39program->fsh_ = 0;40program->vshader_source = vshader_src;41program->fshader_source = fshader_src;42strcpy(program->name, "[srcshader]");43strcpy(program->vshader_filename, "");44strcpy(program->fshader_filename, "");45if (glsl_recompile(program, error_message)) {46active_programs.insert(program);47} else {48ERROR_LOG(Log::G3D, "Failed compiling GLSL program from source strings");49delete program;50return 0;51}52return program;53}5455// Not wanting to change ReadLocalFile semantics.56// TODO: Use C++11 unique_ptr, remove delete[]57struct AutoCharArrayBuf {58AutoCharArrayBuf(char *buf = nullptr) : buf_(buf) {59}60~AutoCharArrayBuf() {61delete [] buf_;62buf_ = nullptr;63}64void reset(char *buf) {65delete[] buf_;66buf_ = buf;67}68operator char *() {69return buf_;70}7172private:73char *buf_;74};7576bool glsl_recompile(GLSLProgram *program, std::string *error_message) {77struct stat vs, fs;78AutoCharArrayBuf vsh_src, fsh_src;7980if (strlen(program->vshader_filename) > 0 && 0 == stat(program->vshader_filename, &vs)) {81program->vshader_mtime = vs.st_mtime;82if (!program->vshader_source) {83size_t sz;84vsh_src.reset((char *)File::ReadLocalFile(Path(program->vshader_filename), &sz));85}86} else {87program->vshader_mtime = 0;88}8990if (strlen(program->fshader_filename) > 0 && 0 == stat(program->fshader_filename, &fs)) {91program->fshader_mtime = fs.st_mtime;92if (!program->fshader_source) {93size_t sz;94fsh_src.reset((char *)File::ReadLocalFile(Path(program->fshader_filename), &sz));95}96} else {97program->fshader_mtime = 0;98}99100if (!program->vshader_source && !vsh_src) {101size_t sz;102vsh_src.reset((char *)g_VFS.ReadFile(program->vshader_filename, &sz));103}104if (!program->vshader_source && !vsh_src) {105ERROR_LOG(Log::G3D, "File missing: %s", program->vshader_filename);106if (error_message) {107*error_message = std::string("File missing: ") + program->vshader_filename;108}109return false;110}111if (!program->fshader_source && !fsh_src) {112size_t sz;113fsh_src.reset((char *)g_VFS.ReadFile(program->fshader_filename, &sz));114}115if (!program->fshader_source && !fsh_src) {116ERROR_LOG(Log::G3D, "File missing: %s", program->fshader_filename);117if (error_message) {118*error_message = std::string("File missing: ") + program->fshader_filename;119}120return false;121}122123GLuint vsh = glCreateShader(GL_VERTEX_SHADER);124const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src);125if (!CompileShader(vsh_str, vsh, program->vshader_filename, error_message)) {126return false;127}128129const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src);130GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);131if (!CompileShader(fsh_str, fsh, program->fshader_filename, error_message)) {132glDeleteShader(vsh);133return false;134}135136GLuint prog = glCreateProgram();137glAttachShader(prog, vsh);138glAttachShader(prog, fsh);139140glLinkProgram(prog);141142GLint linkStatus;143glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);144if (linkStatus == GL_FALSE) {145GLint bufLength = 0;146glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);147if (bufLength) {148char* buf = new char[bufLength + 1]; // safety149glGetProgramInfoLog(prog, bufLength, NULL, buf);150INFO_LOG(Log::G3D, "vsh: %i fsh: %i", vsh, fsh);151ERROR_LOG(Log::G3D, "Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf);152if (error_message) {153*error_message = buf;154}155delete [] buf;156} else {157INFO_LOG(Log::G3D, "vsh: %i fsh: %i", vsh, fsh);158ERROR_LOG(Log::G3D, "Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus);159if (error_message) {160*error_message = "(no error message available)";161}162}163glDeleteShader(vsh);164glDeleteShader(fsh);165return false;166}167168// Destroy the old program, if any.169if (program->program_) {170glDeleteProgram(program->program_);171}172173program->program_ = prog;174program->vsh_ = vsh;175program->fsh_ = fsh;176177program->sampler0 = glGetUniformLocation(program->program_, "sampler0");178program->sampler1 = glGetUniformLocation(program->program_, "sampler1");179180program->a_position = glGetAttribLocation(program->program_, "a_position");181program->a_color = glGetAttribLocation(program->program_, "a_color");182program->a_normal = glGetAttribLocation(program->program_, "a_normal");183program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0");184program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1");185186program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj");187program->u_world = glGetUniformLocation(program->program_, "u_world");188program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj");189program->u_fog = glGetUniformLocation(program->program_, "u_fog");190program->u_sundir = glGetUniformLocation(program->program_, "u_sundir");191program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos");192193//INFO_LOG(Log::G3D, "Shader compilation success: %s %s",194// program->vshader_filename,195// program->fshader_filename);196return true;197}198199int glsl_attrib_loc(const GLSLProgram *program, const char *name) {200return glGetAttribLocation(program->program_, name);201}202203int glsl_uniform_loc(const GLSLProgram *program, const char *name) {204return glGetUniformLocation(program->program_, name);205}206207void glsl_destroy(GLSLProgram *program) {208if (program) {209glDeleteShader(program->vsh_);210glDeleteShader(program->fsh_);211glDeleteProgram(program->program_);212active_programs.erase(program);213} else {214ERROR_LOG(Log::G3D, "Deleting null GLSL program!");215}216delete program;217}218219static const GLSLProgram *curProgram;220221void glsl_bind(const GLSLProgram *program) {222if (program)223glUseProgram(program->program_);224else225glUseProgram(0);226curProgram = program;227}228229void glsl_unbind() {230glUseProgram(0);231curProgram = nullptr;232}233234const GLSLProgram *glsl_get_program() {235return curProgram;236}237238239