13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 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 SSBO layout case.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fSSBOLayoutCase.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluProgramInterfaceQuery.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VarType;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::StructType;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::StructMember;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace bb
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct LayoutFlagsFmt
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 flags;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LayoutFlagsFmt (deUint32 flags_) : flags(flags_) {}
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const LayoutFlagsFmt& fmt)
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32	bit;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	token;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} bitDesc[] =
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_SHARED,		"shared"		},
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_PACKED,		"packed"		},
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_STD140,		"std140"		},
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_STD430,		"std430"		},
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_ROW_MAJOR,		"row_major"		},
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ LAYOUT_COLUMN_MAJOR,	"column_major"	}
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 remBits = fmt.flags;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (remBits & bitDesc[descNdx].bit)
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (remBits != fmt.flags)
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				str << ", ";
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << bitDesc[descNdx].token;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			remBits &= ~bitDesc[descNdx].bit;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(remBits == 0);
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// BufferVar implementation.
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferVar::BufferVar (const char* name, const VarType& type, deUint32 flags)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_name	(name)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_type	(type)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_flags	(flags)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// BufferBlock implementation.
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferBlock::BufferBlock (const char* blockName)
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_blockName	(blockName)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_arraySize	(-1)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_flags		(0)
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setArraySize(0);
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferBlock::setArraySize (int arraySize)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(arraySize >= 0);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_lastUnsizedArraySizes.resize(arraySize == 0 ? 1 : arraySize, 0);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_arraySize = arraySize;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BlockLayoutEntry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockLayoutEntry (void)
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: size(0)
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			name;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					size;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<int>	activeVarIndices;
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& stream, const BlockLayoutEntry& entry)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << entry.name << " { name = " << entry.name
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", size = " << entry.size
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", activeVarIndices = [";
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<int>::const_iterator i = entry.activeVarIndices.begin(); i != entry.activeVarIndices.end(); i++)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (i != entry.activeVarIndices.begin())
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			stream << ", ";
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		stream << *i;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << "] }";
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return stream;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BufferVarLayoutEntry
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferVarLayoutEntry (void)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: type					(glu::TYPE_LAST)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, blockNdx				(-1)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, offset				(-1)
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, arraySize				(-1)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, arrayStride			(-1)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, matrixStride			(-1)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, topLevelArraySize		(-1)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, topLevelArrayStride	(-1)
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, isRowMajor			(false)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			name;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType		type;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					blockNdx;
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					offset;
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					arraySize;
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					arrayStride;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					matrixStride;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					topLevelArraySize;
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					topLevelArrayStride;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				isRowMajor;
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic bool isUnsizedArray (const BufferVarLayoutEntry& entry)
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(entry.arraySize != 0 || entry.topLevelArraySize != 0);
1868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return entry.arraySize == 0 || entry.topLevelArraySize == 0;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& stream, const BufferVarLayoutEntry& entry)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream << entry.name << " { type = " << glu::getDataTypeName(entry.type)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", blockNdx = " << entry.blockNdx
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", offset = " << entry.offset
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", arraySize = " << entry.arraySize
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", arrayStride = " << entry.arrayStride
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", matrixStride = " << entry.matrixStride
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", topLevelArraySize = " << entry.topLevelArraySize
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", topLevelArrayStride = " << entry.topLevelArrayStride
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << ", isRowMajor = " << (entry.isRowMajor ? "true" : "false")
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << " }";
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return stream;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BufferLayout
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<BlockLayoutEntry>		blocks;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<BufferVarLayoutEntry>	bufferVars;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int									getVariableIndex		(const string& name) const;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int									getBlockIndex			(const string& name) const;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2012-01-24 pyry] Speed up lookups using hash.
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint BufferLayout::getVariableIndex (const string& name) const
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)bufferVars.size(); ndx++)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (bufferVars[ndx].name == name)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ndx;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint BufferLayout::getBlockIndex (const string& name) const
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (blocks[ndx].name == name)
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ndx;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ShaderInterface implementation.
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderInterface::ShaderInterface (void)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderInterface::~ShaderInterface (void)
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<StructType*>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<BufferBlock*>::iterator i = m_bufferBlocks.begin(); i != m_bufferBlocks.end(); i++)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStructType& ShaderInterface::allocStruct (const char* name)
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_structs.reserve(m_structs.size()+1);
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_structs.push_back(new StructType(name));
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *m_structs.back();
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct StructNameEquals
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string name;
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	StructNameEquals (const char* name_) : name(name_) {}
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const StructType* type) const
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return type->getTypeName() && name == type->getTypeName();
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst StructType* ShaderInterface::findStruct (const char* name) const
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<StructType*>::const_iterator pos = std::find_if(m_structs.begin(), m_structs.end(), StructNameEquals(name));
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pos != m_structs.end() ? *pos : DE_NULL;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderInterface::getNamedStructs (std::vector<const StructType*>& structs) const
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<StructType*>::const_iterator i = m_structs.begin(); i != m_structs.end(); i++)
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((*i)->getTypeName() != DE_NULL)
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			structs.push_back(*i);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferBlock& ShaderInterface::allocBlock (const char* name)
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_bufferBlocks.reserve(m_bufferBlocks.size()+1);
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_bufferBlocks.push_back(new BufferBlock(name));
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *m_bufferBlocks.back();
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// BlockDataPtr
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BlockDataPtr
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void*		ptr;
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			size;						//!< Redundant, for debugging purposes.
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			lastUnsizedArraySize;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockDataPtr (void* ptr_, int size_, int lastUnsizedArraySize_)
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: ptr					(ptr_)
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, size					(size_)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, lastUnsizedArraySize	(lastUnsizedArraySize_)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockDataPtr (void)
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: ptr					(DE_NULL)
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, size					(0)
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, lastUnsizedArraySize	(0)
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace // Utilities
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint findBlockIndex (const BufferLayout& layout, const string& name)
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)layout.blocks.size(); ndx++)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (layout.blocks[ndx].name == name)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ndx;
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Layout computation.
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint getDataTypeByteSize (glu::DataType type)
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return glu::getDataTypeScalarSize(type)*sizeof(deUint32);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint getDataTypeByteAlignment (glu::DataType type)
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT:
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT:
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT:
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL:		return 1*sizeof(deUint32);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC2:
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC2:
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC2:
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC2:	return 2*sizeof(deUint32);
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC3:
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC3:
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC3:
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC3:	// Fall-through to vec4
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC4:
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC4:
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC4:
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC4:	return 4*sizeof(deUint32);
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int deRoundUp32 (int a, int b)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int d = a/b;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return d*b == a ? a : (d+1)*b;
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeStd140BaseAlignment (const VarType& type, deUint32 layoutFlags)
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int vec4Alignment = sizeof(deUint32)*4;
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType basicType = type.getBasicType();
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeMatrix(basicType))
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool	isRowMajor	= !!(layoutFlags & LAYOUT_ROW_MAJOR);
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	vecSize		= isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 : glu::getDataTypeMatrixNumRows(basicType);
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	vecAlign	= deAlign32(getDataTypeByteAlignment(glu::getDataTypeFloatVec(vecSize)), vec4Alignment);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return vecAlign;
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getDataTypeByteAlignment(basicType);
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int elemAlignment = computeStd140BaseAlignment(type.getElementType(), layoutFlags);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Round up to alignment of vec4
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return deAlign32(elemAlignment, vec4Alignment);
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(type.isStructType());
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxBaseAlignment = 0;
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxBaseAlignment = de::max(maxBaseAlignment, computeStd140BaseAlignment(memberIter->getType(), layoutFlags));
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return deAlign32(maxBaseAlignment, vec4Alignment);
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeStd430BaseAlignment (const VarType& type, deUint32 layoutFlags)
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Otherwise identical to std140 except that alignment of structures and arrays
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// are not rounded up to alignment of vec4.
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::DataType basicType = type.getBasicType();
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeMatrix(basicType))
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool	isRowMajor	= !!(layoutFlags & LAYOUT_ROW_MAJOR);
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	vecSize		= isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 : glu::getDataTypeMatrixNumRows(basicType);
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	vecAlign	= getDataTypeByteAlignment(glu::getDataTypeFloatVec(vecSize));
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return vecAlign;
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getDataTypeByteAlignment(basicType);
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return computeStd430BaseAlignment(type.getElementType(), layoutFlags);
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(type.isStructType());
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int maxBaseAlignment = 0;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			maxBaseAlignment = de::max(maxBaseAlignment, computeStd430BaseAlignment(memberIter->getType(), layoutFlags));
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return maxBaseAlignment;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 mergeLayoutFlags (deUint32 prevFlags, deUint32 newFlags)
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	packingMask		= LAYOUT_PACKED|LAYOUT_SHARED|LAYOUT_STD140|LAYOUT_STD430;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	matrixMask		= LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR;
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 mergedFlags = 0;
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mergedFlags |= ((newFlags & packingMask)	? newFlags : prevFlags) & packingMask;
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mergedFlags |= ((newFlags & matrixMask)		? newFlags : prevFlags) & matrixMask;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return mergedFlags;
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Appends all child elements to layout, returns value that should be appended to offset.
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeReferenceLayout (
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferLayout&		layout,
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					curBlockNdx,
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					baseOffset,
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string&	curPrefix,
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType&		type,
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			layoutFlags)
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Reference layout uses std430 rules by default. std140 rules are
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// choosen only for blocks that have std140 layout.
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	isStd140			= (layoutFlags & LAYOUT_STD140) != 0;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	baseAlignment		= isStd140 ? computeStd140BaseAlignment(type, layoutFlags)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   : computeStd430BaseAlignment(type, layoutFlags);
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			curOffset			= deAlign32(baseOffset, baseAlignment);
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	topLevelArraySize	= 1; // Default values
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	topLevelArrayStride	= 0;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isBasicType())
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		basicType	= type.getBasicType();
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BufferVarLayoutEntry	entry;
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.name					= curPrefix;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.type					= basicType;
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.arraySize				= 1;
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.arrayStride			= 0;
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.matrixStride			= 0;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.topLevelArraySize		= topLevelArraySize;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.topLevelArrayStride	= topLevelArrayStride;
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.blockNdx				= curBlockNdx;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeMatrix(basicType))
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Array of vectors as specified in rules 5 & 7.
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool	isRowMajor			= !!(layoutFlags & LAYOUT_ROW_MAJOR);
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	numVecs				= isRowMajor ? glu::getDataTypeMatrixNumRows(basicType)
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														 : glu::getDataTypeMatrixNumColumns(basicType);
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset		= curOffset;
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.matrixStride	= baseAlignment;
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.isRowMajor	= isRowMajor;
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += numVecs*baseAlignment;
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Scalar or vector.
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset = curOffset;
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += getDataTypeByteSize(basicType);
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		layout.bufferVars.push_back(entry);
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const VarType&	elemType	= type.getElementType();
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Array of scalars or vectors.
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		elemBasicType	= elemType.getBasicType();
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				stride			= baseAlignment;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BufferVarLayoutEntry	entry;
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name					= curPrefix + "[0]"; // Array variables are always postfixed with [0]
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.type					= elemBasicType;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.blockNdx				= curBlockNdx;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset				= curOffset;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arraySize				= type.getArraySize();
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arrayStride			= stride;
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.matrixStride			= 0;
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArraySize		= topLevelArraySize;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArrayStride	= topLevelArrayStride;
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += stride*type.getArraySize();
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			layout.bufferVars.push_back(entry);
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Array of matrices.
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType			elemBasicType	= elemType.getBasicType();
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					isRowMajor		= !!(layoutFlags & LAYOUT_ROW_MAJOR);
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					numVecs			= isRowMajor ? glu::getDataTypeMatrixNumRows(elemBasicType)
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 : glu::getDataTypeMatrixNumColumns(elemBasicType);
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					vecStride		= baseAlignment;
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BufferVarLayoutEntry		entry;
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name					= curPrefix + "[0]"; // Array variables are always postfixed with [0]
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.type					= elemBasicType;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.blockNdx				= curBlockNdx;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset				= curOffset;
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arraySize				= type.getArraySize();
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arrayStride			= vecStride*numVecs;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.matrixStride			= vecStride;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.isRowMajor			= isRowMajor;
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArraySize		= topLevelArraySize;
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArrayStride	= topLevelArrayStride;
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += numVecs*vecStride*type.getArraySize();
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			layout.bufferVars.push_back(entry);
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curOffset += computeReferenceLayout(layout, curBlockNdx, curOffset, curPrefix + "[" + de::toString(elemNdx) + "]", type.getElementType(), layoutFlags);
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(type.isStructType());
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += computeReferenceLayout(layout, curBlockNdx, curOffset, curPrefix + "." + memberIter->getName(), memberIter->getType(), layoutFlags);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curOffset = deAlign32(curOffset, baseAlignment);
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return curOffset-baseOffset;
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Appends all child elements to layout, returns offset increment.
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeReferenceLayout (BufferLayout& layout, int curBlockNdx, const std::string& blockPrefix, int baseOffset, const BufferVar& bufVar, deUint32 blockLayoutFlags)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType&	varType			= bufVar.getType();
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	combinedFlags	= mergeLayoutFlags(blockLayoutFlags, bufVar.getFlags());
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (varType.isArrayType())
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Top-level arrays need special care.
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		topLevelArraySize	= varType.getArraySize() == VarType::UNSIZED_ARRAY ? 0 : varType.getArraySize();
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	prefix				= blockPrefix + bufVar.getName() + "[0]";
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isStd140			= (blockLayoutFlags & LAYOUT_STD140) != 0;
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		vec4Align			= sizeof(deUint32)*4;
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		baseAlignment		= isStd140 ? computeStd140BaseAlignment(varType, combinedFlags)
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   : computeStd430BaseAlignment(varType, combinedFlags);
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				curOffset			= deAlign32(baseOffset, baseAlignment);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const VarType&	elemType			= varType.getElementType();
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Array of scalars or vectors.
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		elemBasicType	= elemType.getBasicType();
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				elemBaseAlign	= getDataTypeByteAlignment(elemBasicType);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				stride			= isStd140 ? deAlign32(elemBaseAlign, vec4Align) : elemBaseAlign;
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BufferVarLayoutEntry	entry;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name					= prefix;
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArraySize		= 1;
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArrayStride	= 0;
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.type					= elemBasicType;
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.blockNdx				= curBlockNdx;
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset				= curOffset;
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arraySize				= topLevelArraySize;
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arrayStride			= stride;
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.matrixStride			= 0;
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			layout.bufferVars.push_back(entry);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += stride*topLevelArraySize;
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Array of matrices.
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		elemBasicType	= elemType.getBasicType();
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool				isRowMajor		= !!(combinedFlags & LAYOUT_ROW_MAJOR);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				vecSize			= isRowMajor ? glu::getDataTypeMatrixNumColumns(elemBasicType)
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 : glu::getDataTypeMatrixNumRows(elemBasicType);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				numVecs			= isRowMajor ? glu::getDataTypeMatrixNumRows(elemBasicType)
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 : glu::getDataTypeMatrixNumColumns(elemBasicType);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		vecType			= glu::getDataTypeFloatVec(vecSize);
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				vecBaseAlign	= getDataTypeByteAlignment(vecType);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				stride			= isStd140 ? deAlign32(vecBaseAlign, vec4Align) : vecBaseAlign;
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BufferVarLayoutEntry	entry;
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name					= prefix;
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArraySize		= 1;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.topLevelArrayStride	= 0;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.type					= elemBasicType;
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.blockNdx				= curBlockNdx;
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.offset				= curOffset;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arraySize				= topLevelArraySize;
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.arrayStride			= stride*numVecs;
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.matrixStride			= stride;
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.isRowMajor			= isRowMajor;
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			layout.bufferVars.push_back(entry);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += stride*numVecs*topLevelArraySize;
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Struct base alignment is not added multiple times as curOffset supplied to computeReferenceLayout
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// was already aligned correctly. Thus computeReferenceLayout should not add any extra padding
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// before struct. Padding after struct will be added as it should.
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			//
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Stride could be computed prior to creating child elements, but it would essentially require running
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// the layout computation twice. Instead we fix stride to child elements afterwards.
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	firstChildNdx	= (int)layout.bufferVars.size();
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	stride			= computeReferenceLayout(layout, curBlockNdx, curOffset, prefix, varType.getElementType(), combinedFlags);
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int childNdx = firstChildNdx; childNdx < (int)layout.bufferVars.size(); childNdx++)
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				layout.bufferVars[childNdx].topLevelArraySize	= topLevelArraySize;
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				layout.bufferVars[childNdx].topLevelArrayStride	= stride;
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += stride*topLevelArraySize;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return curOffset-baseOffset;
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return computeReferenceLayout(layout, curBlockNdx, baseOffset, blockPrefix + bufVar.getName(), varType, combinedFlags);
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeReferenceLayout (BufferLayout& layout, const ShaderInterface& interface)
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numBlocks = interface.getNumBlocks();
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&	block			= interface.getBlock(blockNdx);
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool				hasInstanceName	= block.getInstanceName() != DE_NULL;
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string			blockPrefix		= hasInstanceName ? (std::string(block.getBlockName()) + ".") : std::string("");
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					curOffset		= 0;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					activeBlockNdx	= (int)layout.blocks.size();
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					firstVarNdx		= (int)layout.bufferVars.size();
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (BufferBlock::const_iterator varIter = block.begin(); varIter != block.end(); varIter++)
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVar& bufVar = *varIter;
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += computeReferenceLayout(layout, activeBlockNdx,  blockPrefix, curOffset, bufVar, block.getFlags());
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	varIndicesEnd	= (int)layout.bufferVars.size();
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	blockSize		= curOffset;
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	numInstances	= block.isArray() ? block.getArraySize() : 1;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Create block layout entries for each instance.
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Allocate entry for instance.
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			layout.blocks.push_back(BlockLayoutEntry());
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			BlockLayoutEntry& blockEntry = layout.blocks.back();
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			blockEntry.name = block.getBlockName();
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			blockEntry.size = blockSize;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Compute active variable set for block.
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int varNdx = firstVarNdx; varNdx < varIndicesEnd; varNdx++)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				blockEntry.activeVarIndices.push_back(varNdx);
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (block.isArray())
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				blockEntry.name += "[" + de::toString(instanceNdx) + "]";
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Value generator.
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid generateValue (const BufferVarLayoutEntry& entry, int unsizedArraySize, void* basePtr, de::Random& rnd)
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType	scalarType		= glu::getDataTypeScalarType(entry.type);
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			scalarSize		= glu::getDataTypeScalarSize(entry.type);
7358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			arraySize		= entry.arraySize == 0 ? unsizedArraySize : entry.arraySize;
7368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			arrayStride		= entry.arrayStride;
7378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			topLevelSize	= entry.topLevelArraySize == 0 ? unsizedArraySize : entry.topLevelArraySize;
7388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			topLevelStride	= entry.topLevelArrayStride;
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			isMatrix		= glu::isDataTypeMatrix(entry.type);
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numVecs			= isMatrix ? (entry.isRowMajor ? glu::getDataTypeMatrixNumRows(entry.type) : glu::getDataTypeMatrixNumColumns(entry.type)) : 1;
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			vecSize			= scalarSize / numVecs;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			compSize		= sizeof(deUint32);
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(scalarSize%numVecs == 0);
7458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(topLevelSize >= 0);
7468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(arraySize >= 0);
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (int topElemNdx = 0; topElemNdx < topLevelSize; topElemNdx++)
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* const topElemPtr = (deUint8*)basePtr + entry.offset + topElemNdx*topLevelStride;
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elemNdx = 0; elemNdx < arraySize; elemNdx++)
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8* const elemPtr = topElemPtr + elemNdx*arrayStride;
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint8* const vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int compNdx = 0; compNdx < vecSize; compNdx++)
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deUint8* const compPtr = vecPtr + compSize*compNdx;
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					switch (scalarType)
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::TYPE_FLOAT:	*((float*)compPtr)		= (float)rnd.getInt(-9, 9);						break;
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::TYPE_INT:		*((int*)compPtr)		= rnd.getInt(-9, 9);							break;
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::TYPE_UINT:	*((deUint32*)compPtr)	= (deUint32)rnd.getInt(0, 9);					break;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// \note Random bit pattern is used for true values. Spec states that all non-zero values are
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						//       interpreted as true but some implementations fail this.
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						case glu::TYPE_BOOL:	*((deUint32*)compPtr)	= rnd.getBool() ? rnd.getUint32()|1u : 0u;		break;
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						default:
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							DE_ASSERT(false);
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateValues (const BufferLayout& layout, const vector<BlockDataPtr>& blockPointers, deUint32 seed)
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random	rnd			(seed);
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	numBlocks	= (int)layout.blocks.size();
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numBlocks == (int)blockPointers.size());
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&	blockLayout	= layout.blocks[blockNdx];
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockDataPtr&		blockPtr	= blockPointers[blockNdx];
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numEntries	= (int)layout.blocks[blockNdx].activeVarIndices.size();
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const int					varNdx		= blockLayout.activeVarIndices[entryNdx];
7978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const BufferVarLayoutEntry&	varEntry	= layout.bufferVars[varNdx];
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			generateValue(varEntry, blockPtr.lastUnsizedArraySize, blockPtr.ptr, rnd);
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shader generator.
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* getCompareFuncForType (glu::DataType type)
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT:			return "bool compare_float    (highp float a, highp float b)  { return abs(a - b) < 0.05; }\n";
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC2:		return "bool compare_vec2     (highp vec2 a, highp vec2 b)    { return compare_float(a.x, b.x)&&compare_float(a.y, b.y); }\n";
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC3:		return "bool compare_vec3     (highp vec3 a, highp vec3 b)    { return compare_float(a.x, b.x)&&compare_float(a.y, b.y)&&compare_float(a.z, b.z); }\n";
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC4:		return "bool compare_vec4     (highp vec4 a, highp vec4 b)    { return compare_float(a.x, b.x)&&compare_float(a.y, b.y)&&compare_float(a.z, b.z)&&compare_float(a.w, b.w); }\n";
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2:		return "bool compare_mat2     (highp mat2 a, highp mat2 b)    { return compare_vec2(a[0], b[0])&&compare_vec2(a[1], b[1]); }\n";
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2X3:	return "bool compare_mat2x3   (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])&&compare_vec3(a[1], b[1]); }\n";
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2X4:	return "bool compare_mat2x4   (highp mat2x4 a, highp mat2x4 b){ return compare_vec4(a[0], b[0])&&compare_vec4(a[1], b[1]); }\n";
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3X2:	return "bool compare_mat3x2   (highp mat3x2 a, highp mat3x2 b){ return compare_vec2(a[0], b[0])&&compare_vec2(a[1], b[1])&&compare_vec2(a[2], b[2]); }\n";
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3:		return "bool compare_mat3     (highp mat3 a, highp mat3 b)    { return compare_vec3(a[0], b[0])&&compare_vec3(a[1], b[1])&&compare_vec3(a[2], b[2]); }\n";
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3X4:	return "bool compare_mat3x4   (highp mat3x4 a, highp mat3x4 b){ return compare_vec4(a[0], b[0])&&compare_vec4(a[1], b[1])&&compare_vec4(a[2], b[2]); }\n";
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4X2:	return "bool compare_mat4x2   (highp mat4x2 a, highp mat4x2 b){ return compare_vec2(a[0], b[0])&&compare_vec2(a[1], b[1])&&compare_vec2(a[2], b[2])&&compare_vec2(a[3], b[3]); }\n";
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4X3:	return "bool compare_mat4x3   (highp mat4x3 a, highp mat4x3 b){ return compare_vec3(a[0], b[0])&&compare_vec3(a[1], b[1])&&compare_vec3(a[2], b[2])&&compare_vec3(a[3], b[3]); }\n";
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4:		return "bool compare_mat4     (highp mat4 a, highp mat4 b)    { return compare_vec4(a[0], b[0])&&compare_vec4(a[1], b[1])&&compare_vec4(a[2], b[2])&&compare_vec4(a[3], b[3]); }\n";
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT:				return "bool compare_int      (highp int a, highp int b)      { return a == b; }\n";
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC2:		return "bool compare_ivec2    (highp ivec2 a, highp ivec2 b)  { return a == b; }\n";
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC3:		return "bool compare_ivec3    (highp ivec3 a, highp ivec3 b)  { return a == b; }\n";
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_VEC4:		return "bool compare_ivec4    (highp ivec4 a, highp ivec4 b)  { return a == b; }\n";
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT:			return "bool compare_uint     (highp uint a, highp uint b)    { return a == b; }\n";
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC2:		return "bool compare_uvec2    (highp uvec2 a, highp uvec2 b)  { return a == b; }\n";
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC3:		return "bool compare_uvec3    (highp uvec3 a, highp uvec3 b)  { return a == b; }\n";
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_VEC4:		return "bool compare_uvec4    (highp uvec4 a, highp uvec4 b)  { return a == b; }\n";
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL:			return "bool compare_bool     (bool a, bool b)                { return a == b; }\n";
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC2:		return "bool compare_bvec2    (bvec2 a, bvec2 b)              { return a == b; }\n";
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC3:		return "bool compare_bvec3    (bvec3 a, bvec3 b)              { return a == b; }\n";
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_BOOL_VEC4:		return "bool compare_bvec4    (bvec4 a, bvec4 b)              { return a == b; }\n";
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid getCompareDependencies (std::set<glu::DataType>& compareFuncs, glu::DataType basicType)
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (basicType)
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC2:
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC3:
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC4:
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(glu::TYPE_FLOAT);
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(basicType);
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2:
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2X3:
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT2X4:
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3X2:
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3:
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT3X4:
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4X2:
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4X3:
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_MAT4:
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(glu::TYPE_FLOAT);
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)));
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(basicType);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			compareFuncs.insert(basicType);
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const VarType& type)
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type.isStructType())
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (StructType::ConstIterator iter = type.getStructPtr()->begin(); iter != type.getStructPtr()->end(); ++iter)
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			collectUniqueBasicTypes(basicTypes, iter->getType());
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (type.isArrayType())
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		collectUniqueBasicTypes(basicTypes, type.getElementType());
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(type.isBasicType());
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		basicTypes.insert(type.getBasicType());
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const BufferBlock& bufferBlock)
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (BufferBlock::const_iterator iter = bufferBlock.begin(); iter != bufferBlock.end(); ++iter)
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		collectUniqueBasicTypes(basicTypes, iter->getType());
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const ShaderInterface& interface)
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < interface.getNumBlocks(); ++ndx)
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		collectUniqueBasicTypes(basicTypes, interface.getBlock(ndx));
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateCompareFuncs (std::ostream& str, const ShaderInterface& interface)
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::set<glu::DataType> types;
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::set<glu::DataType> compareFuncs;
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Collect unique basic types
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	collectUniqueBasicTypes(types, interface);
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Set of compare functions required
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::set<glu::DataType>::const_iterator iter = types.begin(); iter != types.end(); ++iter)
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		getCompareDependencies(compareFuncs, *iter);
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int type = 0; type < glu::TYPE_LAST; ++type)
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (compareFuncs.find(glu::DataType(type)) != compareFuncs.end())
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << getCompareFuncForType(glu::DataType(type));
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Indent
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int level;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Indent (int level_) : level(level_) {}
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const Indent& indent)
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < indent.level; i++)
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << "\t";
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateDeclaration (std::ostream& src, const BufferVar& bufferVar, int indentLevel)
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [pyry] Qualifiers
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((bufferVar.getFlags() & LAYOUT_MASK) != 0)
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << "layout(" << LayoutFlagsFmt(bufferVar.getFlags() & LAYOUT_MASK) << ") ";
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << glu::declare(bufferVar.getType(), bufferVar.getName(), indentLevel);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateDeclaration (std::ostream& src, const BufferBlock& block, int bindingPoint)
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "layout(";
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((block.getFlags() & LAYOUT_MASK) != 0)
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK) << ", ";
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "binding = " << bindingPoint;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << ") ";
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "buffer " << block.getBlockName();
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "\n{\n";
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (BufferBlock::const_iterator varIter = block.begin(); varIter != block.end(); varIter++)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << Indent(1);
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		generateDeclaration(src, *varIter, 1 /* indent level */);
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << ";\n";
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "}";
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.getInstanceName() != DE_NULL)
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << " " << block.getInstanceName();
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (block.isArray())
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << "[" << block.getArraySize() << "]";
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!block.isArray());
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << ";\n";
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateImmMatrixSrc (std::ostream& src, glu::DataType basicType, int matrixStride, bool isRowMajor, const void* valuePtr)
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(glu::isDataTypeMatrix(basicType));
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		compSize		= sizeof(deUint32);
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numRows			= glu::getDataTypeMatrixNumRows(basicType);
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numCols			= glu::getDataTypeMatrixNumColumns(basicType);
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << glu::getDataTypeName(basicType) << "(";
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Constructed in column-wise order.
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int colNdx = 0; colNdx < numCols; colNdx++)
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8*	compPtr	= (const deUint8*)valuePtr + (isRowMajor ? rowNdx*matrixStride + colNdx*compSize
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				: colNdx*matrixStride + rowNdx*compSize);
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (colNdx > 0 || rowNdx > 0)
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				src << ", ";
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << de::floatToString(*((const float*)compPtr), 1);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << ")";
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateImmScalarVectorSrc (std::ostream& src, glu::DataType basicType, const void* valuePtr)
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(glu::isDataTypeFloatOrVec(basicType)	||
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  glu::isDataTypeIntOrIVec(basicType)	||
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  glu::isDataTypeUintOrUVec(basicType)	||
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  glu::isDataTypeBoolOrBVec(basicType));
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				compSize		= sizeof(deUint32);
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (scalarSize > 1)
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << glu::getDataTypeName(basicType) << "(";
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8* compPtr = (const deUint8*)valuePtr + scalarNdx*compSize;
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (scalarNdx > 0)
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << ", ";
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (scalarType)
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_FLOAT:	src << de::floatToString(*((const float*)compPtr), 1);			break;
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_INT:		src << *((const int*)compPtr);									break;
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_UINT:	src << *((const deUint32*)compPtr) << "u";						break;
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_BOOL:	src << (*((const deUint32*)compPtr) != 0u ? "true" : "false");	break;
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (scalarSize > 1)
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << ")";
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring getAPIName (const BufferBlock& block, const BufferVar& var, const glu::TypeComponentVector& accessPath)
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream name;
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.getInstanceName())
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name << block.getBlockName() << ".";
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << var.getName();
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (glu::TypeComponentVector::const_iterator pathComp = accessPath.begin(); pathComp != accessPath.end(); pathComp++)
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pathComp->type == glu::VarTypeComponent::STRUCT_MEMBER)
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VarType		curType		= glu::getVarType(var.getType(), accessPath.begin(), pathComp);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const StructType*	structPtr	= curType.getStructPtr();
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "." << structPtr->getMember(pathComp->index).getName();
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (pathComp->type == glu::VarTypeComponent::ARRAY_ELEMENT)
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (pathComp == accessPath.begin() || (pathComp+1) == accessPath.end())
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "[0]"; // Top- / bottom-level array
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				name << "[" << pathComp->index << "]";
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return name.str();
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring getShaderName (const BufferBlock& block, int instanceNdx, const BufferVar& var, const glu::TypeComponentVector& accessPath)
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream name;
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (block.getInstanceName())
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name << block.getInstanceName();
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (block.isArray())
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "[" << instanceNdx << "]";
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name << ".";
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(instanceNdx == 0);
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	name << var.getName();
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (glu::TypeComponentVector::const_iterator pathComp = accessPath.begin(); pathComp != accessPath.end(); pathComp++)
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pathComp->type == glu::VarTypeComponent::STRUCT_MEMBER)
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const VarType		curType		= glu::getVarType(var.getType(), accessPath.begin(), pathComp);
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const StructType*	structPtr	= curType.getStructPtr();
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "." << structPtr->getMember(pathComp->index).getName();
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (pathComp->type == glu::VarTypeComponent::ARRAY_ELEMENT)
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			name << "[" << pathComp->index << "]";
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return name.str();
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeOffset (const BufferVarLayoutEntry& varLayout, const glu::TypeComponentVector& accessPath)
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	topLevelNdx		= (accessPath.size() > 1 && accessPath.front().type == glu::VarTypeComponent::ARRAY_ELEMENT) ? accessPath.front().index : 0;
11148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	bottomLevelNdx	= (!accessPath.empty() && accessPath.back().type == glu::VarTypeComponent::ARRAY_ELEMENT) ? accessPath.back().index : 0;
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return varLayout.offset + varLayout.topLevelArrayStride*topLevelNdx + varLayout.arrayStride*bottomLevelNdx;
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateCompareSrc (
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostream&				src,
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*					resultVar,
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferLayout&			bufferLayout,
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferBlock&			block,
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							instanceNdx,
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BlockDataPtr&			blockPtr,
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferVar&			bufVar,
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::SubTypeAccess&	accessPath)
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType curType = accessPath.getType();
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (curType.isArrayType())
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = curType.getArraySize() == VarType::UNSIZED_ARRAY ? block.getLastUnsizedArraySize(instanceNdx) : curType.getArraySize();
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elemNdx = 0; elemNdx < arraySize; elemNdx++)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			generateCompareSrc(src, resultVar, bufferLayout, block, instanceNdx, blockPtr, bufVar, accessPath.element(elemNdx));
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (curType.isStructType())
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numMembers = curType.getStructPtr()->getNumMembers();
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < numMembers; memberNdx++)
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			generateCompareSrc(src, resultVar, bufferLayout, block, instanceNdx, blockPtr, bufVar, accessPath.member(memberNdx));
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(curType.isBasicType());
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	apiName	= getAPIName(block, bufVar, accessPath.getPath());
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		varNdx	= bufferLayout.getVariableIndex(apiName);
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(varNdx >= 0);
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	varLayout		= bufferLayout.bufferVars[varNdx];
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string				shaderName		= getShaderName(block, instanceNdx, bufVar, accessPath.getPath());
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType			basicType		= curType.getBasicType();
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					isMatrix		= glu::isDataTypeMatrix(basicType);
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*					typeName		= glu::getDataTypeName(basicType);
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const void*					valuePtr		= (const deUint8*)blockPtr.ptr + computeOffset(varLayout, accessPath.getPath());
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << "\t" << resultVar << " = " << resultVar << " && compare_" << typeName << "(" << shaderName << ", ";
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isMatrix)
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateImmMatrixSrc(src, basicType, varLayout.matrixStride, varLayout.isRowMajor, valuePtr);
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateImmScalarVectorSrc(src, basicType, valuePtr);
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << ");\n";
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateCompareSrc (std::ostream& src, const char* resultVar, const ShaderInterface& interface, const BufferLayout& layout, const vector<BlockDataPtr>& blockPointers)
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int declNdx = 0; declNdx < interface.getNumBlocks(); declNdx++)
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&	block			= interface.getBlock(declNdx);
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isArray			= block.isArray();
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numInstances	= isArray ? block.getArraySize() : 1;
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!isArray || block.getInstanceName());
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string		instanceName	= block.getBlockName() + (isArray ? "[" + de::toString(instanceNdx) + "]" : string(""));
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			blockNdx		= layout.getBlockIndex(instanceName);
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr&	blockPtr		= blockPointers[blockNdx];
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (BufferBlock::const_iterator varIter = block.begin(); varIter != block.end(); varIter++)
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVar& bufVar = *varIter;
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if ((bufVar.getFlags() & ACCESS_READ) == 0)
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue; // Don't read from that variable.
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateCompareSrc(src, resultVar, layout, block, instanceNdx, blockPtr, bufVar, glu::SubTypeAccess(bufVar.getType()));
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-10-14 pyry] Almost identical to generateCompareSrc - unify?
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateWriteSrc (
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostream&				src,
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferLayout&			bufferLayout,
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferBlock&			block,
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							instanceNdx,
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BlockDataPtr&			blockPtr,
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferVar&			bufVar,
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::SubTypeAccess&	accessPath)
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType curType = accessPath.getType();
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (curType.isArrayType())
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = curType.getArraySize() == VarType::UNSIZED_ARRAY ? block.getLastUnsizedArraySize(instanceNdx) : curType.getArraySize();
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elemNdx = 0; elemNdx < arraySize; elemNdx++)
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			generateWriteSrc(src, bufferLayout, block, instanceNdx, blockPtr, bufVar, accessPath.element(elemNdx));
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (curType.isStructType())
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numMembers = curType.getStructPtr()->getNumMembers();
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < numMembers; memberNdx++)
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			generateWriteSrc(src, bufferLayout, block, instanceNdx, blockPtr, bufVar, accessPath.member(memberNdx));
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(curType.isBasicType());
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	apiName	= getAPIName(block, bufVar, accessPath.getPath());
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		varNdx	= bufferLayout.getVariableIndex(apiName);
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(varNdx >= 0);
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	varLayout		= bufferLayout.bufferVars[varNdx];
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string				shaderName		= getShaderName(block, instanceNdx, bufVar, accessPath.getPath());
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType			basicType		= curType.getBasicType();
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					isMatrix		= glu::isDataTypeMatrix(basicType);
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const void*					valuePtr		= (const deUint8*)blockPtr.ptr + computeOffset(varLayout, accessPath.getPath());
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << "\t" << shaderName << " = ";
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isMatrix)
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateImmMatrixSrc(src, basicType, varLayout.matrixStride, varLayout.isRowMajor, valuePtr);
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateImmScalarVectorSrc(src, basicType, valuePtr);
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			src << ";\n";
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateWriteSrc (std::ostream& src, const ShaderInterface& interface, const BufferLayout& layout, const vector<BlockDataPtr>& blockPointers)
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int declNdx = 0; declNdx < interface.getNumBlocks(); declNdx++)
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&	block			= interface.getBlock(declNdx);
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isArray			= block.isArray();
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numInstances	= isArray ? block.getArraySize() : 1;
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!isArray || block.getInstanceName());
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string		instanceName	= block.getBlockName() + (isArray ? "[" + de::toString(instanceNdx) + "]" : string(""));
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			blockNdx		= layout.getBlockIndex(instanceName);
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr&	blockPtr		= blockPointers[blockNdx];
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (BufferBlock::const_iterator varIter = block.begin(); varIter != block.end(); varIter++)
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVar& bufVar = *varIter;
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if ((bufVar.getFlags() & ACCESS_WRITE) == 0)
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue; // Don't write to that variable.
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				generateWriteSrc(src, layout, block, instanceNdx, blockPtr, bufVar, glu::SubTypeAccess(bufVar.getType()));
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring generateComputeShader (glu::GLSLVersion glslVersion, const ShaderInterface& interface, const BufferLayout& layout, const vector<BlockDataPtr>& comparePtrs, const vector<BlockDataPtr>& writePtrs)
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream src;
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion == glu::GLSL_VERSION_430);
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "layout(local_size_x = 1) in;\n";
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "\n";
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<const StructType*> namedStructs;
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	interface.getNamedStructs(namedStructs);
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src << glu::declare(*structIter) << ";\n";
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int bindingPoint = 0;
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockNdx = 0; blockNdx < interface.getNumBlocks(); blockNdx++)
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferBlock& block = interface.getBlock(blockNdx);
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			generateDeclaration(src, block, bindingPoint);
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bindingPoint += block.isArray() ? block.getArraySize() : 1;
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Atomic counter for counting passed invocations.
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "\nlayout(binding = 0) uniform atomic_uint ac_numPassed;\n";
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Comparison utilities.
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "\n";
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateCompareFuncs(src, interface);
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "\n"
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "void main (void)\n"
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "{\n"
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "	bool allOk = true;\n";
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Value compare.
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateCompareSrc(src, "allOk", interface, layout, comparePtrs);
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "	if (allOk)\n"
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "		atomicCounterIncrement(ac_numPassed);\n"
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Value write.
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateWriteSrc(src, interface, layout, writePtrs);
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	src << "}\n";
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return src.str();
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid getGLBufferLayout (const glw::Functions& gl, BufferLayout& layout, deUint32 program)
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		numActiveBufferVars	= 0;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		numActiveBlocks		= 0;
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getProgramInterfaceiv(program, GL_BUFFER_VARIABLE,		GL_ACTIVE_RESOURCES,	&numActiveBufferVars);
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK,	GL_ACTIVE_RESOURCES,	&numActiveBlocks);
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get number of buffer variables and buffer blocks");
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Block entries.
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	layout.blocks.resize(numActiveBlocks);
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numActiveBlocks; blockNdx++)
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BlockLayoutEntry&	entry				= layout.blocks[blockNdx];
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32		queryParams[]		= { GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES, GL_NAME_LENGTH };
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					returnValues[]		= { 0, 0, 0 };
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(queryParams) == DE_LENGTH_OF_ARRAY(returnValues));
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int returnLength = 0;
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, (deUint32)blockNdx, DE_LENGTH_OF_ARRAY(queryParams), &queryParams[0], DE_LENGTH_OF_ARRAY(returnValues), &returnLength, &returnValues[0]);
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv(GL_SHADER_STORAGE_BLOCK) failed");
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (returnLength != DE_LENGTH_OF_ARRAY(returnValues))
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceiv(GL_SHADER_STORAGE_BLOCK) returned wrong number of values");
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.size = returnValues[0];
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Query active variables
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (returnValues[1] > 0)
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		numBlockVars	= returnValues[1];
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	queryArg		= GL_ACTIVE_VARIABLES;
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				retLength		= 0;
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.activeVarIndices.resize(numBlockVars);
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, (deUint32)blockNdx, 1, &queryArg, numBlockVars, &retLength, &entry.activeVarIndices[0]);
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv(GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_VARIABLES) failed");
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (retLength != numBlockVars)
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceiv(GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_VARIABLES) returned wrong number of values");
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Query name
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (returnValues[2] > 0)
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		nameLen		= returnValues[2];
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				retLen		= 0;
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<char>	name		(nameLen);
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, (deUint32)blockNdx, (glw::GLsizei)name.size(), &retLen, &name[0]);
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName(GL_SHADER_STORAGE_BLOCK) failed");
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (retLen+1 != nameLen)
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceName(GL_SHADER_STORAGE_BLOCK) returned invalid name. Number of characters written is inconsistent with NAME_LENGTH property.");
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (name[nameLen-1] != 0)
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceName(GL_SHADER_STORAGE_BLOCK) returned invalid name. Expected null terminator at index " + de::toString(nameLen-1));
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name = &name[0];
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("glGetProgramResourceiv() returned invalid GL_NAME_LENGTH");
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	layout.bufferVars.resize(numActiveBufferVars);
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int bufVarNdx = 0; bufVarNdx < numActiveBufferVars; bufVarNdx++)
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BufferVarLayoutEntry&	entry				= layout.bufferVars[bufVarNdx];
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			queryParams[] =
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_BLOCK_INDEX,					// 0
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_TYPE,						// 1
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_OFFSET,						// 2
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_ARRAY_SIZE,					// 3
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_ARRAY_STRIDE,				// 4
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_MATRIX_STRIDE,				// 5
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_TOP_LEVEL_ARRAY_SIZE,		// 6
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_TOP_LEVEL_ARRAY_STRIDE,		// 7
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_IS_ROW_MAJOR,				// 8
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GL_NAME_LENGTH					// 9
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int returnValues[DE_LENGTH_OF_ARRAY(queryParams)];
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(queryParams) == DE_LENGTH_OF_ARRAY(returnValues));
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int returnLength = 0;
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceiv(program, GL_BUFFER_VARIABLE, (deUint32)bufVarNdx, DE_LENGTH_OF_ARRAY(queryParams), &queryParams[0], DE_LENGTH_OF_ARRAY(returnValues), &returnLength, &returnValues[0]);
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv(GL_BUFFER_VARIABLE) failed");
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (returnLength != DE_LENGTH_OF_ARRAY(returnValues))
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceiv(GL_BUFFER_VARIABLE) returned wrong number of values");
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Map values
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.blockNdx				= returnValues[0];
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.type					= glu::getDataTypeFromGLType(returnValues[1]);
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.offset				= returnValues[2];
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.arraySize				= returnValues[3];
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.arrayStride			= returnValues[4];
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.matrixStride			= returnValues[5];
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.topLevelArraySize		= returnValues[6];
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.topLevelArrayStride	= returnValues[7];
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		entry.isRowMajor			= returnValues[8] != 0;
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Query name
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(queryParams[9] == GL_NAME_LENGTH);
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (returnValues[9] > 0)
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		nameLen		= returnValues[9];
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				retLen		= 0;
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			vector<char>	name		(nameLen);
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getProgramResourceName(program, GL_BUFFER_VARIABLE, (deUint32)bufVarNdx, (glw::GLsizei)name.size(), &retLen, &name[0]);
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName(GL_BUFFER_VARIABLE) failed");
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (retLen+1 != nameLen)
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceName(GL_BUFFER_VARIABLE) returned invalid name. Number of characters written is inconsistent with NAME_LENGTH property.");
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (name[nameLen-1] != 0)
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("glGetProgramResourceName(GL_BUFFER_VARIABLE) returned invalid name. Expected null terminator at index " + de::toString(nameLen-1));
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			entry.name = &name[0];
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("glGetProgramResourceiv() returned invalid GL_NAME_LENGTH");
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyBufferVarData (const BufferVarLayoutEntry& dstEntry, const BlockDataPtr& dstBlockPtr, const BufferVarLayoutEntry& srcEntry, const BlockDataPtr& srcBlockPtr)
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstEntry.arraySize <= srcEntry.arraySize);
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstEntry.topLevelArraySize <= srcEntry.topLevelArraySize);
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstBlockPtr.lastUnsizedArraySize <= srcBlockPtr.lastUnsizedArraySize);
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstEntry.type == srcEntry.type);
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* const			dstBasePtr			= (deUint8*)dstBlockPtr.ptr + dstEntry.offset;
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8* const	srcBasePtr			= (const deUint8*)srcBlockPtr.ptr + srcEntry.offset;
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				scalarSize			= glu::getDataTypeScalarSize(dstEntry.type);
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool				isMatrix			= glu::isDataTypeMatrix(dstEntry.type);
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				compSize			= sizeof(deUint32);
14828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				dstArraySize		= dstEntry.arraySize == 0 ? dstBlockPtr.lastUnsizedArraySize : dstEntry.arraySize;
14838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				dstArrayStride		= dstEntry.arrayStride;
14848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				dstTopLevelSize		= dstEntry.topLevelArraySize == 0 ? dstBlockPtr.lastUnsizedArraySize : dstEntry.topLevelArraySize;
14858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				dstTopLevelStride	= dstEntry.topLevelArrayStride;
14868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				srcArraySize		= srcEntry.arraySize == 0 ? srcBlockPtr.lastUnsizedArraySize : srcEntry.arraySize;
14878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				srcArrayStride		= srcEntry.arrayStride;
14888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				srcTopLevelSize		= srcEntry.topLevelArraySize == 0 ? srcBlockPtr.lastUnsizedArraySize : srcEntry.topLevelArraySize;
14898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				srcTopLevelStride	= srcEntry.topLevelArrayStride;
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstArraySize <= srcArraySize && dstTopLevelSize <= srcTopLevelSize);
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(srcArraySize && srcTopLevelSize);
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int topElemNdx = 0; topElemNdx < dstTopLevelSize; topElemNdx++)
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* const			dstTopPtr	= dstBasePtr + topElemNdx*dstTopLevelStride;
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8* const	srcTopPtr	= srcBasePtr + topElemNdx*srcTopLevelStride;
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elementNdx = 0; elementNdx < dstArraySize; elementNdx++)
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8* const			dstElemPtr	= dstTopPtr + elementNdx*dstArrayStride;
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8* const	srcElemPtr	= srcTopPtr + elementNdx*srcArrayStride;
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isMatrix)
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	numRows	= glu::getDataTypeMatrixNumRows(dstEntry.type);
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	numCols	= glu::getDataTypeMatrixNumColumns(dstEntry.type);
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int colNdx = 0; colNdx < numCols; colNdx++)
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						deUint8*		dstCompPtr	= dstElemPtr + (dstEntry.isRowMajor ? rowNdx*dstEntry.matrixStride + colNdx*compSize
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						: colNdx*dstEntry.matrixStride + rowNdx*compSize);
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const deUint8*	srcCompPtr	= srcElemPtr + (srcEntry.isRowMajor ? rowNdx*srcEntry.matrixStride + colNdx*compSize
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						: colNdx*srcEntry.matrixStride + rowNdx*compSize);
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT((deIntptr)(srcCompPtr + compSize) - (deIntptr)srcBlockPtr.ptr <= (deIntptr)srcBlockPtr.size);
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT((deIntptr)(dstCompPtr + compSize) - (deIntptr)dstBlockPtr.ptr <= (deIntptr)dstBlockPtr.size);
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						deMemcpy(dstCompPtr, srcCompPtr, compSize);
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT((deIntptr)(srcElemPtr + scalarSize*compSize) - (deIntptr)srcBlockPtr.ptr <= (deIntptr)srcBlockPtr.size);
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT((deIntptr)(dstElemPtr + scalarSize*compSize) - (deIntptr)dstBlockPtr.ptr <= (deIntptr)dstBlockPtr.size);
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deMemcpy(dstElemPtr, srcElemPtr, scalarSize*compSize);
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyData (const BufferLayout& dstLayout, const vector<BlockDataPtr>& dstBlockPointers, const BufferLayout& srcLayout, const vector<BlockDataPtr>& srcBlockPointers)
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Src layout is used as reference in case of activeVarIndices happens to be incorrect in dstLayout blocks.
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int numBlocks = (int)srcLayout.blocks.size();
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int srcBlockNdx = 0; srcBlockNdx < numBlocks; srcBlockNdx++)
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		srcBlock	= srcLayout.blocks[srcBlockNdx];
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockDataPtr&			srcBlockPtr	= srcBlockPointers[srcBlockNdx];
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							dstBlockNdx	= dstLayout.getBlockIndex(srcBlock.name.c_str());
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (dstBlockNdx >= 0)
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(de::inBounds(dstBlockNdx, 0, (int)dstBlockPointers.size()));
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr& dstBlockPtr = dstBlockPointers[dstBlockNdx];
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (vector<int>::const_iterator srcVarNdxIter = srcBlock.activeVarIndices.begin(); srcVarNdxIter != srcBlock.activeVarIndices.end(); srcVarNdxIter++)
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVarLayoutEntry&	srcEntry	= srcLayout.bufferVars[*srcVarNdxIter];
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int							dstVarNdx	= dstLayout.getVariableIndex(srcEntry.name.c_str());
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (dstVarNdx >= 0)
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					copyBufferVarData(dstLayout.bufferVars[dstVarNdx], dstBlockPtr, srcEntry, srcBlockPtr);
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyNonWrittenData (
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferLayout&			layout,
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferBlock&			block,
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							instanceNdx,
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BlockDataPtr&			srcBlockPtr,
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BlockDataPtr&			dstBlockPtr,
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BufferVar&			bufVar,
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::SubTypeAccess&	accessPath)
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType curType = accessPath.getType();
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (curType.isArrayType())
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int arraySize = curType.getArraySize() == VarType::UNSIZED_ARRAY ? block.getLastUnsizedArraySize(instanceNdx) : curType.getArraySize();
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elemNdx = 0; elemNdx < arraySize; elemNdx++)
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			copyNonWrittenData(layout, block, instanceNdx, srcBlockPtr, dstBlockPtr, bufVar, accessPath.element(elemNdx));
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (curType.isStructType())
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int numMembers = curType.getStructPtr()->getNumMembers();
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int memberNdx = 0; memberNdx < numMembers; memberNdx++)
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			copyNonWrittenData(layout, block, instanceNdx, srcBlockPtr, dstBlockPtr, bufVar, accessPath.member(memberNdx));
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(curType.isBasicType());
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	apiName	= getAPIName(block, bufVar, accessPath.getPath());
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		varNdx	= layout.getVariableIndex(apiName);
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(varNdx >= 0);
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry& varLayout = layout.bufferVars[varNdx];
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			copyBufferVarData(varLayout, dstBlockPtr, varLayout, srcBlockPtr);
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid copyNonWrittenData (const ShaderInterface& interface, const BufferLayout& layout, const vector<BlockDataPtr>& srcPtrs, const vector<BlockDataPtr>& dstPtrs)
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int declNdx = 0; declNdx < interface.getNumBlocks(); declNdx++)
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&	block			= interface.getBlock(declNdx);
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isArray			= block.isArray();
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numInstances	= isArray ? block.getArraySize() : 1;
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!isArray || block.getInstanceName());
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string		instanceName	= block.getBlockName() + (isArray ? "[" + de::toString(instanceNdx) + "]" : string(""));
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			blockNdx		= layout.getBlockIndex(instanceName);
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr&	srcBlockPtr		= srcPtrs[blockNdx];
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr&	dstBlockPtr		= dstPtrs[blockNdx];
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (BufferBlock::const_iterator varIter = block.begin(); varIter != block.end(); varIter++)
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVar& bufVar = *varIter;
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (bufVar.getFlags() & ACCESS_WRITE)
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue;
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				copyNonWrittenData(layout, block, instanceNdx, srcBlockPtr, dstBlockPtr, bufVar, glu::SubTypeAccess(bufVar.getType()));
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareComponents (glu::DataType scalarType, const void* ref, const void* res, int numComps)
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (scalarType == glu::TYPE_FLOAT)
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float threshold = 0.05f; // Same as used in shaders - should be fine for values being used.
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numComps; ndx++)
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refVal		= *((const float*)ref + ndx);
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		resVal		= *((const float*)res + ndx);
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (deFloatAbs(resVal - refVal) >= threshold)
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (scalarType == glu::TYPE_BOOL)
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numComps; ndx++)
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	refVal		= *((const deUint32*)ref + ndx);
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	resVal		= *((const deUint32*)res + ndx);
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if ((refVal != 0) != (resVal != 0))
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(scalarType == glu::TYPE_INT || scalarType == glu::TYPE_UINT);
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numComps; ndx++)
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	refVal		= *((const deUint32*)ref + ndx);
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	resVal		= *((const deUint32*)res + ndx);
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (refVal != resVal)
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareBufferVarData (tcu::TestLog& log, const BufferVarLayoutEntry& refEntry, const BlockDataPtr& refBlockPtr, const BufferVarLayoutEntry& resEntry, const BlockDataPtr& resBlockPtr)
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(resEntry.arraySize <= refEntry.arraySize);
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(resEntry.topLevelArraySize <= refEntry.topLevelArraySize);
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(resBlockPtr.lastUnsizedArraySize <= refBlockPtr.lastUnsizedArraySize);
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(resEntry.type == refEntry.type);
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* const			resBasePtr			= (deUint8*)resBlockPtr.ptr + resEntry.offset;
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8* const	refBasePtr			= (const deUint8*)refBlockPtr.ptr + refEntry.offset;
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		scalarType			= glu::getDataTypeScalarType(refEntry.type);
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				scalarSize			= glu::getDataTypeScalarSize(resEntry.type);
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool				isMatrix			= glu::isDataTypeMatrix(resEntry.type);
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				compSize			= sizeof(deUint32);
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				maxPrints			= 3;
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numFailed			= 0;
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				resArraySize		= resEntry.arraySize == 0 ? resBlockPtr.lastUnsizedArraySize : resEntry.arraySize;
16938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				resArrayStride		= resEntry.arrayStride;
16948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				resTopLevelSize		= resEntry.topLevelArraySize == 0 ? resBlockPtr.lastUnsizedArraySize : resEntry.topLevelArraySize;
16958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				resTopLevelStride	= resEntry.topLevelArrayStride;
16968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				refArraySize		= refEntry.arraySize == 0 ? refBlockPtr.lastUnsizedArraySize : refEntry.arraySize;
16978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				refArrayStride		= refEntry.arrayStride;
16988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				refTopLevelSize		= refEntry.topLevelArraySize == 0 ? refBlockPtr.lastUnsizedArraySize : refEntry.topLevelArraySize;
16998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int				refTopLevelStride	= refEntry.topLevelArrayStride;
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(resArraySize <= refArraySize && resTopLevelSize <= refTopLevelSize);
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(refArraySize && refTopLevelSize);
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int topElemNdx = 0; topElemNdx < resTopLevelSize; topElemNdx++)
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* const			resTopPtr	= resBasePtr + topElemNdx*resTopLevelStride;
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8* const	refTopPtr	= refBasePtr + topElemNdx*refTopLevelStride;
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int elementNdx = 0; elementNdx < resArraySize; elementNdx++)
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8* const			resElemPtr	= resTopPtr + elementNdx*resArrayStride;
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8* const	refElemPtr	= refTopPtr + elementNdx*refArrayStride;
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isMatrix)
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	numRows	= glu::getDataTypeMatrixNumRows(resEntry.type);
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	numCols	= glu::getDataTypeMatrixNumColumns(resEntry.type);
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool		isOk	= true;
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int colNdx = 0; colNdx < numCols; colNdx++)
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						deUint8*		resCompPtr	= resElemPtr + (resEntry.isRowMajor ? rowNdx*resEntry.matrixStride + colNdx*compSize
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						: colNdx*resEntry.matrixStride + rowNdx*compSize);
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const deUint8*	refCompPtr	= refElemPtr + (refEntry.isRowMajor ? rowNdx*refEntry.matrixStride + colNdx*compSize
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						: colNdx*refEntry.matrixStride + rowNdx*compSize);
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT((deIntptr)(refCompPtr + compSize) - (deIntptr)refBlockPtr.ptr <= (deIntptr)refBlockPtr.size);
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						DE_ASSERT((deIntptr)(resCompPtr + compSize) - (deIntptr)resBlockPtr.ptr <= (deIntptr)resBlockPtr.size);
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						isOk = isOk && compareComponents(scalarType, resCompPtr, refCompPtr, 1);
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (numFailed < maxPrints)
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						std::ostringstream expected, got;
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						generateImmMatrixSrc(expected, refEntry.type, refEntry.matrixStride, refEntry.isRowMajor, refElemPtr);
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						generateImmMatrixSrc(got, resEntry.type, resEntry.matrixStride, resEntry.isRowMajor, resElemPtr);
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						log << TestLog::Message << "ERROR: mismatch in " << refEntry.name << ", top-level ndx " << topElemNdx << ", bottom-level ndx " << elementNdx << ":\n"
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< "  expected " << expected.str() << "\n"
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< "  got " << got.str()
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< TestLog::EndMessage;
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT((deIntptr)(refElemPtr + scalarSize*compSize) - (deIntptr)refBlockPtr.ptr <= (deIntptr)refBlockPtr.size);
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT((deIntptr)(resElemPtr + scalarSize*compSize) - (deIntptr)resBlockPtr.ptr <= (deIntptr)resBlockPtr.size);
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool isOk = compareComponents(scalarType, resElemPtr, refElemPtr, scalarSize);
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (numFailed < maxPrints)
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						std::ostringstream expected, got;
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						generateImmScalarVectorSrc(expected, refEntry.type, refElemPtr);
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						generateImmScalarVectorSrc(got, resEntry.type, resElemPtr);
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						log << TestLog::Message << "ERROR: mismatch in " << refEntry.name << ", top-level ndx " << topElemNdx << ", bottom-level ndx " << elementNdx << ":\n"
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< "  expected " << expected.str() << "\n"
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< "  got " << got.str()
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< TestLog::EndMessage;
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailed >= maxPrints)
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "... (" << numFailed << " failures for " << refEntry.name << " in total)" << TestLog::EndMessage;
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed == 0;
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareData (tcu::TestLog& log, const BufferLayout& refLayout, const vector<BlockDataPtr>& refBlockPointers, const BufferLayout& resLayout, const vector<BlockDataPtr>& resBlockPointers)
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	numBlocks	= (int)refLayout.blocks.size();
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		allOk		= true;
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int refBlockNdx = 0; refBlockNdx < numBlocks; refBlockNdx++)
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		refBlock	= refLayout.blocks[refBlockNdx];
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockDataPtr&			refBlockPtr	= refBlockPointers[refBlockNdx];
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							resBlockNdx	= resLayout.getBlockIndex(refBlock.name.c_str());
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (resBlockNdx >= 0)
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(de::inBounds(resBlockNdx, 0, (int)resBlockPointers.size()));
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockDataPtr& resBlockPtr = resBlockPointers[resBlockNdx];
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (vector<int>::const_iterator refVarNdxIter = refBlock.activeVarIndices.begin(); refVarNdxIter != refBlock.activeVarIndices.end(); refVarNdxIter++)
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVarLayoutEntry&	refEntry	= refLayout.bufferVars[*refVarNdxIter];
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int							resVarNdx	= resLayout.getVariableIndex(refEntry.name.c_str());
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (resVarNdx >= 0)
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const BufferVarLayoutEntry& resEntry = resLayout.bufferVars[resVarNdx];
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					allOk = compareBufferVarData(log, refEntry, refBlockPtr, resEntry, resBlockPtr) && allOk;
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return allOk;
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring getBlockAPIName (const BufferBlock& block, int instanceNdx)
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(block.isArray() || instanceNdx == 0);
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return block.getBlockName() + (block.isArray() ? ("[" + de::toString(instanceNdx) + "]") : string());
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry// \note Some implementations don't report block members in the order they are declared.
18238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry//		 For checking whether size has to be adjusted by some top-level array actual size,
18248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry//		 we only need to know a) whether there is a unsized top-level array, and b)
18258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry//		 what is stride of that array.
18268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic bool hasUnsizedArray (const BufferLayout& layout, const BlockLayoutEntry& entry)
18288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
18298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (vector<int>::const_iterator varNdx = entry.activeVarIndices.begin(); varNdx != entry.activeVarIndices.end(); ++varNdx)
18308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
18318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (isUnsizedArray(layout.bufferVars[*varNdx]))
18328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			return true;
18338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
18348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return false;
18368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
18378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic int getUnsizedArrayStride (const BufferLayout& layout, const BlockLayoutEntry& entry)
18398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
18408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (vector<int>::const_iterator varNdx = entry.activeVarIndices.begin(); varNdx != entry.activeVarIndices.end(); ++varNdx)
18418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
18428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const BufferVarLayoutEntry& varEntry = layout.bufferVars[*varNdx];
18438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (varEntry.arraySize == 0)
18458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			return varEntry.arrayStride;
18468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (varEntry.topLevelArraySize == 0)
18478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			return varEntry.topLevelArrayStride;
18488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
18498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return 0;
18518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
18528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<int> computeBufferSizes (const ShaderInterface& interface, const BufferLayout& layout)
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int> sizes(layout.blocks.size());
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int declNdx = 0; declNdx < interface.getNumBlocks(); declNdx++)
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&	block			= interface.getBlock(declNdx);
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isArray			= block.isArray();
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numInstances	= isArray ? block.getArraySize() : 1;
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string	apiName		= getBlockAPIName(block, instanceNdx);
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		blockNdx	= layout.getBlockIndex(apiName);
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (blockNdx >= 0)
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BlockLayoutEntry&		blockLayout		= layout.blocks[blockNdx];
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int					baseSize		= blockLayout.size;
18728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool					isLastUnsized	= hasUnsizedArray(layout, blockLayout);
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int					lastArraySize	= isLastUnsized ? block.getLastUnsizedArraySize(instanceNdx) : 0;
18748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const int					stride			= isLastUnsized ? getUnsizedArrayStride(layout, blockLayout) : 0;
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				sizes[blockNdx] = baseSize + lastArraySize*stride;
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sizes;
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockDataPtr getBlockDataPtr (const BufferLayout& layout, const BlockLayoutEntry& blockLayout, void* ptr, int bufferSize)
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const bool	isLastUnsized	= hasUnsizedArray(layout, blockLayout);
18878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	baseSize		= blockLayout.size;
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isLastUnsized)
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int		lastArrayStride	= getUnsizedArrayStride(layout, blockLayout);
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		lastArraySize	= (bufferSize-baseSize) / (lastArrayStride ? lastArrayStride : 1);
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(baseSize + lastArraySize*lastArrayStride == bufferSize);
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return BlockDataPtr(ptr, bufferSize, lastArraySize);
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return BlockDataPtr(ptr, bufferSize, 0);
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct RefDataStorage
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint8>			data;
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<BlockDataPtr>	pointers;
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Buffer
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				buffer;
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						size;
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Buffer (deUint32 buffer_, int size_) : buffer(buffer_), size(size_) {}
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Buffer (void) : buffer(0), size(0) {}
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BlockLocation
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						index;
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						offset;
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						size;
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockLocation (int index_, int offset_, int size_) : index(index_), offset(offset_), size(size_) {}
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockLocation (void) : index(0), offset(0), size(0) {}
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid initRefDataStorage (const ShaderInterface& interface, const BufferLayout& layout, RefDataStorage& storage)
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(storage.data.empty() && storage.pointers.empty());
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<int>	bufferSizes = computeBufferSizes(interface, layout);
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					totalSize	= 0;
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<int>::const_iterator sizeIter = bufferSizes.begin(); sizeIter != bufferSizes.end(); ++sizeIter)
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalSize += *sizeIter;
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	storage.data.resize(totalSize);
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Pointers for each block.
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8*	basePtr		= storage.data.empty() ? DE_NULL : &storage.data[0];
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			curOffset	= 0;
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(bufferSizes.size() == layout.blocks.size());
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(totalSize == 0 || basePtr);
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		storage.pointers.resize(layout.blocks.size());
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockLayoutEntry&	blockLayout		= layout.blocks[blockNdx];
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				bufferSize		= bufferSizes[blockNdx];
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			storage.pointers[blockNdx] = getBlockDataPtr(layout, blockLayout, basePtr + curOffset, bufferSize);
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curOffset += bufferSize;
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<BlockDataPtr> blockLocationsToPtrs (const BufferLayout& layout, const vector<BlockLocation>& blockLocations, const vector<void*>& bufPtrs)
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<BlockDataPtr> blockPtrs(blockLocations.size());
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(layout.blocks.size() == blockLocations.size());
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&	blockLayout		= layout.blocks[blockNdx];
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLocation&	location		= blockLocations[blockNdx];
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		blockPtrs[blockNdx] = getBlockDataPtr(layout, blockLayout, (deUint8*)bufPtrs[location.index] + location.offset, location.size);
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return blockPtrs;
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvector<void*> mapBuffers (const glw::Functions& gl, const vector<Buffer>& buffers, deUint32 access)
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<void*> mapPtrs(buffers.size(), DE_NULL);
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)buffers.size(); ndx++)
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (buffers[ndx].size > 0)
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffers[ndx].buffer);
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mapPtrs[ndx] = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffers[ndx].size, access);
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to map buffer");
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_CHECK(mapPtrs[ndx]);
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mapPtrs[ndx] = DE_NULL;
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mapPtrs;
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)buffers.size(); ndx++)
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (mapPtrs[ndx])
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffers[ndx].buffer);
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid unmapBuffers (const glw::Functions& gl, const vector<Buffer>& buffers)
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)buffers.size(); ndx++)
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (buffers[ndx].size > 0)
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffers[ndx].buffer);
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unmap buffer");
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous (utilities)
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BufferManager
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BufferManager	(const glu::RenderContext& renderCtx);
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~BufferManager	(void);
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32					allocBuffer		(void);
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BufferManager	(const BufferManager& other);
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferManager&				operator=		(const BufferManager& other);
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&	m_renderCtx;
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>		m_buffers;
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferManager::BufferManager (const glu::RenderContext& renderCtx)
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_renderCtx(renderCtx)
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferManager::~BufferManager (void)
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_buffers.empty())
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_renderCtx.getFunctions().deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint32 BufferManager::allocBuffer (void)
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 buf = 0;
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_buffers.reserve(m_buffers.size()+1);
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_renderCtx.getFunctions().genBuffers(1, &buf);
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(m_renderCtx.getFunctions().getError(), "Failed to allocate buffer");
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_buffers.push_back(buf);
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf;
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // bb
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace bb;
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// SSBOLayoutCase.
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20753c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySSBOLayoutCase::SSBOLayoutCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, glu::GLSLVersion glslVersion, BufferMode bufferMode)
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(testCtx, name, description)
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_renderCtx	(renderCtx)
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_glslVersion	(glslVersion)
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferMode	(bufferMode)
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion == glu::GLSL_VERSION_430);
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20843c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySSBOLayoutCase::~SSBOLayoutCase (void)
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20883c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySSBOLayoutCase::IterateResult SSBOLayoutCase::iterate (void)
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&					log				= m_testCtx.getLog();
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl				= m_renderCtx.getFunctions();
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferLayout				refLayout;		// std140 / std430 layout.
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferLayout				glLayout;		// Layout reported by GL.
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RefDataStorage				initialData;	// Initial data stored in buffer.
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RefDataStorage				writeData;		// Data written by compute shader.
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BufferManager				bufferManager	(m_renderCtx);
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Buffer>				buffers;		// Buffers allocated for storage
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<BlockLocation>		blockLocations;	// Block locations in storage (index, offset)
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize result to pass.
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeReferenceLayout	(refLayout, m_interface);
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initRefDataStorage		(m_interface, refLayout, initialData);
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initRefDataStorage		(m_interface, refLayout, writeData);
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateValues			(refLayout, initialData.pointers, deStringHash(getName()) ^ 0xad2f7214);
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateValues			(refLayout, writeData.pointers, deStringHash(getName()) ^ 0x25ca4e7);
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	copyNonWrittenData		(m_interface, refLayout, initialData.pointers, writeData.pointers);
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderProgram program(m_renderCtx, glu::ProgramSources() << glu::ComputeSource(generateComputeShader(m_glslVersion, m_interface, refLayout, initialData.pointers, writeData.pointers)));
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << program;
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!program.isOk())
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compile failed.
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return STOP;
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Query layout from GL.
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	getGLBufferLayout(gl, glLayout, program.getProgram());
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Print layout to log.
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ScopedLogSection section(log, "ActiveBufferBlocks", "Active Buffer Blocks");
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockNdx = 0; blockNdx < (int)glLayout.blocks.size(); blockNdx++)
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << blockNdx << ": " << glLayout.blocks[blockNdx] << TestLog::EndMessage;
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ScopedLogSection section(log, "ActiveBufferVars", "Active Buffer Variables");
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int varNdx = 0; varNdx < (int)glLayout.bufferVars.size(); varNdx++)
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << varNdx << ": " << glLayout.bufferVars[varNdx] << TestLog::EndMessage;
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify layouts.
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!checkLayoutIndices(glLayout) || !checkLayoutBounds(glLayout) || !compareTypes(refLayout, glLayout))
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid layout");
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return STOP; // It is not safe to use the given layout.
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!compareStdBlocks(refLayout, glLayout))
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid std140 or std430 layout");
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!compareSharedBlocks(refLayout, glLayout))
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid shared layout");
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!checkIndexQueries(program.getProgram(), glLayout))
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsintent block index query results");
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Allocate GL buffers & compute placement.
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numBlocks		= (int)glLayout.blocks.size();
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>	bufferSizes		= computeBufferSizes(m_interface, glLayout);
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(bufferSizes.size() == glLayout.blocks.size());
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		blockLocations.resize(numBlocks);
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_bufferMode == BUFFERMODE_PER_BLOCK)
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buffers.resize(numBlocks);
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int bufferSize = bufferSizes[blockNdx];
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buffers[blockNdx].size = bufferSize;
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				blockLocations[blockNdx] = BlockLocation(blockNdx, 0, bufferSize);
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(m_bufferMode == BUFFERMODE_SINGLE);
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		bindingAlignment	= 0;
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		totalSize			= 0;
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &bindingAlignment);
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int curOffset = 0;
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(bufferSizes.size() == glLayout.blocks.size());
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int bufferSize = bufferSizes[blockNdx];
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (bindingAlignment > 0)
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						curOffset = deRoundUp32(curOffset, bindingAlignment);
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					blockLocations[blockNdx] = BlockLocation(0, curOffset, bufferSize);
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					curOffset += bufferSize;
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				totalSize = curOffset;
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buffers.resize(1);
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buffers[0].size = totalSize;
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int bufNdx = 0; bufNdx < (int)buffers.size(); bufNdx++)
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		bufferSize	= buffers[bufNdx].size;
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	buffer		= bufferManager.allocBuffer();
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_STATIC_DRAW);
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate buffer");
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buffers[bufNdx].buffer = buffer;
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<void*>			mapPtrs			= mapBuffers(gl, buffers, GL_MAP_WRITE_BIT);
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<BlockDataPtr>	mappedBlockPtrs	= blockLocationsToPtrs(glLayout, blockLocations, mapPtrs);
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		copyData(glLayout, mappedBlockPtrs, refLayout, initialData.pointers);
22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		unmapBuffers(gl, buffers);
22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int bindingPoint = 0;
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockDeclNdx = 0; blockDeclNdx < m_interface.getNumBlocks(); blockDeclNdx++)
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferBlock&	block		= m_interface.getBlock(blockDeclNdx);
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int			numInst		= block.isArray() ? block.getArraySize() : 1;
22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int instNdx = 0; instNdx < numInst; instNdx++)
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string	instName	= getBlockAPIName(block, instNdx);
22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		layoutNdx	= findBlockIndex(glLayout, instName);
22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (layoutNdx >= 0)
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const BlockLocation& blockLoc = blockLocations[layoutNdx];
22448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
22458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (blockLoc.size > 0)
22468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, bindingPoint, buffers[blockLoc.index].buffer, blockLoc.offset, blockLoc.size);
22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bindingPoint += 1;
22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffers");
22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool execOk = execute(program.getProgram());
22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (execOk)
22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<void*>			mapPtrs			= mapBuffers(gl, buffers, GL_MAP_READ_BIT);
22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const vector<BlockDataPtr>	mappedBlockPtrs	= blockLocationsToPtrs(glLayout, blockLocations, mapPtrs);
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool					compareOk		= compareData(m_testCtx.getLog(), refLayout, writeData.pointers, glLayout, mappedBlockPtrs);
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			unmapBuffers(gl, buffers);
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!compareOk)
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader execution failed");
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::compareStdBlocks (const BufferLayout& refLayout, const BufferLayout& cmpLayout) const
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log			= m_testCtx.getLog();
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numBlocks	= m_interface.getNumBlocks();
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&		block			= m_interface.getBlock(blockNdx);
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isArray			= block.isArray();
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string				instanceName	= string(block.getBlockName()) + (isArray ? "[0]" : "");
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						refBlockNdx		= refLayout.getBlockIndex(instanceName.c_str());
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						cmpBlockNdx		= cmpLayout.getBlockIndex(instanceName.c_str());
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((block.getFlags() & (LAYOUT_STD140|LAYOUT_STD430)) == 0)
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue; // Not std* layout.
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(refBlockNdx >= 0);
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpBlockNdx < 0)
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Not found.
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Buffer block '" << instanceName << "' not found" << TestLog::EndMessage;
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		refBlockLayout	= refLayout.blocks[refBlockNdx];
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		cmpBlockLayout	= cmpLayout.blocks[cmpBlockNdx];
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2012-01-24 pyry] Verify that activeVarIndices is correct.
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2012-01-24 pyry] Verify all instances.
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (refBlockLayout.activeVarIndices.size() != cmpBlockLayout.activeVarIndices.size())
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Number of active variables differ in block '" << instanceName
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "' (expected " << refBlockLayout.activeVarIndices.size()
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ", got " << cmpBlockLayout.activeVarIndices.size()
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ")" << TestLog::EndMessage;
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<int>::const_iterator ndxIter = refBlockLayout.activeVarIndices.begin(); ndxIter != refBlockLayout.activeVarIndices.end(); ndxIter++)
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	refEntry	= refLayout.bufferVars[*ndxIter];
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int							cmpEntryNdx	= cmpLayout.getVariableIndex(refEntry.name.c_str());
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (cmpEntryNdx < 0)
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Error: Buffer variable '" << refEntry.name << "' not found" << TestLog::EndMessage;
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = false;
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	cmpEntry	= cmpLayout.bufferVars[cmpEntryNdx];
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (refEntry.type					!= cmpEntry.type				||
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.arraySize				!= cmpEntry.arraySize			||
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.offset					!= cmpEntry.offset				||
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.arrayStride			!= cmpEntry.arrayStride			||
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.matrixStride			!= cmpEntry.matrixStride		||
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.topLevelArraySize		!= cmpEntry.topLevelArraySize	||
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.topLevelArrayStride	!= cmpEntry.topLevelArrayStride	||
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.isRowMajor				!= cmpEntry.isRowMajor)
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Error: Layout mismatch in '" << refEntry.name << "':\n"
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "  expected: " << refEntry << "\n"
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "  got: " << cmpEntry
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::EndMessage;
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = false;
23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::compareSharedBlocks (const BufferLayout& refLayout, const BufferLayout& cmpLayout) const
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log			= m_testCtx.getLog();
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numBlocks	= m_interface.getNumBlocks();
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&		block			= m_interface.getBlock(blockNdx);
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isArray			= block.isArray();
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::string				instanceName	= string(block.getBlockName()) + (isArray ? "[0]" : "");
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						refBlockNdx		= refLayout.getBlockIndex(instanceName.c_str());
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						cmpBlockNdx		= cmpLayout.getBlockIndex(instanceName.c_str());
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((block.getFlags() & LAYOUT_SHARED) == 0)
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue; // Not shared layout.
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(refBlockNdx >= 0);
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmpBlockNdx < 0)
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Not found, should it?
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Buffer block '" << instanceName << "' not found" << TestLog::EndMessage;
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		refBlockLayout	= refLayout.blocks[refBlockNdx];
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		cmpBlockLayout	= cmpLayout.blocks[cmpBlockNdx];
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (refBlockLayout.activeVarIndices.size() != cmpBlockLayout.activeVarIndices.size())
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Number of active variables differ in block '" << instanceName
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "' (expected " << refBlockLayout.activeVarIndices.size()
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ", got " << cmpBlockLayout.activeVarIndices.size()
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ")" << TestLog::EndMessage;
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<int>::const_iterator ndxIter = refBlockLayout.activeVarIndices.begin(); ndxIter != refBlockLayout.activeVarIndices.end(); ndxIter++)
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	refEntry	= refLayout.bufferVars[*ndxIter];
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int							cmpEntryNdx	= cmpLayout.getVariableIndex(refEntry.name.c_str());
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (cmpEntryNdx < 0)
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Error: Buffer variable '" << refEntry.name << "' not found" << TestLog::EndMessage;
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = false;
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BufferVarLayoutEntry&	cmpEntry	= cmpLayout.bufferVars[cmpEntryNdx];
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (refEntry.type				!= cmpEntry.type				||
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.arraySize			!= cmpEntry.arraySize			||
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.topLevelArraySize	!= cmpEntry.topLevelArraySize	||
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				refEntry.isRowMajor	!= cmpEntry.isRowMajor)
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Error: Type / array size mismatch in '" << refEntry.name << "':\n"
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "  expected: " << refEntry << "\n"
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "  got: " << cmpEntry
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< TestLog::EndMessage;
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = false;
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::compareTypes (const BufferLayout& refLayout, const BufferLayout& cmpLayout) const
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log			= m_testCtx.getLog();
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numBlocks	= m_interface.getNumBlocks();
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferBlock&		block			= m_interface.getBlock(blockNdx);
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					isArray			= block.isArray();
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numInstances	= isArray ? block.getArraySize() : 1;
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::ostringstream instanceName;
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			instanceName << block.getBlockName();
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isArray)
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				instanceName << "[" << instanceNdx << "]";
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int cmpBlockNdx = cmpLayout.getBlockIndex(instanceName.str().c_str());
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (cmpBlockNdx < 0)
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const BlockLayoutEntry& cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (vector<int>::const_iterator ndxIter = cmpBlockLayout.activeVarIndices.begin(); ndxIter != cmpBlockLayout.activeVarIndices.end(); ndxIter++)
24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVarLayoutEntry&	cmpEntry	= cmpLayout.bufferVars[*ndxIter];
24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int							refEntryNdx	= refLayout.getVariableIndex(cmpEntry.name.c_str());
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (refEntryNdx < 0)
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Error: Buffer variable '" << cmpEntry.name << "' not found in reference layout" << TestLog::EndMessage;
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = false;
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue;
24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const BufferVarLayoutEntry&	refEntry	= refLayout.bufferVars[refEntryNdx];
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (refEntry.type != cmpEntry.type)
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Error: Buffer variable type mismatch in '" << refEntry.name << "':\n"
24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "  expected: " << glu::getDataTypeName(refEntry.type) << "\n"
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "  got: " << glu::getDataTypeName(cmpEntry.type)
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::EndMessage;
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = false;
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (refEntry.arraySize < cmpEntry.arraySize)
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Error: Invalid array size in '" << refEntry.name << "': expected <= " << refEntry.arraySize << TestLog::EndMessage;
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = false;
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (refEntry.topLevelArraySize < cmpEntry.topLevelArraySize)
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "Error: Invalid top-level array size in '" << refEntry.name << "': expected <= " << refEntry.topLevelArraySize << TestLog::EndMessage;
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = false;
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::checkLayoutIndices (const BufferLayout& layout) const
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log			= m_testCtx.getLog();
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numVars		= (int)layout.bufferVars.size();
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numBlocks	= (int)layout.blocks.size();
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check variable block indices.
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < numVars; varNdx++)
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferVarLayoutEntry& bufVar = layout.bufferVars[varNdx];
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (bufVar.blockNdx < 0 || !deInBounds32(bufVar.blockNdx, 0, numBlocks))
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Invalid block index in buffer variable '" << bufVar.name << "'" << TestLog::EndMessage;
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check active variables.
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry& block = layout.blocks[blockNdx];
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<int>::const_iterator varNdxIter = block.activeVarIndices.begin(); varNdxIter != block.activeVarIndices.end(); varNdxIter++)
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!deInBounds32(*varNdxIter, 0, numVars))
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "Error: Invalid active variable index " << *varNdxIter << " in block '" << block.name << "'" << TestLog::EndMessage;
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = false;
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::checkLayoutBounds (const BufferLayout& layout) const
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&	log			= m_testCtx.getLog();
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	numVars		= (int)layout.bufferVars.size();
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool		isOk		= true;
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < numVars; varNdx++)
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferVarLayoutEntry& var = layout.bufferVars[varNdx];
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (var.blockNdx < 0 || isUnsizedArray(var))
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		block			= layout.blocks[var.blockNdx];
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool					isMatrix		= glu::isDataTypeMatrix(var.type);
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					numVecs			= isMatrix ? (var.isRowMajor ? glu::getDataTypeMatrixNumRows(var.type) : glu::getDataTypeMatrixNumColumns(var.type)) : 1;
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					numComps		= isMatrix ? (var.isRowMajor ? glu::getDataTypeMatrixNumColumns(var.type) : glu::getDataTypeMatrixNumRows(var.type)) : glu::getDataTypeScalarSize(var.type);
25468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int					numElements		= var.arraySize;
25478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int					topLevelSize	= var.topLevelArraySize;
25488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int					arrayStride		= var.arrayStride;
25498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int					topLevelStride	= var.topLevelArrayStride;
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					compSize		= sizeof(deUint32);
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					vecSize			= numComps*compSize;
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							minOffset		= 0;
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							maxOffset		= 0;
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// For negative strides.
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		minOffset	= de::min(minOffset, (numVecs-1)*var.matrixStride);
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		minOffset	= de::min(minOffset, (numElements-1)*arrayStride);
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		minOffset	= de::min(minOffset, (topLevelSize-1)*topLevelStride + (numElements-1)*arrayStride + (numVecs-1)*var.matrixStride);
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxOffset	= de::max(maxOffset, vecSize);
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxOffset	= de::max(maxOffset, (numVecs-1)*var.matrixStride + vecSize);
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxOffset	= de::max(maxOffset, (numElements-1)*arrayStride + vecSize);
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxOffset	= de::max(maxOffset, (topLevelSize-1)*topLevelStride + (numElements-1)*arrayStride + vecSize);
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxOffset	= de::max(maxOffset, (topLevelSize-1)*topLevelStride + (numElements-1)*arrayStride + (numVecs-1)*var.matrixStride + vecSize);
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (var.offset+minOffset < 0 || var.offset+maxOffset > block.size)
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "Error: Variable '" << var.name << "' out of block bounds" << TestLog::EndMessage;
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::checkIndexQueries (deUint32 program, const BufferLayout& layout) const
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&				log			= m_testCtx.getLog();
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl			= m_renderCtx.getFunctions();
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						allOk		= true;
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Spec mandates that buffer blocks are assigned consecutive locations from 0.
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 BlockLayoutEntries are stored in that order in UniformLayout.
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BlockLayoutEntry&		block		= layout.blocks[blockNdx];
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int					queriedNdx	= gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, block.name.c_str());
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (queriedNdx != blockNdx)
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: glGetProgramResourceIndex(" << block.name << ") returned " << queriedNdx << ", expected " << blockNdx << "!" << TestLog::EndMessage;
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allOk = false;
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex()");
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return allOk;
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool SSBOLayoutCase::execute (deUint32 program)
26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl				= m_renderCtx.getFunctions();
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32						numPassedLoc	= gl.getProgramResourceIndex(program, GL_UNIFORM, "ac_numPassed");
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::InterfaceVariableInfo	acVarInfo		= numPassedLoc != GL_INVALID_INDEX ? glu::getProgramInterfaceVariableInfo(gl, program, GL_UNIFORM, numPassedLoc)
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																						   : glu::InterfaceVariableInfo();
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::InterfaceBlockInfo		acBufferInfo	= acVarInfo.atomicCounterBufferIndex != GL_INVALID_INDEX ? glu::getProgramInterfaceBlockInfo(gl, program, GL_ATOMIC_COUNTER_BUFFER, acVarInfo.atomicCounterBufferIndex)
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																												 : glu::InterfaceBlockInfo();
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::Buffer					acBuffer		(m_renderCtx);
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool								isOk			= true;
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numPassedLoc == GL_INVALID_INDEX)
26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("No location for ac_numPassed found");
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (acBufferInfo.index == GL_INVALID_INDEX)
26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("ac_numPassed buffer index is GL_INVALID_INDEX");
26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (acBufferInfo.dataSize == 0)
26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("ac_numPassed buffer size = 0");
26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize atomic counter buffer.
26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<deUint8> emptyData(acBufferInfo.dataSize, 0);
26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, *acBuffer);
26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, (glw::GLsizeiptr)emptyData.size(), &emptyData[0], GL_STATIC_READ);
26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, acBufferInfo.index, *acBuffer);
26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setting up buffer for ac_numPassed failed");
26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(program);
26333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(1, 1, 1);
26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() failed");
26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back ac_numPassed data.
26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void*	mapPtr		= gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, acBufferInfo.dataSize, GL_MAP_READ_BIT);
26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	refCount	= 1;
26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			resCount	= 0;
26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER) failed");
26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK(mapPtr);
26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		resCount = *(const int*)((const deUint8*)mapPtr + acVarInfo.offset);
26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER) failed");
26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (refCount != resCount)
26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << TestLog::Message << "ERROR: ac_numPassed = " << resCount << ", expected " << refCount << TestLog::EndMessage;
26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isOk = false;
26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Shader execution failed");
26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isOk;
26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
2664