/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Wrapper for GL program object.
 *//*--------------------------------------------------------------------*/

#include "gluShaderProgram.hpp"
#include "gluRenderContext.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "tcuTestLog.hpp"
#include "deClock.h"

#include <cstring>

using std::string;

namespace glu
{

// Shader

Shader::Shader (const RenderContext& renderCtx, ShaderType shaderType)
	: m_gl		(renderCtx.getFunctions())
	, m_shader	(0)
{
	m_info.type	= shaderType;
	m_shader	= m_gl.createShader(getGLShaderType(shaderType));
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
	TCU_CHECK(m_shader);
}

Shader::Shader (const glw::Functions& gl, ShaderType shaderType)
	: m_gl		(gl)
	, m_shader	(0)
{
	m_info.type	= shaderType;
	m_shader	= m_gl.createShader(getGLShaderType(shaderType));
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
	TCU_CHECK(m_shader);
}

Shader::~Shader (void)
{
	m_gl.deleteShader(m_shader);
}

void Shader::setSources (int numSourceStrings, const char* const* sourceStrings, const int* lengths)
{
	m_gl.shaderSource(m_shader, numSourceStrings, sourceStrings, lengths);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glShaderSource()");

	m_info.source.clear();
	for (int ndx = 0; ndx < numSourceStrings; ndx++)
	{
		const size_t length = lengths && lengths[ndx] >= 0 ? lengths[ndx] : strlen(sourceStrings[ndx]);
		m_info.source += std::string(sourceStrings[ndx], length);
	}
}

void Shader::compile (void)
{
	m_info.compileOk		= false;
	m_info.compileTimeUs	= 0;
	m_info.infoLog.clear();

	{
		deUint64 compileStart = deGetMicroseconds();
		m_gl.compileShader(m_shader);
		m_info.compileTimeUs = deGetMicroseconds() - compileStart;
	}

	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCompileShader()");

	// Query status
	{
		int compileStatus = 0;

		m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus);
		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");

		m_info.compileOk = compileStatus != GL_FALSE;
	}

	// Query log
	{
		int infoLogLen = 0;
		int unusedLen;

		m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen);
		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");

		if (infoLogLen > 0)
		{
			// The INFO_LOG_LENGTH query and the buffer query implementations have
			// very commonly off-by-one errors. Try to work around these issues.

			// add tolerance for off-by-one in log length, buffer write, and for terminator
			std::vector<char> infoLog(infoLogLen + 3, '\0');

			// claim buf size is one smaller to protect from off-by-one writing over buffer bounds
			m_gl.getShaderInfoLog(m_shader, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]);

			if (infoLog[(int)(infoLog.size()) - 1] != '\0')
			{
				// return whole buffer if null terminator was overwritten
				m_info.infoLog = std::string(&infoLog[0], infoLog.size());
			}
			else
			{
				// read as C string. infoLog is guaranteed to be 0-terminated
				m_info.infoLog = std::string(&infoLog[0]);
			}
		}
	}
}

void Shader::specialize (const char* entryPoint, glw::GLuint numSpecializationConstants,
						 const glw::GLuint* constantIndex, const glw::GLuint* constantValue)
{
	m_info.compileOk		= false;
	m_info.compileTimeUs	= 0;
	m_info.infoLog.clear();

	{
		deUint64 compileStart = deGetMicroseconds();
		m_gl.specializeShader(m_shader, entryPoint, numSpecializationConstants, constantIndex, constantValue);
		m_info.compileTimeUs = deGetMicroseconds() - compileStart;
	}

	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glSpecializeShader()");

	// Query status
	{
		int compileStatus = 0;

		m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus);
		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");

		m_info.compileOk = compileStatus != GL_FALSE;
	}

	// Query log
	{
		int infoLogLen = 0;
		int unusedLen;

		m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen);
		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");

		if (infoLogLen > 0)
		{
			// The INFO_LOG_LENGTH query and the buffer query implementations have
			// very commonly off-by-one errors. Try to work around these issues.

			// add tolerance for off-by-one in log length, buffer write, and for terminator
			std::vector<char> infoLog(infoLogLen + 3, '\0');

			// claim buf size is one smaller to protect from off-by-one writing over buffer bounds
			m_gl.getShaderInfoLog(m_shader, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderInfoLog()");

			if (infoLog[(int)(infoLog.size()) - 1] != '\0')
			{
				// return whole buffer if null terminator was overwritten
				m_info.infoLog = std::string(&infoLog[0], infoLog.size());
			}
			else
			{
				// read as C string. infoLog is guaranteed to be 0-terminated
				m_info.infoLog = std::string(&infoLog[0]);
			}
		}
	}
}

