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