13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Fragment shader output tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \todo [2012-04-10 pyry] Missing:
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  + non-contiguous attachments in framebuffer
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fFragmentOutputTests.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexture.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// For getFormatName() \todo [pyry] Move to glu?
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fFboTestUtil.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec2;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec4;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::BVec4;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing FboTestUtil::getFormatName;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing FboTestUtil::getFramebufferReadFormat;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BufferSpec
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferSpec (void)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: format	(GL_NONE)
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, width		(0)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, height	(0)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, samples	(0)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferSpec (deUint32 format_, int width_, int height_, int samples_)
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: format	(format_)
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, width		(width_)
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, height	(height_)
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, samples	(samples_)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	format;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			width;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			height;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			samples;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct FragmentOutput
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentOutput (void)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: type			(glu::TYPE_LAST)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, precision		(glu::PRECISION_LAST)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, location		(0)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, arrayLength	(0)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentOutput (glu::DataType type_, glu::Precision precision_, int location_, int arrayLength_ = 0)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: type			(type_)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, precision		(precision_)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, location		(location_)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, arrayLength	(arrayLength_)
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType	type;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision	precision;
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				location;
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				arrayLength;	//!< 0 if not an array.
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct OutputVec
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<FragmentOutput> outputs;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OutputVec& operator<< (const FragmentOutput& output)
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs.push_back(output);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return *this;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<FragmentOutput> toVec (void) const
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return outputs;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FragmentOutputCase : public TestCase
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								FragmentOutputCase			(Context& context, const char* name, const char* desc, const vector<BufferSpec>& fboSpec, const vector<FragmentOutput>& outputs);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~FragmentOutputCase			(void);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit						(void);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								FragmentOutputCase			(const FragmentOutputCase& other);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FragmentOutputCase&			operator=					(const FragmentOutputCase& other);
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<BufferSpec>			m_fboSpec;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<FragmentOutput>		m_outputs;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*			m_program;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					m_framebuffer;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>			m_renderbuffers;
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentOutputCase::FragmentOutputCase (Context& context, const char* name, const char* desc, const vector<BufferSpec>& fboSpec, const vector<FragmentOutput>& outputs)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, desc)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_fboSpec		(fboSpec)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_outputs		(outputs)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program		(DE_NULL)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_framebuffer	(0)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentOutputCase::~FragmentOutputCase (void)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::ShaderProgram* createProgram (const glu::RenderContext& context, const vector<FragmentOutput>& outputs)
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	vtx;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	frag;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "#version 300 es\n"
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in highp vec4 a_position;\n";
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "#version 300 es\n";
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Input-output declarations.
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int outNdx = 0; outNdx < (int)outputs.size(); outNdx++)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const FragmentOutput&	output		= outputs[outNdx];
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isArray		= output.arrayLength > 0;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				typeName	= glu::getDataTypeName(output.type);
184c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos		const char*				outputPrec	= glu::getPrecisionName(output.precision);
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isFloat		= glu::isDataTypeFloatOrVec(output.type);
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				interp		= isFloat ? "smooth" : "flat";
187c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos		const char*				interpPrec	= isFloat ? "highp" : outputPrec;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isArray)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int elemNdx = 0; elemNdx < output.arrayLength; elemNdx++)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
193c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				vtx << "in " << interpPrec << " " << typeName << " in" << outNdx << "_" << elemNdx << ";\n"
194c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos					<< interp << " out " << interpPrec << " " << typeName << " var" << outNdx << "_" << elemNdx << ";\n";
195c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				frag << interp << " in " << interpPrec << " " << typeName << " var" << outNdx << "_" << elemNdx << ";\n";
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
197c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos			frag << "layout(location = " << output.location << ") out " << outputPrec << " " << typeName << " out" << outNdx << "[" << output.arrayLength << "];\n";
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
201c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos			vtx << "in " << interpPrec << " " << typeName << " in" << outNdx << ";\n"
202c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				<< interp << " out " << interpPrec << " " << typeName << " var" << outNdx << ";\n";
203c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos			frag << interp << " in " << interpPrec << " " << typeName << " var" << outNdx << ";\n"
204c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				 << "layout(location = " << output.location << ") out " << outputPrec << " " << typeName << " out" << outNdx << ";\n";
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "\nvoid main()\n{\n";
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "\nvoid main()\n{\n";
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "	gl_Position = a_position;\n";
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Copy body
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int outNdx = 0; outNdx < (int)outputs.size(); outNdx++)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const FragmentOutput&	output		= outputs[outNdx];
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isArray		= output.arrayLength > 0;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isArray)
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int elemNdx = 0; elemNdx < output.arrayLength; elemNdx++)
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				vtx << "\tvar" << outNdx << "_" << elemNdx << " = in" << outNdx << "_" << elemNdx << ";\n";
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				frag << "\tout" << outNdx << "[" << elemNdx << "] = var" << outNdx << "_" << elemNdx << ";\n";
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vtx << "\tvar" << outNdx << " = in" << outNdx << ";\n";
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frag << "\tout" << outNdx << " = var" << outNdx << ";\n";
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vtx << "}\n";
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	frag << "}\n";
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str()));
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FragmentOutputCase::init (void)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log		= m_testCtx.getLog();
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check that all attachments are supported
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<BufferSpec>::const_iterator bufIter = m_fboSpec.begin(); bufIter != m_fboSpec.end(); ++bufIter)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!glu::isSizedFormatColorRenderable(m_context.getRenderContext(), m_context.getContextInfo(), bufIter->format))
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError("Unsupported attachment format");
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = createProgram(m_context.getRenderContext(), m_outputs);
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << *m_program;
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Compile failed");
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Print render target info to log.
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::Section("Framebuffer", "Framebuffer configuration");
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)m_fboSpec.size(); ndx++)
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "COLOR_ATTACHMENT" << ndx << ": "
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< glu::getPixelFormatStr(m_fboSpec[ndx].format) << ", "
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< m_fboSpec[ndx].width << "x" << m_fboSpec[ndx].height << ", "
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								<< m_fboSpec[ndx].samples << " samples"
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::EndMessage;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndSection;
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create framebuffer.
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_renderbuffers.resize(m_fboSpec.size(), 0);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genFramebuffers(1, &m_framebuffer);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genRenderbuffers((int)m_renderbuffers.size(), &m_renderbuffers[0]);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int bufNdx = 0; bufNdx < (int)m_renderbuffers.size(); bufNdx++)
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32			rbo			= m_renderbuffers[bufNdx];
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferSpec&	bufSpec		= m_fboSpec[bufNdx];
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32			attachment	= GL_COLOR_ATTACHMENT0+bufNdx;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.renderbufferStorageMultisample(GL_RENDERBUFFER, bufSpec.samples, bufSpec.format, bufSpec.width, bufSpec.height);
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo);
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After framebuffer setup");
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 fboStatus = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (fboStatus == GL_FRAMEBUFFER_UNSUPPORTED)
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Framebuffer not supported", "", __FILE__, __LINE__);
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError((string("Incomplete framebuffer: ") + glu::getFramebufferStatusStr(fboStatus).toString()).c_str(), "", __FILE__, __LINE__);
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After init");
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FragmentOutputCase::deinit (void)
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_framebuffer)
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteFramebuffers(1, &m_framebuffer);
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_framebuffer = 0;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_renderbuffers.empty())
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.deleteRenderbuffers((int)m_renderbuffers.size(), &m_renderbuffers[0]);
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_renderbuffers.clear();
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic IVec2 getMinSize (const vector<BufferSpec>& fboSpec)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec2 minSize(0x7fffffff, 0x7fffffff);
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<BufferSpec>::const_iterator i = fboSpec.begin(); i != fboSpec.end(); i++)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		minSize.x() = de::min(minSize.x(), i->width);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		minSize.y() = de::min(minSize.y(), i->height);
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return minSize;
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumInputVectors (const vector<FragmentOutput>& outputs)
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numVecs = 0;
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<FragmentOutput>::const_iterator i = outputs.begin(); i != outputs.end(); i++)
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numVecs += (i->arrayLength > 0 ? i->arrayLength : 1);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numVecs;
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic Vec2 getFloatRange (glu::Precision precision)
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-04-09 pyry] Not quite the full ranges.
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const Vec2 ranges[] =
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(-2.0f, 2.0f),
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(-16000.0f, 16000.0f),
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2(-1e35f, 1e35f)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ranges[precision];
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic IVec2 getIntRange (glu::Precision precision)
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const IVec2 ranges[] =
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVec2(-(1<< 7), (1<< 7)-1),
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVec2(-(1<<15), (1<<15)-1),
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVec2(0x80000000, 0x7fffffff)
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ranges[precision];
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic UVec2 getUintRange (glu::Precision precision)
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const UVec2 ranges[] =
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UVec2(0, (1<< 8)-1),
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UVec2(0, (1<<16)-1),
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UVec2(0, 0xffffffffu)
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ranges[precision];
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline Vec4 readVec4 (const float* ptr, int numComponents)
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numComponents >= 1);
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Vec4(ptr[0],
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numComponents >= 2 ? ptr[1] : 0.0f,
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numComponents >= 3 ? ptr[2] : 0.0f,
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numComponents >= 4 ? ptr[3] : 0.0f);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline IVec4 readIVec4 (const int* ptr, int numComponents)
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numComponents >= 1);
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return IVec4(ptr[0],
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 numComponents >= 2 ? ptr[1] : 0,
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 numComponents >= 3 ? ptr[2] : 0,
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 numComponents >= 4 ? ptr[3] : 0);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void renderFloatReference (const tcu::PixelBufferAccess& dst, int gridWidth, int gridHeight, int numComponents, const float* vertices)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39989a729134d6a1880d2b59426dfe14d615381e314Jarkko Pöyry	const bool	isSRGB		= tcu::isSRGB(dst.getFormat());
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float	cellW		= (float)dst.getWidth() / (float)(gridWidth-1);
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float	cellH		= (float)dst.getHeight() / (float)(gridHeight-1);
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		cellX	= de::clamp(deFloorFloatToInt32((float)x / cellW), 0, gridWidth-2);
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		cellY	= de::clamp(deFloorFloatToInt32((float)y / cellH), 0, gridHeight-2);
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		xf		= ((float)x - (float)cellX*cellW + 0.5f) / cellW;
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		yf		= ((float)y - (float)cellY*cellH + 0.5f) / cellH;
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4		v00		= readVec4(vertices + ((cellY+0)*gridWidth + cellX+0)*numComponents, numComponents);
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4		v01		= readVec4(vertices + ((cellY+1)*gridWidth + cellX+0)*numComponents, numComponents);
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4		v10		= readVec4(vertices + ((cellY+0)*gridWidth + cellX+1)*numComponents, numComponents);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4		v11		= readVec4(vertices + ((cellY+1)*gridWidth + cellX+1)*numComponents, numComponents);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		tri		= xf + yf >= 1.0f;
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4&		v0		= tri ? v11 : v00;
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4&		v1		= tri ? v01 : v10;
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4&		v2		= tri ? v10 : v01;
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		s		= tri ? 1.0f-xf : xf;
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		t		= tri ? 1.0f-yf : yf;
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4		color	= v0 + (v1-v0)*s + (v2-v0)*t;
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(isSRGB ? tcu::linearToSRGB(color) : color, x, y);
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void renderIntReference (const tcu::PixelBufferAccess& dst, int gridWidth, int gridHeight, int numComponents, const int* vertices)
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	cellW		= (float)dst.getWidth() / (float)(gridWidth-1);
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	cellH		= (float)dst.getHeight() / (float)(gridHeight-1);
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			cellX	= de::clamp(deFloorFloatToInt32((float)x / cellW), 0, gridWidth-2);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			cellY	= de::clamp(deFloorFloatToInt32((float)y / cellH), 0, gridHeight-2);
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec4		c		= readIVec4(vertices + (cellY*gridWidth + cellX+1)*numComponents, numComponents);
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(c, x, y);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const IVec4 s_swizzles[] =
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(0,1,2,3),
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(1,2,3,0),
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(2,3,0,1),
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(3,0,1,2),
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(3,2,1,0),
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(2,1,0,3),
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(1,0,3,2),
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec4(0,3,2,1)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vector<T, 4> swizzleVec (const tcu::Vector<T, 4>& vec, int swzNdx)
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IVec4& swz = s_swizzles[swzNdx % DE_LENGTH_OF_ARRAY(s_swizzles)];
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return vec.swizzle(swz[0], swz[1], swz[2], swz[3]);
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct AttachmentData
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TextureFormat		format;					//!< Actual format of attachment.
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TextureFormat		referenceFormat;		//!< Used for reference rendering.
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TextureFormat		readFormat;
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numWrittenChannels;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision			outPrecision;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint8>			renderedData;
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint8>			referenceData;
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4797aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvitemplate<typename Type>
4807aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvistring valueRangeToString (int numValidChannels, const tcu::Vector<Type, 4>& minValue, const tcu::Vector<Type, 4>& maxValue)
4817aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi{
4827aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	std::ostringstream stream;
4837aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
4847aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	stream << "(";
4857aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
4867aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	for (int i = 0; i < 4; i++)
4877aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	{
4887aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		if (i != 0)
4897aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			stream << ", ";
4907aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
4917aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		if (i < numValidChannels)
4927aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			stream << minValue[i] << " -> " << maxValue[i];
4937aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		else
4947aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			stream << "Undef";
4957aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	}
4967aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
4977aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	stream << ")";
4987aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
4997aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	return stream.str();
5007aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi}
5017aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5027aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvivoid clearUndefined (const tcu::PixelBufferAccess& access, int numValidChannels)
5037aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi{
5047aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	for (int y = 0; y < access.getHeight(); y++)
5057aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	for (int x = 0; x < access.getWidth(); x++)
5067aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	{
5077aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		switch (tcu::getTextureChannelClass(access.getFormat().type))
5087aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		{
5097aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
5107aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			{
5117aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				const Vec4	srcPixel	= access.getPixel(x, y);
5127aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				Vec4		dstPixel	(0.0f, 0.0f, 0.0f, 1.0f);
5137aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5147aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				for (int channelNdx = 0; channelNdx < numValidChannels; channelNdx++)
5157aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi					dstPixel[channelNdx] = srcPixel[channelNdx];
5167aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5177aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				access.setPixel(dstPixel, x, y);
5187aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				break;
5197aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			}
5207aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5217aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
5227aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
5237aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
5247aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
5257aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			{
5267aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				const IVec4	bitDepth	= tcu::getTextureFormatBitDepth(access.getFormat());
5277aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				const IVec4	srcPixel	= access.getPixelInt(x, y);
5287aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				IVec4		dstPixel	(0, 0, 0, (0x1u << (deUint64)bitDepth.w()) - 1);
5297aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5307aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				for (int channelNdx = 0; channelNdx < numValidChannels; channelNdx++)
5317aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi					dstPixel[channelNdx] = srcPixel[channelNdx];
5327aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5337aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				access.setPixel(dstPixel, x, y);
5347aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				break;
5357aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			}
5367aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5377aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi			default:
5387aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi				DE_ASSERT(false);
5397aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		}
5407aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi	}
5417aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi}
5427aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentOutputCase::IterateResult FragmentOutputCase::iterate (void)
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log					= m_testCtx.getLog();
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl					= m_context.getRenderContext().getFunctions();
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute grid size & index list.
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					minCellSize			= 8;
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IVec2					minBufSize			= getMinSize(m_fboSpec);
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					gridWidth			= de::clamp(minBufSize.x()/minCellSize, 1, 255)+1;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					gridHeight			= de::clamp(minBufSize.y()/minCellSize, 1, 255)+1;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numVertices			= gridWidth*gridHeight;
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numQuads			= (gridWidth-1)*(gridHeight-1);
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numIndices			= numQuads*6;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numInputVecs		= getNumInputVectors(m_outputs);
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<vector<deUint32> >	inputs				(numInputVecs);
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>				positions			(numVertices*4);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint16>			indices				(numIndices);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					readAlignment		= 4;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					viewportW			= minBufSize.x();
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					viewportH			= minBufSize.y();
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					numAttachments		= (int)m_fboSpec.size();
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>			drawBuffers			(numAttachments);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<AttachmentData>		attachments			(numAttachments);
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize attachment data.
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numAttachments; ndx++)
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormat		texFmt			= glu::mapGLInternalFormat(m_fboSpec[ndx].format);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureChannelClass	chnClass		= tcu::getTextureChannelClass(texFmt.type);
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool						isFixedPoint	= chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Fixed-point formats use float reference to enable more accurate result verification.
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormat		refFmt			= isFixedPoint ? tcu::TextureFormat(texFmt.order, tcu::TextureFormat::FLOAT) : texFmt;
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormat		readFmt			= getFramebufferReadFormat(texFmt);
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						attachmentW		= m_fboSpec[ndx].width;
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						attachmentH		= m_fboSpec[ndx].height;
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawBuffers[ndx]					= GL_COLOR_ATTACHMENT0+ndx;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attachments[ndx].format				= texFmt;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attachments[ndx].readFormat			= readFmt;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attachments[ndx].referenceFormat	= refFmt;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attachments[ndx].renderedData.resize(readFmt.getPixelSize()*attachmentW*attachmentH);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		attachments[ndx].referenceData.resize(refFmt.getPixelSize()*attachmentW*attachmentH);
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize indices.
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	quadY	= quadNdx / (gridWidth-1);
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int quadX	= quadNdx - quadY*(gridWidth-1);
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+0] = quadX + quadY*gridWidth;
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+1] = quadX + (quadY+1)*gridWidth;
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+2] = quadX + quadY*gridWidth + 1;
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+3] = indices[quadNdx*6+1];
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+4] = quadX + (quadY+1)*gridWidth + 1;
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		indices[quadNdx*6+5] = indices[quadNdx*6+2];
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < gridHeight; y++)
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < gridWidth; x++)
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf	= (float)x / (float)(gridWidth-1);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf	= (float)y / (float)(gridHeight-1);
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			positions[(y*gridWidth + x)*4 + 0] = 2.0f*xf - 1.0f;
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			positions[(y*gridWidth + x)*4 + 1] = 2.0f*yf - 1.0f;
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			positions[(y*gridWidth + x)*4 + 2] = 0.0f;
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			positions[(y*gridWidth + x)*4 + 3] = 1.0f;
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize input vectors.
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int curInVec = 0;
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++)
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const FragmentOutput&	output		= m_outputs[outputNdx];
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isFloat		= glu::isDataTypeFloatOrVec(output.type);
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isInt		= glu::isDataTypeIntOrIVec(output.type);
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isUint		= glu::isDataTypeUintOrUVec(output.type);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numVecs		= output.arrayLength > 0 ? output.arrayLength : 1;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numScalars	= glu::getDataTypeScalarSize(output.type);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				inputs[curInVec].resize(numVertices*numScalars);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Record how many outputs are written in attachment.
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(output.location+vecNdx < (int)attachments.size());
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				attachments[output.location+vecNdx].numWrittenChannels	= numScalars;
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				attachments[output.location+vecNdx].outPrecision		= output.precision;
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (isFloat)
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec2		range	= getFloatRange(output.precision);
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec4		minVal	(range.x());
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Vec4		maxVal	(range.y());
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					float*		dst		= (float*)&inputs[curInVec][0];
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size()))
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// \note Floating-point precision conversion is not well-defined. For that reason we must
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						//       limit value range to intersection of both data type and render target value ranges.
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(attachments[output.location+vecNdx].format);
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						minVal = tcu::max(minVal, fmtInfo.valueMin);
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						maxVal = tcu::min(maxVal, fmtInfo.valueMax);
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6597aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi					m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: " << valueRangeToString(numScalars, minVal, maxVal) << TestLog::EndMessage;
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int y = 0; y < gridHeight; y++)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int x = 0; x < gridWidth; x++)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float	xf	= (float)x / (float)(gridWidth-1);
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float	yf	= (float)y / (float)(gridHeight-1);
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float	f0	= (xf + yf) * 0.5f;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float	f1	= 0.5f + (xf - yf) * 0.5f;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							Vec4	f	= swizzleVec(Vec4(f0, f1, 1.0f-f0, 1.0f-f1), curInVec);
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							Vec4	c	= minVal + (maxVal-minVal)*f;
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							float*	v	= dst + (y*gridWidth + x)*numScalars;
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int ndx = 0; ndx < numScalars; ndx++)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								v[ndx] = c[ndx];
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isInt)
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const IVec2	range	= getIntRange(output.precision);
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					IVec4		minVal	(range.x());
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					IVec4		maxVal	(range.y());
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size()))
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// Limit to range of output format as conversion mode is not specified.
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const IVec4 fmtBits		= tcu::getTextureFormatBitDepth(attachments[output.location+vecNdx].format);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const BVec4	isZero		= lessThanEqual(fmtBits, IVec4(0));
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const IVec4	fmtMinVal	= (-(tcu::Vector<deInt64, 4>(1) << (fmtBits-1).cast<deInt64>())).asInt();
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const IVec4	fmtMaxVal	= ((tcu::Vector<deInt64, 4>(1) << (fmtBits-1).cast<deInt64>())-deInt64(1)).asInt();
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						minVal = select(minVal, tcu::max(minVal, fmtMinVal), isZero);
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						maxVal = select(maxVal, tcu::min(maxVal, fmtMaxVal), isZero);
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6977aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi					m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: " << valueRangeToString(numScalars, minVal, maxVal) << TestLog::EndMessage;
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const IVec4	rangeDiv	= swizzleVec((IVec4(gridWidth, gridHeight, gridWidth, gridHeight)-1), curInVec);
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const IVec4	step		= ((maxVal.cast<deInt64>() - minVal.cast<deInt64>()) / (rangeDiv.cast<deInt64>())).asInt();
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deInt32*	dst			= (deInt32*)&inputs[curInVec][0];
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int y = 0; y < gridHeight; y++)
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int x = 0; x < gridWidth; x++)
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							int			ix	= gridWidth - x - 1;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							int			iy	= gridHeight - y - 1;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							IVec4		c	= minVal + step*swizzleVec(IVec4(x, y, ix, iy), curInVec);
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							deInt32*	v	= dst + (y*gridWidth + x)*numScalars;
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							DE_ASSERT(boolAll(logicalAnd(greaterThanEqual(c, minVal), lessThanEqual(c, maxVal))));
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int ndx = 0; ndx < numScalars; ndx++)
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								v[ndx] = c[ndx];
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isUint)
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const UVec2	range	= getUintRange(output.precision);
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					UVec4		maxVal	(range.y());
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size()))
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// Limit to range of output format as conversion mode is not specified.
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const IVec4	fmtBits		= tcu::getTextureFormatBitDepth(attachments[output.location+vecNdx].format);
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const UVec4	fmtMaxVal	= ((tcu::Vector<deUint64, 4>(1) << fmtBits.cast<deUint64>())-deUint64(1)).asUint();
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						maxVal = tcu::min(maxVal, fmtMaxVal);
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7337aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi					m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: "  << valueRangeToString(numScalars, UVec4(0), maxVal) << TestLog::EndMessage;
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const IVec4	rangeDiv	= swizzleVec((IVec4(gridWidth, gridHeight, gridWidth, gridHeight)-1), curInVec);
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const UVec4	step		= maxVal / rangeDiv.asUint();
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deUint32*	dst			= &inputs[curInVec][0];
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(range.x() == 0);
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int y = 0; y < gridHeight; y++)
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						for (int x = 0; x < gridWidth; x++)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						{
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							int			ix	= gridWidth - x - 1;
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							int			iy	= gridHeight - y - 1;
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							UVec4		c	= step*swizzleVec(IVec4(x, y, ix, iy).asUint(), curInVec);
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							deUint32*	v	= dst + (y*gridWidth + x)*numScalars;
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							DE_ASSERT(boolAll(lessThanEqual(c, maxVal)));
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							for (int ndx = 0; ndx < numScalars; ndx++)
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								v[ndx] = c[ndx];
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						}
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(false);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInVec += 1;
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render using gl.
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, viewportW, viewportH);
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]);
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.disable(GL_DITHER); // Dithering causes issues with unorm formats. Those issues could be worked around in threshold, but it makes validation less accurate.
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int curInVec = 0;
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++)
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const FragmentOutput&	output			= m_outputs[outputNdx];
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isArray			= output.arrayLength > 0;
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isFloat			= glu::isDataTypeFloatOrVec(output.type);
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isInt			= glu::isDataTypeIntOrIVec(output.type);
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isUint			= glu::isDataTypeUintOrUVec(output.type);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						scalarSize		= glu::getDataTypeScalarSize(output.type);
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32				glScalarType	= isFloat	? GL_FLOAT			:
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  isInt		? GL_INT			:
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  isUint	? GL_UNSIGNED_INT	: GL_NONE;
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numVecs			= isArray ? output.arrayLength : 1;
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string	name	= string("in") + de::toString(outputNdx) + (isArray ? string("_") + de::toString(vecNdx) : string());
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int		loc		= gl.getAttribLocation(m_program->getProgram(), name.c_str());
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (loc >= 0)
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.enableVertexAttribArray(loc);
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (isFloat)
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						gl.vertexAttribPointer(loc, scalarSize, glScalarType, GL_FALSE, 0, &inputs[curInVec][0]);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						gl.vertexAttribIPointer(loc, scalarSize, glScalarType, 0, &inputs[curInVec][0]);
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Warning: No location for attribute '" << name << "' found." << TestLog::EndMessage;
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInVec += 1;
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int posLoc = gl.getAttribLocation(m_program->getProgram(), "a_position");
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK(posLoc >= 0);
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.enableVertexAttribArray(posLoc);
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &positions[0]);
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "After attribute setup");
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, &indices[0]);
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements");
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read all attachment points.
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numAttachments; ndx++)
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8227aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		const glu::TransferFormat		transferFmt			= glu::getTransferFormat(attachments[ndx].readFormat);
8237aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		void*							dst					= &attachments[ndx].renderedData[0];
8247aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		const int						attachmentW			= m_fboSpec[ndx].width;
8257aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		const int						attachmentH			= m_fboSpec[ndx].height;
8267aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		const int						numValidChannels	= attachments[ndx].numWrittenChannels;
8277aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		const tcu::PixelBufferAccess	rendered			(attachments[ndx].readFormat, attachmentW, attachmentH, 1, deAlign32(attachments[ndx].readFormat.getPixelSize()*attachmentW, readAlignment), 0, &attachments[ndx].renderedData[0]);
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.readBuffer(GL_COLOR_ATTACHMENT0+ndx);
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.readPixels(0, 0, minBufSize.x(), minBufSize.y(), transferFmt.format, transferFmt.dataType, dst);
8317aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi
8327aced58032d4360fd408015c01f1ab37d67fc9afMika Isojärvi		clearUndefined(rendered, numValidChannels);
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render reference images.
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int curInNdx = 0;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++)
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const FragmentOutput&	output			= m_outputs[outputNdx];
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool				isArray			= output.arrayLength > 0;
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool				isFloat			= glu::isDataTypeFloatOrVec(output.type);
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool				isInt			= glu::isDataTypeIntOrIVec(output.type);
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool				isUint			= glu::isDataTypeUintOrUVec(output.type);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				scalarSize		= glu::getDataTypeScalarSize(output.type);
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				numVecs			= isArray ? output.arrayLength : 1;
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		location	= output.location+vecNdx;
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const void*		inputData	= &inputs[curInNdx][0];
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(de::inBounds(location, 0, (int)m_fboSpec.size()));
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int						bufW			= m_fboSpec[location].width;
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int						bufH			= m_fboSpec[location].height;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::PixelBufferAccess	buf				(attachments[location].referenceFormat, bufW, bufH, 1, &attachments[location].referenceData[0]);
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::PixelBufferAccess	viewportBuf		= getSubregion(buf, 0, 0, 0, viewportW, viewportH, 1);
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (isInt || isUint)
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					renderIntReference(viewportBuf, gridWidth, gridHeight, scalarSize, (const int*)inputData);
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isFloat)
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					renderFloatReference(viewportBuf, gridWidth, gridHeight, scalarSize, (const float*)inputData);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(false);
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInNdx += 1;
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare all images.
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool allLevelsOk = true;
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int attachNdx = 0; attachNdx < numAttachments; attachNdx++)
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						attachmentW			= m_fboSpec[attachNdx].width;
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						attachmentH			= m_fboSpec[attachNdx].height;
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						numValidChannels	= attachments[attachNdx].numWrittenChannels;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::BVec4				cmpMask				(numValidChannels >= 1, numValidChannels >= 2, numValidChannels >= 3, numValidChannels >= 4);
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision			outPrecision		= attachments[attachNdx].outPrecision;
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormat&		format				= attachments[attachNdx].format;
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ConstPixelBufferAccess		rendered			(attachments[attachNdx].readFormat, attachmentW, attachmentH, 1, deAlign32(attachments[attachNdx].readFormat.getPixelSize()*attachmentW, readAlignment), 0, &attachments[attachNdx].renderedData[0]);
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ConstPixelBufferAccess		reference			(attachments[attachNdx].referenceFormat, attachmentW, attachmentH, 1, &attachments[attachNdx].referenceData[0]);
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TextureChannelClass		texClass			= tcu::getTextureChannelClass(format.type);
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool							isOk				= true;
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string					name				= string("Attachment") + de::toString(attachNdx);
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string					desc				= string("Color attachment ") + de::toString(attachNdx);
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "Attachment " << attachNdx << ": " << numValidChannels << " channels have defined values and used for comparison" << TestLog::EndMessage;
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (texClass)
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
895c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				const deUint32	interpThreshold		= 4;	//!< 4 ULP interpolation threshold (interpolation always in highp)
896c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				deUint32		outTypeThreshold	= 0;	//!< Threshold based on output type
897c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				UVec4			formatThreshold;			//!< Threshold computed based on format.
898c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				UVec4			finalThreshold;
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9002cd1e178d456ed3fe617603abffebda7bb18075dPyry Haulos				// 1 ULP rounding error is allowed for smaller floating-point formats
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (format.type)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9032cd1e178d456ed3fe617603abffebda7bb18075dPyry Haulos					case tcu::TextureFormat::FLOAT:							formatThreshold = UVec4(0);											break;
9042cd1e178d456ed3fe617603abffebda7bb18075dPyry Haulos					case tcu::TextureFormat::HALF_FLOAT:					formatThreshold = UVec4((1<<(23-10)));								break;
9052cd1e178d456ed3fe617603abffebda7bb18075dPyry Haulos					case tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	formatThreshold = UVec4((1<<(23-6)), (1<<(23-6)), (1<<(23-5)), 0);	break;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
911c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				// 1 ULP rounding error for highp -> output precision cast
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (outPrecision)
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
914c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos					case glu::PRECISION_LOWP:		outTypeThreshold	= (1<<(23-8));	break;
915c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos					case glu::PRECISION_MEDIUMP:	outTypeThreshold	= (1<<(23-10));	break;
916c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos					case glu::PRECISION_HIGHP:		outTypeThreshold	= 0;			break;
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT(false);
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
921c214f65602ccd453afeeeb2c674ba121e7a9f8afPyry Haulos				finalThreshold = select(max(formatThreshold, UVec4(deMax32(interpThreshold, outTypeThreshold))), UVec4(~0u), cmpMask);
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, finalThreshold, tcu::COMPARE_LOG_RESULT);
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note glReadPixels() allows only 8 bits to be read. This means that RGB10_A2 will loose some
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// bits in the process and it must be taken into account when computing threshold.
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const IVec4		bits			= min(IVec4(8), tcu::getTextureFormatBitDepth(format));
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec4		baseThreshold	= 1.0f / ((IVec4(1) << bits)-1).asFloat();
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const Vec4		threshold		= select(baseThreshold, Vec4(2.0f), cmpMask);
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::UVec4 threshold = select(UVec4(0u), UVec4(~0u), cmpMask);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_FAIL("Unsupported comparison");
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allLevelsOk = false;
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(allLevelsOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							allLevelsOk ? "Pass"				: "Image comparison failed");
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentOutputTests::FragmentOutputTests (Context& context)
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "fragment_out", "Fragment output tests")
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9663c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentOutputTests::~FragmentOutputTests (void)
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic FragmentOutputCase* createRandomCase (Context& context, int minRenderTargets, int maxRenderTargets, deUint32 seed)
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const glu::DataType outputTypes[] =
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT,
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC2,
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC3,
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT_VEC4,
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT,
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC2,
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC3,
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT_VEC4,
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT,
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC2,
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC3,
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT_VEC4
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const glu::Precision precisions[] =
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_LOWP,
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_MEDIUMP,
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_HIGHP
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 floatFormats[] =
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32F,
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16F,
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R11F_G11F_B10F,
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32F,
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16F,
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32F,
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16F,
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8,
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_SRGB8_ALPHA8,
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB10_A2,
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA4,
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB5_A1,
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB8,
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB565,
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8,
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 intFormats[] =
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32I,
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16I,
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8I,
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32I,
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16I,
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8I,
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32I,
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16I,
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8I
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 uintFormats[] =
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32UI,
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16UI,
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8UI,
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB10_A2UI,
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32UI,
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16UI,
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8UI,
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32UI,
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16UI,
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8UI
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					rnd			(seed);
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<FragmentOutput>		outputs;
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<BufferSpec>			targets;
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::DataType>		outTypes;
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							numTargets	= rnd.getInt(minRenderTargets, maxRenderTargets);
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					width		= 128; // \todo [2012-04-10 pyry] Separate randomized sizes per target?
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					height		= 64;
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					samples		= 0;
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute outputs.
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int curLoc = 0;
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (curLoc < numTargets)
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			useArray		= rnd.getFloat() < 0.3f;
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				maxArrayLen		= numTargets-curLoc;
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				arrayLen		= useArray ? rnd.getInt(1, maxArrayLen) : 0;
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType	basicType		= rnd.choose<glu::DataType>(&outputTypes[0], &outputTypes[0] + DE_LENGTH_OF_ARRAY(outputTypes));
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Precision	precision		= rnd.choose<glu::Precision>(&precisions[0], &precisions[0] + DE_LENGTH_OF_ARRAY(precisions));
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numLocations	= useArray ? arrayLen : 1;
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		outputs.push_back(FragmentOutput(basicType, precision, curLoc, arrayLen));
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numLocations; ndx++)
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outTypes.push_back(basicType);
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curLoc += numLocations;
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(curLoc == numTargets);
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)outTypes.size() == numTargets);
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compute buffers.
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while ((int)targets.size() < numTargets)
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType	outType		= outTypes[targets.size()];
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			isFloat		= glu::isDataTypeFloatOrVec(outType);
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			isInt		= glu::isDataTypeIntOrIVec(outType);
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			isUint		= glu::isDataTypeUintOrUVec(outType);
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		format		= 0;
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isFloat)
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			format = rnd.choose<deUint32>(&floatFormats[0], &floatFormats[0] + DE_LENGTH_OF_ARRAY(floatFormats));
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isInt)
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			format = rnd.choose<deUint32>(&intFormats[0], &intFormats[0] + DE_LENGTH_OF_ARRAY(intFormats));
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (isUint)
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			format = rnd.choose<deUint32>(&uintFormats[0], &uintFormats[0] + DE_LENGTH_OF_ARRAY(uintFormats));
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		targets.push_back(BufferSpec(format, width, height, samples));
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new FragmentOutputCase(context, de::toString(seed).c_str(), "", targets, outputs);
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FragmentOutputTests::init (void)
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 requiredFloatFormats[] =
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32F,
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16F,
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R11F_G11F_B10F,
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32F,
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16F,
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32F,
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16F
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 requiredFixedFormats[] =
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8,
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_SRGB8_ALPHA8,
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB10_A2,
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA4,
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB5_A1,
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB8,
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB565,
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8,
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 requiredIntFormats[] =
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32I,
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16I,
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8I,
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32I,
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16I,
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8I,
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32I,
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16I,
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8I
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint32 requiredUintFormats[] =
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA32UI,
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA16UI,
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGBA8UI,
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RGB10_A2UI,
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG32UI,
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG16UI,
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_RG8UI,
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R32UI,
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R16UI,
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GL_R8UI
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const glu::Precision precisions[] =
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_LOWP,
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_MEDIUMP,
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::PRECISION_HIGHP
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .basic.
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic fragment output tests");
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(basicGroup);
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	width	= 64;
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	height	= 64;
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	samples	= 0;
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .float
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point output tests");
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		basicGroup->addChild(floatGroup);
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFloatFormats); fmtNdx++)
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredFloatFormats[fmtNdx];
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fboSpec.push_back(BufferSpec(format, width, height, samples));
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT,		prec, 0)).toVec()));
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2,	prec, 0)).toVec()));
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3,	prec, 0)).toVec()));
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4,	prec, 0)).toVec()));
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .fixed
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* fixedGroup = new tcu::TestCaseGroup(m_testCtx, "fixed", "Fixed-point output tests");
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		basicGroup->addChild(fixedGroup);
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFixedFormats); fmtNdx++)
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredFixedFormats[fmtNdx];
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fboSpec.push_back(BufferSpec(format, width, height, samples));
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT,		prec, 0)).toVec()));
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2,	prec, 0)).toVec()));
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3,	prec, 0)).toVec()));
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4,	prec, 0)).toVec()));
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .int
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer output tests");
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		basicGroup->addChild(intGroup);
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredIntFormats); fmtNdx++)
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredIntFormats[fmtNdx];
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fboSpec.push_back(BufferSpec(format, width, height, samples));
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_int").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT,		prec, 0)).toVec()));
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC2,	prec, 0)).toVec()));
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC3,	prec, 0)).toVec()));
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC4,	prec, 0)).toVec()));
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .uint
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Usigned integer output tests");
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		basicGroup->addChild(uintGroup);
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredUintFormats); fmtNdx++)
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredUintFormats[fmtNdx];
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fboSpec.push_back(BufferSpec(format, width, height, samples));
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uint").c_str(),		"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT,			prec, 0)).toVec()));
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC2,	prec, 0)).toVec()));
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC3,	prec, 0)).toVec()));
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC4,	prec, 0)).toVec()));
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .array
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* arrayGroup = new tcu::TestCaseGroup(m_testCtx, "array", "Array outputs");
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(arrayGroup);
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	width		= 64;
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	height		= 64;
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	samples		= 0;
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numTargets	= 3;
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .float
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point output tests");
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		arrayGroup->addChild(floatGroup);
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFloatFormats); fmtNdx++)
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredFloatFormats[fmtNdx];
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numTargets; ndx++)
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fboSpec.push_back(BufferSpec(format, width, height, samples));
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT,		prec, 0, numTargets)).toVec()));
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2,	prec, 0, numTargets)).toVec()));
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3,	prec, 0, numTargets)).toVec()));
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4,	prec, 0, numTargets)).toVec()));
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .fixed
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* fixedGroup = new tcu::TestCaseGroup(m_testCtx, "fixed", "Fixed-point output tests");
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		arrayGroup->addChild(fixedGroup);
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFixedFormats); fmtNdx++)
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredFixedFormats[fmtNdx];
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numTargets; ndx++)
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fboSpec.push_back(BufferSpec(format, width, height, samples));
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT,		prec, 0, numTargets)).toVec()));
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2,	prec, 0, numTargets)).toVec()));
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3,	prec, 0, numTargets)).toVec()));
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4,	prec, 0, numTargets)).toVec()));
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .int
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer output tests");
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		arrayGroup->addChild(intGroup);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredIntFormats); fmtNdx++)
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredIntFormats[fmtNdx];
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numTargets; ndx++)
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fboSpec.push_back(BufferSpec(format, width, height, samples));
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_int").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT,		prec, 0, numTargets)).toVec()));
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC2,	prec, 0, numTargets)).toVec()));
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC3,	prec, 0, numTargets)).toVec()));
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC4,	prec, 0, numTargets)).toVec()));
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .uint
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Usigned integer output tests");
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		arrayGroup->addChild(uintGroup);
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredUintFormats); fmtNdx++)
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32			format		= requiredUintFormats[fmtNdx];
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			string				fmtName		= getFormatName(format);
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<BufferSpec>	fboSpec;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numTargets; ndx++)
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fboSpec.push_back(BufferSpec(format, width, height, samples));
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::Precision	prec		= precisions[precNdx];
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				string			precName	= glu::getPrecisionName(prec);
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uint").c_str(),		"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT,			prec, 0, numTargets)).toVec()));
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec2").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC2,	prec, 0, numTargets)).toVec()));
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec3").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC3,	prec, 0, numTargets)).toVec()));
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec4").c_str(),	"",	fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC4,	prec, 0, numTargets)).toVec()));
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .random
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random fragment output cases");
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(randomGroup);
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (deUint32 seed = 0; seed < 100; seed++)
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			randomGroup->addChild(createRandomCase(m_context, 2, 4, seed));
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1372