// Program

static bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
{
	int	linkStatus				= 0;

	gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
	return (linkStatus != GL_FALSE);
}

static std::string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
{
	int infoLogLen = 0;
	int unusedLen;

	gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");

	if (infoLogLen > 0)
	{
		// The INFO_LOG_LENGTH query and the buffer query implementations have
		// very commonly off-by-one errors. Try to work around these issues.

		// add tolerance for off-by-one in log length, buffer write, and for terminator
		std::vector<char> infoLog(infoLogLen + 3, '\0');

		// claim buf size is one smaller to protect from off-by-one writing over buffer bounds
		gl.getProgramInfoLog(program, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]);

		// return whole buffer if null terminator was overwritten
		if (infoLog[(int)(infoLog.size()) - 1] != '\0')
			return std::string(&infoLog[0], infoLog.size());

		// read as C string. infoLog is guaranteed to be 0-terminated
		return std::string(&infoLog[0]);
	}
	return std::string();
}

Program::Program (const RenderContext& renderCtx)
	: m_gl		(renderCtx.getFunctions())
	, m_program	(0)
{
	m_program = m_gl.createProgram();
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
}

Program::Program (const glw::Functions& gl)
	: m_gl		(gl)
	, m_program	(0)
{
	m_program = m_gl.createProgram();
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
}

Program::Program (const RenderContext& renderCtx, deUint32 program)
	: m_gl		(renderCtx.getFunctions())
	, m_program	(program)
{
	m_info.linkOk	= getProgramLinkStatus(m_gl, program);
	m_info.infoLog	= getProgramInfoLog(m_gl, program);
}

Program::~Program (void)
{
	m_gl.deleteProgram(m_program);
}

void Program::attachShader (deUint32 shader)
{
	m_gl.attachShader(m_program, shader);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glAttachShader()");
}

void Program::detachShader (deUint32 shader)
{
	m_gl.detachShader(m_program, shader);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDetachShader()");
}

void Program::bindAttribLocation (deUint32 location, const char* name)
{
	m_gl.bindAttribLocation(m_program, location, name);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindAttribLocation()");
}

void Program::transformFeedbackVaryings (int count, const char* const* varyings, deUint32 bufferMode)
{
	m_gl.transformFeedbackVaryings(m_program, count, varyings, bufferMode);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTransformFeedbackVaryings()");
}

void Program::link (void)
{
	m_info.linkOk		= false;
	m_info.linkTimeUs	= 0;
	m_info.infoLog.clear();

	{
		deUint64 linkStart = deGetMicroseconds();
		m_gl.linkProgram(m_program);
		m_info.linkTimeUs = deGetMicroseconds() - linkStart;
	}
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glLinkProgram()");

	m_info.linkOk	= getProgramLinkStatus(m_gl, m_program);
	m_info.infoLog	= getProgramInfoLog(m_gl, m_program);
}

bool Program::isSeparable (void) const
{
	int separable = GL_FALSE;

	m_gl.getProgramiv(m_program, GL_PROGRAM_SEPARABLE, &separable);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetProgramiv()");

	return (separable != GL_FALSE);
}

void Program::setSeparable (bool separable)
{
	m_gl.programParameteri(m_program, GL_PROGRAM_SEPARABLE, separable);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glProgramParameteri()");
}

// ProgramPipeline

ProgramPipeline::ProgramPipeline (const RenderContext& renderCtx)
	: m_gl			(renderCtx.getFunctions())
	, m_pipeline	(0)
{
	m_gl.genProgramPipelines(1, &m_pipeline);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
}

