• 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  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Random uniform block layout case.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRandomUniformBlockCase.hpp"
27 #include "deRandom.hpp"
28 
29 namespace vkt
30 {
31 namespace ubo
32 {
33 
34 namespace
35 {
36 
genName(char first,char last,int ndx)37 static std::string genName (char first, char last, int ndx)
38 {
39 	std::string	str			= "";
40 	int			alphabetLen	= last - first + 1;
41 
42 	while (ndx > alphabetLen)
43 	{
44 		str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
45 		ndx = (ndx - 1) / alphabetLen;
46 	}
47 
48 	str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
49 
50 	return str;
51 }
52 
53 } // anonymous
54 
RandomUniformBlockCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,BufferMode bufferMode,deUint32 features,deUint32 seed)55 RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext&	testCtx,
56 												const std::string&	name,
57 												const std::string&	description,
58 												BufferMode			bufferMode,
59 												deUint32			features,
60 												deUint32			seed)
61 	: UniformBlockCase						(testCtx, name, description, bufferMode, LOAD_FULL_MATRIX, (features & FEATURE_OUT_OF_ORDER_OFFSETS) != 0u)
62 	, m_features							(features)
63 	, m_maxVertexBlocks						((features & FEATURE_VERTEX_BLOCKS)		? 4 : 0)
64 	, m_maxFragmentBlocks					((features & FEATURE_FRAGMENT_BLOCKS)	? 4 : 0)
65 	, m_maxSharedBlocks						((features & FEATURE_SHARED_BLOCKS)		? 4 : 0)
66 	, m_maxInstances						((features & FEATURE_INSTANCE_ARRAYS)	? 3 : 0)
67 	, m_maxArrayLength						((features & FEATURE_ARRAYS)			? 8 : 0)
68 	, m_maxStructDepth						((features & FEATURE_STRUCTS)			? 2 : 0)
69 	, m_maxBlockMembers						(5)
70 	, m_maxStructMembers					(4)
71 	, m_seed								(seed)
72 	, m_blockNdx							(1)
73 	, m_uniformNdx							(1)
74 	, m_structNdx							(1)
75 	, m_availableDescriptorUniformBuffers	(12)
76 {
77 	de::Random rnd(m_seed);
78 
79 	int numShared		= m_maxSharedBlocks				> 0	? rnd.getInt(1, m_maxSharedBlocks)				: 0;
80 	int numVtxBlocks	= m_maxVertexBlocks-numShared	> 0	? rnd.getInt(1, m_maxVertexBlocks - numShared)	: 0;
81 	int	numFragBlocks	= m_maxFragmentBlocks-numShared	> 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared): 0;
82 
83 	// calculate how many additional descriptors we can use for arrays
84 	// this is needed for descriptor_indexing testing as we need to take in to account
85 	// maxPerStageDescriptorUniformBuffers limit and we can't query it as we need to
86 	// generate shaders before Context is created; minimal value of this limit is 12
87 	m_availableDescriptorUniformBuffers -= numVtxBlocks + numFragBlocks;
88 
89 	for (int ndx = 0; ndx < numShared; ndx++)
90 		generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);
91 
92 	for (int ndx = 0; ndx < numVtxBlocks; ndx++)
93 		generateBlock(rnd, DECLARE_VERTEX);
94 
95 	for (int ndx = 0; ndx < numFragBlocks; ndx++)
96 		generateBlock(rnd, DECLARE_FRAGMENT);
97 
98 	init();
99 }
100 
generateBlock(de::Random & rnd,deUint32 layoutFlags)101 void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
102 {
103 	DE_ASSERT(m_blockNdx <= 'z' - 'a');
104 
105 	const float		instanceArrayWeight	= 0.3f;
106 	UniformBlock&	block				= m_interface.allocBlock(std::string("Block") + (char)('A' + m_blockNdx));
107 	int				numInstances		= (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
108 	int				numUniforms			= rnd.getInt(1, m_maxBlockMembers);
109 
110 	if (m_features & FEATURE_DESCRIPTOR_INDEXING)
111 	{
112 		// generate arrays only when we are within the limit
113 		if (m_availableDescriptorUniformBuffers > 3)
114 			numInstances = rnd.getInt(2, 4);
115 		else if (m_availableDescriptorUniformBuffers > 1)
116 			numInstances = m_availableDescriptorUniformBuffers;
117 		else
118 			numInstances = 0;
119 		m_availableDescriptorUniformBuffers -= numInstances;
120 	}
121 
122 	if (numInstances > 0)
123 		block.setArraySize(numInstances);
124 
125 	if (numInstances > 0 || rnd.getBool())
126 		block.setInstanceName(std::string("block") + (char)('A' + m_blockNdx));
127 
128 	// Layout flag candidates.
129 	std::vector<deUint32> layoutFlagCandidates;
130 	layoutFlagCandidates.push_back(0);
131 
132 	if (m_features & FEATURE_STD140_LAYOUT)
133 		layoutFlagCandidates.push_back(LAYOUT_STD140);
134 
135 	if (m_features & FEATURE_STD430_LAYOUT)
136 		layoutFlagCandidates.push_back(LAYOUT_STD430);
137 
138 	if (m_features & FEATURE_SCALAR_LAYOUT)
139 		layoutFlagCandidates.push_back(LAYOUT_SCALAR);
140 
141 	if (m_features & FEATURE_16BIT_STORAGE)
142 		layoutFlags |= LAYOUT_16BIT_STORAGE;
143 
144 	if (m_features & FEATURE_8BIT_STORAGE)
145 		layoutFlags |= LAYOUT_8BIT_STORAGE;
146 
147 	if (m_features & FEATURE_DESCRIPTOR_INDEXING)
148 		layoutFlags |= LAYOUT_DESCRIPTOR_INDEXING;
149 
150 	layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
151 
152 	if (m_features & FEATURE_MATRIX_LAYOUT)
153 	{
154 		static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
155 		layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
156 	}
157 
158 	block.setFlags(layoutFlags);
159 
160 	for (int ndx = 0; ndx < numUniforms; ndx++)
161 		generateUniform(rnd, block, numInstances ? numInstances : 1);
162 
163 	m_blockNdx += 1;
164 }
165 
generateUniform(de::Random & rnd,UniformBlock & block,deUint32 complexity)166 void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block, deUint32 complexity)
167 {
168 	const float		unusedVtxWeight		= 0.15f;
169 	const float		unusedFragWeight	= 0.15f;
170 	bool			unusedOk			= (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
171 	deUint32		flags				= 0;
172 	std::string		name				= genName('a', 'z', m_uniformNdx);
173 	VarType			type				= generateType(rnd, 0, true, complexity);
174 
175 	flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
176 	flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
177 
178 	block.addUniform(Uniform(name, type, flags));
179 
180 	m_uniformNdx += 1;
181 }
182 
generateType(de::Random & rnd,int typeDepth,bool arrayOk,deUint32 complexity)183 VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk, deUint32 complexity)
184 {
185 	const float structWeight	= 0.1f;
186 	const float arrayWeight		= 0.1f;
187 
188 	if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
189 	{
190 		const float				unusedVtxWeight		= 0.15f;
191 		const float				unusedFragWeight	= 0.15f;
192 		bool					unusedOk			= (m_features & FEATURE_UNUSED_MEMBERS) != 0;
193 		std::vector<VarType>	memberTypes;
194 		int						numMembers = rnd.getInt(1, m_maxStructMembers);
195 
196 		// Generate members first so nested struct declarations are in correct order.
197 		for (int ndx = 0; ndx < numMembers; ndx++)
198 			memberTypes.push_back(generateType(rnd, typeDepth+1, true, complexity));
199 
200 		StructType& structType = m_interface.allocStruct(std::string("s") + genName('A', 'Z', m_structNdx));
201 		m_structNdx += 1;
202 
203 		DE_ASSERT(numMembers <= 'Z' - 'A');
204 		for (int ndx = 0; ndx < numMembers; ndx++)
205 		{
206 			deUint32 flags = 0;
207 
208 			flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
209 			flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
210 
211 			structType.addMember(std::string("m") + (char)('A' + ndx), memberTypes[ndx], flags);
212 		}
213 
214 		return VarType(&structType, m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);
215 	}
216 	else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
217 	{
218 		const bool	arraysOfArraysOk	= (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
219 		int			arrayLength			= rnd.getInt(1, m_maxArrayLength);
220 
221 		if (complexity * arrayLength >= 70)
222 		{
223 			// Trim overly complicated cases (affects 18 cases out of 1576)
224 			arrayLength = 1;
225 		}
226 
227 		VarType		elementType			= generateType(rnd, typeDepth, arraysOfArraysOk, complexity * arrayLength);
228 		return VarType(elementType, arrayLength);
229 	}
230 	else
231 	{
232 		std::vector<glu::DataType> typeCandidates;
233 
234 		typeCandidates.push_back(glu::TYPE_FLOAT);
235 		typeCandidates.push_back(glu::TYPE_INT);
236 		typeCandidates.push_back(glu::TYPE_UINT);
237 		typeCandidates.push_back(glu::TYPE_BOOL);
238 
239 		if (m_features & FEATURE_16BIT_STORAGE) {
240 			typeCandidates.push_back(glu::TYPE_UINT16);
241 			typeCandidates.push_back(glu::TYPE_INT16);
242 			typeCandidates.push_back(glu::TYPE_FLOAT16);
243 		}
244 
245 		if (m_features & FEATURE_8BIT_STORAGE) {
246 			typeCandidates.push_back(glu::TYPE_UINT8);
247 			typeCandidates.push_back(glu::TYPE_INT8);
248 		}
249 
250 		if (m_features & FEATURE_VECTORS)
251 		{
252 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
253 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
254 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
255 			typeCandidates.push_back(glu::TYPE_INT_VEC2);
256 			typeCandidates.push_back(glu::TYPE_INT_VEC3);
257 			typeCandidates.push_back(glu::TYPE_INT_VEC4);
258 			typeCandidates.push_back(glu::TYPE_UINT_VEC2);
259 			typeCandidates.push_back(glu::TYPE_UINT_VEC3);
260 			typeCandidates.push_back(glu::TYPE_UINT_VEC4);
261 			typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
262 			typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
263 			typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
264 			if (m_features & FEATURE_16BIT_STORAGE)
265 			{
266 				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC2);
267 				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC3);
268 				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC4);
269 				typeCandidates.push_back(glu::TYPE_INT16_VEC2);
270 				typeCandidates.push_back(glu::TYPE_INT16_VEC3);
271 				typeCandidates.push_back(glu::TYPE_INT16_VEC4);
272 				typeCandidates.push_back(glu::TYPE_UINT16_VEC2);
273 				typeCandidates.push_back(glu::TYPE_UINT16_VEC3);
274 				typeCandidates.push_back(glu::TYPE_UINT16_VEC4);
275 			}
276 			if (m_features & FEATURE_8BIT_STORAGE)
277 			{
278 				typeCandidates.push_back(glu::TYPE_INT8_VEC2);
279 				typeCandidates.push_back(glu::TYPE_INT8_VEC3);
280 				typeCandidates.push_back(glu::TYPE_INT8_VEC4);
281 				typeCandidates.push_back(glu::TYPE_UINT8_VEC2);
282 				typeCandidates.push_back(glu::TYPE_UINT8_VEC3);
283 				typeCandidates.push_back(glu::TYPE_UINT8_VEC4);
284 			}
285 		}
286 
287 		if (m_features & FEATURE_MATRICES)
288 		{
289 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
290 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
291 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
292 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
293 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
294 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
295 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
296 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
297 		}
298 
299 		glu::DataType	type	= rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
300 		deUint32		flags	= (m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);
301 
302 		if (glu::dataTypeSupportsPrecisionModifier(type))
303 		{
304 			// Precision.
305 			static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
306 			flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
307 		}
308 
309 		return VarType(type, flags);
310 	}
311 }
312 
313 } // ubo
314 } // vkt
315