• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  * Copyright (c) 2018 The Khronos Group Inc.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Vulkan Transform Feedback Random Layout Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktTransformFeedbackRandomLayoutCase.hpp"
28 #include "deRandom.hpp"
29 
30 namespace vkt
31 {
32 namespace TransformFeedback
33 {
34 
35 namespace
36 {
37 
genName(char first,char last,int ndx)38 static std::string genName (char first, char last, int ndx)
39 {
40 	std::string	str			= "";
41 	int			alphabetLen	= last - first + 1;
42 
43 	while (ndx > alphabetLen)
44 	{
45 		str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
46 		ndx = (ndx - 1) / alphabetLen;
47 	}
48 
49 	str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
50 
51 	return str;
52 }
53 
54 } // anonymous
55 
RandomInterfaceBlockCase(tcu::TestContext & testCtx,const std::string & name,const TestStageFlags testStageFlags,deUint32 features,deUint32 seed)56 RandomInterfaceBlockCase::RandomInterfaceBlockCase (tcu::TestContext&		testCtx,
57 													const std::string&		name,
58 													const TestStageFlags	testStageFlags,
59 													deUint32				features,
60 													deUint32				seed)
61 	: InterfaceBlockCase		(testCtx, name, LOAD_FULL_MATRIX, testStageFlags, (features & FEATURE_OUT_OF_ORDER_OFFSETS) != 0u)
62 	, m_features				(features)
63 	, m_explicitXfbOffsets		((features & (FEATURE_OUT_OF_ORDER_OFFSETS | FEATURE_MISSING_BLOCK_MEMBERS)) != 0u)
64 	, m_maxBlocks				(3)
65 	, m_maxInstances			((features & FEATURE_INSTANCE_ARRAYS)	? 3 : 0)
66 	, m_maxArrayLength			((features & FEATURE_ARRAYS)			? 4 : 0)
67 	, m_maxStructDepth			((features & FEATURE_STRUCTS)			? 2 : 0)
68 	, m_maxBlockMembers			(3)
69 	, m_maxStructMembers		(3)
70 	, m_seed					(seed)
71 	, m_blockNdx				(1)
72 	, m_interfaceNdx			(1)
73 	, m_structNdx				(1)
74 	, m_primitiveTypeCandidates	(fillTypeCandidates())
75 {
76 	de::Random rnd(m_seed);
77 
78 	int				numBlocks	= rnd.getInt(1, m_maxBlocks);
79 	InterfaceFlags	stage		= static_cast<InterfaceFlags>(LAYOUT_XFBBUFFER | LAYOUT_XFBOFFSET);
80 
81 	for (int ndx = 0; ndx < numBlocks; ndx++)
82 		generateBlock(rnd, stage);
83 
84 	// m_primitiveTypeCandidates is required during generation only
85 	m_primitiveTypeCandidates.clear();
86 
87 	init();
88 }
89 
fillTypeCandidates()90 std::vector<glu::DataType> RandomInterfaceBlockCase::fillTypeCandidates()
91 {
92 	std::vector<glu::DataType> typeCandidates;
93 
94 	typeCandidates.reserve(32);
95 
96 	typeCandidates.push_back(glu::TYPE_FLOAT);
97 	typeCandidates.push_back(glu::TYPE_INT);
98 	typeCandidates.push_back(glu::TYPE_UINT);
99 
100 	if (m_features & FEATURE_DOUBLES)
101 		typeCandidates.push_back(glu::TYPE_DOUBLE);
102 
103 	if (m_features & FEATURE_VECTORS)
104 	{
105 		typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
106 		typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
107 		typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
108 		typeCandidates.push_back(glu::TYPE_INT_VEC2);
109 		typeCandidates.push_back(glu::TYPE_INT_VEC3);
110 		typeCandidates.push_back(glu::TYPE_INT_VEC4);
111 		typeCandidates.push_back(glu::TYPE_UINT_VEC2);
112 		typeCandidates.push_back(glu::TYPE_UINT_VEC3);
113 		typeCandidates.push_back(glu::TYPE_UINT_VEC4);
114 
115 		if (m_features & FEATURE_DOUBLES)
116 		{
117 			typeCandidates.push_back(glu::TYPE_DOUBLE_VEC2);
118 			typeCandidates.push_back(glu::TYPE_DOUBLE_VEC3);
119 			typeCandidates.push_back(glu::TYPE_DOUBLE_VEC4);
120 		}
121 	}
122 
123 	if (m_features & FEATURE_MATRICES)
124 	{
125 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
126 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
127 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
128 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
129 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
130 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
131 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
132 		typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
133 
134 		if (m_features & FEATURE_DOUBLES)
135 		{
136 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT2);
137 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT2X3);
138 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT3X2);
139 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT3);
140 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT3X4);
141 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT4X2);
142 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT4X3);
143 			typeCandidates.push_back(glu::TYPE_DOUBLE_MAT4);
144 		}
145 	}
146 
147 	return typeCandidates;
148 }
149 
generateBlock(de::Random & rnd,deUint32 layoutFlags)150 void RandomInterfaceBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
151 {
152 	DE_ASSERT(m_blockNdx <= 'z' - 'a');
153 
154 	const float		instanceArrayWeight		= 0.3f;
155 	InterfaceBlock&	block					= m_interface.allocBlock(std::string("Block") + (char)('A' + m_blockNdx));
156 	int				numInstances			= (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
157 	int				numBlockMembers			= rnd.getInt(1, m_maxBlockMembers);
158 	int				numUnassignedOrMissing	= 0;
159 
160 	if (numInstances > 0)
161 		block.setArraySize(numInstances);
162 
163 	if (numInstances > 0 || rnd.getBool())
164 		block.setInstanceName(std::string("block") + (char)('A' + m_blockNdx));
165 
166 	block.setFlags(layoutFlags);
167 
168 	for (int ndx = 0; ndx < numBlockMembers; ndx++)
169 		generateBlockMember(rnd, block, numBlockMembers, numUnassignedOrMissing);
170 
171 	m_blockNdx += 1;
172 }
173 
generateBlockMember(de::Random & rnd,InterfaceBlock & block,const int numBlockMembers,int & numUnassignedOrMissing)174 void RandomInterfaceBlockCase::generateBlockMember (de::Random& rnd, InterfaceBlock& block, const int numBlockMembers, int& numUnassignedOrMissing)
175 {
176 	const float		unassignedBlockMembersWeight	= 0.15f;
177 	const float		missingBlockMembersWeight		= 0.15f;
178 	const bool		unassignedAllowed				= (m_features & FEATURE_UNASSIGNED_BLOCK_MEMBERS) != 0;
179 	const bool		missingAllowed					= (m_features & FEATURE_MISSING_BLOCK_MEMBERS) != 0;
180 	deUint32		flags							= 0;
181 	std::string		name							= genName('a', 'z', m_interfaceNdx);
182 	VarType			type							= generateType(rnd, 0, true);
183 
184 	if (numUnassignedOrMissing < numBlockMembers - 1)
185 	{
186 		if (missingAllowed && rnd.getFloat() < missingBlockMembersWeight)
187 		{
188 			flags |= FIELD_MISSING;
189 			numUnassignedOrMissing++;
190 		}
191 		else if (unassignedAllowed && rnd.getFloat() < unassignedBlockMembersWeight)
192 		{
193 			flags |= FIELD_UNASSIGNED;
194 			numUnassignedOrMissing++;
195 		}
196 	}
197 
198 	block.addInterfaceMember(InterfaceBlockMember(name, type, flags));
199 
200 	m_interfaceNdx += 1;
201 }
202 
generateType(de::Random & rnd,int typeDepth,bool arrayOk)203 VarType RandomInterfaceBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
204 {
205 	const float structWeight	= 0.1f;
206 	const float arrayWeight		= 0.1f;
207 
208 	if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
209 	{
210 		const float				unassignedFieldWeight	= 0.15f;
211 		const bool				unassignedOk			= (m_features & FEATURE_UNASSIGNED_FIELDS) != 0;
212 		const int				numMembers				= rnd.getInt(1, m_maxStructMembers);
213 		std::vector<VarType>	memberTypes;
214 
215 		// Generate members first so nested struct declarations are in correct order.
216 		for (int ndx = 0; ndx < numMembers; ndx++)
217 			memberTypes.push_back(generateType(rnd, typeDepth+1, true));
218 
219 		StructType& structType = m_interface.allocStruct(std::string("s") + genName('A', 'Z', m_structNdx));
220 		m_structNdx += 1;
221 
222 		DE_ASSERT(numMembers <= 'Z' - 'A');
223 		for (int ndx = 0; ndx < numMembers; ndx++)
224 		{
225 			deUint32 flags = 0;
226 
227 			if (unassignedOk && rnd.getFloat() < unassignedFieldWeight)
228 			{
229 				flags |= FIELD_UNASSIGNED;
230 			}
231 
232 			structType.addMember(std::string("m") + (char)('A' + ndx), memberTypes[ndx], flags);
233 		}
234 
235 		return VarType(&structType, m_explicitXfbOffsets ? static_cast<deUint32>(LAYOUT_XFBOFFSET) : 0u);
236 	}
237 	else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
238 	{
239 		const bool	arraysOfArraysOk	= (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
240 		const int	arrayLength			= rnd.getInt(1, m_maxArrayLength);
241 		VarType		elementType			= generateType(rnd, typeDepth, arraysOfArraysOk);
242 
243 		return VarType(elementType, arrayLength);
244 	}
245 	else
246 	{
247 		glu::DataType	type	= rnd.choose<glu::DataType>(m_primitiveTypeCandidates.begin(), m_primitiveTypeCandidates.end());
248 		deUint32		flags	= (m_explicitXfbOffsets ? static_cast<deUint32>(LAYOUT_XFBOFFSET) : 0u);
249 
250 		if (glu::dataTypeSupportsPrecisionModifier(type))
251 		{
252 			// Precision.
253 			static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
254 			flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
255 		}
256 
257 		return VarType(type, flags);
258 	}
259 }
260 
261 } // TransformFeedback
262 } // vkt
263