ProgramPipeline::ProgramPipeline (const glw::Functions& gl)
	: m_gl			(gl)
	, m_pipeline	(0)
{
	m_gl.genProgramPipelines(1, &m_pipeline);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
}

ProgramPipeline::~ProgramPipeline (void)
{
	m_gl.deleteProgramPipelines(1, &m_pipeline);
}

void ProgramPipeline::useProgramStages (deUint32 stages, deUint32 program)
{
	m_gl.useProgramStages(m_pipeline, stages, program);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgramStages()");
}

void ProgramPipeline::activeShaderProgram (deUint32 program)
{
	m_gl.activeShaderProgram(m_pipeline, program);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glActiveShaderProgram()");
}

bool ProgramPipeline::isValid (void)
{
	glw::GLint status = GL_FALSE;
	m_gl.validateProgramPipeline(m_pipeline);
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glValidateProgramPipeline()");

	m_gl.getProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status);

	return (status != GL_FALSE);
}

// ShaderProgram

ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSources& sources)
	: m_program(renderCtx.getFunctions())
{
	init(renderCtx.getFunctions(), sources);
}

ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramBinaries& binaries)
	: m_program(renderCtx.getFunctions())
{
	init(renderCtx.getFunctions(), binaries);
}

ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramSources& sources)
	: m_program(gl)
{
	init(gl, sources);
}

ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramBinaries& binaries)
	: m_program(gl)
{
	init(gl, binaries);
}

void ShaderProgram::init (const glw::Functions& gl, const ProgramSources& sources)
{
	try
	{
		bool shadersOk = true;

		for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
		{
			for (int shaderNdx = 0; shaderNdx < (int)sources.sources[shaderType].size(); ++shaderNdx)
			{
				const char* source	= sources.sources[shaderType][shaderNdx].c_str();
				const int	length	= (int)sources.sources[shaderType][shaderNdx].size();

				m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1);

				m_shaders[shaderType].push_back(new Shader(gl, ShaderType(shaderType)));
				m_shaders[shaderType].back()->setSources(1, &source, &length);
				m_shaders[shaderType].back()->compile();

				shadersOk = shadersOk && m_shaders[shaderType].back()->getCompileStatus();
			}
		}

		if (shadersOk)
		{
			for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
				for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
					m_program.attachShader(m_shaders[shaderType][shaderNdx]->getShader());

			for (std::vector<AttribLocationBinding>::const_iterator binding = sources.attribLocationBindings.begin(); binding != sources.attribLocationBindings.end(); ++binding)
				m_program.bindAttribLocation(binding->location, binding->name.c_str());

			DE_ASSERT((sources.transformFeedbackBufferMode == GL_NONE) == sources.transformFeedbackVaryings.empty());
			if (sources.transformFeedbackBufferMode != GL_NONE)
			{
				std::vector<const char*> tfVaryings(sources.transformFeedbackVaryings.size());
				for (int ndx = 0; ndx < (int)tfVaryings.size(); ndx++)
					tfVaryings[ndx] = sources.transformFeedbackVaryings[ndx].c_str();

				m_program.transformFeedbackVaryings((int)tfVaryings.size(), &tfVaryings[0], sources.transformFeedbackBufferMode);
			}

			if (sources.separable)
				m_program.setSeparable(true);

			m_program.link();
		}
	}
	catch (...)
	{
		for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
			for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
				delete m_shaders[shaderType][shaderNdx];
		throw;
	}
}

