1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Wrapper for GL program object.
22 *//*--------------------------------------------------------------------*/
24 #include "gluShaderProgram.hpp"
25 #include "gluRenderContext.hpp"
26 #include "glwFunctions.hpp"
27 #include "glwEnums.hpp"
28 #include "tcuTestLog.hpp"
40 Shader::Shader (const RenderContext& renderCtx, ShaderType shaderType)
41 : m_gl (renderCtx.getFunctions())
44 m_info.type = shaderType;
45 m_shader = m_gl.createShader(getGLShaderType(shaderType));
46 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
50 Shader::Shader (const glw::Functions& gl, ShaderType shaderType)
54 m_info.type = shaderType;
55 m_shader = m_gl.createShader(getGLShaderType(shaderType));
56 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
60 Shader::~Shader (void)
62 m_gl.deleteShader(m_shader);
65 void Shader::setSources (int numSourceStrings, const char* const* sourceStrings, const int* lengths)
67 m_gl.shaderSource(m_shader, numSourceStrings, sourceStrings, lengths);
68 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glShaderSource()");
70 m_info.source.clear();
71 for (int ndx = 0; ndx < numSourceStrings; ndx++)
73 const size_t length = lengths && lengths[ndx] >= 0 ? lengths[ndx] : strlen(sourceStrings[ndx]);
74 m_info.source += std::string(sourceStrings[ndx], length);
78 void Shader::compile (void)
80 m_info.compileOk = false;
81 m_info.compileTimeUs = 0;
82 m_info.infoLog.clear();
85 deUint64 compileStart = deGetMicroseconds();
86 m_gl.compileShader(m_shader);
87 m_info.compileTimeUs = deGetMicroseconds() - compileStart;
90 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCompileShader()");
92 // Query status & log.
94 int compileStatus = 0;
98 m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus);
99 m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen);
100 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");
102 m_info.compileOk = compileStatus != GL_FALSE;
106 std::vector<char> infoLog(infoLogLen);
107 m_gl.getShaderInfoLog(m_shader, (int)infoLog.size(), &unusedLen, &infoLog[0]);
108 m_info.infoLog = std::string(&infoLog[0], infoLogLen);
115 static bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
119 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
120 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
121 return (linkStatus != GL_FALSE);
124 static std::string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
129 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen);
130 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
134 std::vector<char> infoLog(infoLogLen);
135 gl.getProgramInfoLog(program, (int)infoLog.size(), &unusedLen, &infoLog[0]);
136 return std::string(&infoLog[0], infoLogLen);
138 return std::string();
141 Program::Program (const RenderContext& renderCtx)
142 : m_gl (renderCtx.getFunctions())
145 m_program = m_gl.createProgram();
146 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
149 Program::Program (const glw::Functions& gl)
153 m_program = m_gl.createProgram();
154 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
157 Program::Program (const RenderContext& renderCtx, deUint32 program)
158 : m_gl (renderCtx.getFunctions())
159 , m_program (program)
161 m_info.linkOk = getProgramLinkStatus(m_gl, program);
162 m_info.infoLog = getProgramInfoLog(m_gl, program);
165 Program::~Program (void)
167 m_gl.deleteProgram(m_program);
170 void Program::attachShader (deUint32 shader)
172 m_gl.attachShader(m_program, shader);
173 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glAttachShader()");
176 void Program::detachShader (deUint32 shader)
178 m_gl.detachShader(m_program, shader);
179 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDetachShader()");
182 void Program::bindAttribLocation (deUint32 location, const char* name)
184 m_gl.bindAttribLocation(m_program, location, name);
185 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindAttribLocation()");
188 void Program::transformFeedbackVaryings (int count, const char* const* varyings, deUint32 bufferMode)
190 m_gl.transformFeedbackVaryings(m_program, count, varyings, bufferMode);
191 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTransformFeedbackVaryings()");
194 void Program::link (void)
196 m_info.linkOk = false;
197 m_info.linkTimeUs = 0;
198 m_info.infoLog.clear();
201 deUint64 linkStart = deGetMicroseconds();
202 m_gl.linkProgram(m_program);
203 m_info.linkTimeUs = deGetMicroseconds() - linkStart;
205 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glLinkProgram()");
207 m_info.linkOk = getProgramLinkStatus(m_gl, m_program);
208 m_info.infoLog = getProgramInfoLog(m_gl, m_program);
211 bool Program::isSeparable (void) const
213 int separable = GL_FALSE;
215 m_gl.getProgramiv(m_program, GL_PROGRAM_SEPARABLE, &separable);
216 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetProgramiv()");
218 return (separable != GL_FALSE);
221 void Program::setSeparable (bool separable)
223 m_gl.programParameteri(m_program, GL_PROGRAM_SEPARABLE, separable);
224 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glProgramParameteri()");
229 ProgramPipeline::ProgramPipeline (const RenderContext& renderCtx)
230 : m_gl (renderCtx.getFunctions())
233 m_gl.genProgramPipelines(1, &m_pipeline);
234 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
237 ProgramPipeline::ProgramPipeline (const glw::Functions& gl)
241 m_gl.genProgramPipelines(1, &m_pipeline);
242 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
245 ProgramPipeline::~ProgramPipeline (void)
247 m_gl.deleteProgramPipelines(1, &m_pipeline);
250 void ProgramPipeline::useProgramStages (deUint32 stages, deUint32 program)
252 m_gl.useProgramStages(m_pipeline, stages, program);
253 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgramStages()");
256 void ProgramPipeline::activeShaderProgram (deUint32 program)
258 m_gl.activeShaderProgram(m_pipeline, program);
259 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glActiveShaderProgram()");
262 bool ProgramPipeline::isValid (void)
264 glw::GLint status = GL_FALSE;
265 m_gl.validateProgramPipeline(m_pipeline);
266 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glValidateProgramPipeline()");
268 m_gl.getProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status);
270 return (status != GL_FALSE);
275 ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSources& sources)
276 : m_program(renderCtx.getFunctions())
278 init(renderCtx.getFunctions(), sources);
281 ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramSources& sources)
287 void ShaderProgram::init (const glw::Functions& gl, const ProgramSources& sources)
291 bool shadersOk = true;
293 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
295 for (int shaderNdx = 0; shaderNdx < (int)sources.sources[shaderType].size(); ++shaderNdx)
297 const char* source = sources.sources[shaderType][shaderNdx].c_str();
298 const int length = (int)sources.sources[shaderType][shaderNdx].size();
300 m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1);
302 m_shaders[shaderType].push_back(new Shader(gl, ShaderType(shaderType)));
303 m_shaders[shaderType].back()->setSources(1, &source, &length);
304 m_shaders[shaderType].back()->compile();
306 shadersOk = shadersOk && m_shaders[shaderType].back()->getCompileStatus();
312 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
313 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
314 m_program.attachShader(m_shaders[shaderType][shaderNdx]->getShader());
316 for (std::vector<AttribLocationBinding>::const_iterator binding = sources.attribLocationBindings.begin(); binding != sources.attribLocationBindings.end(); ++binding)
317 m_program.bindAttribLocation(binding->location, binding->name.c_str());
319 DE_ASSERT((sources.transformFeedbackBufferMode == GL_NONE) == sources.transformFeedbackVaryings.empty());
320 if (sources.transformFeedbackBufferMode != GL_NONE)
322 std::vector<const char*> tfVaryings(sources.transformFeedbackVaryings.size());
323 for (int ndx = 0; ndx < (int)tfVaryings.size(); ndx++)
324 tfVaryings[ndx] = sources.transformFeedbackVaryings[ndx].c_str();
326 m_program.transformFeedbackVaryings((int)tfVaryings.size(), &tfVaryings[0], sources.transformFeedbackBufferMode);
329 if (sources.separable)
330 m_program.setSeparable(true);
337 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
338 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
339 delete m_shaders[shaderType][shaderNdx];
344 ShaderProgram::~ShaderProgram (void)
346 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
347 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
348 delete m_shaders[shaderType][shaderNdx];
353 deUint32 getGLShaderType (ShaderType shaderType)
355 static const deUint32 s_typeMap[] =
360 GL_TESS_CONTROL_SHADER,
361 GL_TESS_EVALUATION_SHADER,
364 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
365 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
366 return s_typeMap[shaderType];
369 deUint32 getGLShaderTypeBit (ShaderType shaderType)
371 static const deUint32 s_typebitMap[] =
373 GL_VERTEX_SHADER_BIT,
374 GL_FRAGMENT_SHADER_BIT,
375 GL_GEOMETRY_SHADER_BIT,
376 GL_TESS_CONTROL_SHADER_BIT,
377 GL_TESS_EVALUATION_SHADER_BIT,
378 GL_COMPUTE_SHADER_BIT
380 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typebitMap) == SHADERTYPE_LAST);
381 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typebitMap)));
382 return s_typebitMap[shaderType];
385 qpShaderType getLogShaderType (ShaderType shaderType)
387 static const qpShaderType s_typeMap[] =
389 QP_SHADER_TYPE_VERTEX,
390 QP_SHADER_TYPE_FRAGMENT,
391 QP_SHADER_TYPE_GEOMETRY,
392 QP_SHADER_TYPE_TESS_CONTROL,
393 QP_SHADER_TYPE_TESS_EVALUATION,
394 QP_SHADER_TYPE_COMPUTE
396 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
397 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
398 return s_typeMap[shaderType];
401 static tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderInfo& shaderInfo)
403 return log << tcu::TestLog::Shader(getLogShaderType(shaderInfo.type), shaderInfo.source, shaderInfo.compileOk, shaderInfo.infoLog);
406 tcu::TestLog& operator<< (tcu::TestLog& log, const Shader& shader)
408 return log << tcu::TestLog::ShaderProgram(false, "Plain shader") << shader.getInfo() << tcu::TestLog::EndShaderProgram;
411 tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgram& program)
413 const ProgramInfo& progInfo = program.getProgramInfo();
415 log << tcu::TestLog::ShaderProgram(progInfo.linkOk, progInfo.infoLog);
418 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADERTYPE_LAST; shaderTypeNdx++)
420 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx;
422 for (int shaderNdx = 0; shaderNdx < program.getNumShaders(shaderType); ++shaderNdx)
423 log << program.getShaderInfo(shaderType, shaderNdx);
428 log << tcu::TestLog::EndShaderProgram;
431 log << tcu::TestLog::EndShaderProgram;
438 const char* description;
439 } s_compileTimeDesc[] =
441 { "VertexCompileTime", "Vertex shader compile time" },
442 { "FragmentCompileTime", "Fragment shader compile time" },
443 { "GeometryCompileTime", "Geometry shader compile time" },
444 { "TessControlCompileTime", "Tesselation control shader compile time" },
445 { "TessEvaluationCompileTime", "Tesselation evaluation shader compile time" },
446 { "ComputeCompileTime", "Compute shader compile time" },
448 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_compileTimeDesc) == SHADERTYPE_LAST);
450 bool allShadersOk = true;
452 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADERTYPE_LAST; shaderTypeNdx++)
454 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx;
456 for (int shaderNdx = 0; shaderNdx < program.getNumShaders(shaderType); ++shaderNdx)
458 const ShaderInfo& shaderInfo = program.getShaderInfo(shaderType, shaderNdx);
459 log << tcu::TestLog::Float(s_compileTimeDesc[shaderType].name, s_compileTimeDesc[shaderType].description, "ms", QP_KEY_TAG_TIME, (float)shaderInfo.compileTimeUs / 1000.0f);
460 allShadersOk = allShadersOk && shaderInfo.compileOk;
465 log << tcu::TestLog::Float("LinkTime", "Link time", "ms", QP_KEY_TAG_TIME, (float)progInfo.linkTimeUs / 1000.0f);