diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/util/shader_utils.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/util/shader_utils.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/util/shader_utils.cpp b/Source/ThirdParty/ANGLE/util/shader_utils.cpp new file mode 100644 index 000000000..f92d71570 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/shader_utils.cpp @@ -0,0 +1,191 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "shader_utils.h" + +#include <vector> +#include <iostream> +#include <fstream> + +static std::string ReadFileToString(const std::string &source) +{ + std::ifstream stream(source.c_str()); + if (!stream) + { + std::cerr << "Failed to load shader file: " << source; + return ""; + } + + std::string result; + + stream.seekg(0, std::ios::end); + result.reserve(static_cast<unsigned int>(stream.tellg())); + stream.seekg(0, std::ios::beg); + + result.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); + + return result; +} + +GLuint CompileShader(GLenum type, const std::string &source) +{ + GLuint shader = glCreateShader(type); + + const char *sourceArray[1] = { source.c_str() }; + glShaderSource(shader, 1, sourceArray, NULL); + glCompileShader(shader); + + GLint compileResult; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + + if (compileResult == 0) + { + GLint infoLogLength; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); + + // Info log length includes the null terminator, so 1 means that the info log is an empty + // string. + if (infoLogLength > 1) + { + std::vector<GLchar> infoLog(infoLogLength); + glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), NULL, &infoLog[0]); + std::cerr << "shader compilation failed: " << &infoLog[0]; + } + else + { + std::cerr << "shader compilation failed. <Empty log message>"; + } + + glDeleteShader(shader); + shader = 0; + } + + return shader; +} + +GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath) +{ + std::string source = ReadFileToString(sourcePath); + if (source.empty()) + { + return 0; + } + + return CompileShader(type, source); +} + +GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages) +{ + GLint linkStatus; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus == 0) + { + if (outputErrorMessages) + { + GLint infoLogLength; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); + + // Info log length includes the null terminator, so 1 means that the info log is an + // empty string. + if (infoLogLength > 1) + { + std::vector<GLchar> infoLog(infoLogLength); + glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr, + &infoLog[0]); + + std::cerr << "program link failed: " << &infoLog[0]; + } + else + { + std::cerr << "program link failed. <Empty log message>"; + } + } + + glDeleteProgram(program); + return 0; + } + + return program; +} + +GLuint CompileProgramWithTransformFeedback( + const std::string &vsSource, + const std::string &fsSource, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum bufferMode) +{ + GLuint program = glCreateProgram(); + + GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); + GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); + + if (vs == 0 || fs == 0) + { + glDeleteShader(fs); + glDeleteShader(vs); + glDeleteProgram(program); + return 0; + } + + glAttachShader(program, vs); + glDeleteShader(vs); + + glAttachShader(program, fs); + glDeleteShader(fs); + + if (transformFeedbackVaryings.size() > 0) + { + std::vector<const char *> constCharTFVaryings; + + for (const std::string &transformFeedbackVarying : transformFeedbackVaryings) + { + constCharTFVaryings.push_back(transformFeedbackVarying.c_str()); + } + + glTransformFeedbackVaryings(program, static_cast<GLsizei>(transformFeedbackVaryings.size()), + &constCharTFVaryings[0], bufferMode); + } + + glLinkProgram(program); + + return CheckLinkStatusAndReturnProgram(program, true); +} + +GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource) +{ + std::vector<std::string> emptyVector; + return CompileProgramWithTransformFeedback(vsSource, fsSource, emptyVector, GL_NONE); +} + +GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath) +{ + std::string vsSource = ReadFileToString(vsPath); + std::string fsSource = ReadFileToString(fsPath); + if (vsSource.empty() || fsSource.empty()) + { + return 0; + } + + return CompileProgram(vsSource, fsSource); +} + +GLuint CompileComputeProgram(const std::string &csSource, bool outputErrorMessages) +{ + GLuint program = glCreateProgram(); + + GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource); + if (cs == 0) + { + glDeleteProgram(program); + return 0; + } + + glAttachShader(program, cs); + + glLinkProgram(program); + + return CheckLinkStatusAndReturnProgram(program, outputErrorMessages); +} |