void ShaderProgram::init (const glw::Functions& gl, const ProgramBinaries& binaries)
{
	try
	{
		bool shadersOk = true;

		for (deUint32 binaryNdx = 0; binaryNdx < binaries.binaries.size(); ++binaryNdx)
		{
			ShaderBinary shaderBinary = binaries.binaries[binaryNdx];
			if (!shaderBinary.binary.empty())
			{
				const char* binary	= (const char*)shaderBinary.binary.data();
				const int	length	= (int)(shaderBinary.binary.size() * sizeof(deUint32));

				DE_ASSERT(shaderBinary.shaderEntryPoints.size() == shaderBinary.shaderTypes.size());

				std::vector<Shader*> shaders;
				for (deUint32 shaderTypeNdx = 0; shaderTypeNdx < shaderBinary.shaderTypes.size(); ++shaderTypeNdx)
				{
					ShaderType shaderType = shaderBinary.shaderTypes[shaderTypeNdx];

					Shader* shader = new Shader(gl, ShaderType(shaderType));

					m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1);
					m_shaders[shaderType].push_back(shader);
					shaders.push_back(shader);
				}

				setBinary(gl, shaders, binaries.binaryFormat, binary, length);

				for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
				{
					shaders[shaderNdx]->specialize(shaderBinary.shaderEntryPoints[shaderNdx].c_str(),
												   (deUint32)shaderBinary.specializationIndices.size(),
												   shaderBinary.specializationIndices.data(),
												   shaderBinary.specializationValues.data());

					shadersOk = shadersOk && shaders[shaderNdx]->getCompileStatus();
				}
			}
		}

		if (shadersOk)
		{
			for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
				for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
					m_program.attachShader(m_shaders[shaderType][shaderNdx]->getShader());

			m_program.link();
		}
	}
	catch (...)
	{
		for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
			for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
				delete m_shaders[shaderType][shaderNdx];
		throw;
	}
}

void ShaderProgram::setBinary (const glw::Functions& gl, std::vector<Shader*>& shaders, glw::GLenum binaryFormat, const void* binaryData, const int length)
{
	std::vector<glw::GLuint> shaderVec;
	for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
		shaderVec.push_back(shaders[shaderNdx]->getShader());

	gl.shaderBinary((glw::GLsizei)shaderVec.size(), shaderVec.data(), binaryFormat, binaryData, length);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderBinary");

	for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
	{
		glw::GLint shaderState;
		gl.getShaderiv(shaders[shaderNdx]->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
		GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");

		DE_ASSERT(shaderState == GL_TRUE);
	}
}

ShaderProgram::~ShaderProgram (void)
{
	for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
		for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
			delete m_shaders[shaderType][shaderNdx];
}

// Utilities

deUint32 getGLShaderType (ShaderType shaderType)
{
	static const deUint32 s_typeMap[] =
	{
		GL_VERTEX_SHADER,
		GL_FRAGMENT_SHADER,
		GL_GEOMETRY_SHADER,
		GL_TESS_CONTROL_SHADER,
		GL_TESS_EVALUATION_SHADER,
		GL_COMPUTE_SHADER
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
	return s_typeMap[shaderType];
}

deUint32 getGLShaderTypeBit (ShaderType shaderType)
{
	static const deUint32 s_typebitMap[] =
	{
		GL_VERTEX_SHADER_BIT,
		GL_FRAGMENT_SHADER_BIT,
		GL_GEOMETRY_SHADER_BIT,
		GL_TESS_CONTROL_SHADER_BIT,
		GL_TESS_EVALUATION_SHADER_BIT,
		GL_COMPUTE_SHADER_BIT
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typebitMap) == SHADERTYPE_LAST);
	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typebitMap)));
	return s_typebitMap[shaderType];
}

qpShaderType getLogShaderType (ShaderType shaderType)
{
	static const qpShaderType s_typeMap[] =
	{
		QP_SHADER_TYPE_VERTEX,
		QP_SHADER_TYPE_FRAGMENT,
		QP_SHADER_TYPE_GEOMETRY,
		QP_SHADER_TYPE_TESS_CONTROL,
		QP_SHADER_TYPE_TESS_EVALUATION,
		QP_SHADER_TYPE_COMPUTE
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
	return s_typeMap[shaderType];
}

tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderInfo& shaderInfo)
{
	return log << tcu::TestLog::Shader(getLogShaderType(shaderInfo.type), shaderInfo.source, shaderInfo.compileOk, shaderInfo.infoLog);
}

