2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
7 #include "shader_utils.h"
13 static std::string ReadFileToString(const std::string &source)
15 std::ifstream stream(source.c_str());
18 std::cerr << "Failed to load shader file: " << source;
24 stream.seekg(0, std::ios::end);
25 result.reserve(static_cast<unsigned int>(stream.tellg()));
26 stream.seekg(0, std::ios::beg);
28 result.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
33 GLuint CompileShader(GLenum type, const std::string &source)
35 GLuint shader = glCreateShader(type);
37 const char *sourceArray[1] = { source.c_str() };
38 glShaderSource(shader, 1, sourceArray, nullptr);
39 glCompileShader(shader);
42 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
44 if (compileResult == 0)
47 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
49 // Info log length includes the null terminator, so 1 means that the info log is an empty
51 if (infoLogLength > 1)
53 std::vector<GLchar> infoLog(infoLogLength);
54 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
55 std::cerr << "shader compilation failed: " << &infoLog[0];
59 std::cerr << "shader compilation failed. <Empty log message>";
62 std::cerr << std::endl;
64 glDeleteShader(shader);
71 GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
73 std::string source = ReadFileToString(sourcePath);
79 return CompileShader(type, source);
82 GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
84 if (glGetError() != GL_NO_ERROR)
88 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
91 if (outputErrorMessages)
94 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
96 // Info log length includes the null terminator, so 1 means that the info log is an
98 if (infoLogLength > 1)
100 std::vector<GLchar> infoLog(infoLogLength);
101 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
104 std::cerr << "program link failed: " << &infoLog[0];
108 std::cerr << "program link failed. <Empty log message>";
112 glDeleteProgram(program);
119 GLuint CompileProgramWithTransformFeedback(
120 const std::string &vsSource,
121 const std::string &fsSource,
122 const std::vector<std::string> &transformFeedbackVaryings,
125 return CompileProgramWithGSAndTransformFeedback(vsSource, "", fsSource,
126 transformFeedbackVaryings, bufferMode);
129 GLuint CompileProgramWithGSAndTransformFeedback(
130 const std::string &vsSource,
131 const std::string &gsSource,
132 const std::string &fsSource,
133 const std::vector<std::string> &transformFeedbackVaryings,
136 GLuint program = glCreateProgram();
138 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
139 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
141 if (vs == 0 || fs == 0)
145 glDeleteProgram(program);
149 glAttachShader(program, vs);
152 glAttachShader(program, fs);
155 if (!gsSource.empty())
157 GLuint gs = CompileShader(GL_GEOMETRY_SHADER_EXT, gsSource);
162 glDeleteProgram(program);
166 glAttachShader(program, gs);
170 if (transformFeedbackVaryings.size() > 0)
172 std::vector<const char *> constCharTFVaryings;
174 for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
176 constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
179 glTransformFeedbackVaryings(program, static_cast<GLsizei>(transformFeedbackVaryings.size()),
180 &constCharTFVaryings[0], bufferMode);
183 glLinkProgram(program);
185 return CheckLinkStatusAndReturnProgram(program, true);
188 GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
190 return CompileProgramWithGS(vsSource, "", fsSource);
193 GLuint CompileProgramWithGS(const std::string &vsSource,
194 const std::string &gsSource,
195 const std::string &fsSource)
197 std::vector<std::string> emptyVector;
198 return CompileProgramWithGSAndTransformFeedback(vsSource, gsSource, fsSource, emptyVector,
202 GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
204 std::string vsSource = ReadFileToString(vsPath);
205 std::string fsSource = ReadFileToString(fsPath);
206 if (vsSource.empty() || fsSource.empty())
211 return CompileProgram(vsSource, fsSource);
214 GLuint CompileComputeProgram(const std::string &csSource, bool outputErrorMessages)
216 GLuint program = glCreateProgram();
218 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
221 glDeleteProgram(program);
225 glAttachShader(program, cs);
227 glLinkProgram(program);
229 return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
232 GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
234 GLuint program = glCreateProgram();
235 glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
236 return CheckLinkStatusAndReturnProgram(program, true);
239 GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
241 GLuint program = glCreateProgram();
242 glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
243 return CheckLinkStatusAndReturnProgram(program, true);
246 bool LinkAttachedProgram(GLuint program)
248 glLinkProgram(program);
249 return (CheckLinkStatusAndReturnProgram(program, true) != 0);