1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2018 NVIDIA Corporation
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *	  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Vulkan descriptor set tests
23  *//*--------------------------------------------------------------------*/
24 
25 // These tests generate random descriptor set layouts, where each descriptor
26 // set has a random number of bindings, each binding has a random array size
27 // and random descriptor type. The descriptor types are all backed by buffers
28 // or buffer views, and each buffer is filled with a unique integer starting
29 // from zero. The shader fetches from each descriptor (possibly using dynamic
30 // indexing of the descriptor array) and compares against the expected value.
31 //
32 // The different test cases vary the maximum number of descriptors used of
33 // each type. "Low" limit tests use the spec minimum maximum limit, "high"
34 // limit tests use up to 4k descriptors of the corresponding type. Test cases
35 // also vary the type indexing used, and shader stage.
36 
37 #include "vktBindingDescriptorSetRandomTests.hpp"
38 
39 #include "vkBufferWithMemory.hpp"
40 #include "vkImageWithMemory.hpp"
41 #include "vkQueryUtil.hpp"
42 #include "vkBuilderUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkTypeUtil.hpp"
45 #include "vktTestGroupUtil.hpp"
46 #include "vktTestCase.hpp"
47 
48 #include "deDefs.h"
49 #include "deMath.h"
50 #include "deRandom.h"
51 #include "deSharedPtr.hpp"
52 #include "deString.h"
53 
54 #include "tcuTestCase.hpp"
55 #include "tcuTestLog.hpp"
56 
57 #include <string>
58 #include <sstream>
59 
60 namespace vkt
61 {
62 namespace BindingModel
63 {
64 namespace
65 {
66 using namespace vk;
67 using namespace std;
68 
69 static const deUint32 DIM = 8;
70 
71 typedef enum
72 {
73 	INDEX_TYPE_NONE = 0,
74 	INDEX_TYPE_CONSTANT,
75 	INDEX_TYPE_PUSHCONSTANT,
76 	INDEX_TYPE_DEPENDENT,
77 	INDEX_TYPE_RUNTIME_SIZE,
78 } IndexType;
79 
80 typedef enum
81 {
82 	STAGE_COMPUTE = 0,
83 	STAGE_VERTEX,
84 	STAGE_FRAGMENT,
85 } Stage;
86 
87 typedef enum
88 {
89 	UPDATE_AFTER_BIND_DISABLED = 0,
90 	UPDATE_AFTER_BIND_ENABLED,
91 } UpdateAfterBind;
92 
93 const VkFlags allShaderStages = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
94 const VkFlags allPipelineStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
95 
96 struct CaseDef
97 {
98 	IndexType indexType;
99 	deUint32 numDescriptorSets;
100 	deUint32 maxPerStageUniformBuffers;
101 	deUint32 maxUniformBuffersDynamic;
102 	deUint32 maxPerStageStorageBuffers;
103 	deUint32 maxStorageBuffersDynamic;
104 	deUint32 maxPerStageSampledImages;
105 	deUint32 maxPerStageStorageImages;
106 	deUint32 maxInlineUniformBlocks;
107 	deUint32 maxInlineUniformBlockSize;
108 	Stage stage;
109 	UpdateAfterBind uab;
110 	deUint32 seed;
111 };
112 
113 
114 class RandomLayout
115 {
116 public:
RandomLayout(deUint32 numSets)117 	RandomLayout(deUint32 numSets) :
118 		layoutBindings(numSets),
119 		layoutBindingFlags(numSets),
120 		arraySizes(numSets),
121 		variableDescriptorSizes(numSets)
122 		{
123 		}
124 
125 	// These three are indexed by [set][binding]
126 	vector<vector<VkDescriptorSetLayoutBinding> > layoutBindings;
127 	vector<vector<VkDescriptorBindingFlagsEXT> > layoutBindingFlags;
128 	vector<vector<deUint32> > arraySizes;
129 	// size of the variable descriptor (last) binding in each set
130 	vector<deUint32> variableDescriptorSizes;
131 
132 };
133 
134 
135 class DescriptorSetRandomTestInstance : public TestInstance
136 {
137 public:
138 						DescriptorSetRandomTestInstance		(Context& context, const CaseDef& data);
139 						~DescriptorSetRandomTestInstance	(void);
140 	tcu::TestStatus		iterate								(void);
141 private:
142 	CaseDef				m_data;
143 
144 	enum
145 	{
146 		WIDTH = 256,
147 		HEIGHT = 256
148 	};
149 };
150 
DescriptorSetRandomTestInstance(Context & context,const CaseDef & data)151 DescriptorSetRandomTestInstance::DescriptorSetRandomTestInstance (Context& context, const CaseDef& data)
152 	: vkt::TestInstance		(context)
153 	, m_data				(data)
154 {
155 }
156 
~DescriptorSetRandomTestInstance(void)157 DescriptorSetRandomTestInstance::~DescriptorSetRandomTestInstance (void)
158 {
159 }
160 
161 class DescriptorSetRandomTestCase : public TestCase
162 {
163 	public:
164 								DescriptorSetRandomTestCase		(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
165 								~DescriptorSetRandomTestCase	(void);
166 	virtual	void				initPrograms					(SourceCollections& programCollection) const;
167 	virtual TestInstance*		createInstance					(Context& context) const;
168 	virtual void				checkSupport					(Context& context) const;
169 
170 private:
171 	CaseDef					m_data;
172 };
173 
DescriptorSetRandomTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)174 DescriptorSetRandomTestCase::DescriptorSetRandomTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
175 	: vkt::TestCase	(context, name, desc)
176 	, m_data		(data)
177 {
178 }
179 
~DescriptorSetRandomTestCase(void)180 DescriptorSetRandomTestCase::~DescriptorSetRandomTestCase	(void)
181 {
182 }
183 
checkSupport(Context & context) const184 void DescriptorSetRandomTestCase::checkSupport(Context& context) const
185 {
186 	VkPhysicalDeviceInlineUniformBlockPropertiesEXT inlineUniformProperties;
187 	deMemset(&inlineUniformProperties, 0, sizeof(inlineUniformProperties));
188 	inlineUniformProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT;
189 
190 	VkPhysicalDeviceProperties2 properties;
191 	deMemset(&properties, 0, sizeof(properties));
192 	properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
193 
194 	if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_inline_uniform_block"))
195 	{
196 		properties.pNext = &inlineUniformProperties;
197 	}
198 
199 	context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
200 
201 	VkPhysicalDeviceInlineUniformBlockFeaturesEXT inlineUniformFeatures;
202 	deMemset(&inlineUniformFeatures, 0, sizeof(inlineUniformFeatures));
203 	inlineUniformFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT;
204 
205 	VkPhysicalDeviceDescriptorIndexingFeaturesEXT indexingFeatures;
206 	deMemset(&indexingFeatures, 0, sizeof(indexingFeatures));
207 	indexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
208 
209 	VkPhysicalDeviceFeatures2 features;
210 	deMemset(&features, 0, sizeof(features));
211 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
212 
213 	if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_descriptor_indexing") &&
214 		isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_inline_uniform_block"))
215 	{
216 		indexingFeatures.pNext = &inlineUniformFeatures;
217 		features.pNext = &indexingFeatures;
218 	}
219 	else if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_descriptor_indexing"))
220 	{
221 		features.pNext = &indexingFeatures;
222 	}
223 	else if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_inline_uniform_block"))
224 	{
225 		features.pNext = &inlineUniformFeatures;
226 	}
227 
228 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features);
229 	if (m_data.stage == STAGE_VERTEX && !features.features.vertexPipelineStoresAndAtomics)
230 	{
231 		return TCU_THROW(NotSupportedError, "Vertex pipeline stores and atomics not supported");
232 	}
233 
234 	if ((m_data.indexType == INDEX_TYPE_PUSHCONSTANT ||
235 		 m_data.indexType == INDEX_TYPE_DEPENDENT ||
236 		 m_data.indexType == INDEX_TYPE_RUNTIME_SIZE) &&
237 		(!features.features.shaderUniformBufferArrayDynamicIndexing ||
238 		 !features.features.shaderStorageBufferArrayDynamicIndexing ||
239 		 !features.features.shaderSampledImageArrayDynamicIndexing ||
240 		 !features.features.shaderStorageImageArrayDynamicIndexing ||
241 		 !indexingFeatures.shaderUniformTexelBufferArrayDynamicIndexing ||
242 		 !indexingFeatures.shaderStorageTexelBufferArrayDynamicIndexing))
243 	{
244 		TCU_THROW(NotSupportedError, "Dynamic indexing not supported");
245 	}
246 
247 	if (m_data.numDescriptorSets > properties.properties.limits.maxBoundDescriptorSets)
248 	{
249 		TCU_THROW(NotSupportedError, "Number of descriptor sets not supported");
250 	}
251 
252 	if ((m_data.maxPerStageUniformBuffers + m_data.maxPerStageStorageBuffers +
253 		m_data.maxPerStageSampledImages + m_data.maxPerStageStorageImages) >
254 		properties.properties.limits.maxPerStageResources)
255 	{
256 		TCU_THROW(NotSupportedError, "Number of descriptors not supported");
257 	}
258 
259 	if (m_data.maxPerStageUniformBuffers > properties.properties.limits.maxPerStageDescriptorUniformBuffers ||
260 		m_data.maxPerStageStorageBuffers > properties.properties.limits.maxPerStageDescriptorStorageBuffers ||
261 		m_data.maxUniformBuffersDynamic  > properties.properties.limits.maxDescriptorSetUniformBuffersDynamic ||
262 		m_data.maxStorageBuffersDynamic  > properties.properties.limits.maxDescriptorSetStorageBuffersDynamic ||
263 		m_data.maxPerStageSampledImages  > properties.properties.limits.maxPerStageDescriptorSampledImages ||
264 		m_data.maxPerStageStorageImages  > properties.properties.limits.maxPerStageDescriptorStorageImages)
265 	{
266 		TCU_THROW(NotSupportedError, "Number of descriptors not supported");
267 	}
268 
269 	if (m_data.maxInlineUniformBlocks != 0 &&
270 		!inlineUniformFeatures.inlineUniformBlock)
271 	{
272 		TCU_THROW(NotSupportedError, "Inline uniform blocks not supported");
273 	}
274 
275 	if (m_data.maxInlineUniformBlocks > inlineUniformProperties.maxPerStageDescriptorInlineUniformBlocks)
276 	{
277 		TCU_THROW(NotSupportedError, "Number of inline uniform blocks not supported");
278 	}
279 
280 	if (m_data.maxInlineUniformBlocks != 0 &&
281 		m_data.maxInlineUniformBlockSize > inlineUniformProperties.maxInlineUniformBlockSize)
282 	{
283 		TCU_THROW(NotSupportedError, "Inline uniform block size not supported");
284 	}
285 
286 	if (m_data.indexType == INDEX_TYPE_RUNTIME_SIZE &&
287 		!indexingFeatures.runtimeDescriptorArray)
288 	{
289 		TCU_THROW(NotSupportedError, "runtimeDescriptorArray not supported");
290 	}
291 }
292 
293 // Return a random value in the range [min, max]
randRange(deRandom * rnd,deInt32 min,deInt32 max)294 deInt32 randRange(deRandom *rnd, deInt32 min, deInt32 max)
295 {
296 	if (max < 0)
297 		return 0;
298 
299 	return (deRandom_getUint32(rnd) % (max - min + 1)) + min;
300 }
301 
generateRandomLayout(RandomLayout & randomLayout,const CaseDef & caseDef)302 void generateRandomLayout(RandomLayout &randomLayout, const CaseDef &caseDef)
303 {
304 	deRandom rnd;
305 	deRandom_init(&rnd, caseDef.seed);
306 
307 	// Count the number of each resource type, to avoid overflowing the limits.
308 	deUint32 numUBO = 0;
309 	deUint32 numUBODyn = 0;
310 	deUint32 numSSBO = 0;
311 	deUint32 numSSBODyn = 0;
312 	deUint32 numImage = 0;
313 	deUint32 numTexBuffer = 0;
314 	deUint32 numInlineUniformBlocks = 0;
315 
316 	// TODO: Consider varying these
317 	deUint32 minBindings = 0;
318 	deUint32 maxBindings = 32;
319 	// No larger than 32 elements for dynamic indexing tests, due to 128B limit
320 	// for push constants (used for the indices)
321 	deUint32 maxArray = caseDef.indexType == INDEX_TYPE_NONE ? 0 : 32;
322 
323 	// Each set has a random number of bindings, each binding has a random
324 	// array size and a random descriptor type.
325 	for (deUint32 s = 0; s < caseDef.numDescriptorSets; ++s)
326 	{
327 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
328 		vector<VkDescriptorBindingFlagsEXT> &bindingsFlags = randomLayout.layoutBindingFlags[s];
329 		vector<deUint32> &arraySizes = randomLayout.arraySizes[s];
330 		int numBindings = randRange(&rnd, minBindings, maxBindings);
331 
332 		// Guarantee room for the output image
333 		if (s == 0 && numBindings == 0)
334 		{
335 			numBindings = 1;
336 		}
337 
338 		bindings = vector<VkDescriptorSetLayoutBinding>(numBindings);
339 		bindingsFlags = vector<VkDescriptorBindingFlagsEXT>(numBindings);
340 		arraySizes = vector<deUint32>(numBindings);
341 	}
342 
343 	// BUFFER_DYNAMIC descriptor types cannot be used with VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT bindings in one set
344 	bool allowDynamicBuffers = caseDef.uab != UPDATE_AFTER_BIND_ENABLED;
345 
346 	// Iterate over bindings first, then over sets. This prevents the low-limit bindings
347 	// from getting clustered in low-numbered sets.
348 	for (deUint32 b = 0; b <= maxBindings; ++b)
349 	{
350 		for (deUint32 s = 0; s < caseDef.numDescriptorSets; ++s)
351 		{
352 			vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
353 			vector<deUint32> &arraySizes = randomLayout.arraySizes[s];
354 
355 			if (b >= bindings.size())
356 			{
357 				continue;
358 			}
359 
360 			VkDescriptorSetLayoutBinding &binding = bindings[b];
361 			binding.binding = b;
362 			binding.pImmutableSamplers = NULL;
363 			binding.stageFlags = allShaderStages;
364 
365 			// Output image
366 			if (s == 0 && b == 0)
367 			{
368 				binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
369 				binding.descriptorCount = 1;
370 				numImage++;
371 				arraySizes[b] = 0;
372 				continue;
373 			}
374 
375 			binding.descriptorCount = 0;
376 
377 			// Select a random type of descriptor.
378 			int r = randRange(&rnd, 0, (allowDynamicBuffers ? 6 : 4));
379 			switch (r)
380 			{
381 			default: DE_ASSERT(0); // Fallthrough
382 			case 0:
383 				binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
384 				if (numUBO < caseDef.maxPerStageUniformBuffers)
385 				{
386 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, caseDef.maxPerStageUniformBuffers - numUBO));
387 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
388 					numUBO += binding.descriptorCount;
389 				}
390 				break;
391 			case 1:
392 				binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
393 				if (numSSBO < caseDef.maxPerStageStorageBuffers)
394 				{
395 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, caseDef.maxPerStageStorageBuffers - numSSBO));
396 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
397 					numSSBO += binding.descriptorCount;
398 				}
399 				break;
400 			case 2:
401 				binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
402 				if (numImage < caseDef.maxPerStageStorageImages)
403 				{
404 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, caseDef.maxPerStageStorageImages - numImage));
405 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
406 					numImage += binding.descriptorCount;
407 				}
408 				break;
409 			case 3:
410 				binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
411 				if (numTexBuffer < caseDef.maxPerStageSampledImages)
412 				{
413 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, caseDef.maxPerStageSampledImages - numTexBuffer));
414 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
415 					numTexBuffer += binding.descriptorCount;
416 				}
417 				break;
418 			case 4:
419 				if (caseDef.maxInlineUniformBlocks > 0)
420 				{
421 					binding.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
422 					if (numInlineUniformBlocks < caseDef.maxInlineUniformBlocks)
423 					{
424 						arraySizes[b] = randRange(&rnd, 1, (caseDef.maxInlineUniformBlockSize - 16) / 16); // subtract 16 for "ivec4 dummy"
425 						arraySizes[b] = de::min(maxArray, arraySizes[b]);
426 						binding.descriptorCount = (arraySizes[b] ? arraySizes[b] : 1) * 16 + 16; // add 16 for "ivec4 dummy"
427 						numInlineUniformBlocks++;
428 					}
429 				}
430 				else
431 				{
432 					// Plug in a dummy descriptor type, so validation layers that don't
433 					// support inline_uniform_block don't crash.
434 					binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
435 				}
436 				break;
437 			case 5:
438 				binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
439 				if (numUBODyn < caseDef.maxUniformBuffersDynamic &&
440 					numUBO < caseDef.maxPerStageUniformBuffers)
441 				{
442 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, de::min(caseDef.maxUniformBuffersDynamic - numUBODyn,
443 																				 caseDef.maxPerStageUniformBuffers - numUBO)));
444 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
445 					numUBO += binding.descriptorCount;
446 					numUBODyn += binding.descriptorCount;
447 				}
448 				break;
449 			case 6:
450 				binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
451 				if (numSSBODyn < caseDef.maxStorageBuffersDynamic &&
452 					numSSBO < caseDef.maxPerStageStorageBuffers)
453 				{
454 					arraySizes[b] = randRange(&rnd, 0, de::min(maxArray, de::min(caseDef.maxStorageBuffersDynamic - numSSBODyn,
455 																				 caseDef.maxPerStageStorageBuffers - numSSBO)));
456 					binding.descriptorCount = arraySizes[b] ? arraySizes[b] : 1;
457 					numSSBO += binding.descriptorCount;
458 					numSSBODyn += binding.descriptorCount;
459 				}
460 				break;
461 			}
462 		}
463 	}
464 
465 	for (deUint32 s = 0; s < caseDef.numDescriptorSets; ++s)
466 	{
467 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
468 		vector<VkDescriptorBindingFlagsEXT> &bindingsFlags = randomLayout.layoutBindingFlags[s];
469 		vector<deUint32> &variableDescriptorSizes = randomLayout.variableDescriptorSizes;
470 
471 		// Choose a variable descriptor count size. If the feature is not supported, we'll just
472 		// allocate the whole thing later on.
473 		if (bindings.size() > 0 &&
474 			bindings[bindings.size()-1].descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC &&
475 			bindings[bindings.size()-1].descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC &&
476 			!(s == 0 && bindings.size() == 1) && // Don't cut out the output image binding
477 			randRange(&rnd, 1,4) == 1) // 1 in 4 chance
478 		{
479 
480 			bindingsFlags[bindings.size()-1] |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
481 			variableDescriptorSizes[s] = randRange(&rnd, 0,bindings[bindings.size()-1].descriptorCount);
482 			if (bindings[bindings.size()-1].descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
483 			{
484 				// keep a multiple of 16B
485 				variableDescriptorSizes[s] &= ~0xF;
486 			}
487 		}
488 	}
489 }
490 
initPrograms(SourceCollections & programCollection) const491 void DescriptorSetRandomTestCase::initPrograms (SourceCollections& programCollection) const
492 {
493 	RandomLayout randomLayout(m_data.numDescriptorSets);
494 	generateRandomLayout(randomLayout, m_data);
495 
496 	std::stringstream decls, checks;
497 
498 	deUint32 descriptor = 0;
499 	for (deUint32 s = 0; s < m_data.numDescriptorSets; ++s)
500 	{
501 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
502 		vector<VkDescriptorBindingFlagsEXT> bindingsFlags = randomLayout.layoutBindingFlags[s];
503 		vector<deUint32> &arraySizes = randomLayout.arraySizes[s];
504 		vector<deUint32> &variableDescriptorSizes = randomLayout.variableDescriptorSizes;
505 
506 		for (size_t b = 0; b < bindings.size(); ++b)
507 		{
508 			VkDescriptorSetLayoutBinding &binding = bindings[b];
509 			deUint32 descriptorIncrement = (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 16 : 1;
510 
511 			// Construct the declaration for the binding
512 			if (binding.descriptorCount > 0)
513 			{
514 				std::stringstream array;
515 				if (m_data.indexType == INDEX_TYPE_RUNTIME_SIZE &&
516 					binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
517 				{
518 					if (arraySizes[b])
519 					{
520 						array << "[]";
521 					}
522 				}
523 				else
524 				{
525 					if (arraySizes[b])
526 					{
527 						array << "[" << arraySizes[b] << "]";
528 					}
529 				}
530 				switch (binding.descriptorType)
531 				{
532 				case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
533 					decls << "layout(set = " << s << ", binding = " << b << ") uniform inlineubodef" << s << "_" << b << " { ivec4 dummy; int val" << array.str() << "; } inlineubo" << s << "_" << b << ";\n";
534 					break;
535 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
536 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
537 					decls << "layout(set = " << s << ", binding = " << b << ") uniform ubodef" << s << "_" << b << " { int val; } ubo" << s << "_" << b << array.str()  << ";\n";
538 					break;
539 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
540 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
541 					decls << "layout(set = " << s << ", binding = " << b << ") buffer sbodef" << s << "_" << b << " { int val; } ssbo" << s << "_" << b << array.str()  << ";\n";
542 					break;
543 				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
544 					decls << "layout(set = " << s << ", binding = " << b << ") uniform itextureBuffer texbo" << s << "_" << b << array.str()  << ";\n";
545 					break;
546 				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
547 					decls << "layout(r32i, set = " << s << ", binding = " << b << ") uniform iimageBuffer image" << s << "_" << b << array.str()  << ";\n";
548 					break;
549 				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
550 					decls << "layout(r32ui, set = " << s << ", binding = " << b << ") uniform uimage2D image" << s << "_" << b << array.str()  << ";\n";
551 					break;
552 				default: DE_ASSERT(0);
553 				}
554 
555 				for (deUint32 ai = 0; ai < de::max(1u, arraySizes[b]); ++ai, descriptor += descriptorIncrement)
556 				{
557 					// Don't access descriptors past the end of the allocated range for
558 					// variable descriptor count
559 					if (b == bindings.size() - 1 &&
560 						(bindingsFlags[b] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT))
561 					{
562 						if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
563 						{
564 							// Convert to bytes and add 16 for "ivec4 dummy" in case of inline uniform block
565 							const deUint32 uboRange = ai*16 + 16;
566 							if (uboRange >= variableDescriptorSizes[s])
567 								continue;
568 						}
569 						else
570 						{
571 							if (ai >= variableDescriptorSizes[s])
572 								continue;
573 						}
574 					}
575 
576 					if (s == 0 && b == 0)
577 					{
578 						// This is the output image, skip.
579 						continue;
580 					}
581 
582 					// Check that the value in the descriptor equals its descriptor number.
583 					// i.e. check "ubo[c].val == descriptor" or "ubo[pushconst[c]].val == descriptor"
584 
585 					// First, construct the index. This can be a constant literal, a value
586 					// from a push constant, or a function of the previous descriptor value.
587 					std::stringstream ind;
588 					switch (m_data.indexType)
589 					{
590 					case INDEX_TYPE_NONE:
591 					case INDEX_TYPE_CONSTANT:
592 						// The index is just the constant literal
593 						if (arraySizes[b])
594 						{
595 							ind << "[" << ai << "]";
596 						}
597 						break;
598 					case INDEX_TYPE_PUSHCONSTANT:
599 						// identity is an int[], directly index it
600 						if (arraySizes[b])
601 						{
602 							ind << "[pc.identity[" << ai << "]]";
603 						}
604 						break;
605 					case INDEX_TYPE_RUNTIME_SIZE:
606 					case INDEX_TYPE_DEPENDENT:
607 						// Index is a function of the previous return value (which is reset to zero)
608 						if (arraySizes[b])
609 						{
610 							ind << "[accum + " << ai << "]";
611 						}
612 						break;
613 					default: DE_ASSERT(0);
614 					}
615 
616 					// For very large bindings, only check every N=201 descriptors (chosen arbitrarily)
617 					bool checkDescriptor = true;
618 					if (binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
619 					{
620 						// For "large" bindings, only check every N=3 descriptors (chosen arbitrarily).
621 						// This is meant to reduce shader compile time.
622 						if (ai > 2 &&
623 							binding.descriptorCount >= 4 &&
624 							(ai % 3) != 0)
625 						{
626 							checkDescriptor = false;
627 						}
628 					}
629 
630 					if (checkDescriptor)
631 					{
632 						// Fetch from the descriptor.
633 						switch (binding.descriptorType)
634 						{
635 						case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
636 							checks << "  temp = inlineubo" << s << "_" << b << ".val" << ind.str() << ";\n";
637 							break;
638 						case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
639 						case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
640 							checks << "  temp = ubo" << s << "_" << b << ind.str() << ".val;\n";
641 							break;
642 						case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
643 						case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
644 							checks << "  temp = ssbo" << s << "_" << b << ind.str() << ".val;\n";
645 							break;
646 						case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
647 							checks << "  temp = texelFetch(texbo" << s << "_" << b << ind.str() << ", 0).x;\n";
648 							break;
649 						case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
650 							checks << "  temp = imageLoad(image" << s << "_" << b << ind.str() << ", 0).x;\n";
651 							break;
652 						default: DE_ASSERT(0);
653 						}
654 						if (m_data.indexType == INDEX_TYPE_DEPENDENT || m_data.indexType == INDEX_TYPE_RUNTIME_SIZE)
655 						{
656 							// Set accum to zero, it is added to the next index.
657 							checks << "  accum = temp - " << descriptor << ";\n";
658 						}
659 						else
660 						{
661 							// Accumulate any incorrect values.
662 							checks << "  accum |= temp - " << descriptor << ";\n";
663 						}
664 					}
665 				}
666 			}
667 		}
668 	}
669 
670 	std::stringstream pushdecl;
671 	switch (m_data.indexType)
672 	{
673 	case INDEX_TYPE_PUSHCONSTANT:
674 		pushdecl << "layout (push_constant, std430) uniform Block { int identity[32]; } pc;\n";
675 		break;
676 	default: DE_ASSERT(0);
677 	case INDEX_TYPE_NONE:
678 	case INDEX_TYPE_CONSTANT:
679 	case INDEX_TYPE_DEPENDENT:
680 	case INDEX_TYPE_RUNTIME_SIZE:
681 		break;
682 	}
683 
684 
685 	switch (m_data.stage)
686 	{
687 	default: DE_ASSERT(0); // Fallthrough
688 	case STAGE_COMPUTE:
689 		{
690 			std::stringstream css;
691 			css <<
692 				"#version 450 core\n"
693 				"#extension GL_EXT_nonuniform_qualifier : enable\n"
694 				<< pushdecl.str()
695 				<< decls.str() <<
696 				"layout(local_size_x = 1, local_size_y = 1) in;\n"
697 				"void main()\n"
698 				"{\n"
699 				"  int accum = 0, temp;\n"
700 				<< checks.str() <<
701 				"  uvec4 color = (accum != 0) ? uvec4(0,0,0,0) : uvec4(1,0,0,1);\n"
702 				"  imageStore(image0_0, ivec2(gl_GlobalInvocationID.xy), color);\n"
703 				"}\n";
704 
705 			programCollection.glslSources.add("test") << glu::ComputeSource(css.str());
706 			break;
707 		}
708 	case STAGE_VERTEX:
709 		{
710 			std::stringstream vss;
711 			vss <<
712 				"#version 450 core\n"
713 				"#extension GL_EXT_nonuniform_qualifier : enable\n"
714 				<< pushdecl.str()
715 				<< decls.str()  <<
716 				"void main()\n"
717 				"{\n"
718 				"  int accum = 0, temp;\n"
719 				<< checks.str() <<
720 				"  uvec4 color = (accum != 0) ? uvec4(0,0,0,0) : uvec4(1,0,0,1);\n"
721 				"  imageStore(image0_0, ivec2(gl_VertexIndex % " << DIM << ", gl_VertexIndex / " << DIM << "), color);\n"
722 				"  gl_PointSize = 1.0f;\n"
723 				"  gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
724 				"}\n";
725 
726 			programCollection.glslSources.add("test") << glu::VertexSource(vss.str());
727 			break;
728 		}
729 	case STAGE_FRAGMENT:
730 		{
731 			std::stringstream vss;
732 			vss <<
733 				"#version 450 core\n"
734 				"void main()\n"
735 				"{\n"
736 				// full-viewport quad
737 				"  gl_Position = vec4( 2.0*float(gl_VertexIndex&2) - 1.0, 4.0*(gl_VertexIndex&1)-1.0, 1.0 - 2.0 * float(gl_VertexIndex&1), 1);\n"
738 				"}\n";
739 
740 			programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
741 
742 			std::stringstream fss;
743 			fss <<
744 				"#version 450 core\n"
745 				"#extension GL_EXT_nonuniform_qualifier : enable\n"
746 				<< pushdecl.str()
747 				<< decls.str() <<
748 				"void main()\n"
749 				"{\n"
750 				"  int accum = 0, temp;\n"
751 				<< checks.str() <<
752 				"  uvec4 color = (accum != 0) ? uvec4(0,0,0,0) : uvec4(1,0,0,1);\n"
753 				"  imageStore(image0_0, ivec2(gl_FragCoord.x, gl_FragCoord.y), color);\n"
754 				"}\n";
755 
756 			programCollection.glslSources.add("test") << glu::FragmentSource(fss.str());
757 			break;
758 		}
759 	}
760 
761 }
762 
createInstance(Context & context) const763 TestInstance* DescriptorSetRandomTestCase::createInstance (Context& context) const
764 {
765 	return new DescriptorSetRandomTestInstance(context, m_data);
766 }
767 
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)768 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
769 										 const VkBufferUsageFlags	usage)
770 {
771 	const VkBufferCreateInfo bufferCreateInfo =
772 	{
773 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
774 		DE_NULL,								// const void*			pNext;
775 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
776 		bufferSize,								// VkDeviceSize			size;
777 		usage,									// VkBufferUsageFlags	usage;
778 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
779 		0u,										// deUint32				queueFamilyIndexCount;
780 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
781 	};
782 	return bufferCreateInfo;
783 }
784 
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const void * pNext,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)785 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
786 										 const VkDevice					device,
787 										 const void*					pNext,
788 										 const VkDescriptorPool			descriptorPool,
789 										 const VkDescriptorSetLayout	setLayout)
790 {
791 	const VkDescriptorSetAllocateInfo allocateParams =
792 	{
793 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
794 		pNext,												// const void*					pNext;
795 		descriptorPool,										// VkDescriptorPool				descriptorPool;
796 		1u,													// deUint32						setLayoutCount;
797 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
798 	};
799 	return allocateDescriptorSet(vk, device, &allocateParams);
800 }
801 
makeBufferImageCopy(const VkExtent3D extent,const VkImageSubresourceLayers subresourceLayers)802 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D					extent,
803 									   const VkImageSubresourceLayers	subresourceLayers)
804 {
805 	const VkBufferImageCopy copyParams =
806 	{
807 		0ull,										//	VkDeviceSize				bufferOffset;
808 		0u,											//	deUint32					bufferRowLength;
809 		0u,											//	deUint32					bufferImageHeight;
810 		subresourceLayers,							//	VkImageSubresourceLayers	imageSubresource;
811 		makeOffset3D(0, 0, 0),						//	VkOffset3D					imageOffset;
812 		extent,										//	VkExtent3D					imageExtent;
813 	};
814 	return copyParams;
815 }
816 
iterate(void)817 tcu::TestStatus DescriptorSetRandomTestInstance::iterate (void)
818 {
819 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
820 	const VkDevice			device					= m_context.getDevice();
821 	Allocator&				allocator				= m_context.getDefaultAllocator();
822 
823 	RandomLayout randomLayout(m_data.numDescriptorSets);
824 	generateRandomLayout(randomLayout, m_data);
825 
826 
827 	VkPhysicalDeviceProperties2 properties;
828 	deMemset(&properties, 0, sizeof(properties));
829 	properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
830 
831 	m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &properties);
832 
833 	VkPhysicalDeviceInlineUniformBlockFeaturesEXT inlineUniformFeatures;
834 	deMemset(&inlineUniformFeatures, 0, sizeof(inlineUniformFeatures));
835 	inlineUniformFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT;
836 
837 	VkPhysicalDeviceDescriptorIndexingFeaturesEXT indexingFeatures;
838 	deMemset(&indexingFeatures, 0, sizeof(indexingFeatures));
839 	indexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
840 
841 	VkPhysicalDeviceFeatures2 features;
842 	deMemset(&features, 0, sizeof(features));
843 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
844 
845 	if (isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_EXT_descriptor_indexing") &&
846 		isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_EXT_inline_uniform_block"))
847 	{
848 		indexingFeatures.pNext = &inlineUniformFeatures;
849 		features.pNext = &indexingFeatures;
850 	}
851 	else if (isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_EXT_descriptor_indexing"))
852 	{
853 		features.pNext = &indexingFeatures;
854 	}
855 	else if (isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_EXT_inline_uniform_block"))
856 	{
857 		features.pNext = &inlineUniformFeatures;
858 	}
859 
860 	m_context.getInstanceInterface().getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &features);
861 
862 	deRandom rnd;
863 	deRandom_init(&rnd, m_data.seed);
864 
865 	VkPipelineBindPoint bindPoint = m_data.stage == STAGE_COMPUTE ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
866 
867 	DE_ASSERT(m_data.numDescriptorSets <= 32);
868 	Move<vk::VkDescriptorSetLayout>	descriptorSetLayouts[32];
869 	Move<vk::VkDescriptorPool>		descriptorPools[32];
870 	Move<vk::VkDescriptorSet>		descriptorSets[32];
871 
872 	deUint32 numDescriptors = 0;
873 	for (deUint32 s = 0; s < m_data.numDescriptorSets; ++s)
874 	{
875 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
876 		vector<VkDescriptorBindingFlagsEXT> &bindingsFlags = randomLayout.layoutBindingFlags[s];
877 		vector<deUint32> &variableDescriptorSizes = randomLayout.variableDescriptorSizes;
878 
879 		VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
880 		VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
881 
882 		for (size_t b = 0; b < bindings.size(); ++b)
883 		{
884 			VkDescriptorSetLayoutBinding &binding = bindings[b];
885 			numDescriptors += binding.descriptorCount;
886 
887 			// Randomly choose some bindings to use update-after-bind, if it is supported
888 			if (m_data.uab == UPDATE_AFTER_BIND_ENABLED &&
889 				randRange(&rnd, 1, 8) == 1 && // 1 in 8 chance
890 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER			|| indexingFeatures.descriptorBindingUniformBufferUpdateAfterBind) &&
891 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE				|| indexingFeatures.descriptorBindingStorageImageUpdateAfterBind) &&
892 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER			|| indexingFeatures.descriptorBindingStorageBufferUpdateAfterBind) &&
893 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER		|| indexingFeatures.descriptorBindingUniformTexelBufferUpdateAfterBind) &&
894 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER		|| indexingFeatures.descriptorBindingStorageTexelBufferUpdateAfterBind) &&
895 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT	|| inlineUniformFeatures.descriptorBindingInlineUniformBlockUpdateAfterBind) &&
896 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) &&
897 				(binding.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC))
898 			{
899 				bindingsFlags[b] |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
900 				layoutCreateFlags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
901 				poolCreateFlags |= VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
902 			}
903 
904 			if (!indexingFeatures.descriptorBindingVariableDescriptorCount)
905 			{
906 				bindingsFlags[b] &= ~VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
907 			}
908 		}
909 
910 		// Create a layout and allocate a descriptor set for it.
911 
912 		const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingFlagsInfo =
913 		{
914 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,	// VkStructureType						sType;
915 			DE_NULL,																// const void*							pNext;
916 			(deUint32)bindings.size(),												// uint32_t								bindingCount;
917 			bindings.empty() ? DE_NULL : &bindingsFlags[0],							// const VkDescriptorBindingFlagsEXT*	pBindingFlags;
918 		};
919 
920 		const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
921 		{
922 			vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
923 			&bindingFlagsInfo,
924 
925 			layoutCreateFlags,
926 			(deUint32)bindings.size(),
927 			bindings.empty() ? DE_NULL : &bindings[0]
928 		};
929 
930 		descriptorSetLayouts[s] = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
931 
932 		vk::DescriptorPoolBuilder poolBuilder;
933 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, m_data.maxPerStageUniformBuffers);
934 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, m_data.maxUniformBuffersDynamic);
935 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_data.maxPerStageStorageBuffers);
936 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, m_data.maxStorageBuffersDynamic);
937 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, m_data.maxPerStageSampledImages);
938 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, m_data.maxPerStageStorageImages);
939 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1);
940 		if (m_data.maxInlineUniformBlocks)
941 		{
942 			poolBuilder.addType(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, m_data.maxInlineUniformBlocks * m_data.maxInlineUniformBlockSize);
943 		}
944 
945 		VkDescriptorPoolInlineUniformBlockCreateInfoEXT inlineUniformBlockPoolCreateInfo =
946 		{
947 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT,	// VkStructureType	sType;
948 			DE_NULL,																// const void*		pNext;
949 			m_data.maxInlineUniformBlocks,											// uint32_t			maxInlineUniformBlockBindings;
950 		};
951 
952 		descriptorPools[s] = poolBuilder.build(vk, device, poolCreateFlags, 1u,
953 											   m_data.maxInlineUniformBlocks ? &inlineUniformBlockPoolCreateInfo : DE_NULL);
954 
955 		VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variableCountInfo =
956 		{
957 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT,	// VkStructureType	sType;
958 			DE_NULL,																		// const void*		pNext;
959 			0,																				// uint32_t			descriptorSetCount;
960 			DE_NULL,																		// const uint32_t*	pDescriptorCounts;
961 		};
962 
963 		const void *pNext = DE_NULL;
964 		if (bindings.size() > 0 &&
965 			bindingsFlags[bindings.size()-1] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT)
966 		{
967 			variableCountInfo.descriptorSetCount = 1;
968 			variableCountInfo.pDescriptorCounts = &variableDescriptorSizes[s];
969 			pNext = &variableCountInfo;
970 		}
971 
972 		descriptorSets[s] = makeDescriptorSet(vk, device, pNext, *descriptorPools[s], *descriptorSetLayouts[s]);
973 	}
974 
975 
976 	VkDeviceSize	align = de::max(de::max(de::max(properties.properties.limits.minTexelBufferOffsetAlignment,
977 													properties.properties.limits.minUniformBufferOffsetAlignment),
978 													properties.properties.limits.minStorageBufferOffsetAlignment),
979 													(VkDeviceSize)sizeof(deUint32));
980 
981 	de::MovePtr<BufferWithMemory> buffer;
982 	buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
983 		vk, device, allocator, makeBufferCreateInfo(align*numDescriptors,
984 													VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
985 													VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
986 													VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
987 													VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
988 													MemoryRequirement::HostVisible));
989 	deUint8 *bufferPtr = (deUint8 *)buffer->getAllocation().getHostPtr();
990 
991 	typedef vk::Unique<vk::VkBufferView>					BufferViewHandleUp;
992 	typedef de::SharedPtr<BufferViewHandleUp>				BufferViewHandleSp;
993 
994 	vector<BufferViewHandleSp>	bufferViews(de::max(1u,numDescriptors));
995 
996 	// Create a buffer and view for each descriptor. Fill descriptor 'd'
997 	// with an integer value equal to 'd'.
998 	int descriptor = 0;
999 	for (deUint32 s = 0; s < m_data.numDescriptorSets; ++s)
1000 	{
1001 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
1002 		for (size_t b = 0; b < bindings.size(); ++b)
1003 		{
1004 			VkDescriptorSetLayoutBinding &binding = bindings[b];
1005 
1006 			if (binding.descriptorCount == 0)
1007 			{
1008 				continue;
1009 			}
1010 			if (binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1011 			{
1012 				for (deUint32 d = descriptor; d < descriptor + binding.descriptorCount; ++d)
1013 				{
1014 					deUint32 *ptr = (deUint32 *)(bufferPtr + align*d);
1015 					*ptr = d;
1016 
1017 					const vk::VkBufferViewCreateInfo viewCreateInfo =
1018 					{
1019 						vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
1020 						DE_NULL,
1021 						(vk::VkBufferViewCreateFlags)0,
1022 						**buffer,								// buffer
1023 						VK_FORMAT_R32_SINT,						// format
1024 						(vk::VkDeviceSize)align*d,				// offset
1025 						(vk::VkDeviceSize)sizeof(deUint32)		// range
1026 					};
1027 					vk::Move<vk::VkBufferView> bufferView = vk::createBufferView(vk, device, &viewCreateInfo);
1028 					bufferViews[d] = BufferViewHandleSp(new BufferViewHandleUp(bufferView));
1029 				}
1030 				descriptor += binding.descriptorCount;
1031 			}
1032 			else
1033 			{
1034 				// subtract 16 for "ivec4 dummy"
1035 				DE_ASSERT(binding.descriptorCount >= 16);
1036 				descriptor += binding.descriptorCount - 16;
1037 			}
1038 		}
1039 	}
1040 
1041 	flushMappedMemoryRange(vk, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1042 
1043 	const VkQueue					queue					= m_context.getUniversalQueue();
1044 	Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, 0, m_context.getUniversalQueueFamilyIndex());
1045 	Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1046 
1047 	beginCommandBuffer(vk, *cmdBuffer, 0u);
1048 
1049 	// Push constants are used for dynamic indexing. PushConstant[i] = i.
1050 
1051 	const VkPushConstantRange pushConstRange =
1052 	{
1053 		allShaderStages,		// VkShaderStageFlags	stageFlags
1054 		0,						// deUint32				offset
1055 		128						// deUint32				size
1056 	};
1057 
1058 	vector<vk::VkDescriptorSetLayout>	descriptorSetLayoutsRaw(m_data.numDescriptorSets);
1059 	for (size_t i = 0; i < m_data.numDescriptorSets; ++i)
1060 	{
1061 		descriptorSetLayoutsRaw[i] = descriptorSetLayouts[i].get();
1062 	}
1063 
1064 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1065 	{
1066 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
1067 		DE_NULL,													// pNext
1068 		(VkPipelineLayoutCreateFlags)0,
1069 		m_data.numDescriptorSets,									// setLayoutCount
1070 		&descriptorSetLayoutsRaw[0],								// pSetLayouts
1071 		m_data.indexType == INDEX_TYPE_PUSHCONSTANT ? 1u : 0u,		// pushConstantRangeCount
1072 		&pushConstRange,											// pPushConstantRanges
1073 	};
1074 
1075 	Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1076 
1077 	if (m_data.indexType == INDEX_TYPE_PUSHCONSTANT)
1078 	{
1079 		// PushConstant[i] = i
1080 		for (deUint32 i = 0; i < (deUint32)(128 / sizeof(deUint32)); ++i)
1081 		{
1082 			vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, allShaderStages,
1083 								(deUint32)(i * sizeof(deUint32)), (deUint32)sizeof(deUint32), &i);
1084 		}
1085 	}
1086 
1087 	de::MovePtr<BufferWithMemory> copyBuffer;
1088 	copyBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1089 		vk, device, allocator, makeBufferCreateInfo(DIM*DIM*sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
1090 
1091 	const VkImageCreateInfo			imageCreateInfo			=
1092 	{
1093 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1094 		DE_NULL,								// const void*				pNext;
1095 		(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1096 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1097 		VK_FORMAT_R32_UINT,						// VkFormat					format;
1098 		{
1099 			DIM,								// deUint32	width;
1100 			DIM,								// deUint32	height;
1101 			1u									// deUint32	depth;
1102 		},										// VkExtent3D				extent;
1103 		1u,										// deUint32					mipLevels;
1104 		1u,										// deUint32					arrayLayers;
1105 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1106 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1107 		VK_IMAGE_USAGE_STORAGE_BIT
1108 		| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
1109 		| VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
1110 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1111 		0u,										// deUint32					queueFamilyIndexCount;
1112 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1113 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1114 	};
1115 
1116 	VkImageViewCreateInfo		imageViewCreateInfo		=
1117 	{
1118 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1119 		DE_NULL,									// const void*				pNext;
1120 		(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1121 		DE_NULL,									// VkImage					image;
1122 		VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
1123 		VK_FORMAT_R32_UINT,							// VkFormat					format;
1124 		{
1125 			VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1126 			VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1127 			VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1128 			VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1129 		},											// VkComponentMapping		 components;
1130 		{
1131 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1132 			0u,										// deUint32				baseMipLevel;
1133 			1u,										// deUint32				levelCount;
1134 			0u,										// deUint32				baseArrayLayer;
1135 			1u										// deUint32				layerCount;
1136 		}											// VkImageSubresourceRange	subresourceRange;
1137 	};
1138 
1139 	de::MovePtr<ImageWithMemory> image;
1140 	Move<VkImageView> imageView;
1141 
1142 	image = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1143 		vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1144 	imageViewCreateInfo.image = **image;
1145 	imageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1146 
1147 	descriptor = 0;
1148 	for (deUint32 s = 0; s < m_data.numDescriptorSets; ++s)
1149 	{
1150 		vector<VkDescriptorSetLayoutBinding> &bindings = randomLayout.layoutBindings[s];
1151 		vector<VkDescriptorBindingFlagsEXT> &bindingsFlags = randomLayout.layoutBindingFlags[s];
1152 		vector<deUint32> &arraySizes = randomLayout.arraySizes[s];
1153 		vector<deUint32> &variableDescriptorSizes = randomLayout.variableDescriptorSizes;
1154 
1155 		vector<VkDescriptorBufferInfo> bufferInfoVec(numDescriptors);
1156 		vector<VkDescriptorImageInfo> imageInfoVec(numDescriptors);
1157 		vector<VkBufferView> bufferViewVec(numDescriptors);
1158 		vector<VkWriteDescriptorSetInlineUniformBlockEXT> inlineInfoVec(numDescriptors);
1159 		vector<deUint32> descriptorNumber(numDescriptors);
1160 		vector<VkWriteDescriptorSet> writesBeforeBindVec(0);
1161 		vector<VkWriteDescriptorSet> writesAfterBindVec(0);
1162 		int vecIndex = 0;
1163 		int numDynamic = 0;
1164 
1165 		vector<VkDescriptorUpdateTemplateEntry> imgTemplateEntriesBefore, imgTemplateEntriesAfter,
1166 												bufTemplateEntriesBefore, bufTemplateEntriesAfter,
1167 												texelBufTemplateEntriesBefore, texelBufTemplateEntriesAfter,
1168 												inlineTemplateEntriesBefore, inlineTemplateEntriesAfter;
1169 
1170 		for (size_t b = 0; b < bindings.size(); ++b)
1171 		{
1172 			VkDescriptorSetLayoutBinding &binding = bindings[b];
1173 			deUint32 descriptorIncrement = (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 16 : 1;
1174 
1175 			// Construct the declaration for the binding
1176 			if (binding.descriptorCount > 0)
1177 			{
1178 				bool updateAfterBind = !!(bindingsFlags[b] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT);
1179 				for (deUint32 ai = 0; ai < de::max(1u, arraySizes[b]); ++ai, descriptor += descriptorIncrement)
1180 				{
1181 					// Don't access descriptors past the end of the allocated range for
1182 					// variable descriptor count
1183 					if (b == bindings.size() - 1 &&
1184 						(bindingsFlags[b] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT))
1185 					{
1186 						if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1187 						{
1188 							// Convert to bytes and add 16 for "ivec4 dummy" in case of inline uniform block
1189 							const deUint32 uboRange = ai*16 + 16;
1190 							if (uboRange >= variableDescriptorSizes[s])
1191 								continue;
1192 						}
1193 						else
1194 						{
1195 							if (ai >= variableDescriptorSizes[s])
1196 								continue;
1197 						}
1198 					}
1199 
1200 					// output image
1201 					imageInfoVec[vecIndex] = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1202 
1203 					if (binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1204 					{
1205 						bufferInfoVec[vecIndex] = makeDescriptorBufferInfo(**buffer, descriptor*align, sizeof(deUint32));
1206 						bufferViewVec[vecIndex] = **bufferViews[descriptor];
1207 					}
1208 
1209 					descriptorNumber[descriptor] = descriptor;
1210 
1211 					VkWriteDescriptorSet w =
1212 					{
1213 						VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1214 						DE_NULL,														// pNext
1215 						*descriptorSets[s],												// dstSet
1216 						(deUint32)b,													// binding
1217 						ai,																// dstArrayElement
1218 						1u,																// descriptorCount
1219 						binding.descriptorType,											// descriptorType
1220 						&imageInfoVec[vecIndex],										// pImageInfo
1221 						&bufferInfoVec[vecIndex],										// pBufferInfo
1222 						&bufferViewVec[vecIndex],										// pTexelBufferView
1223 					};
1224 
1225 					if (binding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1226 					{
1227 						VkWriteDescriptorSetInlineUniformBlockEXT inlineUniformBlock =
1228 						{
1229 							VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT,	// VkStructureType	sType;
1230 							DE_NULL,															// const void*		pNext;
1231 							sizeof(deUint32),													// uint32_t			dataSize;
1232 							&descriptorNumber[descriptor],										// const void*		pData;
1233 						};
1234 
1235 						inlineInfoVec[vecIndex] = inlineUniformBlock;
1236 						w.dstArrayElement = ai*16 + 16; // add 16 to skip "ivec4 dummy"
1237 						w.pNext = &inlineInfoVec[vecIndex];
1238 						w.descriptorCount = sizeof(deUint32);
1239 					}
1240 
1241 					VkDescriptorUpdateTemplateEntry templateEntry =
1242 					{
1243 						(deUint32)b,				// uint32_t				dstBinding;
1244 						ai,							// uint32_t				dstArrayElement;
1245 						1u,							// uint32_t				descriptorCount;
1246 						binding.descriptorType,		// VkDescriptorType		descriptorType;
1247 						0,							// size_t				offset;
1248 						0,							// size_t				stride;
1249 					};
1250 
1251 					switch (binding.descriptorType)
1252 					{
1253 					default: DE_ASSERT(0); // Fallthrough
1254 					case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1255 						templateEntry.offset = vecIndex * sizeof(VkDescriptorImageInfo);
1256 						(updateAfterBind ? imgTemplateEntriesAfter : imgTemplateEntriesBefore).push_back(templateEntry);
1257 						break;
1258 					case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1259 					case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1260 						templateEntry.offset = vecIndex * sizeof(VkBufferView);
1261 						(updateAfterBind ? texelBufTemplateEntriesAfter : texelBufTemplateEntriesBefore).push_back(templateEntry);
1262 						break;
1263 					case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1264 					case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1265 					case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1266 					case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1267 						templateEntry.offset = vecIndex * sizeof(VkDescriptorBufferInfo);
1268 						(updateAfterBind ? bufTemplateEntriesAfter : bufTemplateEntriesBefore).push_back(templateEntry);
1269 						break;
1270 					case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
1271 						templateEntry.offset = descriptor * sizeof(deUint32);
1272 						templateEntry.dstArrayElement = ai*16 + 16; // add 16 to skip "ivec4 dummy"
1273 						templateEntry.descriptorCount = sizeof(deUint32);
1274 						(updateAfterBind ? inlineTemplateEntriesAfter : inlineTemplateEntriesBefore).push_back(templateEntry);
1275 						break;
1276 					}
1277 
1278 					vecIndex++;
1279 
1280 					(updateAfterBind ? writesAfterBindVec : writesBeforeBindVec).push_back(w);
1281 
1282 					// Count the number of dynamic descriptors in this set.
1283 					if (binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
1284 						binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
1285 					{
1286 						numDynamic++;
1287 					}
1288 				}
1289 			}
1290 		}
1291 
1292 		// Make zeros have at least one element so &zeros[0] works
1293 		vector<deUint32> zeros(de::max(1,numDynamic));
1294 		deMemset(&zeros[0], 0, numDynamic * sizeof(deUint32));
1295 
1296 		// Randomly select between vkUpdateDescriptorSets and vkUpdateDescriptorSetWithTemplate
1297 		if (randRange(&rnd, 1, 2) == 1 &&
1298 			m_context.contextSupports(vk::ApiVersion(1, 1, 0)))
1299 		{
1300 			VkDescriptorUpdateTemplateCreateInfo templateCreateInfo =
1301 			{
1302 				VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,	// VkStructureType							sType;
1303 				NULL,														// void*									pNext;
1304 				0,															// VkDescriptorUpdateTemplateCreateFlags	flags;
1305 				0,															// uint32_t									descriptorUpdateEntryCount;
1306 				DE_NULL,													// uint32_t									descriptorUpdateEntryCount;
1307 				VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,			// VkDescriptorUpdateTemplateType			templateType;
1308 				descriptorSetLayouts[s].get(),								// VkDescriptorSetLayout					descriptorSetLayout;
1309 				bindPoint,													// VkPipelineBindPoint						pipelineBindPoint;
1310 				0,															// VkPipelineLayout							pipelineLayout;
1311 				0,															// uint32_t									set;
1312 			};
1313 
1314 			void *templateVectorData[] =
1315 			{
1316 				&imageInfoVec[0],
1317 				&bufferInfoVec[0],
1318 				&bufferViewVec[0],
1319 				&descriptorNumber[0],
1320 			};
1321 
1322 			vector<VkDescriptorUpdateTemplateEntry> *templateVectorsBefore[] =
1323 			{
1324 				&imgTemplateEntriesBefore,
1325 				&bufTemplateEntriesBefore,
1326 				&texelBufTemplateEntriesBefore,
1327 				&inlineTemplateEntriesBefore,
1328 			};
1329 
1330 			vector<VkDescriptorUpdateTemplateEntry> *templateVectorsAfter[] =
1331 			{
1332 				&imgTemplateEntriesAfter,
1333 				&bufTemplateEntriesAfter,
1334 				&texelBufTemplateEntriesAfter,
1335 				&inlineTemplateEntriesAfter,
1336 			};
1337 
1338 			for (size_t i = 0; i < sizeof(templateVectorsBefore) / sizeof(templateVectorsBefore[0]); ++i)
1339 			{
1340 				if (templateVectorsBefore[i]->size())
1341 				{
1342 					templateCreateInfo.descriptorUpdateEntryCount = (deUint32)templateVectorsBefore[i]->size();
1343 					templateCreateInfo.pDescriptorUpdateEntries = &((*templateVectorsBefore[i])[0]);
1344 					Move<VkDescriptorUpdateTemplate> descriptorUpdateTemplate = createDescriptorUpdateTemplate(vk, device, &templateCreateInfo, NULL);
1345 					vk.updateDescriptorSetWithTemplate(device, descriptorSets[s].get(), *descriptorUpdateTemplate, templateVectorData[i]);
1346 				}
1347 			}
1348 
1349 			vk.cmdBindDescriptorSets(*cmdBuffer, bindPoint, *pipelineLayout, s, 1, &descriptorSets[s].get(), numDynamic, &zeros[0]);
1350 
1351 			for (size_t i = 0; i < sizeof(templateVectorsAfter) / sizeof(templateVectorsAfter[0]); ++i)
1352 			{
1353 				if (templateVectorsAfter[i]->size())
1354 				{
1355 					templateCreateInfo.descriptorUpdateEntryCount = (deUint32)templateVectorsAfter[i]->size();
1356 					templateCreateInfo.pDescriptorUpdateEntries = &((*templateVectorsAfter[i])[0]);
1357 					Move<VkDescriptorUpdateTemplate> descriptorUpdateTemplate = createDescriptorUpdateTemplate(vk, device, &templateCreateInfo, NULL);
1358 					vk.updateDescriptorSetWithTemplate(device, descriptorSets[s].get(), *descriptorUpdateTemplate, templateVectorData[i]);
1359 				}
1360 			}
1361 
1362 		}
1363 		else
1364 		{
1365 			if (writesBeforeBindVec.size())
1366 			{
1367 				vk.updateDescriptorSets(device, (deUint32)writesBeforeBindVec.size(), &writesBeforeBindVec[0], 0, NULL);
1368 			}
1369 
1370 			vk.cmdBindDescriptorSets(*cmdBuffer, bindPoint, *pipelineLayout, s, 1, &descriptorSets[s].get(), numDynamic, &zeros[0]);
1371 
1372 			if (writesAfterBindVec.size())
1373 			{
1374 				vk.updateDescriptorSets(device, (deUint32)writesAfterBindVec.size(), &writesAfterBindVec[0], 0, NULL);
1375 			}
1376 		}
1377 	}
1378 
1379 	Move<VkPipeline> pipeline;
1380 	Move<VkRenderPass> renderPass;
1381 	Move<VkFramebuffer> framebuffer;
1382 
1383 	if (m_data.stage == STAGE_COMPUTE)
1384 	{
1385 		const Unique<VkShaderModule>	shader(createShaderModule(vk, device, m_context.getBinaryCollection().get("test"), 0));
1386 
1387 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo =
1388 		{
1389 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1390 			DE_NULL,
1391 			(VkPipelineShaderStageCreateFlags)0,
1392 			VK_SHADER_STAGE_COMPUTE_BIT,								// stage
1393 			*shader,													// shader
1394 			"main",
1395 			DE_NULL,													// pSpecializationInfo
1396 		};
1397 
1398 		const VkComputePipelineCreateInfo		pipelineCreateInfo =
1399 		{
1400 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1401 			DE_NULL,
1402 			0u,															// flags
1403 			shaderCreateInfo,											// cs
1404 			*pipelineLayout,											// layout
1405 			(vk::VkPipeline)0,											// basePipelineHandle
1406 			0u,															// basePipelineIndex
1407 		};
1408 		pipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1409 	}
1410 	else
1411 	{
1412 
1413 		const vk::VkSubpassDescription		subpassDesc			=
1414 		{
1415 			(vk::VkSubpassDescriptionFlags)0,
1416 			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
1417 			0u,														// inputCount
1418 			DE_NULL,												// pInputAttachments
1419 			0u,														// colorCount
1420 			DE_NULL,												// pColorAttachments
1421 			DE_NULL,												// pResolveAttachments
1422 			DE_NULL,												// depthStencilAttachment
1423 			0u,														// preserveCount
1424 			DE_NULL,												// pPreserveAttachments
1425 		};
1426 		const vk::VkRenderPassCreateInfo	renderPassParams	=
1427 		{
1428 			vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// sType
1429 			DE_NULL,												// pNext
1430 			(vk::VkRenderPassCreateFlags)0,
1431 			0u,														// attachmentCount
1432 			DE_NULL,												// pAttachments
1433 			1u,														// subpassCount
1434 			&subpassDesc,											// pSubpasses
1435 			0u,														// dependencyCount
1436 			DE_NULL,												// pDependencies
1437 		};
1438 
1439 		renderPass = createRenderPass(vk, device, &renderPassParams);
1440 
1441 		const vk::VkFramebufferCreateInfo	framebufferParams	=
1442 		{
1443 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
1444 			DE_NULL,										// pNext
1445 			(vk::VkFramebufferCreateFlags)0,
1446 			*renderPass,									// renderPass
1447 			0u,												// attachmentCount
1448 			DE_NULL,										// pAttachments
1449 			DIM,											// width
1450 			DIM,											// height
1451 			1u,												// layers
1452 		};
1453 
1454 		framebuffer = createFramebuffer(vk, device, &framebufferParams);
1455 
1456 		const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
1457 		{
1458 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1459 			DE_NULL,													// const void*								pNext;
1460 			(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
1461 			0u,															// deUint32									vertexBindingDescriptionCount;
1462 			DE_NULL,													// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1463 			0u,															// deUint32									vertexAttributeDescriptionCount;
1464 			DE_NULL														// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1465 		};
1466 
1467 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateCreateInfo	=
1468 		{
1469 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1470 			DE_NULL,														// const void*								pNext;
1471 			(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
1472 			(m_data.stage == STAGE_VERTEX) ? VK_PRIMITIVE_TOPOLOGY_POINT_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology						topology;
1473 			VK_FALSE														// VkBool32									primitiveRestartEnable;
1474 		};
1475 
1476 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
1477 		{
1478 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
1479 			DE_NULL,														// const void*								pNext;
1480 			(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
1481 			VK_FALSE,														// VkBool32									depthClampEnable;
1482 			(m_data.stage == STAGE_VERTEX) ? VK_TRUE : VK_FALSE,			// VkBool32									rasterizerDiscardEnable;
1483 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
1484 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
1485 			VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
1486 			VK_FALSE,														// VkBool32									depthBiasEnable;
1487 			0.0f,															// float									depthBiasConstantFactor;
1488 			0.0f,															// float									depthBiasClamp;
1489 			0.0f,															// float									depthBiasSlopeFactor;
1490 			1.0f															// float									lineWidth;
1491 		};
1492 
1493 		const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo =
1494 		{
1495 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1496 			DE_NULL,													// const void*								pNext
1497 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
1498 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
1499 			VK_FALSE,													// VkBool32									sampleShadingEnable
1500 			1.0f,														// float									minSampleShading
1501 			DE_NULL,													// const VkSampleMask*						pSampleMask
1502 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
1503 			VK_FALSE													// VkBool32									alphaToOneEnable
1504 		};
1505 
1506 		VkViewport viewport = makeViewport(DIM, DIM);
1507 		VkRect2D scissor = makeRect2D(DIM, DIM);
1508 
1509 		const VkPipelineViewportStateCreateInfo			viewportStateCreateInfo				=
1510 		{
1511 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType							sType
1512 			DE_NULL,												// const void*								pNext
1513 			(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags		flags
1514 			1u,														// deUint32									viewportCount
1515 			&viewport,												// const VkViewport*						pViewports
1516 			1u,														// deUint32									scissorCount
1517 			&scissor												// const VkRect2D*							pScissors
1518 		};
1519 
1520 		Move<VkShaderModule> fs;
1521 		Move<VkShaderModule> vs;
1522 
1523 		deUint32 numStages;
1524 		if (m_data.stage == STAGE_VERTEX)
1525 		{
1526 			vs = createShaderModule(vk, device, m_context.getBinaryCollection().get("test"), 0);
1527 			fs = createShaderModule(vk, device, m_context.getBinaryCollection().get("test"), 0); // bogus
1528 			numStages = 1u;
1529 		}
1530 		else
1531 		{
1532 			vs = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1533 			fs = createShaderModule(vk, device, m_context.getBinaryCollection().get("test"), 0);
1534 			numStages = 2u;
1535 		}
1536 
1537 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo[2] =
1538 		{
1539 			{
1540 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1541 				DE_NULL,
1542 				(VkPipelineShaderStageCreateFlags)0,
1543 				VK_SHADER_STAGE_VERTEX_BIT,									// stage
1544 				*vs,														// shader
1545 				"main",
1546 				DE_NULL,													// pSpecializationInfo
1547 			},
1548 			{
1549 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1550 				DE_NULL,
1551 				(VkPipelineShaderStageCreateFlags)0,
1552 				VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
1553 				*fs,														// shader
1554 				"main",
1555 				DE_NULL,													// pSpecializationInfo
1556 			}
1557 		};
1558 
1559 		const VkGraphicsPipelineCreateInfo				graphicsPipelineCreateInfo		=
1560 		{
1561 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1562 			DE_NULL,											// const void*										pNext;
1563 			(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
1564 			numStages,											// deUint32											stageCount;
1565 			&shaderCreateInfo[0],								// const VkPipelineShaderStageCreateInfo*			pStages;
1566 			&vertexInputStateCreateInfo,						// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1567 			&inputAssemblyStateCreateInfo,						// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1568 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1569 			&viewportStateCreateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
1570 			&rasterizationStateCreateInfo,						// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
1571 			&multisampleStateCreateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1572 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1573 			DE_NULL,											// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1574 			DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1575 			pipelineLayout.get(),								// VkPipelineLayout									layout;
1576 			renderPass.get(),									// VkRenderPass										renderPass;
1577 			0u,													// deUint32											subpass;
1578 			DE_NULL,											// VkPipeline										basePipelineHandle;
1579 			0													// int												basePipelineIndex;
1580 		};
1581 
1582 		pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
1583 	}
1584 
1585 	const VkImageMemoryBarrier imageBarrier =
1586 	{
1587 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1588 		DE_NULL,											// const void*			pNext
1589 		0u,													// VkAccessFlags		srcAccessMask
1590 		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1591 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1592 		VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1593 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1594 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1595 		**image,											// VkImage				image
1596 		{
1597 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1598 			0u,										// uint32_t				baseMipLevel
1599 			1u,										// uint32_t				mipLevels,
1600 			0u,										// uint32_t				baseArray
1601 			1u,										// uint32_t				arraySize
1602 		}
1603 	};
1604 
1605 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1606 							(VkDependencyFlags)0,
1607 							0, (const VkMemoryBarrier*)DE_NULL,
1608 							0, (const VkBufferMemoryBarrier*)DE_NULL,
1609 							1, &imageBarrier);
1610 
1611 	vk.cmdBindPipeline(*cmdBuffer, bindPoint, *pipeline);
1612 
1613 	VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1614 	VkClearValue clearColor = makeClearValueColorU32(0,0,0,0);
1615 
1616 	VkMemoryBarrier					memBarrier =
1617 	{
1618 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// sType
1619 		DE_NULL,							// pNext
1620 		0u,									// srcAccessMask
1621 		0u,									// dstAccessMask
1622 	};
1623 
1624 	vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1625 
1626 	memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1627 	memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1628 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages,
1629 		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
1630 
1631 	if (m_data.stage == STAGE_COMPUTE)
1632 	{
1633 		vk.cmdDispatch(*cmdBuffer, DIM, DIM, 1);
1634 	}
1635 	else
1636 	{
1637 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer,
1638 						makeRect2D(DIM, DIM),
1639 						0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1640 		// Draw a point cloud for vertex shader testing, and a single quad for fragment shader testing
1641 		if (m_data.stage == STAGE_VERTEX)
1642 		{
1643 			vk.cmdDraw(*cmdBuffer, DIM*DIM, 1u, 0u, 0u);
1644 		}
1645 		else
1646 		{
1647 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1648 		}
1649 		endRenderPass(vk, *cmdBuffer);
1650 	}
1651 
1652 	memBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1653 	memBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1654 	vk.cmdPipelineBarrier(*cmdBuffer, allPipelineStages, VK_PIPELINE_STAGE_TRANSFER_BIT,
1655 		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
1656 
1657 	const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(DIM, DIM, 1u),
1658 															 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1659 	vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **copyBuffer, 1u, &copyRegion);
1660 
1661 	endCommandBuffer(vk, *cmdBuffer);
1662 
1663 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1664 
1665 	deUint32 *ptr = (deUint32 *)copyBuffer->getAllocation().getHostPtr();
1666 	invalidateMappedMemoryRange(vk, device, copyBuffer->getAllocation().getMemory(), copyBuffer->getAllocation().getOffset(), DIM*DIM*sizeof(deUint32));
1667 
1668 	qpTestResult res = QP_TEST_RESULT_PASS;
1669 
1670 	for (deUint32 i = 0; i < DIM*DIM; ++i)
1671 	{
1672 		if (ptr[i] != 1)
1673 		{
1674 			res = QP_TEST_RESULT_FAIL;
1675 		}
1676 	}
1677 
1678 	return tcu::TestStatus(res, qpGetTestResultName(res));
1679 }
1680 
1681 }	// anonymous
1682 
createDescriptorSetRandomTests(tcu::TestContext & testCtx)1683 tcu::TestCaseGroup*	createDescriptorSetRandomTests (tcu::TestContext& testCtx)
1684 {
1685 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "descriptorset_random", "Randomly-generated desciptor set layouts"));
1686 
1687 	deUint32 seed = 0;
1688 
1689 	typedef struct
1690 	{
1691 		deUint32				count;
1692 		const char*				name;
1693 		const char*				description;
1694 	} TestGroupCase;
1695 
1696 	TestGroupCase setsCases[] =
1697 	{
1698 		{ 4,	"sets4",	"4 descriptor sets"		},
1699 		{ 8,	"sets8",	"8 descriptor sets"		},
1700 		{ 16,	"sets16",	"16 descriptor sets"	},
1701 		{ 32,	"sets32",	"32 descriptor sets"	},
1702 	};
1703 
1704 	TestGroupCase indexCases[] =
1705 	{
1706 		{ INDEX_TYPE_NONE,			"noarray",		"all descriptor declarations are not arrays"		},
1707 		{ INDEX_TYPE_CONSTANT,		"constant",		"constant indexing of descriptor arrays"			},
1708 		{ INDEX_TYPE_PUSHCONSTANT,	"unifindexed",	"indexing descriptor arrays with push constants"	},
1709 		{ INDEX_TYPE_DEPENDENT,		"dynindexed",	"dynamically uniform indexing descriptor arrays"	},
1710 		{ INDEX_TYPE_RUNTIME_SIZE,	"runtimesize",	"runtime-size declarations of descriptor arrays"	},
1711 	};
1712 
1713 	TestGroupCase uboCases[] =
1714 	{
1715 		{ 12,			"ubolimitlow",		"spec minmax ubo limit"		},
1716 		{ 4096,			"ubolimithigh",		"high ubo limit"			},
1717 	};
1718 
1719 	TestGroupCase sboCases[] =
1720 	{
1721 		{ 4,			"sbolimitlow",		"spec minmax ssbo limit"	},
1722 		{ 4096,			"sbolimithigh",		"high ssbo limit"			},
1723 	};
1724 
1725 	static const struct
1726 	{
1727 		deUint32				texCount;
1728 		deUint32				imgCount;
1729 		const char*				name;
1730 		const char*				description;
1731 	} imgCases[] =
1732 	{
1733 		{ 16, 4,		"imglimitlow",		"spec minmax image limit"	},
1734 		{ 4096, 4096,	"imglimithigh",		"high image limit"			},
1735 	};
1736 
1737 	static const struct
1738 	{
1739 		deUint32				iubCount;
1740 		deUint32				iubSize;
1741 		const char*				name;
1742 		const char*				description;
1743 	} iubCases[] =
1744 	{
1745 		{ 0, 0,		"noiub",			"no inline_uniform_block"			},
1746 		{ 4, 256,	"iublimitlow",		"inline_uniform_block low limit"	},
1747 		{ 8, 4096,	"iublimithigh",		"inline_uniform_block high limit"	},
1748 	};
1749 
1750 	TestGroupCase stageCases[] =
1751 	{
1752 		{ STAGE_COMPUTE,	"comp",		"compute"	},
1753 		{ STAGE_FRAGMENT,	"frag",		"fragment"	},
1754 		{ STAGE_VERTEX,		"vert",		"vertex"	},
1755 	};
1756 
1757 	TestGroupCase uabCases[] =
1758 	{
1759 		{ UPDATE_AFTER_BIND_DISABLED,	"nouab",	"no update after bind"		},
1760 	};
1761 
1762 	for (int setsNdx = 0; setsNdx < DE_LENGTH_OF_ARRAY(setsCases); setsNdx++)
1763 	{
1764 		de::MovePtr<tcu::TestCaseGroup> setsGroup(new tcu::TestCaseGroup(testCtx, setsCases[setsNdx].name, setsCases[setsNdx].description));
1765 		for (int indexNdx = 0; indexNdx < DE_LENGTH_OF_ARRAY(indexCases); indexNdx++)
1766 		{
1767 			de::MovePtr<tcu::TestCaseGroup> indexGroup(new tcu::TestCaseGroup(testCtx, indexCases[indexNdx].name, indexCases[indexNdx].description));
1768 			for (int uboNdx = 0; uboNdx < DE_LENGTH_OF_ARRAY(uboCases); uboNdx++)
1769 			{
1770 				de::MovePtr<tcu::TestCaseGroup> uboGroup(new tcu::TestCaseGroup(testCtx, uboCases[uboNdx].name, uboCases[uboNdx].description));
1771 				for (int sboNdx = 0; sboNdx < DE_LENGTH_OF_ARRAY(sboCases); sboNdx++)
1772 				{
1773 					de::MovePtr<tcu::TestCaseGroup> sboGroup(new tcu::TestCaseGroup(testCtx, sboCases[sboNdx].name, sboCases[sboNdx].description));
1774 					for (int imgNdx = 0; imgNdx < DE_LENGTH_OF_ARRAY(imgCases); imgNdx++)
1775 					{
1776 						de::MovePtr<tcu::TestCaseGroup> imgGroup(new tcu::TestCaseGroup(testCtx, imgCases[imgNdx].name, imgCases[imgNdx].description));
1777 						for (int iubNdx = 0; iubNdx < DE_LENGTH_OF_ARRAY(iubCases); iubNdx++)
1778 						{
1779 							de::MovePtr<tcu::TestCaseGroup> iubGroup(new tcu::TestCaseGroup(testCtx, iubCases[iubNdx].name, iubCases[iubNdx].description));
1780 							for (int uabNdx = 0; uabNdx < DE_LENGTH_OF_ARRAY(uabCases); uabNdx++)
1781 							{
1782 								de::MovePtr<tcu::TestCaseGroup> uabGroup(new tcu::TestCaseGroup(testCtx, uabCases[uabNdx].name, uabCases[uabNdx].description));
1783 								bool updateAfterBind = (UpdateAfterBind)uabCases[uabNdx].count == UPDATE_AFTER_BIND_ENABLED;
1784 								for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stageCases); stageNdx++)
1785 								{
1786 									de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stageCases[stageNdx].name, stageCases[stageNdx].description));
1787 									deUint32 numSeeds = (setsCases[setsNdx].count == 4 && uboNdx == 0 && sboNdx == 0 && imgNdx == 0 && iubNdx == 0) ? 10 : 1;
1788 									for (deUint32 rnd = 0; rnd < numSeeds; ++rnd)
1789 									{
1790 										CaseDef c =
1791 										{
1792 											(IndexType)indexCases[indexNdx].count,							// IndexType indexType;
1793 											setsCases[setsNdx].count,										// deUint32 numDescriptorSets;
1794 											uboCases[uboNdx].count,											// deUint32 maxPerStageUniformBuffers;
1795 											8,																// deUint32 maxUniformBuffersDynamic;
1796 											sboCases[sboNdx].count,											// deUint32 maxPerStageStorageBuffers;
1797 											4,																// deUint32 maxStorageBuffersDynamic;
1798 											imgCases[imgNdx].texCount,										// deUint32 maxPerStageSampledImages;
1799 											imgCases[imgNdx].imgCount,										// deUint32 maxPerStageStorageImages;
1800 											iubCases[iubNdx].iubCount,										// deUint32 maxInlineUniformBlocks;
1801 											iubCases[iubNdx].iubSize,										// deUint32 maxInlineUniformBlockSize;
1802 											(Stage)stageCases[stageNdx].count,								// Stage stage;
1803 											(UpdateAfterBind)uabCases[uabNdx].count,						// UpdateAfterBind uab;
1804 											seed++,															// deUint32 seed;
1805 										};
1806 
1807 										string name = de::toString(rnd);
1808 										stageGroup->addChild(new DescriptorSetRandomTestCase(testCtx, name.c_str(), "test", c));
1809 									}
1810 									(updateAfterBind ? uabGroup : iubGroup)->addChild(stageGroup.release());
1811 								}
1812 								if (updateAfterBind)
1813 								{
1814 									iubGroup->addChild(uabGroup.release());
1815 								}
1816 							}
1817 							imgGroup->addChild(iubGroup.release());
1818 						}
1819 						sboGroup->addChild(imgGroup.release());
1820 					}
1821 					uboGroup->addChild(sboGroup.release());
1822 				}
1823 				indexGroup->addChild(uboGroup.release());
1824 			}
1825 			setsGroup->addChild(indexGroup.release());
1826 		}
1827 		group->addChild(setsGroup.release());
1828 	}
1829 	return group.release();
1830 }
1831 
1832 }	// BindingModel
1833 }	// vkt
1834