• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests for descriptor updates.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktBindingDescriptorUpdateTests.hpp"
25 #include "vktBindingDescriptorUpdateASTests.hpp"
26 
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 
30 #include "vkRefUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "vkImageWithMemory.hpp"
40 #include "vkBufferWithMemory.hpp"
41 
42 #include "tcuTexture.hpp"
43 #include "tcuTestLog.hpp"
44 
45 #include "deRandom.hpp"
46 
47 #include <string>
48 #include <vector>
49 #include <utility>
50 #include <memory>
51 #include <math.h>
52 
53 namespace vkt
54 {
55 namespace BindingModel
56 {
57 namespace
58 {
59 
60 // Test matches VkPositiveLayerTest.EmptyDescriptorUpdateTest
EmptyDescriptorUpdateCase(Context & context)61 tcu::TestStatus EmptyDescriptorUpdateCase (Context& context)
62 {
63 	const vk::DeviceInterface&				vki					= context.getDeviceInterface();
64 	const vk::VkDevice						device				= context.getDevice();
65 	vk::Allocator&							allocator			= context.getDefaultAllocator();
66 
67 	// Create layout with two uniform buffer descriptors w/ empty binding between them
68 	vk::DescriptorSetLayoutBuilder			builder;
69 
70 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);
71 	builder.addBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, (vk::VkShaderStageFlags)0, DE_NULL);
72 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);
73 
74 	vk::Unique<vk::VkDescriptorSetLayout>	layout				(builder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0));
75 
76 	// Create descriptor pool
77 	vk::Unique<vk::VkDescriptorPool>		descriptorPool		(vk::DescriptorPoolBuilder().addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2).build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
78 
79 	// Create descriptor set
80 	const vk::VkDescriptorSetAllocateInfo	setAllocateInfo		=
81 	{
82 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType
83 		DE_NULL,											// const void*					pNext
84 		*descriptorPool,									// VkDescriptorPool				descriptorPool
85 		1,													// deUint32						descriptorSetCount
86 		&layout.get()										// const VkDescriptorSetLayout*	pSetLayouts
87 	};
88 
89 	vk::Unique<vk::VkDescriptorSet>			descriptorSet		(allocateDescriptorSet(vki, device, &setAllocateInfo));
90 
91 	// Create a buffer to be used for update
92 	const vk::VkBufferCreateInfo			bufferCreateInfo	=
93 	{
94 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType
95 		DE_NULL,									// const void*			pNext
96 		(vk::VkBufferCreateFlags)DE_NULL,			// VkBufferCreateFlags	flags
97 		256,										// VkDeviceSize			size
98 		vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,		// VkBufferUsageFlags	usage
99 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode
100 		0,											// deUint32				queueFamilyIndexCount
101 		DE_NULL										// const deUint32*		pQueueFamilyIndices
102 	};
103 
104 	vk::Unique<vk::VkBuffer>				buffer				(createBuffer(vki, device, &bufferCreateInfo));
105 	const vk::VkMemoryRequirements			requirements		= vk::getBufferMemoryRequirements(vki, device, *buffer);
106 	de::MovePtr<vk::Allocation>				allocation			= allocator.allocate(requirements, vk::MemoryRequirement::Any);
107 
108 	VK_CHECK(vki.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
109 
110 	// Only update the descriptor at binding 2
111 	const vk::VkDescriptorBufferInfo		descriptorInfo		=
112 	{
113 		*buffer,		// VkBuffer		buffer
114 		0,				// VkDeviceSize	offset
115 		VK_WHOLE_SIZE	// VkDeviceSize	range
116 	};
117 
118 	const vk::VkWriteDescriptorSet			descriptorWrite		=
119 	{
120 		vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureTypes					Type
121 		DE_NULL,									// const void*						pNext
122 		*descriptorSet,								// VkDescriptorSet					dstSet
123 		2,											// deUint32							dstBinding
124 		0,											// deUint32							dstArrayElement
125 		1,											// deUint32							descriptorCount
126 		vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,		// VkDescriptorType					descriptorType
127 		DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo
128 		&descriptorInfo,							// const VkDescriptorBufferInfo*	pBufferInfo
129 		DE_NULL										// const VkBufferView*				pTexelBufferView
130 	};
131 
132 	vki.updateDescriptorSets(device, 1, &descriptorWrite, 0, DE_NULL);
133 
134 	// Test should always pass
135 	return tcu::TestStatus::pass("Pass");
136 }
137 
138 
createEmptyDescriptorUpdateTests(tcu::TestContext & testCtx)139 tcu::TestCaseGroup* createEmptyDescriptorUpdateTests (tcu::TestContext& testCtx)
140 {
141 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "empty_descriptor", "Update last descriptor in a set that includes an empty binding"));
142 
143 	addFunctionCase(group.get(), "uniform_buffer", "", EmptyDescriptorUpdateCase);
144 
145 	return group.release();
146 }
147 
148 enum class PointerCase
149 {
150 	ZERO = 0,
151 	ONE,
152 	DESTROYED,
153 };
154 
155 struct SamplerlessParams
156 {
157 	vk::VkDescriptorType	type;
158 	PointerCase				pointer;
159 	deUint32				descriptorSet;
160 };
161 
162 class SamplerlessDescriptorWriteTestCase : public vkt::TestCase
163 {
164 public:
165 								SamplerlessDescriptorWriteTestCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const SamplerlessParams& params);
~SamplerlessDescriptorWriteTestCase(void)166 	virtual						~SamplerlessDescriptorWriteTestCase	(void) {}
167 
168 	virtual void				initPrograms						(vk::SourceCollections& programCollection) const;
169 	virtual vkt::TestInstance*	createInstance						(Context& context) const;
170 	virtual void				checkSupport						(Context& context) const;
171 
172 	vk::VkFormatFeatureFlagBits	getMainImageFeature					(void) const;
173 
174 	static const vk::VkFormat	kImageFormat						= vk::VK_FORMAT_R8G8B8A8_UNORM;
175 private:
176 	SamplerlessParams			m_params;
177 };
178 
179 class SamplerlessDescriptorWriteTestInstance : public vkt::TestInstance
180 {
181 public:
182 								SamplerlessDescriptorWriteTestInstance	(Context& context, const SamplerlessParams& params);
~SamplerlessDescriptorWriteTestInstance(void)183 	virtual						~SamplerlessDescriptorWriteTestInstance	(void) {}
184 
185 	vk::VkSampler				getSamplerHandle						(void) const;
186 	virtual tcu::TestStatus		iterate									(void);
187 
188 	vk::VkExtent3D				getMainImageExtent						(void) const;
189 	vk::VkImageUsageFlags		getMainImageUsage						(void) const;
190 	vk::VkImageLayout			getMainImageShaderLayout				(void) const;
191 
192 	static const vk::VkFormat	kImageFormat							= SamplerlessDescriptorWriteTestCase::kImageFormat;
193 	static const vk::VkExtent3D	kFramebufferExtent;
194 	static const vk::VkExtent3D	kMinimumExtent;
195 	static const tcu::Vec4		kDescriptorColor;
196 private:
197 	SamplerlessParams			m_params;
198 };
199 
200 const vk::VkExtent3D	SamplerlessDescriptorWriteTestInstance::kFramebufferExtent	= vk::makeExtent3D(64u, 64u, 1u);
201 const vk::VkExtent3D	SamplerlessDescriptorWriteTestInstance::kMinimumExtent		= vk::makeExtent3D(1u, 1u, 1u);
202 const tcu::Vec4			SamplerlessDescriptorWriteTestInstance::kDescriptorColor	{0.0f, 1.0f, 0.0f, 1.0f};
203 
SamplerlessDescriptorWriteTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const SamplerlessParams & params)204 SamplerlessDescriptorWriteTestCase::SamplerlessDescriptorWriteTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const SamplerlessParams& params)
205 	: vkt::TestCase{testCtx, name, description}
206 	, m_params(params)
207 {
208 }
209 
initPrograms(vk::SourceCollections & programCollection) const210 void SamplerlessDescriptorWriteTestCase::initPrograms (vk::SourceCollections& programCollection) const
211 {
212 	const std::string vertexShader =
213 		"#version 450\n"
214 		"layout(location=0) in vec4 position;\n"
215 		"void main() { gl_Position = position; }\n";
216 
217 	programCollection.glslSources.add("vert") << glu::VertexSource(vertexShader);
218 
219 	std::string descriptorDecl;
220 	std::string readOp;
221 	std::string extensions;
222 
223 	switch (m_params.type)
224 	{
225 	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
226 		extensions		= "#extension GL_EXT_samplerless_texture_functions : require\n";
227 		descriptorDecl	= "layout(set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform texture2D img;";
228 		readOp			= "texelFetch(img, ivec2(0, 0), 0)";
229 		break;
230 	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
231 		descriptorDecl	= "layout(rgba8, set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform image2D img;";
232 		readOp			= "imageLoad(img, ivec2(0, 0))";
233 		break;
234 	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
235 		descriptorDecl	= "layout(input_attachment_index=0, set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform subpassInput img;";
236 		readOp			= "subpassLoad(img)";
237 		break;
238 	default:
239 		DE_ASSERT(false);
240 		break;
241 	}
242 
243 	std::ostringstream fragmentShader;
244 
245 	fragmentShader
246 		<< "#version 450\n"
247 		<< extensions
248 		<< descriptorDecl << "\n"
249 		<< "layout(location = 0) out vec4 color_out;\n"
250 		<< "void main()\n"
251 		<< "{\n"
252 		<< "    color_out = " << readOp << ";\n"
253 		<< "}\n"
254 		;
255 
256 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentShader.str());
257 }
258 
getMainImageFeature(void) const259 vk::VkFormatFeatureFlagBits SamplerlessDescriptorWriteTestCase::getMainImageFeature (void) const
260 {
261 	vk::VkFormatFeatureFlagBits feature = static_cast<vk::VkFormatFeatureFlagBits>(0);
262 
263 	switch (m_params.type)
264 	{
265 	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		feature = vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;		break;
266 	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		feature = vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;		break;
267 	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	feature = vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;	break;
268 	default:
269 		DE_ASSERT(false);
270 		break;
271 	}
272 
273 	return feature;
274 }
275 
checkSupport(Context & context) const276 void SamplerlessDescriptorWriteTestCase::checkSupport (Context& context) const
277 {
278 	const auto&	vki				= context.getInstanceInterface();
279 	const auto	physicalDevice	= context.getPhysicalDevice();
280 	const auto	mainFeature		= getMainImageFeature();
281 
282 	const vk::VkFormatFeatureFlags features =
283 	(
284 		vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT		|	// For color clearing.
285 		vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT	|	// For the separate frame buffer image (uses the same format).
286 		mainFeature
287 	);
288 
289 	const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
290 	if ((props.optimalTilingFeatures & features) != features)
291 		TCU_THROW(NotSupportedError, "Image format does not support the required features");
292 }
293 
createInstance(Context & context) const294 vkt::TestInstance* SamplerlessDescriptorWriteTestCase::createInstance (Context& context) const
295 {
296 	return new SamplerlessDescriptorWriteTestInstance{context, m_params};
297 }
298 
SamplerlessDescriptorWriteTestInstance(Context & context,const SamplerlessParams & params)299 SamplerlessDescriptorWriteTestInstance::SamplerlessDescriptorWriteTestInstance (Context& context, const SamplerlessParams& params)
300 	: vkt::TestInstance{context}
301 	, m_params(params)
302 {
303 }
304 
305 struct DestroyedSampler
306 {
307 	vk::VkSampler sampler;
308 
DestroyedSamplervkt::BindingModel::__anond6e0c07e0111::DestroyedSampler309 	DestroyedSampler (Context& context)
310 		: sampler{DE_NULL}
311 	{
312 		const vk::VkSamplerCreateInfo createInfo =
313 		{
314 			vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
315 			nullptr,										// const void*			pNext;
316 			0u,												// VkSamplerCreateFlags	flags;
317 			vk::VK_FILTER_NEAREST,							// VkFilter				magFilter;
318 			vk::VK_FILTER_NEAREST,							// VkFilter				minFilter;
319 			vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
320 			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeU;
321 			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeV;
322 			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeW;
323 			0.0f,											// float				mipLodBias;
324 			VK_FALSE,										// VkBool32				anisotropyEnable;
325 			1.0f,											// float				maxAnisotropy;
326 			VK_FALSE,										// VkBool32				compareEnable;
327 			vk::VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
328 			0.0f,											// float				minLod;
329 			0.0f,											// float				maxLod;
330 			vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor		borderColor;
331 			VK_FALSE,										// VkBool32				unnormalizedCoordinates;
332 		};
333 		const auto newSampler = vk::createSampler(context.getDeviceInterface(), context.getDevice(), &createInfo);
334 		sampler = newSampler.get();
335 		// newSampler will be destroyed here and sampler will hold the former handle.
336 	}
337 };
338 
getSamplerHandle(void) const339 vk::VkSampler SamplerlessDescriptorWriteTestInstance::getSamplerHandle (void) const
340 {
341 	if (m_params.pointer == PointerCase::ZERO)	return vk::VkSampler{DE_NULL};
342 	if (m_params.pointer == PointerCase::ONE)	return vk::VkSampler{1};
343 	static const DestroyedSampler destroyedSampler{m_context};
344 	return destroyedSampler.sampler;
345 }
346 
getMainImageExtent(void) const347 vk::VkExtent3D SamplerlessDescriptorWriteTestInstance::getMainImageExtent (void) const
348 {
349 	const vk::VkExtent3D* extent = nullptr;
350 
351 	switch (m_params.type)
352 	{
353 	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		// fallthrough
354 	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		extent = &kMinimumExtent;		break;
355 	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	extent = &kFramebufferExtent;	break;
356 	default:
357 		DE_ASSERT(false);
358 		break;
359 	}
360 
361 	return *extent;
362 }
363 
getMainImageUsage(void) const364 vk::VkImageUsageFlags SamplerlessDescriptorWriteTestInstance::getMainImageUsage (void) const
365 {
366 	vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;	// Used when clearing the image.
367 
368 	switch (m_params.type)
369 	{
370 	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		usage |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;			break;
371 	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		usage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;			break;
372 	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	usage |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;	break;
373 	default:
374 		DE_ASSERT(false);
375 		break;
376 	}
377 
378 	return usage;
379 }
380 
getMainImageShaderLayout(void) const381 vk::VkImageLayout SamplerlessDescriptorWriteTestInstance::getMainImageShaderLayout (void) const
382 {
383 	vk::VkImageLayout layout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
384 
385 	switch (m_params.type)
386 	{
387 	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		// fallthrough
388 	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	layout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;	break;
389 	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		layout = vk::VK_IMAGE_LAYOUT_GENERAL;					break;
390 	default:
391 		DE_ASSERT(false);
392 		break;
393 	}
394 
395 	return layout;
396 }
397 
398 
iterate(void)399 tcu::TestStatus SamplerlessDescriptorWriteTestInstance::iterate (void)
400 {
401 	const auto&	vkd			= m_context.getDeviceInterface();
402 	const auto	device		= m_context.getDevice();
403 	auto&		allocator	= m_context.getDefaultAllocator();
404 	const auto	queue		= m_context.getUniversalQueue();
405 	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
406 	const auto	tcuFormat	= vk::mapVkFormat(kImageFormat);
407 
408 	const vk::VkImageCreateInfo mainImgCreateInfo =
409 	{
410 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
411 		nullptr,									// const void*				pNext;
412 		0u,											// VkImageCreateFlags		flags;
413 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
414 		kImageFormat,								// VkFormat					format;
415 		getMainImageExtent(),						// VkExtent3D				extent;
416 		1u,											// deUint32					mipLevels;
417 		1u,											// deUint32					arrayLayers;
418 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
419 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
420 		getMainImageUsage(),						// VkImageUsageFlags		usage;
421 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
422 		1u,											// deUint32					queueFamilyIndexCount;
423 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
424 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
425 	};
426 
427 	const vk::VkImageCreateInfo fbImgCreateInfo =
428 	{
429 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
430 		nullptr,									// const void*				pNext;
431 		0u,											// VkImageCreateFlags		flags;
432 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
433 		kImageFormat,								// VkFormat					format;
434 		kFramebufferExtent,							// VkExtent3D				extent;
435 		1u,											// deUint32					mipLevels;
436 		1u,											// deUint32					arrayLayers;
437 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
438 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
439 		(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |	// VkImageUsageFlags		usage;
440 		 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT),			// Used when verifying the image.
441 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
442 		1u,											// deUint32					queueFamilyIndexCount;
443 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
444 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
445 	};
446 
447 	// Create main and framebuffer images.
448 	const vk::ImageWithMemory mainImage	{vkd, device, allocator, mainImgCreateInfo,	vk::MemoryRequirement::Any};
449 	const vk::ImageWithMemory fbImage	{vkd, device, allocator, fbImgCreateInfo,	vk::MemoryRequirement::Any};
450 
451 	// Corresponding image views.
452 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
453 	const auto mainView					= vk::makeImageView(vkd, device, mainImage.get(),	vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);
454 	const auto fbView					= vk::makeImageView(vkd, device, fbImage.get(),		vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);
455 
456 	// Buffer to copy rendering result to.
457 	const vk::VkDeviceSize		resultsBufferSize	= static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * kFramebufferExtent.width * kFramebufferExtent.height * kFramebufferExtent.depth);
458 	const auto					resultsBufferInfo	= vk::makeBufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
459 	const vk::BufferWithMemory	resultsBuffer		{vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};
460 
461 	const std::vector<tcu::Vec4> fullScreenQuad =
462 	{
463 		{ -1.f, -1.f,	0.f, 1.f },
464 		{  1.f, -1.f,	0.f, 1.f },
465 		{ -1.f,  1.f,	0.f, 1.f },
466 		{ -1.f,  1.f,	0.f, 1.f },
467 		{  1.f, -1.f,	0.f, 1.f },
468 		{  1.f,  1.f,	0.f, 1.f },
469 	};
470 
471 	// Vertex buffer.
472 	const vk::VkDeviceSize		vertexBufferSize	= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
473 	const auto					vertexBufferInfo	= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
474 	const vk::BufferWithMemory	vertexBuffer		{vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};
475 
476 	// Copy data to vertex buffer.
477 	const auto&	vertexAlloc		= vertexBuffer.getAllocation();
478 	const auto	vertexDataPtr	= reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
479 	deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
480 	vk::flushAlloc(vkd, device, vertexAlloc);
481 
482 	// Descriptor set layouts.
483 	vk::DescriptorSetLayoutBuilder layoutBuilder;
484 	std::vector<vk::Move<vk::VkDescriptorSetLayout>> descriptorSetLayouts;
485 	// Create layouts for required amount of empty descriptor sets before the one that is actually used.
486 	for (deUint32 descIdx = 0u; descIdx < m_params.descriptorSet; descIdx++)
487 	{
488 		descriptorSetLayouts.push_back(layoutBuilder.build(vkd, device));
489 	}
490 	// Create a layout for the descriptor set that is actually used.
491 	layoutBuilder.addSingleBinding(m_params.type, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
492 	descriptorSetLayouts.push_back(layoutBuilder.build(vkd, device));
493 
494 	// Descriptor pool.
495 	vk::DescriptorPoolBuilder poolBuilder;
496 	poolBuilder.addType(m_params.type);
497 	const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, m_params.descriptorSet + 1);
498 
499 	// Descriptor sets.
500 	std::vector<vk::Move<vk::VkDescriptorSet>> descriptorSets;
501 	for (deUint32 descIdx = 0u; descIdx < m_params.descriptorSet; descIdx++)
502 	{
503 		descriptorSets.push_back(vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayouts[descIdx].get()));
504 	}
505 	descriptorSets.push_back(vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayouts[m_params.descriptorSet].get()));
506 
507 	// Update descriptor set with the descriptor.
508 	// IMPORTANT: the chosen sampler handle is used here.
509 	vk::DescriptorSetUpdateBuilder updateBuilder;
510 	const auto descriptorImageInfo = vk::makeDescriptorImageInfo(getSamplerHandle(), mainView.get(), getMainImageShaderLayout());
511 	updateBuilder.writeSingle(descriptorSets[m_params.descriptorSet].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), m_params.type, &descriptorImageInfo);
512 	updateBuilder.update(vkd, device);
513 
514 	// Shader modules.
515 	const auto vertexModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
516 	const auto fragModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
517 
518 	// Render pass.
519 	const vk::VkAttachmentDescription fbAttachment =
520 	{
521 		0u,												// VkAttachmentDescriptionFlags	flags;
522 		kImageFormat,									// VkFormat						format;
523 		vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
524 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
525 		vk::VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
526 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
527 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
528 		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout;
529 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout				finalLayout;
530 	};
531 
532 	std::vector<vk::VkAttachmentDescription> attachmentDescs;
533 	attachmentDescs.push_back(fbAttachment);
534 
535 	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
536 	{
537 		// Add it as a frame buffer attachment.
538 		const vk::VkAttachmentDescription inputAttachment =
539 		{
540 			0u,												// VkAttachmentDescriptionFlags	flags;
541 			kImageFormat,									// VkFormat						format;
542 			vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
543 			vk::VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp			loadOp;
544 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			storeOp;
545 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
546 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
547 			getMainImageShaderLayout(),						// VkImageLayout				initialLayout;
548 			getMainImageShaderLayout(),						// VkImageLayout				finalLayout;
549 		};
550 
551 		attachmentDescs.push_back(inputAttachment);
552 	}
553 
554 	std::vector<vk::VkAttachmentReference> inputAttachments;
555 	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
556 	{
557 		const vk::VkAttachmentReference inputRef =
558 		{
559 			1u,												// deUint32			attachment;
560 			getMainImageShaderLayout(),						// VkImageLayout	layout;
561 		};
562 
563 		inputAttachments.push_back(inputRef);
564 	}
565 
566 	const vk::VkAttachmentReference colorRef =
567 	{
568 			0u,												// deUint32			attachment;
569 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout;
570 	};
571 	const std::vector<vk::VkAttachmentReference> colorAttachments(1u, colorRef);
572 
573 	const vk::VkSubpassDescription subpass =
574 	{
575 		0u,																// VkSubpassDescriptionFlags		flags;
576 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,							// VkPipelineBindPoint				pipelineBindPoint;
577 		static_cast<deUint32>(inputAttachments.size()),					// deUint32							inputAttachmentCount;
578 		(inputAttachments.empty() ? nullptr : inputAttachments.data()),	// const VkAttachmentReference*		pInputAttachments;
579 		static_cast<deUint32>(colorAttachments.size()),					// deUint32							colorAttachmentCount;
580 		colorAttachments.data(),										// const VkAttachmentReference*		pColorAttachments;
581 		0u,																// const VkAttachmentReference*		pResolveAttachments;
582 		nullptr,														// const VkAttachmentReference*		pDepthStencilAttachment;
583 		0u,																// deUint32							preserveAttachmentCount;
584 		nullptr,														// const deUint32*					pPreserveAttachments;
585 	};
586 	const std::vector<vk::VkSubpassDescription> subpasses(1u, subpass);
587 
588 	const vk::VkRenderPassCreateInfo renderPassInfo =
589 	{
590 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
591 		nullptr,										// const void*						pNext;
592 		0u,												// VkRenderPassCreateFlags			flags;
593 		static_cast<deUint32>(attachmentDescs.size()),	// deUint32							attachmentCount;
594 		attachmentDescs.data(),							// const VkAttachmentDescription*	pAttachments;
595 		static_cast<deUint32>(subpasses.size()),		// deUint32							subpassCount;
596 		subpasses.data(),								// const VkSubpassDescription*		pSubpasses;
597 		0u,												// deUint32							dependencyCount;
598 		nullptr,										// const VkSubpassDependency*		pDependencies;
599 	};
600 	const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);
601 
602 	// Framebuffer.
603 	std::vector<vk::VkImageView> attachments;
604 	attachments.push_back(fbView.get());
605 	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
606 		attachments.push_back(mainView.get());
607 	const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(attachments.size()), attachments.data(), kFramebufferExtent.width, kFramebufferExtent.height, kFramebufferExtent.depth);
608 
609 	// Pipeline layout.
610 	const auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayouts);
611 
612 	// Graphics pipeline.
613 	const std::vector<vk::VkViewport>	viewports(1u, vk::makeViewport(kFramebufferExtent));
614 	const std::vector<vk::VkRect2D>		scissors(1u, vk::makeRect2D(kFramebufferExtent));
615 
616 	const auto pipeline = vk::makeGraphicsPipeline(
617 		vkd, device, pipelineLayout.get(),
618 		vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
619 		renderPass.get(), viewports, scissors);
620 
621 	// Command pool and command buffer.
622 	const auto cmdPool		= vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
623 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
624 	const auto cmdBuffer	= cmdBufferPtr.get();
625 
626 	// Draw quad.
627 	const vk::VkRect2D		renderArea			= vk::makeRect2D(kFramebufferExtent);
628 	const tcu::Vec4			clearFbColor		(0.0f, 0.0f, 0.0f, 1.0f);
629 	const vk::VkDeviceSize	vertexBufferOffset	= 0ull;
630 
631 	const auto vtxBufferBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
632 	const auto preClearBarrier	= vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mainImage.get(), colorSubresourceRange);
633 	const auto postClearBarrier	= vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
634 						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, getMainImageShaderLayout(), mainImage.get(), colorSubresourceRange);
635 	const auto clearDescColor	= vk::makeClearValueColor(kDescriptorColor);
636 
637 	vk::beginCommandBuffer(vkd, cmdBuffer);
638 
639 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vtxBufferBarrier, 0u, nullptr);
640 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preClearBarrier);
641 	vkd.cmdClearColorImage(cmdBuffer, mainImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDescColor.color, 1u, &colorSubresourceRange);
642 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postClearBarrier);
643 
644 	vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor);
645 	vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
646 	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), m_params.descriptorSet, 1u, &descriptorSets[m_params.descriptorSet].get(), 0u, nullptr);
647 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
648 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
649 	vk::endRenderPass(vkd, cmdBuffer);
650 
651 	const tcu::IVec2 copySize{static_cast<int>(kFramebufferExtent.width), static_cast<int>(kFramebufferExtent.height)};
652 	vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), copySize);
653 
654 	vk::endCommandBuffer(vkd, cmdBuffer);
655 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
656 
657 	// Check results.
658 	const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
659 	vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
660 
661 	const auto							resultsBufferPtr	= reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
662 	const tcu::ConstPixelBufferAccess	resultPixels		{tcuFormat, copySize[0], copySize[1], 1, resultsBufferPtr};
663 
664 	bool pass = true;
665 	for (int x = 0; pass && x < resultPixels.getWidth(); ++x)
666 	for (int y = 0; pass && y < resultPixels.getHeight(); ++y)
667 	for (int z = 0; pass && z < resultPixels.getDepth(); ++z)
668 	{
669 		const auto pixel = resultPixels.getPixel(x, y, z);
670 		pass = (pixel == kDescriptorColor);
671 	}
672 
673 	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
674 	if (!pass)
675 	{
676 		auto& log = m_context.getTestContext().getLog();
677 		log << tcu::TestLog::Image("color", "Rendered image", resultPixels);
678 		status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
679 	}
680 
681 	return status;
682 }
683 
createSamplerlessWriteTests(tcu::TestContext & testCtx)684 tcu::TestCaseGroup* createSamplerlessWriteTests (tcu::TestContext& testCtx)
685 {
686 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "samplerless", "Verify sampler unused with some descriptor image types"));
687 
688 	const std::vector<std::pair<vk::VkDescriptorType, std::string>> descriptorTypes =
689 	{
690 		std::make_pair(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	"sampled_img"),
691 		std::make_pair(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,	"storage_img"),
692 		std::make_pair(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	"input_attachment"),
693 	};
694 
695 	const std::vector<std::pair<PointerCase, std::string>> pointerCases =
696 	{
697 		std::make_pair(PointerCase::ZERO,		"sampler_zero"),
698 		std::make_pair(PointerCase::ONE,		"sampler_one"),
699 		std::make_pair(PointerCase::DESTROYED,	"sampler_destroyed"),
700 	};
701 
702 	for (const auto& typeCase		: descriptorTypes)
703 	for (const auto& pointerCase	: pointerCases)
704 	for (deUint32 descriptorSet = 0u; descriptorSet < 2u; descriptorSet++)
705 	{
706 		std::string			caseName	= typeCase.second + "_" + pointerCase.second;
707 		SamplerlessParams	params		{typeCase.first, pointerCase.first, descriptorSet};
708 		if (descriptorSet > 0u)
709 		{
710 			caseName += "_set_" + std::to_string(descriptorSet);
711 		}
712 
713 		group->addChild(new SamplerlessDescriptorWriteTestCase(testCtx, caseName, "", params));
714 	}
715 
716 	return group.release();
717 }
718 
719 class RandomDescriptorUpdateTestCase : public vkt::TestCase
720 {
721 public:
722 	RandomDescriptorUpdateTestCase				(tcu::TestContext& testCtx, const std::string& name, const std::string& description);
~RandomDescriptorUpdateTestCase(void)723 	virtual	~RandomDescriptorUpdateTestCase		(void) {}
724 
725 	virtual void				initPrograms	(vk::SourceCollections& programCollection) const;
726 	virtual vkt::TestInstance*	createInstance	(Context& context) const;
727 
728 private:
729 };
730 
731 class RandomDescriptorUpdateTestInstance : public vkt::TestInstance
732 {
733 public:
734 	RandomDescriptorUpdateTestInstance			(Context& context);
~RandomDescriptorUpdateTestInstance(void)735 	virtual	~RandomDescriptorUpdateTestInstance	(void) {}
736 
737 	virtual tcu::TestStatus		iterate			(void);
738 
739 	static const vk::VkExtent3D	kFramebufferExtent;
740 	static const vk::VkFormat	kImageFormat;
741 	static const deUint32		kNumBuffers;
742 	static const deUint32		kNumOffsets;
743 	static const deUint32		kNumIterations;
744 
745 private:
746 	deRandom					m_random;
747 };
748 
749 const vk::VkExtent3D	RandomDescriptorUpdateTestInstance::kFramebufferExtent	= vk::makeExtent3D(64u, 64u, 1u);
750 const vk::VkFormat		RandomDescriptorUpdateTestInstance::kImageFormat		= vk::VK_FORMAT_R16G16B16A16_SFLOAT;
751 const deUint32			RandomDescriptorUpdateTestInstance::kNumBuffers			= 3u;
752 const deUint32			RandomDescriptorUpdateTestInstance::kNumOffsets			= 5u;
753 const deUint32			RandomDescriptorUpdateTestInstance::kNumIterations		= 1000u;
754 
RandomDescriptorUpdateTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description)755 RandomDescriptorUpdateTestCase::RandomDescriptorUpdateTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
756 : vkt::TestCase(testCtx, name, description)
757 {
758 }
759 
initPrograms(vk::SourceCollections & programCollection) const760 void RandomDescriptorUpdateTestCase::initPrograms (vk::SourceCollections& programCollection) const
761 {
762 	const std::string vertexShader =
763 			"#version 450\n"
764 			"layout(location=0) in vec4 position;\n"
765 			"void main() { gl_Position = position; }\n";
766 
767 	programCollection.glslSources.add("vert") << glu::VertexSource(vertexShader);
768 
769 	std::ostringstream fragmentShader;
770 
771 	fragmentShader
772 			<< "#version 450\n"
773 			<< "layout(location = 0) out vec4 color_out;\n"
774 			<< "layout(set = 0, binding = 0) uniform buf\n"
775 			<< "{\n"
776 			<< "    vec4 data0;\n"
777 			<< "    vec4 data1;\n"
778 			<< "};\n"
779 			<< "void main()\n"
780 			<< "{\n"
781 			<< "    color_out = data0 + data1;\n"
782 			<< "}\n"
783 			;
784 
785 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentShader.str());
786 }
787 
createInstance(Context & context) const788 vkt::TestInstance* RandomDescriptorUpdateTestCase::createInstance (Context& context) const
789 {
790 	return new RandomDescriptorUpdateTestInstance(context);
791 }
792 
RandomDescriptorUpdateTestInstance(Context & context)793 RandomDescriptorUpdateTestInstance::RandomDescriptorUpdateTestInstance(Context &context)
794 : vkt::TestInstance(context)
795 {
796 	deRandom_init(&m_random, 0);
797 }
798 
iterate()799 tcu::TestStatus RandomDescriptorUpdateTestInstance::iterate()
800 {
801 	const auto&								vkd						= m_context.getDeviceInterface();
802 	const auto								device					= m_context.getDevice();
803 	auto&									allocator				= m_context.getDefaultAllocator();
804 	const auto								queue					= m_context.getUniversalQueue();
805 	const auto								queueIndex				= m_context.getUniversalQueueFamilyIndex();
806 	const auto								tcuFormat				= vk::mapVkFormat(kImageFormat);
807 	vk::DescriptorSetLayoutBuilder			builder;
808 
809 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
810 
811 	vk::Unique<vk::VkDescriptorSetLayout>	layout					(builder.build(vkd, device, (vk::VkDescriptorSetLayoutCreateFlags)0));
812 
813 	// Create descriptor pool
814 	vk::Unique<vk::VkDescriptorPool>		descriptorPool			(vk::DescriptorPoolBuilder().addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1).build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
815 
816 	// Create descriptor set
817 	const vk::VkDescriptorSetAllocateInfo	setAllocateInfo			=
818 	{
819 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType
820 		DE_NULL,											// const void*					pNext
821 		*descriptorPool,									// VkDescriptorPool				descriptorPool
822 		1u,													// deUint32						descriptorSetCount
823 		&layout.get()										// const VkDescriptorSetLayout*	pSetLayouts
824 	};
825 
826 	vk::Unique<vk::VkDescriptorSet>			descriptorSet			(allocateDescriptorSet(vkd, device, &setAllocateInfo));
827 
828 	// The maximum allowed buffer offset alignment is 256 bytes. Meaningful data is placed at these offsets.
829 	const deUint32	bufferSize = 256u * kNumOffsets;
830 
831 	float									bufferContents[kNumBuffers][bufferSize / 4];
832 	float									counter				= 1.0f;
833 	float									sign				= 1.0f;
834 	deUint32								offset				= 0;
835 	deUint32								channelSelector		= 0;
836 
837 	// The buffers are filled with a running counter in one of the channels.
838 	// Both signed and unsigned values are used for each counter. Two vec4s
839 	// are initialized at offsets of 256 bytes (the maximum allowed alignment).
840 	// Everythin else is left as zero.
841 	for (deUint32 b = 0; b < kNumBuffers; b++)
842 	{
843 		deMemset(bufferContents[b], 0, bufferSize);
844 
845 		for (deUint32 o = 0; o < kNumOffsets; o++)
846 		{
847 			offset = o * 64;
848 
849 			// Two vectors at every offset.
850 			for (deUint32 v = 0; v < 2; v++)
851 			{
852 				// Only RGB channels are being tested.
853 				for (deUint32 c = 0; c < 3; c++)
854 				{
855 					if (c == channelSelector)
856 					{
857 						bufferContents[b][offset++] = sign * counter;
858 					}
859 					else
860 					{
861 						bufferContents[b][offset++] = 0.0f;
862 					}
863 				}
864 				// Keep alpha at one.
865 				bufferContents[b][offset++] = 1.0f;
866 
867 				channelSelector = channelSelector + 1;
868 
869 				// All three channels have been filled in. Switch a sign or increase the counter.
870 				if (channelSelector == 3)
871 				{
872 					channelSelector = 0;
873 					if (sign == 1.0f)
874 					{
875 						sign = -1.0f;
876 					}
877 					else
878 					{
879 						sign = 1.0f;
880 						counter += 1.0f;
881 					}
882 				}
883 			}
884 		}
885 	}
886 
887 	const auto								bufferInfo				= vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
888 	std::vector<std::shared_ptr<vk::BufferWithMemory>>	buffers;
889 
890 	for (const auto& contents : bufferContents)
891 	{
892 		buffers.emplace_back(std::make_shared<vk::BufferWithMemory>(vkd, device, allocator, bufferInfo, vk::MemoryRequirement::HostVisible));
893 		const auto&	bufferAlloc	= buffers.back()->getAllocation();
894 		const auto	bufferPtr	= reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset();
895 		deMemcpy(bufferPtr, contents, bufferSize);
896 		vk::flushAlloc(vkd, device, bufferAlloc);
897 	}
898 
899 	// Create framebuffer image and view.
900 	const vk::VkImageCreateInfo				fbImgCreateInfo			=
901 	{
902 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
903 		DE_NULL,									// const void*				pNext
904 		0u,											// VkImageCreateFlags		flags
905 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
906 		kImageFormat,								// VkFormat					format
907 		kFramebufferExtent,							// VkExtent3D				extent
908 		1u,											// deUint32					mipLevels
909 		1u,											// deUint32					arrayLayers
910 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
911 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
912 		(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |	// VkImageUsageFlags		usage
913 		 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
914 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
915 		1u,											// deUint32					queueFamilyIndexCount
916 		&queueIndex,								// const deUint32*			pQueueFamilyIndices
917 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
918 	};
919 
920 	const vk::ImageWithMemory				fbImage					(vkd, device, allocator, fbImgCreateInfo,	vk::MemoryRequirement::Any);
921 	const auto								colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
922 	const auto								fbView					= vk::makeImageView(vkd, device, fbImage.get(),		vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);
923 
924 	// Buffer to copy rendering result to.
925 	const vk::VkDeviceSize					resultsBufferSize		= static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * kFramebufferExtent.width * kFramebufferExtent.height * kFramebufferExtent.depth);
926 	const auto								resultsBufferInfo		= vk::makeBufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
927 	const vk::BufferWithMemory				resultsBuffer			(vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible);
928 
929 	const std::vector<tcu::Vec4>			fullScreenQuad			=
930 	{
931 		{ -1.f, -1.f,	0.f, 1.f },
932 		{  1.f, -1.f,	0.f, 1.f },
933 		{ -1.f,  1.f,	0.f, 1.f },
934 		{ -1.f,  1.f,	0.f, 1.f },
935 		{  1.f, -1.f,	0.f, 1.f },
936 		{  1.f,  1.f,	0.f, 1.f }
937 	};
938 
939 	// Vertex buffer.
940 	const vk::VkDeviceSize					vertexBufferSize		= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
941 	const auto								vertexBufferInfo		= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
942 	const vk::BufferWithMemory				vertexBuffer			(vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible | vk::MemoryRequirement::Coherent);
943 
944 	// Copy data to vertex buffer.
945 	const auto&								vertexAlloc				= vertexBuffer.getAllocation();
946 	const auto								vertexDataPtr			= reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
947 	deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
948 	vk::flushAlloc(vkd, device, vertexAlloc);
949 
950 	// Shader modules.
951 	const auto								vertexModule			= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
952 	const auto								fragModule				= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
953 
954 	// Render pass.
955 	const vk::VkAttachmentDescription		fbAttachment			=
956 	{
957 		0u,												// VkAttachmentDescriptionFlags		flags
958 		kImageFormat,									// VkFormat							format
959 		vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
960 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp
961 		vk::VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
962 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
963 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
964 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
965 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
966 	};
967 
968 	std::vector<vk::VkAttachmentDescription>	attachmentDescs;
969 	attachmentDescs.push_back(fbAttachment);
970 
971 	const vk::VkAttachmentReference			colorRef				=
972 	{
973 		0u,												// deUint32			attachment
974 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
975 	};
976 	const std::vector<vk::VkAttachmentReference> colorAttachments(1u, colorRef);
977 
978 	const vk::VkSubpassDescription				subpass				=
979 	{
980 		0u,												// VkSubpassDescriptionFlags		flags
981 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint				pipelineBindPoint
982 		0u,												// deUint32							inputAttachmentCount
983 		DE_NULL,										// const VkAttachmentReference*		pInputAttachments
984 		static_cast<deUint32>(colorAttachments.size()),	// deUint32							colorAttachmentCount
985 		colorAttachments.data(),						// const VkAttachmentReference*		pColorAttachments
986 		0u,												// const VkAttachmentReference*		pResolveAttachments
987 		DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment
988 		0u,												// deUint32							preserveAttachmentCount
989 		DE_NULL											// const deUint32*					pPreserveAttachments
990 	};
991 	const std::vector<vk::VkSubpassDescription>	subpasses			(1u, subpass);
992 
993 	const vk::VkRenderPassCreateInfo renderPassInfo =
994 	{
995 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
996 		DE_NULL,										// const void*						pNext
997 		0u,												// VkRenderPassCreateFlags			flags
998 		static_cast<deUint32>(attachmentDescs.size()),	// deUint32							attachmentCount
999 		attachmentDescs.data(),							// const VkAttachmentDescription*	pAttachments
1000 		static_cast<deUint32>(subpasses.size()),		// deUint32							subpassCount
1001 		subpasses.data(),								// const VkSubpassDescription*		pSubpasses
1002 		0u,												// deUint32							dependencyCount
1003 		DE_NULL,										// const VkSubpassDependency*		pDependencies
1004 	};
1005 	const auto									renderPass			= vk::createRenderPass(vkd, device, &renderPassInfo);
1006 
1007 	// Framebuffer.
1008 	std::vector<vk::VkImageView>				attachments;
1009 	attachments.push_back(fbView.get());
1010 	const auto									framebuffer			= vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(attachments.size()), attachments.data(), kFramebufferExtent.width, kFramebufferExtent.height, kFramebufferExtent.depth);
1011 
1012 	// Pipeline layout.
1013 	const auto									pipelineLayout		= vk::makePipelineLayout(vkd, device, layout.get());
1014 
1015 	// Graphics pipeline.
1016 	const std::vector<vk::VkViewport>			viewports			(1u, vk::makeViewport(kFramebufferExtent));
1017 	const std::vector<vk::VkRect2D>				scissors			(1u, vk::makeRect2D(kFramebufferExtent));
1018 
1019 	// Use additive alpha blending to accumulate results from all iterations.
1020 	const vk::VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
1021 	{
1022 		VK_TRUE,						// VkBool32					blendEnable
1023 		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcColorBlendFactor
1024 		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			dstColorBlendFactor
1025 		vk::VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
1026 		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcAlphaBlendFactor
1027 		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstAlphaBlendFactor
1028 		vk::VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
1029 		vk::VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
1030 		| vk::VK_COLOR_COMPONENT_G_BIT
1031 		| vk::VK_COLOR_COMPONENT_B_BIT
1032 		| vk::VK_COLOR_COMPONENT_A_BIT
1033 	};
1034 
1035 	const vk::VkPipelineColorBlendStateCreateInfo	colorBlendState	=
1036 	{
1037 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
1038 		DE_NULL,														// const void*									pNext
1039 		0u,																// VkPipelineColorBlendStateCreateFlags			flags
1040 		VK_FALSE,														// VkBool32										logicOpEnable
1041 		vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp
1042 		1u,																// deUint32										attachmentCount
1043 		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments
1044 		{ 1.0f, 1.0f, 1.0f, 1.0f }										// float										blendConstants[4]
1045 	};
1046 
1047 	const auto									pipeline			= vk::makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
1048 																							   vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
1049 																							   renderPass.get(), viewports, scissors, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1050 																							   0u, 0u, DE_NULL, DE_NULL, DE_NULL, DE_NULL, &colorBlendState);
1051 
1052 	// Command pool and command buffer.
1053 	const auto									cmdPool				= vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1054 	const auto									cmdBufferPtr		= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1055 	const auto									cmdBuffer			= cmdBufferPtr.get();
1056 
1057 	const vk::VkRect2D							renderArea			= vk::makeRect2D(kFramebufferExtent);
1058 	const vk::VkDeviceSize						vertexBufferOffset	= 0ull;
1059 
1060 	const auto									vtxBufferBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
1061 	const auto									fbBarrier			= vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, fbImage.get(), colorSubresourceRange);
1062 
1063 	vk::VkClearValue							clearValue;
1064 	clearValue.color.float32[0] = 0.0f;
1065 	clearValue.color.float32[1] = 0.0f;
1066 	clearValue.color.float32[2] = 0.0f;
1067 	clearValue.color.float32[3] = 1.0f;
1068 
1069 	const vk::VkClearAttachment					clearAttachment		=
1070 	{
1071 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
1072 		0u,								// uint32_t				colorAttachment
1073 		clearValue						// VkClearValue			clearValue
1074 	};
1075 
1076 	const vk::VkClearRect						clearRect			=
1077 	{
1078 		vk::makeRect2D(kFramebufferExtent),	// VkRect2D	rect
1079 		0u,									// uint32_t	baseArrayLayer
1080 		1u									// uint32_t	layerCount
1081 	};
1082 
1083 	vk::beginCommandBuffer(vkd, cmdBuffer);
1084 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u,
1085 						   0u, DE_NULL, 1u, &vtxBufferBarrier, 0u, DE_NULL);
1086 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1087 						   0u, DE_NULL, 0u, DE_NULL, 1u, &fbBarrier);
1088 	vk::endCommandBuffer(vkd, cmdBuffer);
1089 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1090 
1091 	struct DescriptorWrite
1092 	{
1093 		deUint32			bufferId;	// Which buffer to use for the descriptor update.
1094 		vk::VkDeviceSize	offset;		// The offset for the descriptor update.
1095 		vk::VkDeviceSize	range;		// The range for the descriptor update.
1096 	};
1097 
1098 	// Each iteration operates on a descriptor mutation which decides the source of the descriptor update.
1099 	struct DescriptorMutation
1100 	{
1101 		deBool							update;		// Determines if a descriptor update is performed.
1102 		deUint32						numDraws;	// The number of consecutive draw calls in a loop.
1103 		std::vector<DescriptorWrite>	writes;		// Multiple redundant writes can be performed.
1104 		// Other ideas to implement:
1105 		// - Sometimes also update the buffer contents.
1106 		// - Multiple descriptor sets.
1107 	};
1108 
1109 	std::vector<DescriptorMutation>				descriptorMutations;
1110 
1111 	// Keep track of the expected result while generating the mutations.
1112 	tcu::Vec4									uboValue0;
1113 	tcu::Vec4									uboValue1;
1114 	tcu::Vec4									expectedColor		(0.0f, 0.0f, 0.0f, 1.0f);
1115 	DescriptorWrite								descWrite			= { 0u, 0u, 32u };
1116 
1117 	for (deUint32 i = 0; i < kNumIterations; i++)
1118 	{
1119 		while (true)
1120 		{
1121 			tcu::Vec4						val0		= uboValue0;
1122 			tcu::Vec4						val1		= uboValue1;
1123 
1124 			deUint32						numWrites	= 1u;
1125 
1126 			// Sometimes do redundant descriptor writes.
1127 			if (deRandom_getUint32(&m_random) % 10 == 0)
1128 				numWrites = deRandom_getUint32(&m_random) % 20 + 1;
1129 
1130 			std::vector<DescriptorWrite>	writes;
1131 
1132 			for (deUint32 w = 0; w < numWrites; w++)
1133 			{
1134 				// The first half: Most of the times change the offset but sometimes the buffer.
1135 				// The second half: Most of the times change the buffer but sometimes change the offset.
1136 				bool	firstHalf	= i < kNumIterations / 2;
1137 				bool	rare		= (deRandom_getUint32(&m_random) % 100u >= (firstHalf ? 98u : 80u));
1138 
1139 				// firstHalf     rare      change
1140 				// --------------------------------
1141 				//     1          0        Offset
1142 				//     1          1        Buffer
1143 				//     0          0        Buffer
1144 				//     0          1        Offset
1145 				//
1146 				// This has a XOR pattern
1147 
1148 				if (firstHalf ^ rare)
1149 					descWrite.offset = (deRandom_getUint32(&m_random) % kNumOffsets) * 256u;
1150 				else
1151 					descWrite.bufferId = deRandom_getUint32(&m_random) % kNumBuffers;
1152 
1153 				writes.push_back(descWrite);
1154 			}
1155 
1156 			DescriptorMutation				mutation	= {i == 0 ? true : deRandom_getBool(&m_random),
1157 										deRandom_getUint32(&m_random) % 10u, writes};
1158 
1159 			const auto&						lastWrite	= mutation.writes.back();
1160 			if (mutation.update)
1161 			{
1162 				for (int c = 0; c < 3; c++)
1163 				{
1164 					val0[c] = bufferContents[lastWrite.bufferId][lastWrite.offset / 4 + c];
1165 					val1[c] = bufferContents[lastWrite.bufferId][lastWrite.offset / 4 + 4 + c];
1166 
1167 					// Sanity check we are reading expected values.
1168 					DE_ASSERT(val0[c] >= -counter && val0[c] <= counter);
1169 					DE_ASSERT(val1[c] >= -counter && val1[c] <= counter);
1170 				}
1171 			}
1172 
1173 			tcu::Vec4						color		= expectedColor + (val0 + val1) * tcu::Vec4(static_cast<float>(mutation.numDraws));
1174 
1175 			// 16-bit float can precisely present integers from -2048..2048. Continue randomizing the mutation
1176 			// until we stay in this range.
1177 			if (color[0] >= -2048.0f && color[0] <= 2048.0f && color[1] >= -2048.0f && color[1] <= 2048.0f
1178 				&& color[2] >= -2048.0f && color[2] <= 2048.0f)
1179 			{
1180 				descriptorMutations.push_back(mutation);
1181 				uboValue0		= val0;
1182 				uboValue1		= val1;
1183 				expectedColor	= color;
1184 				break;
1185 			}
1186 			else
1187 			{
1188 				// Randomize both buffer and offset for a better chance to hit a
1189 				// mutation that pushes the values back to the desired range.
1190 				descWrite.offset = (deRandom_getUint32(&m_random) % kNumOffsets) * 256u;
1191 				descWrite.bufferId = deRandom_getUint32(&m_random) % kNumBuffers;
1192 			}
1193 		}
1194 	}
1195 
1196 	bool first = true;
1197 
1198 	for (auto mutation : descriptorMutations)
1199 	{
1200 		if (mutation.update)
1201 		{
1202 			for (const auto &write : mutation.writes)
1203 			{
1204 				const vk::VkDescriptorBufferInfo descriptorInfo =
1205 				{
1206 					buffers[write.bufferId]->get(),	// VkBuffer		buffer
1207 					write.offset,					// VkDeviceSize	offset
1208 					write.range						// VkDeviceSize	range
1209 				};
1210 
1211 				const vk::VkWriteDescriptorSet descriptorWrite =
1212 				{
1213 					vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureTypes					Type
1214 					DE_NULL,									// const void*						pNext
1215 					*descriptorSet,								// VkDescriptorSet					dstSet
1216 					0,											// deUint32							dstBinding
1217 					0,											// deUint32							dstArrayElement
1218 					1u,											// deUint32							descriptorCount
1219 					vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,		// VkDescriptorType					descriptorType
1220 					DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo
1221 					&descriptorInfo,							// const VkDescriptorBufferInfo*	pBufferInfo
1222 					DE_NULL										// const VkBufferView*				pTexelBufferView
1223 				};
1224 
1225 				vkd.updateDescriptorSets(device, 1, &descriptorWrite, 0, DE_NULL);
1226 			}
1227 		}
1228 
1229 		vk::beginCommandBuffer(vkd, cmdBuffer);
1230 
1231 		vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea);
1232 		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
1233 		// Clear the frame buffer during the first iteration.
1234 		if (first)
1235 		{
1236 			vkd.cmdClearAttachments(cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
1237 			first = false;
1238 		}
1239 		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
1240 								  &descriptorSet.get(), 0u, nullptr);
1241 		vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1242 
1243 		for (deUint32 i = 0u; i < mutation.numDraws; i++)
1244 			vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
1245 
1246 		vk::endRenderPass(vkd, cmdBuffer);
1247 		vk::endCommandBuffer(vkd, cmdBuffer);
1248 		vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1249 	}
1250 
1251 	vk::beginCommandBuffer(vkd, cmdBuffer);
1252 	const tcu::IVec2 copySize{static_cast<int>(kFramebufferExtent.width),
1253 							  static_cast<int>(kFramebufferExtent.height)};
1254 	vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), copySize);
1255 	vk::endCommandBuffer(vkd, cmdBuffer);
1256 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1257 
1258 	// Check results.
1259 	const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
1260 	vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1261 
1262 	const auto							resultsBufferPtr	= reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1263 	const tcu::ConstPixelBufferAccess	resultPixels		{tcuFormat, copySize[0], copySize[1], 1, resultsBufferPtr};
1264 
1265 	// The test only operates on integers, so a tolerance of 0.5 should work.
1266 	const float							tolerance			= 0.5f;
1267 
1268 	bool pass = true;
1269 	for (int x = 0; pass && x < resultPixels.getWidth(); ++x)
1270 		for (int y = 0; pass && y < resultPixels.getHeight(); ++y)
1271 			for (int z = 0; pass && z < resultPixels.getDepth(); ++z)
1272 			{
1273 				const auto pixel = resultPixels.getPixel(x, y, z);
1274 				for (int c = 0; c < 3; c++)
1275 					if (fabs(pixel[c] - expectedColor[c]) > tolerance)
1276 						pass = false;
1277 			}
1278 
1279 	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1280 	if (!pass)
1281 	{
1282 		m_context.getTestContext().getLog() << tcu::TestLog::Image("color", "Rendered image", resultPixels);
1283 		status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1284 	}
1285 
1286 	return status;
1287 }
1288 
createRandomDescriptorUpdateTests(tcu::TestContext & testCtx)1289 tcu::TestCaseGroup* createRandomDescriptorUpdateTests (tcu::TestContext& testCtx)
1290 {
1291 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "random", "Update descriptors randomly between draws"));
1292 
1293 	group->addChild(new RandomDescriptorUpdateTestCase(testCtx, "uniform_buffer", ""));
1294 	return group.release();
1295 }
1296 
1297 } // anonymous
1298 
createDescriptorUpdateTests(tcu::TestContext & testCtx)1299 tcu::TestCaseGroup* createDescriptorUpdateTests (tcu::TestContext& testCtx)
1300 {
1301 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "descriptor_update", "Update descriptor sets"));
1302 
1303 	group->addChild(createEmptyDescriptorUpdateTests(testCtx));
1304 	group->addChild(createSamplerlessWriteTests(testCtx));
1305 	group->addChild(createRandomDescriptorUpdateTests(testCtx));
1306 	group->addChild(createDescriptorUpdateASTests(testCtx));
1307 
1308 	return group.release();
1309 }
1310 
1311 } // BindingModel
1312 } // vkt
1313