1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL (ES) Module
3e5c31af7Sopenharmony_ci * -----------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Random uniform block layout case.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "glsRandomUniformBlockCase.hpp"
25e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
26e5c31af7Sopenharmony_ci#include "deRandom.hpp"
27e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ciusing std::string;
30e5c31af7Sopenharmony_ciusing std::vector;
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_cinamespace deqp
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_cinamespace gls
35e5c31af7Sopenharmony_ci{
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ciusing namespace gls::ub;
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ciRandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext&	testCtx,
40e5c31af7Sopenharmony_ci												glu::RenderContext&	renderCtx,
41e5c31af7Sopenharmony_ci												glu::GLSLVersion	glslVersion,
42e5c31af7Sopenharmony_ci												const char*			name,
43e5c31af7Sopenharmony_ci												const char*			description,
44e5c31af7Sopenharmony_ci												BufferMode			bufferMode,
45e5c31af7Sopenharmony_ci												deUint32			features,
46e5c31af7Sopenharmony_ci												deUint32			seed)
47e5c31af7Sopenharmony_ci	: UniformBlockCase		(testCtx, renderCtx, name, description, glslVersion, bufferMode)
48e5c31af7Sopenharmony_ci	, m_features			(features)
49e5c31af7Sopenharmony_ci	, m_maxVertexBlocks		((features & FEATURE_VERTEX_BLOCKS)		? 4 : 0)
50e5c31af7Sopenharmony_ci	, m_maxFragmentBlocks	((features & FEATURE_FRAGMENT_BLOCKS)	? 4 : 0)
51e5c31af7Sopenharmony_ci	, m_maxSharedBlocks		((features & FEATURE_SHARED_BLOCKS)		? 4 : 0)
52e5c31af7Sopenharmony_ci	, m_maxInstances		((features & FEATURE_INSTANCE_ARRAYS)	? 3 : 0)
53e5c31af7Sopenharmony_ci	, m_maxArrayLength		((features & FEATURE_ARRAYS)			? 8 : 0)
54e5c31af7Sopenharmony_ci	, m_maxStructDepth		((features & FEATURE_STRUCTS)			? 2 : 0)
55e5c31af7Sopenharmony_ci	, m_maxBlockMembers		(5)
56e5c31af7Sopenharmony_ci	, m_maxStructMembers	(4)
57e5c31af7Sopenharmony_ci	, m_seed				(seed)
58e5c31af7Sopenharmony_ci	, m_blockNdx			(1)
59e5c31af7Sopenharmony_ci	, m_uniformNdx			(1)
60e5c31af7Sopenharmony_ci	, m_structNdx			(1)
61e5c31af7Sopenharmony_ci{
62e5c31af7Sopenharmony_ci}
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_civoid RandomUniformBlockCase::init (void)
65e5c31af7Sopenharmony_ci{
66e5c31af7Sopenharmony_ci	de::Random rnd(m_seed);
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_ci	int numShared		= m_maxSharedBlocks				> 0	? rnd.getInt(1, m_maxSharedBlocks)				: 0;
69e5c31af7Sopenharmony_ci	int numVtxBlocks	= m_maxVertexBlocks-numShared	> 0	? rnd.getInt(1, m_maxVertexBlocks-numShared)	: 0;
70e5c31af7Sopenharmony_ci	int	numFragBlocks	= m_maxFragmentBlocks-numShared	> 0 ? rnd.getInt(1, m_maxFragmentBlocks-numShared)	: 0;
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < numShared; ndx++)
73e5c31af7Sopenharmony_ci		generateBlock(rnd, DECLARE_VERTEX|DECLARE_FRAGMENT);
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < numVtxBlocks; ndx++)
76e5c31af7Sopenharmony_ci		generateBlock(rnd, DECLARE_VERTEX);
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < numFragBlocks; ndx++)
79e5c31af7Sopenharmony_ci		generateBlock(rnd, DECLARE_FRAGMENT);
80e5c31af7Sopenharmony_ci}
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_civoid RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
83e5c31af7Sopenharmony_ci{
84e5c31af7Sopenharmony_ci	DE_ASSERT(m_blockNdx <= 'z' - 'a');
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci	const float		instanceArrayWeight	= 0.3f;
87e5c31af7Sopenharmony_ci	UniformBlock&	block				= m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
88e5c31af7Sopenharmony_ci	int				numInstances		= (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
89e5c31af7Sopenharmony_ci	int				numUniforms			= rnd.getInt(1, m_maxBlockMembers);
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci	if (numInstances > 0)
92e5c31af7Sopenharmony_ci		block.setArraySize(numInstances);
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	if (numInstances > 0 || rnd.getBool())
95e5c31af7Sopenharmony_ci		block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ci	// Layout flag candidates.
98e5c31af7Sopenharmony_ci	vector<deUint32> layoutFlagCandidates;
99e5c31af7Sopenharmony_ci	layoutFlagCandidates.push_back(0);
100e5c31af7Sopenharmony_ci	if (m_features & FEATURE_PACKED_LAYOUT)
101e5c31af7Sopenharmony_ci		layoutFlagCandidates.push_back(LAYOUT_SHARED);
102e5c31af7Sopenharmony_ci	if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
103e5c31af7Sopenharmony_ci		layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
104e5c31af7Sopenharmony_ci	if (m_features & FEATURE_STD140_LAYOUT)
105e5c31af7Sopenharmony_ci		layoutFlagCandidates.push_back(LAYOUT_STD140);
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	if (m_features & FEATURE_MATRIX_LAYOUT)
110e5c31af7Sopenharmony_ci	{
111e5c31af7Sopenharmony_ci		static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
112e5c31af7Sopenharmony_ci		layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
113e5c31af7Sopenharmony_ci	}
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ci	block.setFlags(layoutFlags);
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < numUniforms; ndx++)
118e5c31af7Sopenharmony_ci		generateUniform(rnd, block);
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	m_blockNdx += 1;
121e5c31af7Sopenharmony_ci}
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_cistatic std::string genName (char first, char last, int ndx)
124e5c31af7Sopenharmony_ci{
125e5c31af7Sopenharmony_ci	std::string	str			= "";
126e5c31af7Sopenharmony_ci	int			alphabetLen	= last - first + 1;
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci	while (ndx > alphabetLen)
129e5c31af7Sopenharmony_ci	{
130e5c31af7Sopenharmony_ci		str.insert(str.begin(), (char)(first + ((ndx-1)%alphabetLen)));
131e5c31af7Sopenharmony_ci		ndx = ((ndx-1) / alphabetLen);
132e5c31af7Sopenharmony_ci	}
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	str.insert(str.begin(), (char)(first + (ndx%(alphabetLen+1)) - 1));
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ci	return str;
137e5c31af7Sopenharmony_ci}
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_civoid RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci	const float		unusedVtxWeight		= 0.15f;
142e5c31af7Sopenharmony_ci	const float		unusedFragWeight	= 0.15f;
143e5c31af7Sopenharmony_ci	bool			unusedOk			= (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
144e5c31af7Sopenharmony_ci	deUint32		flags				= 0;
145e5c31af7Sopenharmony_ci	std::string		name				= genName('a', 'z', m_uniformNdx);
146e5c31af7Sopenharmony_ci	VarType			type				= generateType(rnd, 0, true);
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci	flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
149e5c31af7Sopenharmony_ci	flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci	block.addUniform(Uniform(name.c_str(), type, flags));
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_ci	m_uniformNdx += 1;
154e5c31af7Sopenharmony_ci}
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ciVarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
157e5c31af7Sopenharmony_ci{
158e5c31af7Sopenharmony_ci	const float structWeight	= 0.1f;
159e5c31af7Sopenharmony_ci	const float arrayWeight		= 0.1f;
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_ci	if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
162e5c31af7Sopenharmony_ci	{
163e5c31af7Sopenharmony_ci		const float		unusedVtxWeight		= 0.15f;
164e5c31af7Sopenharmony_ci		const float		unusedFragWeight	= 0.15f;
165e5c31af7Sopenharmony_ci		bool			unusedOk			= (m_features & FEATURE_UNUSED_MEMBERS) != 0;
166e5c31af7Sopenharmony_ci		vector<VarType>	memberTypes;
167e5c31af7Sopenharmony_ci		int				numMembers = rnd.getInt(1, m_maxStructMembers);
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci		// Generate members first so nested struct declarations are in correct order.
170e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < numMembers; ndx++)
171e5c31af7Sopenharmony_ci			memberTypes.push_back(generateType(rnd, typeDepth+1, true));
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ci		StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
174e5c31af7Sopenharmony_ci		m_structNdx += 1;
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci		DE_ASSERT(numMembers <= 'Z' - 'A');
177e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < numMembers; ndx++)
178e5c31af7Sopenharmony_ci		{
179e5c31af7Sopenharmony_ci			deUint32 flags = 0;
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci			flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
182e5c31af7Sopenharmony_ci			flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci			structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
185e5c31af7Sopenharmony_ci		}
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci		return VarType(&structType);
188e5c31af7Sopenharmony_ci	}
189e5c31af7Sopenharmony_ci	else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		const bool	arraysOfArraysOk	= (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
192e5c31af7Sopenharmony_ci		const int	arrayLength			= rnd.getInt(1, m_maxArrayLength);
193e5c31af7Sopenharmony_ci		VarType	elementType	= generateType(rnd, typeDepth, arraysOfArraysOk);
194e5c31af7Sopenharmony_ci		return VarType(elementType, arrayLength);
195e5c31af7Sopenharmony_ci	}
196e5c31af7Sopenharmony_ci	else
197e5c31af7Sopenharmony_ci	{
198e5c31af7Sopenharmony_ci		vector<glu::DataType> typeCandidates;
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci		typeCandidates.push_back(glu::TYPE_FLOAT);
201e5c31af7Sopenharmony_ci		typeCandidates.push_back(glu::TYPE_INT);
202e5c31af7Sopenharmony_ci		typeCandidates.push_back(glu::TYPE_UINT);
203e5c31af7Sopenharmony_ci		typeCandidates.push_back(glu::TYPE_BOOL);
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci		if (m_features & FEATURE_VECTORS)
206e5c31af7Sopenharmony_ci		{
207e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
208e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
209e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
210e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_INT_VEC2);
211e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_INT_VEC3);
212e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_INT_VEC4);
213e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_UINT_VEC2);
214e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_UINT_VEC3);
215e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_UINT_VEC4);
216e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
217e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
218e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
219e5c31af7Sopenharmony_ci		}
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci		if (m_features & FEATURE_MATRICES)
222e5c31af7Sopenharmony_ci		{
223e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
224e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
225e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
226e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
227e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
228e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
229e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
230e5c31af7Sopenharmony_ci			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
231e5c31af7Sopenharmony_ci		}
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci		glu::DataType	type	= rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
234e5c31af7Sopenharmony_ci		deUint32		flags	= 0;
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci		if (!glu::isDataTypeBoolOrBVec(type))
237e5c31af7Sopenharmony_ci		{
238e5c31af7Sopenharmony_ci			// Precision.
239e5c31af7Sopenharmony_ci			static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
240e5c31af7Sopenharmony_ci			flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
241e5c31af7Sopenharmony_ci		}
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci		return VarType(type, flags);
244e5c31af7Sopenharmony_ci	}
245e5c31af7Sopenharmony_ci}
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci} // gls
248e5c31af7Sopenharmony_ci} // deqp
249