15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*------------------------------------------------------------------------- 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * drawElements Quality Program OpenGL ES Utilities 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ------------------------------------------------ 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2014 The Android Open Source Project 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * you may not use this file except in compliance with the License. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You may obtain a copy of the License at 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * See the License for the specific language governing permissions and 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * limitations under the License. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *//*! 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * \file 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * \brief Wrapper for GL program object. 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *//*--------------------------------------------------------------------*/ 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "gluShaderProgram.hpp" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "gluRenderContext.hpp" 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "glwFunctions.hpp" 27e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "glwEnums.hpp" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tcuTestLog.hpp" 29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "deClock.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31df95704c49daea886ddad70775bda23618d6274dBen Murdoch#include <cstring> 32df95704c49daea886ddad70775bda23618d6274dBen Murdoch 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using std::string; 347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace glu 365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 38521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Shader 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40df95704c49daea886ddad70775bda23618d6274dBen MurdochShader::Shader (const RenderContext& renderCtx, ShaderType shaderType) 418abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) : m_renderCtx (renderCtx) 428abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) , m_shader (0) 438abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){ 448abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) const glw::Functions& gl = m_renderCtx.getFunctions(); 458abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) 468abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) m_info.type = shaderType; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shader = gl.createShader(getGLShaderType(shaderType)); 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader()"); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TCU_CHECK(m_shader); 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)Shader::~Shader (void) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const glw::Functions& gl = m_renderCtx.getFunctions(); 558abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) gl.deleteShader(m_shader); 568abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)} 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Shader::setSources (int numSourceStrings, const char* const* sourceStrings, const int* lengths) 59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const glw::Functions& gl = m_renderCtx.getFunctions(); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gl.shaderSource(m_shader, numSourceStrings, sourceStrings, lengths); 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_info.source.clear(); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int ndx = 0; ndx < numSourceStrings; ndx++) 675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) { 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const size_t length = lengths && lengths[ndx] >= 0 ? lengths[ndx] : strlen(sourceStrings[ndx]); 69e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) m_info.source += std::string(sourceStrings[ndx], length); 70e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 73e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid Shader::compile (void) 7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const glw::Functions& gl = m_renderCtx.getFunctions(); 7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 778abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) m_info.compileOk = false; 78c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_info.compileTimeUs = 0; 79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_info.infoLog.clear(); 80c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deUint64 compileStart = deGetMicroseconds(); 831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) gl.compileShader(m_shader); 848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) m_info.compileTimeUs = deGetMicroseconds() - compileStart; 85c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()"); 88 89 // Query status & log. 90 { 91 int compileStatus = 0; 92 int infoLogLen = 0; 93 int unusedLen; 94 95 gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus); 96 gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen); 97 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); 98 99 m_info.compileOk = compileStatus != GL_FALSE; 100 101 if (infoLogLen > 0) 102 { 103 std::vector<char> infoLog(infoLogLen); 104 gl.getShaderInfoLog(m_shader, (int)infoLog.size(), &unusedLen, &infoLog[0]); 105 m_info.infoLog = std::string(&infoLog[0], infoLogLen); 106 } 107 } 108} 109 110// Program 111 112static bool getProgramLinkStatus (const RenderContext& renderCtx, deUint32 program) 113{ 114 const glw::Functions& gl = renderCtx.getFunctions(); 115 int linkStatus = 0; 116 117 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus); 118 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); 119 return (linkStatus != GL_FALSE); 120} 121 122static std::string getProgramInfoLog (const RenderContext& renderCtx, deUint32 program) 123{ 124 const glw::Functions& gl = renderCtx.getFunctions(); 125 126 int infoLogLen = 0; 127 int unusedLen; 128 129 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen); 130 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); 131 132 if (infoLogLen > 0) 133 { 134 std::vector<char> infoLog(infoLogLen); 135 gl.getProgramInfoLog(program, (int)infoLog.size(), &unusedLen, &infoLog[0]); 136 return std::string(&infoLog[0], infoLogLen); 137 } 138 return std::string(); 139} 140 141Program::Program (const RenderContext& renderCtx) 142 : m_renderCtx (renderCtx) 143 , m_program (0) 144{ 145 const glw::Functions& gl = m_renderCtx.getFunctions(); 146 147 m_program = gl.createProgram(); 148 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram()"); 149} 150 151Program::Program (const RenderContext& renderCtx, deUint32 program) 152 : m_renderCtx (renderCtx) 153 , m_program (program) 154{ 155 m_info.linkOk = getProgramLinkStatus(renderCtx, program); 156 m_info.infoLog = getProgramInfoLog(renderCtx, program); 157} 158 159Program::~Program (void) 160{ 161 const glw::Functions& gl = m_renderCtx.getFunctions(); 162 gl.deleteProgram(m_program); 163} 164 165void Program::attachShader (deUint32 shader) 166{ 167 const glw::Functions& gl = m_renderCtx.getFunctions(); 168 169 gl.attachShader(m_program, shader); 170 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()"); 171} 172 173void Program::detachShader (deUint32 shader) 174{ 175 const glw::Functions& gl = m_renderCtx.getFunctions(); 176 177 gl.detachShader(m_program, shader); 178 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader()"); 179} 180 181void Program::bindAttribLocation (deUint32 location, const char* name) 182{ 183 const glw::Functions& gl = m_renderCtx.getFunctions(); 184 185 gl.bindAttribLocation(m_program, location, name); 186 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation()"); 187} 188 189void Program::transformFeedbackVaryings (int count, const char* const* varyings, deUint32 bufferMode) 190{ 191 const glw::Functions& gl = m_renderCtx.getFunctions(); 192 193 gl.transformFeedbackVaryings(m_program, count, varyings, bufferMode); 194 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings()"); 195} 196 197void Program::link (void) 198{ 199 const glw::Functions& gl = m_renderCtx.getFunctions(); 200 201 m_info.linkOk = false; 202 m_info.linkTimeUs = 0; 203 m_info.infoLog.clear(); 204 205 { 206 deUint64 linkStart = deGetMicroseconds(); 207 gl.linkProgram(m_program); 208 m_info.linkTimeUs = deGetMicroseconds() - linkStart; 209 } 210 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()"); 211 212 m_info.linkOk = getProgramLinkStatus(m_renderCtx, m_program); 213 m_info.infoLog = getProgramInfoLog(m_renderCtx, m_program); 214} 215 216bool Program::isSeparable (void) const 217{ 218 const glw::Functions& gl = m_renderCtx.getFunctions(); 219 int separable = GL_FALSE; 220 221 gl.getProgramiv(m_program, GL_PROGRAM_SEPARABLE, &separable); 222 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); 223 224 return (separable != GL_FALSE); 225} 226 227void Program::setSeparable (bool separable) 228{ 229 const glw::Functions& gl = m_renderCtx.getFunctions(); 230 231 gl.programParameteri(m_program, GL_PROGRAM_SEPARABLE, separable); 232 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri()"); 233} 234 235// ProgramPipeline 236 237ProgramPipeline::ProgramPipeline (const RenderContext& renderCtx) 238 : m_renderCtx (renderCtx) 239 , m_pipeline (0) 240{ 241 const glw::Functions& gl = m_renderCtx.getFunctions(); 242 243 gl.genProgramPipelines(1, &m_pipeline); 244 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines()"); 245} 246 247ProgramPipeline::~ProgramPipeline (void) 248{ 249 const glw::Functions& gl = m_renderCtx.getFunctions(); 250 gl.deleteProgramPipelines(1, &m_pipeline); 251} 252 253void ProgramPipeline::useProgramStages (deUint32 stages, deUint32 program) 254{ 255 const glw::Functions& gl = m_renderCtx.getFunctions(); 256 257 gl.useProgramStages(m_pipeline, stages, program); 258 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages()"); 259} 260 261void ProgramPipeline::activeShaderProgram (deUint32 program) 262{ 263 const glw::Functions& gl = m_renderCtx.getFunctions(); 264 265 gl.activeShaderProgram(m_pipeline, program); 266 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram()"); 267} 268 269bool ProgramPipeline::isValid (void) 270{ 271 const glw::Functions& gl = m_renderCtx.getFunctions(); 272 glw::GLint status = GL_FALSE; 273 gl.validateProgramPipeline(m_pipeline); 274 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline()"); 275 276 gl.getProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status); 277 278 return (status != GL_FALSE); 279} 280 281// ShaderProgram 282 283ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSources& sources) 284 : m_program(renderCtx) 285{ 286 try 287 { 288 bool shadersOk = true; 289 290 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++) 291 { 292 for (int shaderNdx = 0; shaderNdx < (int)sources.sources[shaderType].size(); ++shaderNdx) 293 { 294 const char* source = sources.sources[shaderType][shaderNdx].c_str(); 295 const int length = (int)sources.sources[shaderType][shaderNdx].size(); 296 297 m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1); 298 299 m_shaders[shaderType].push_back(new Shader(renderCtx, ShaderType(shaderType))); 300 m_shaders[shaderType].back()->setSources(1, &source, &length); 301 m_shaders[shaderType].back()->compile(); 302 303 shadersOk = shadersOk && m_shaders[shaderType].back()->getCompileStatus(); 304 } 305 } 306 307 if (shadersOk) 308 { 309 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++) 310 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx) 311 m_program.attachShader(m_shaders[shaderType][shaderNdx]->getShader()); 312 313 for (std::vector<AttribLocationBinding>::const_iterator binding = sources.attribLocationBindings.begin(); binding != sources.attribLocationBindings.end(); ++binding) 314 m_program.bindAttribLocation(binding->location, binding->name.c_str()); 315 316 DE_ASSERT((sources.transformFeedbackBufferMode == GL_NONE) == sources.transformFeedbackVaryings.empty()); 317 if (sources.transformFeedbackBufferMode != GL_NONE) 318 { 319 std::vector<const char*> tfVaryings(sources.transformFeedbackVaryings.size()); 320 for (int ndx = 0; ndx < (int)tfVaryings.size(); ndx++) 321 tfVaryings[ndx] = sources.transformFeedbackVaryings[ndx].c_str(); 322 323 m_program.transformFeedbackVaryings((int)tfVaryings.size(), &tfVaryings[0], sources.transformFeedbackBufferMode); 324 } 325 326 if (sources.separable) 327 m_program.setSeparable(true); 328 329 m_program.link(); 330 } 331 } 332 catch (...) 333 { 334 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++) 335 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx) 336 delete m_shaders[shaderType][shaderNdx]; 337 throw; 338 } 339} 340 341ShaderProgram::~ShaderProgram (void) 342{ 343 for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++) 344 for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx) 345 delete m_shaders[shaderType][shaderNdx]; 346} 347 348// Utilities 349 350deUint32 getGLShaderType (ShaderType shaderType) 351{ 352 static const deUint32 s_typeMap[] = 353 { 354 GL_VERTEX_SHADER, 355 GL_FRAGMENT_SHADER, 356 GL_GEOMETRY_SHADER, 357 GL_TESS_CONTROL_SHADER, 358 GL_TESS_EVALUATION_SHADER, 359 GL_COMPUTE_SHADER 360 }; 361 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST); 362 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap))); 363 return s_typeMap[shaderType]; 364} 365 366deUint32 getGLShaderTypeBit (ShaderType shaderType) 367{ 368 static const deUint32 s_typebitMap[] = 369 { 370 GL_VERTEX_SHADER_BIT, 371 GL_FRAGMENT_SHADER_BIT, 372 GL_GEOMETRY_SHADER_BIT, 373 GL_TESS_CONTROL_SHADER_BIT, 374 GL_TESS_EVALUATION_SHADER_BIT, 375 GL_COMPUTE_SHADER_BIT 376 }; 377 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typebitMap) == SHADERTYPE_LAST); 378 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typebitMap))); 379 return s_typebitMap[shaderType]; 380} 381 382qpShaderType getLogShaderType (ShaderType shaderType) 383{ 384 static const qpShaderType s_typeMap[] = 385 { 386 QP_SHADER_TYPE_VERTEX, 387 QP_SHADER_TYPE_FRAGMENT, 388 QP_SHADER_TYPE_GEOMETRY, 389 QP_SHADER_TYPE_TESS_CONTROL, 390 QP_SHADER_TYPE_TESS_EVALUATION, 391 QP_SHADER_TYPE_COMPUTE 392 }; 393 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST); 394 DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap))); 395 return s_typeMap[shaderType]; 396} 397 398static tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderInfo& shaderInfo) 399{ 400 return log << tcu::TestLog::Shader(getLogShaderType(shaderInfo.type), shaderInfo.source, shaderInfo.compileOk, shaderInfo.infoLog); 401} 402 403tcu::TestLog& operator<< (tcu::TestLog& log, const Shader& shader) 404{ 405 return log << tcu::TestLog::ShaderProgram(false, "Plain shader") << shader.getInfo() << tcu::TestLog::EndShaderProgram; 406} 407 408tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgram& program) 409{ 410 const ProgramInfo& progInfo = program.getProgramInfo(); 411 412 log << tcu::TestLog::ShaderProgram(progInfo.linkOk, progInfo.infoLog); 413 try 414 { 415 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADERTYPE_LAST; shaderTypeNdx++) 416 { 417 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx; 418 419 for (int shaderNdx = 0; shaderNdx < program.getNumShaders(shaderType); ++shaderNdx) 420 log << program.getShaderInfo(shaderType, shaderNdx); 421 } 422 } 423 catch (...) 424 { 425 log << tcu::TestLog::EndShaderProgram; 426 throw; 427 } 428 log << tcu::TestLog::EndShaderProgram; 429 430 // Write statistics. 431 { 432 static const struct 433 { 434 const char* name; 435 const char* description; 436 } s_compileTimeDesc[] = 437 { 438 { "VertexCompileTime", "Vertex shader compile time" }, 439 { "FragmentCompileTime", "Fragment shader compile time" }, 440 { "GeometryCompileTime", "Geometry shader compile time" }, 441 { "TessControlCompileTime", "Tesselation control shader compile time" }, 442 { "TessEvaluationCompileTime", "Tesselation evaluation shader compile time" }, 443 { "ComputeCompileTime", "Compute shader compile time" }, 444 }; 445 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_compileTimeDesc) == SHADERTYPE_LAST); 446 447 bool allShadersOk = true; 448 449 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADERTYPE_LAST; shaderTypeNdx++) 450 { 451 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx; 452 453 for (int shaderNdx = 0; shaderNdx < program.getNumShaders(shaderType); ++shaderNdx) 454 { 455 const ShaderInfo& shaderInfo = program.getShaderInfo(shaderType, shaderNdx); 456 log << tcu::TestLog::Float(s_compileTimeDesc[shaderType].name, s_compileTimeDesc[shaderType].description, "ms", QP_KEY_TAG_TIME, (float)shaderInfo.compileTimeUs / 1000.0f); 457 allShadersOk = allShadersOk && shaderInfo.compileOk; 458 } 459 } 460 461 if (allShadersOk) 462 log << tcu::TestLog::Float("LinkTime", "Link time", "ms", QP_KEY_TAG_TIME, (float)progInfo.linkTimeUs / 1000.0f); 463 } 464 465 return log; 466} 467 468} // glu 469