tcu::TestLog& operator<< (tcu::TestLog& log, const Shader& shader)
{
	return log << tcu::TestLog::ShaderProgram(false, "Plain shader") << shader.getInfo() << tcu::TestLog::EndShaderProgram;
}

static void logShaderProgram (tcu::TestLog& log, const ProgramInfo& programInfo, size_t numShaders, const ShaderInfo* const* shaderInfos)
{
	log << tcu::TestLog::ShaderProgram(programInfo.linkOk, programInfo.infoLog);
	try
	{
		for (size_t shaderNdx = 0; shaderNdx < numShaders; ++shaderNdx)
			log << *shaderInfos[shaderNdx];
	}
	catch (...)
	{
		log << tcu::TestLog::EndShaderProgram;
		throw;
	}
	log << tcu::TestLog::EndShaderProgram;

	// Write statistics.
	{
		static const struct
		{
			const char*		name;
			const char*		description;
		} s_compileTimeDesc[] =
		{
			{ "VertexCompileTime",			"Vertex shader compile time"					},
			{ "FragmentCompileTime",		"Fragment shader compile time"					},
			{ "GeometryCompileTime",		"Geometry shader compile time"					},
			{ "TessControlCompileTime",		"Tesselation control shader compile time"		},
			{ "TessEvaluationCompileTime",	"Tesselation evaluation shader compile time"	},
			{ "ComputeCompileTime",			"Compute shader compile time"					},
		};
		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_compileTimeDesc) == SHADERTYPE_LAST);

		bool allShadersOk = true;

		for (size_t shaderNdx = 0; shaderNdx < numShaders; ++shaderNdx)
		{
			const ShaderInfo&	shaderInfo	= *shaderInfos[shaderNdx];

			log << tcu::TestLog::Float(s_compileTimeDesc[shaderInfo.type].name,
									   s_compileTimeDesc[shaderInfo.type].description,
									   "ms", QP_KEY_TAG_TIME, (float)shaderInfo.compileTimeUs / 1000.0f);

			allShadersOk = allShadersOk && shaderInfo.compileOk;
		}

		if (allShadersOk)
			log << tcu::TestLog::Float("LinkTime", "Link time", "ms", QP_KEY_TAG_TIME, (float)programInfo.linkTimeUs / 1000.0f);
	}
}

tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgramInfo& shaderProgramInfo)
{
	std::vector<const ShaderInfo*>	shaderPtrs	(shaderProgramInfo.shaders.size());

	for (size_t ndx = 0; ndx < shaderPtrs.size(); ndx++)
		shaderPtrs[ndx] = &shaderProgramInfo.shaders[ndx];

	logShaderProgram(log, shaderProgramInfo.program, shaderPtrs.size(), shaderPtrs.empty() ? DE_NULL : &shaderPtrs[0]);

	return log;
}

tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgram& shaderProgram)
{
	std::vector<const ShaderInfo*>	shaderPtrs;

	for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
	{
		for (int shaderNdx = 0; shaderNdx < shaderProgram.getNumShaders((ShaderType)shaderType); shaderNdx++)
			shaderPtrs.push_back(&shaderProgram.getShaderInfo((ShaderType)shaderType, shaderNdx));
	}

	logShaderProgram(log, shaderProgram.getProgramInfo(), shaderPtrs.size(), shaderPtrs.empty() ? DE_NULL : &shaderPtrs[0]);

	return log;
}

tcu::TestLog& operator<< (tcu::TestLog& log, const ProgramSources& sources)
{
	log << tcu::TestLog::ShaderProgram(false, "(Source only)");

	try
	{
		for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
		{
			for (size_t shaderNdx = 0; shaderNdx < sources.sources[shaderType].size(); shaderNdx++)
			{
				log << tcu::TestLog::Shader(getLogShaderType((ShaderType)shaderType),
											sources.sources[shaderType][shaderNdx],
											false, "");
			}
		}
	}
	catch (...)
	{
		log << tcu::TestLog::EndShaderProgram;
		throw;
	}

	log << tcu::TestLog::EndShaderProgram;

	return log;
}

} // glu
