Home | History | Annotate | Download | only in binding_model
      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:
    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 
    151 DescriptorSetRandomTestInstance::DescriptorSetRandomTestInstance (Context& context, const CaseDef& data)
    152 	: vkt::TestInstance		(context)
    153 	, m_data				(data)
    154 {
    155 }
    156 
    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 
    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 
    180 DescriptorSetRandomTestCase::~DescriptorSetRandomTestCase	(void)
    181 {
    182 }
    183 
    184 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]
    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 
    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 
    491 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 
    763 TestInstance* DescriptorSetRandomTestCase::createInstance (Context& context) const
    764 {
    765 	return new DescriptorSetRandomTestInstance(context, m_data);
    766 }
    767 
    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 
    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 
    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 
    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 
   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