From d83d3fe98e826e0bd924fd7de349401e1a1f54dc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 29 Sep 2016 11:11:55 -0700 Subject: [PATCH] Make shader compilation from non-GPU code easier --- libraries/gl/src/gl/GLShaders.cpp | 189 +++++++++++++++++++++++ libraries/gl/src/gl/GLShaders.h | 29 ++++ libraries/gpu-gl/src/gpu/gl/GLShader.cpp | 10 +- libraries/gpu-gl/src/gpu/gl/GLShared.cpp | 181 ---------------------- libraries/gpu-gl/src/gpu/gl/GLShared.h | 2 - 5 files changed, 226 insertions(+), 185 deletions(-) create mode 100644 libraries/gl/src/gl/GLShaders.cpp create mode 100644 libraries/gl/src/gl/GLShaders.h diff --git a/libraries/gl/src/gl/GLShaders.cpp b/libraries/gl/src/gl/GLShaders.cpp new file mode 100644 index 0000000000..b8e1bf7391 --- /dev/null +++ b/libraries/gl/src/gl/GLShaders.cpp @@ -0,0 +1,189 @@ +#include "GLShaders.h" + +#include "GLLogging.h" + +namespace gl { + + +#ifdef SEPARATE_PROGRAM + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject) { +#else + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject) { +#endif + if (shaderSource.empty()) { + qCDebug(glLogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create"; + return false; + } + + // Create the shader object + GLuint glshader = glCreateShader(shaderDomain); + if (!glshader) { + qCDebug(glLogging) << "GLShader::compileShader - failed to create the gl shader object"; + return false; + } + + // Assign the source + const int NUM_SOURCE_STRINGS = 2; + const GLchar* srcstr[] = { defines.c_str(), shaderSource.c_str() }; + glShaderSource(glshader, NUM_SOURCE_STRINGS, srcstr, NULL); + + // Compile ! + glCompileShader(glshader); + + // check if shader compiled + GLint compiled = 0; + glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled); + + // if compilation fails + if (!compiled) { + + // save the source code to a temp file so we can debug easily + /* + std::ofstream filestream; + filestream.open("debugshader.glsl"); + if (filestream.is_open()) { + filestream << srcstr[0]; + filestream << srcstr[1]; + filestream.close(); + } + */ + + GLint infoLength = 0; + glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); + + char* temp = new char[infoLength]; + glGetShaderInfoLog(glshader, infoLength, NULL, temp); + + + /* + filestream.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); + filestream.close(); + } + */ + + qCWarning(glLogging) << "GLShader::compileShader - failed to compile the gl shader object:"; + for (auto s : srcstr) { + qCWarning(glLogging) << s; + } + qCWarning(glLogging) << "GLShader::compileShader - errors:"; + qCWarning(glLogging) << temp; + delete[] temp; + + glDeleteShader(glshader); + return false; + } + + GLuint glprogram = 0; +#ifdef SEPARATE_PROGRAM + // so far so good, program is almost done, need to link: + GLuint glprogram = glCreateProgram(); + if (!glprogram) { + qCDebug(glLogging) << "GLShader::compileShader - failed to create the gl shader & gl program object"; + return false; + } + + glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE); + glAttachShader(glprogram, glshader); + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + + if (!linked) { + /* + // save the source code to a temp file so we can debug easily + std::ofstream filestream; + filestream.open("debugshader.glsl"); + if (filestream.is_open()) { + filestream << shaderSource->source; + filestream.close(); + } + */ + + GLint infoLength = 0; + glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); + + char* temp = new char[infoLength]; + glGetProgramInfoLog(glprogram, infoLength, NULL, temp); + + qCDebug(glLogging) << "GLShader::compileShader - failed to LINK the gl program object :"; + qCDebug(glLogging) << temp; + + /* + filestream.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << String(temp); + filestream.close(); + } + */ + delete[] temp; + + glDeleteShader(glshader); + glDeleteProgram(glprogram); + return false; + } + programObject = glprogram; +#endif + shaderObject = glshader; + return true; +} + +GLuint compileProgram(const std::vector& glshaders) { + // A brand new program: + GLuint glprogram = glCreateProgram(); + if (!glprogram) { + qCDebug(glLogging) << "GLShader::compileProgram - failed to create the gl program object"; + return 0; + } + + // glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); + // Create the program from the sub shaders + for (auto so : glshaders) { + glAttachShader(glprogram, so); + } + + // Link! + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + + if (!linked) { + /* + // save the source code to a temp file so we can debug easily + std::ofstream filestream; + filestream.open("debugshader.glsl"); + if (filestream.is_open()) { + filestream << shaderSource->source; + filestream.close(); + } + */ + + GLint infoLength = 0; + glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); + + char* temp = new char[infoLength]; + glGetProgramInfoLog(glprogram, infoLength, NULL, temp); + + qCDebug(glLogging) << "GLShader::compileProgram - failed to LINK the gl program object :"; + qCDebug(glLogging) << temp; + + /* + filestream.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); + filestream.close(); + } + */ + delete[] temp; + + glDeleteProgram(glprogram); + return 0; + } + + return glprogram; +} + +} diff --git a/libraries/gl/src/gl/GLShaders.h b/libraries/gl/src/gl/GLShaders.h new file mode 100644 index 0000000000..b8c8b6770b --- /dev/null +++ b/libraries/gl/src/gl/GLShaders.h @@ -0,0 +1,29 @@ +// +// Created by Bradley Austin Davis 2016/09/27 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_GLShaders_h +#define hifi_GLShaders_h + +#include "Config.h" + +#include +#include + +namespace gl { +#ifdef SEPARATE_PROGRAM + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject); +#else + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject); +#endif + + GLuint compileProgram(const std::vector& glshaders); + +} + +#endif diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index a2f44b9938..f8d493c25b 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -6,6 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "GLShader.h" +#include + #include "GLBackend.h" using namespace gpu; @@ -68,7 +70,11 @@ GLShader* compileBackendShader(GLBackend& backend, const Shader& shader) { std::string shaderDefines = glslVersion + "\n" + DOMAIN_DEFINES[shader.getType()] + "\n" + VERSION_DEFINES[version]; - bool result = compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram); +#ifdef SEPARATE_PROGRAM + bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram); +#else + bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader); +#endif if (!result) { return nullptr; } @@ -103,7 +109,7 @@ GLShader* compileBackendProgram(GLBackend& backend, const Shader& program) { } } - GLuint glprogram = compileProgram(shaderGLObjects); + GLuint glprogram = ::gl::compileProgram(shaderGLObjects); if (glprogram == 0) { return nullptr; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLShared.cpp b/libraries/gpu-gl/src/gpu/gl/GLShared.cpp index af03da1931..943cb3c7b5 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShared.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShared.cpp @@ -692,187 +692,6 @@ int makeOutputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Sh return 0; //inputsCount; } - -bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject) { - if (shaderSource.empty()) { - qCDebug(gpugllogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create"; - return false; - } - - // Create the shader object - GLuint glshader = glCreateShader(shaderDomain); - if (!glshader) { - qCDebug(gpugllogging) << "GLShader::compileShader - failed to create the gl shader object"; - return false; - } - - // Assign the source - const int NUM_SOURCE_STRINGS = 2; - const GLchar* srcstr[] = { defines.c_str(), shaderSource.c_str() }; - glShaderSource(glshader, NUM_SOURCE_STRINGS, srcstr, NULL); - - // Compile ! - glCompileShader(glshader); - - // check if shader compiled - GLint compiled = 0; - glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled); - - // if compilation fails - if (!compiled) { - - // save the source code to a temp file so we can debug easily - /* - std::ofstream filestream; - filestream.open("debugshader.glsl"); - if (filestream.is_open()) { - filestream << srcstr[0]; - filestream << srcstr[1]; - filestream.close(); - } - */ - - GLint infoLength = 0; - glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); - - char* temp = new char[infoLength]; - glGetShaderInfoLog(glshader, infoLength, NULL, temp); - - - /* - filestream.open("debugshader.glsl.info.txt"); - if (filestream.is_open()) { - filestream << std::string(temp); - filestream.close(); - } - */ - - qCWarning(gpugllogging) << "GLShader::compileShader - failed to compile the gl shader object:"; - for (auto s : srcstr) { - qCWarning(gpugllogging) << s; - } - qCWarning(gpugllogging) << "GLShader::compileShader - errors:"; - qCWarning(gpugllogging) << temp; - delete[] temp; - - glDeleteShader(glshader); - return false; - } - - GLuint glprogram = 0; -#ifdef SEPARATE_PROGRAM - // so far so good, program is almost done, need to link: - GLuint glprogram = glCreateProgram(); - if (!glprogram) { - qCDebug(gpugllogging) << "GLShader::compileShader - failed to create the gl shader & gl program object"; - return false; - } - - glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE); - glAttachShader(glprogram, glshader); - glLinkProgram(glprogram); - - GLint linked = 0; - glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - - if (!linked) { - /* - // save the source code to a temp file so we can debug easily - std::ofstream filestream; - filestream.open("debugshader.glsl"); - if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); - } - */ - - GLint infoLength = 0; - glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); - - char* temp = new char[infoLength]; - glGetProgramInfoLog(glprogram, infoLength, NULL, temp); - - qCDebug(gpugllogging) << "GLShader::compileShader - failed to LINK the gl program object :"; - qCDebug(gpugllogging) << temp; - - /* - filestream.open("debugshader.glsl.info.txt"); - if (filestream.is_open()) { - filestream << String(temp); - filestream.close(); - } - */ - delete[] temp; - - glDeleteShader(glshader); - glDeleteProgram(glprogram); - return false; - } -#endif - - shaderObject = glshader; - programObject = glprogram; - - return true; -} - -GLuint compileProgram(const std::vector& glshaders) { - // A brand new program: - GLuint glprogram = glCreateProgram(); - if (!glprogram) { - qCDebug(gpugllogging) << "GLShader::compileProgram - failed to create the gl program object"; - return 0; - } - - // glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); - // Create the program from the sub shaders - for (auto so : glshaders) { - glAttachShader(glprogram, so); - } - - // Link! - glLinkProgram(glprogram); - - GLint linked = 0; - glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - - if (!linked) { - /* - // save the source code to a temp file so we can debug easily - std::ofstream filestream; - filestream.open("debugshader.glsl"); - if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); - } - */ - - GLint infoLength = 0; - glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); - - char* temp = new char[infoLength]; - glGetProgramInfoLog(glprogram, infoLength, NULL, temp); - - qCDebug(gpugllogging) << "GLShader::compileProgram - failed to LINK the gl program object :"; - qCDebug(gpugllogging) << temp; - - /* - filestream.open("debugshader.glsl.info.txt"); - if (filestream.is_open()) { - filestream << std::string(temp); - filestream.close(); - } - */ - delete[] temp; - - glDeleteProgram(glprogram); - return 0; - } - - return glprogram; -} - - void makeProgramBindings(ShaderObject& shaderObject) { if (!shaderObject.glprogram) { return; diff --git a/libraries/gpu-gl/src/gpu/gl/GLShared.h b/libraries/gpu-gl/src/gpu/gl/GLShared.h index b5dece7cf4..1b2724fe38 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShared.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShared.h @@ -44,8 +44,6 @@ int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers); int makeInputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs); int makeOutputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs); -bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject); -GLuint compileProgram(const std::vector& glshaders); void makeProgramBindings(ShaderObject& shaderObject); enum GLSyncState {