1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Uniform block tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fUniformBlockTests.hpp"
25#include "glsUniformBlockCase.hpp"
26#include "glsRandomUniformBlockCase.hpp"
27#include "tcuCommandLine.hpp"
28#include "deRandom.hpp"
29#include "deStringUtil.hpp"
30
31using std::string;
32using std::vector;
33
34namespace deqp
35{
36namespace gles31
37{
38namespace Functional
39{
40namespace
41{
42
43using gls::UniformBlockCase;
44using gls::RandomUniformBlockCase;
45using namespace gls::ub;
46
47void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, Context& context, const char* groupName, const char* description, UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed)
48{
49	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
50	parentGroup->addChild(group);
51
52	baseSeed += (deUint32)context.getTestContext().getCommandLine().getBaseSeed();
53
54	for (int ndx = 0; ndx < numCases; ndx++)
55		group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(), glu::GLSL_VERSION_310_ES,
56												   de::toString(ndx).c_str(), "", bufferMode, features, (deUint32)ndx+baseSeed));
57}
58
59class BlockBasicTypeCase : public UniformBlockCase
60{
61public:
62	BlockBasicTypeCase (Context& context, const char* name, const char* description, const VarType& type, deUint32 layoutFlags, int numInstances)
63		: UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK)
64	{
65		UniformBlock& block = m_interface.allocBlock("Block");
66		block.addUniform(Uniform("var", type, 0));
67		block.setFlags(layoutFlags);
68
69		if (numInstances > 0)
70		{
71			block.setArraySize(numInstances);
72			block.setInstanceName("block");
73		}
74	}
75};
76
77static void createBlockBasicTypeCases (tcu::TestCaseGroup* group, Context& context, const char* name, const VarType& type, deUint32 layoutFlags, int numInstances = 0)
78{
79	group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(),		"", type, layoutFlags|DECLARE_VERTEX,					numInstances));
80	group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(),	"", type, layoutFlags|DECLARE_FRAGMENT,					numInstances));
81
82	if (!(layoutFlags & LAYOUT_PACKED))
83		group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(),	"", type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	numInstances));
84}
85
86class Block2LevelStructArrayCase : public UniformBlockCase
87{
88public:
89	Block2LevelStructArrayCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
90		: UniformBlockCase	(context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_310_ES, bufferMode)
91		, m_layoutFlags		(layoutFlags)
92		, m_numInstances	(numInstances)
93	{
94	}
95
96	void init (void)
97	{
98		StructType& typeS = m_interface.allocStruct("S");
99		typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
100		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
101		typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
102
103		UniformBlock& block = m_interface.allocBlock("Block");
104		block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
105		block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
106		block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
107		block.setFlags(m_layoutFlags);
108
109		if (m_numInstances > 0)
110		{
111			block.setInstanceName("block");
112			block.setArraySize(m_numInstances);
113		}
114	}
115
116private:
117	deUint32	m_layoutFlags;
118	int			m_numInstances;
119};
120
121} // anonymous
122
123UniformBlockTests::UniformBlockTests (Context& context)
124	: TestCaseGroup(context, "ubo", "Uniform Block tests")
125{
126}
127
128UniformBlockTests::~UniformBlockTests (void)
129{
130}
131
132void UniformBlockTests::init (void)
133{
134	static const glu::DataType basicTypes[] =
135	{
136		glu::TYPE_FLOAT,
137		glu::TYPE_FLOAT_VEC2,
138		glu::TYPE_FLOAT_VEC3,
139		glu::TYPE_FLOAT_VEC4,
140		glu::TYPE_INT,
141		glu::TYPE_INT_VEC2,
142		glu::TYPE_INT_VEC3,
143		glu::TYPE_INT_VEC4,
144		glu::TYPE_UINT,
145		glu::TYPE_UINT_VEC2,
146		glu::TYPE_UINT_VEC3,
147		glu::TYPE_UINT_VEC4,
148		glu::TYPE_BOOL,
149		glu::TYPE_BOOL_VEC2,
150		glu::TYPE_BOOL_VEC3,
151		glu::TYPE_BOOL_VEC4,
152		glu::TYPE_FLOAT_MAT2,
153		glu::TYPE_FLOAT_MAT3,
154		glu::TYPE_FLOAT_MAT4,
155		glu::TYPE_FLOAT_MAT2X3,
156		glu::TYPE_FLOAT_MAT2X4,
157		glu::TYPE_FLOAT_MAT3X2,
158		glu::TYPE_FLOAT_MAT3X4,
159		glu::TYPE_FLOAT_MAT4X2,
160		glu::TYPE_FLOAT_MAT4X3
161	};
162
163	static const struct
164	{
165		const char*		name;
166		deUint32		flags;
167	} layoutFlags[] =
168	{
169		{ "shared",		LAYOUT_SHARED	},
170		{ "packed",		LAYOUT_PACKED	},
171		{ "std140",		LAYOUT_STD140	}
172	};
173
174	static const struct
175	{
176		const char*		name;
177		deUint32		flags;
178	} matrixFlags[] =
179	{
180		{ "row_major",		LAYOUT_ROW_MAJOR	},
181		{ "column_major",	LAYOUT_COLUMN_MAJOR }
182	};
183
184	static const struct
185	{
186		const char*							name;
187		UniformBlockCase::BufferMode		mode;
188	} bufferModes[] =
189	{
190		{ "per_block_buffer",	UniformBlockCase::BUFFERMODE_PER_BLOCK },
191		{ "single_buffer",		UniformBlockCase::BUFFERMODE_SINGLE	}
192	};
193
194	// ubo.2_level_array
195	{
196		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer");
197		addChild(nestedArrayGroup);
198
199		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
200		{
201			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
202			nestedArrayGroup->addChild(layoutGroup);
203
204			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
205			{
206				const glu::DataType	type		= basicTypes[basicTypeNdx];
207				const char*			typeName	= glu::getDataTypeName(type);
208				const int			childSize	= 4;
209				const int			parentSize	= 3;
210				const VarType		childType	(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize);
211				const VarType		parentType	(childType, parentSize);
212
213				createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
214
215				if (glu::isDataTypeMatrix(type))
216				{
217					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
218						createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
219												  parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
220				}
221			}
222		}
223	}
224
225	// ubo.3_level_array
226	{
227		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
228		addChild(nestedArrayGroup);
229
230		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
231		{
232			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
233			nestedArrayGroup->addChild(layoutGroup);
234
235			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
236			{
237				const glu::DataType	type		= basicTypes[basicTypeNdx];
238				const char*			typeName	= glu::getDataTypeName(type);
239				const int			childSize0	= 2;
240				const int			childSize1	= 4;
241				const int			parentSize	= 3;
242				const VarType		childType0	(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize0);
243				const VarType		childType1	(childType0, childSize1);
244				const VarType		parentType	(childType1, parentSize);
245
246				createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
247
248				if (glu::isDataTypeMatrix(type))
249				{
250					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
251						createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
252												  parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
253				}
254			}
255		}
256	}
257
258	// ubo.2_level_struct_array
259	{
260		tcu::TestCaseGroup* structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block");
261		addChild(structArrayArrayGroup);
262
263		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
264		{
265			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
266			structArrayArrayGroup->addChild(modeGroup);
267
268			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
269			{
270				for (int isArray = 0; isArray < 2; isArray++)
271				{
272					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
273					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
274
275					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
276						continue; // Doesn't make sense to add this variant.
277
278					if (isArray)
279						baseName += "_instance_array";
280
281					modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_vertex").c_str(),	"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
282					modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_fragment").c_str(),	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
283
284					if (!(baseFlags & LAYOUT_PACKED))
285						modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_both").c_str(),	"", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
286				}
287			}
288		}
289	}
290
291	// ubo.random
292	{
293		const deUint32	allShaders		= FEATURE_VERTEX_BLOCKS|FEATURE_FRAGMENT_BLOCKS|FEATURE_SHARED_BLOCKS;
294		const deUint32	allLayouts		= FEATURE_PACKED_LAYOUT|FEATURE_SHARED_LAYOUT|FEATURE_STD140_LAYOUT;
295		const deUint32	allBasicTypes	= FEATURE_VECTORS|FEATURE_MATRICES;
296		const deUint32	unused			= FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_UNIFORMS;
297		const deUint32	matFlags		= FEATURE_MATRIX_LAYOUT;
298		const deUint32	basicTypeArrays	= allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS|FEATURE_ARRAYS_OF_ARRAYS;
299		const deUint32	allFeatures		= ~0u;
300
301		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
302		addChild(randomGroup);
303
304		createRandomCaseGroup(randomGroup, m_context, "basic_type_arrays",		"Arrays, per-block buffers",				UniformBlockCase::BUFFERMODE_PER_BLOCK,	basicTypeArrays,	25, 1150);
305		createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers",	"All random features, per-block buffers",	UniformBlockCase::BUFFERMODE_PER_BLOCK,	allFeatures,		50, 11200);
306		createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer",		"All random features, shared buffer",		UniformBlockCase::BUFFERMODE_SINGLE,	allFeatures,		50, 11250);
307	}
308}
309
310} // Functional
311} // gles31
312} // deqp
313