1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Google Inc.
7 * Copyright (c) 2018 ARM Limited.
8 * Copyright (c) 2023 LunarG, Inc.
9 * Copyright (c) 2023 Nintendo
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 *//*!
24 * \file
25 * \brief Push Descriptor Tests
26 *//*--------------------------------------------------------------------*/
27
28#include "vktPipelinePushDescriptorTests.hpp"
29#include "vktPipelineClearUtil.hpp"
30#include "vktPipelineImageUtil.hpp"
31#include "vktPipelineVertexUtil.hpp"
32#include "vktPipelineReferenceRenderer.hpp"
33#include "vktTestCase.hpp"
34#include "vktCustomInstancesDevices.hpp"
35#include "vkImageUtil.hpp"
36#include "vkMemUtil.hpp"
37#include "vkPrograms.hpp"
38#include "vkQueryUtil.hpp"
39#include "vkRef.hpp"
40#include "vkRefUtil.hpp"
41#include "vkTypeUtil.hpp"
42#include "vkCmdUtil.hpp"
43#include "vkObjUtil.hpp"
44#include "vkDeviceUtil.hpp"
45#include "tcuImageCompare.hpp"
46#include "deMemory.h"
47#include "deUniquePtr.hpp"
48#include "tcuTestLog.hpp"
49#include "tcuCommandLine.hpp"
50#include <vector>
51
52namespace vkt
53{
54namespace pipeline
55{
56
57using namespace vk;
58using namespace std;
59
60namespace
61{
62typedef vector<VkExtensionProperties>			Extensions;
63typedef de::SharedPtr<Unique<VkBuffer> >		VkBufferSp;
64typedef de::SharedPtr<Unique<VkImage> >			VkImageSp;
65typedef de::SharedPtr<Unique<VkImageView> >		VkImageViewSp;
66typedef de::SharedPtr<Unique<VkBufferView> >	VkBufferViewSp;
67typedef de::SharedPtr<Allocation>				AllocationSp;
68typedef de::SharedPtr<RenderPassWrapper>		VkRenderPassSp;
69
70constexpr VkDeviceSize kSizeofVec4 = static_cast<VkDeviceSize>(sizeof(tcu::Vec4));
71
72struct TestParams
73{
74	PipelineConstructionType	pipelineConstructionType;		// Used only by graphics pipeline tests
75	VkDescriptorType			descriptorType;
76	deUint32					binding;
77	deUint32					numCalls;						// Number of draw or dispatch calls
78	bool						useMaintenance5;
79};
80
81VkDeviceSize calcItemSize (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, deUint32 numElements = 1u)
82{
83	const auto minAlignment	= getPhysicalDeviceProperties(vki, physicalDevice).limits.minStorageBufferOffsetAlignment;
84	const auto lcm			= de::lcm(de::max(VkDeviceSize{1}, minAlignment), kSizeofVec4);
85	return de::roundUp(kSizeofVec4 * numElements, lcm);
86}
87
88void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
89{
90	for (auto& requiredExtName : requiredExtensions)
91	{
92		if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(requiredExtName)))
93			TCU_THROW(NotSupportedError, (requiredExtName + " is not supported").c_str());
94	}
95}
96
97CustomInstance createInstanceWithGetPhysicalDeviceProperties2 (Context&				context,
98															   const Extensions&	supportedExtensions)
99{
100	vector<string> requiredExtensions = { "VK_KHR_get_physical_device_properties2" };
101	checkAllSupported(supportedExtensions, requiredExtensions);
102
103	return createCustomInstanceWithExtensions(context, requiredExtensions);
104}
105
106const char *innerCString(const string &str)
107{
108	return str.c_str();
109}
110
111Move<VkDevice> createDeviceWithPushDescriptor (const Context&				context,
112											   const PlatformInterface&		vkp,
113											   VkInstance					instance,
114											   const InstanceInterface&		vki,
115											   VkPhysicalDevice				physicalDevice,
116											   const Extensions&			supportedExtensions,
117											   const deUint32				queueFamilyIndex,
118											   const TestParams&			params,
119											   std::vector<std::string>&	enabledExtensions)
120{
121
122	const float						queuePriority			= 1.0f;
123	const VkDeviceQueueCreateInfo	queueInfo				=
124	{
125		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
126		DE_NULL,
127		(VkDeviceQueueCreateFlags)0,
128		queueFamilyIndex,
129		1u,
130		&queuePriority
131	};
132
133	VkPhysicalDeviceFeatures		features;
134	deMemset(&features, 0, sizeof(features));
135
136	vector<string>										requiredExtensionsStr				= { "VK_KHR_push_descriptor" };
137	VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT	graphicsPipelineLibraryFeaturesEXT	= initVulkanStructure();
138	VkPhysicalDeviceDynamicRenderingFeaturesKHR			dynamicRenderingFeaturesKHR			= initVulkanStructure(&graphicsPipelineLibraryFeaturesEXT);
139	VkPhysicalDeviceShaderObjectFeaturesEXT				shaderObjectFeaturesEXT				= initVulkanStructure(&dynamicRenderingFeaturesKHR);
140	VkPhysicalDeviceFeatures2							features2							= initVulkanStructure(&shaderObjectFeaturesEXT);
141	if (isConstructionTypeLibrary(params.pipelineConstructionType))
142	{
143		requiredExtensionsStr.push_back("VK_KHR_pipeline_library");
144		requiredExtensionsStr.push_back("VK_EXT_graphics_pipeline_library");
145		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
146		if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary)
147			TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required");
148	}
149	else if (isConstructionTypeShaderObject(params.pipelineConstructionType))
150	{
151		requiredExtensionsStr.push_back("VK_EXT_shader_object");
152		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
153		if (!shaderObjectFeaturesEXT.shaderObject)
154			TCU_THROW(NotSupportedError, "shaderObjectFeaturesEXT.shaderObject required");
155	}
156	vector<const char *>			requiredExtensions;
157	checkAllSupported(supportedExtensions, requiredExtensionsStr);
158	// We need the contents of requiredExtensionsStr as a vector<const char*> in VkDeviceCreateInfo.
159	transform(begin(requiredExtensionsStr), end(requiredExtensionsStr), back_inserter(requiredExtensions), innerCString);
160
161	// Enable validation layers on this device if validation has been requested from the command line.
162	const VkDeviceCreateInfo		deviceParams    =
163	{
164		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
165		params.pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ? &features2 : DE_NULL,
166		(VkDeviceCreateFlags)0,
167		1u,
168		&queueInfo,
169		0u,
170		DE_NULL,
171		static_cast<deUint32>(requiredExtensions.size()),
172		(requiredExtensions.empty() ? DE_NULL : requiredExtensions.data()),
173		params.pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ? DE_NULL : &features
174	};
175
176	for (const auto& enabledExt : requiredExtensions)
177		enabledExtensions.push_back(enabledExt);
178
179	return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceParams, DE_NULL);
180}
181
182vector<Vertex4RGBA> createQuads (deUint32 numQuads, float size)
183{
184	vector<Vertex4RGBA>	vertices;
185
186	for (deUint32 quadNdx = 0; quadNdx < numQuads; quadNdx++)
187	{
188		const float			xOffset				= -0.5f + (float)quadNdx;
189		const tcu::Vec4		color				(0.0f);
190		const Vertex4RGBA	lowerLeftVertex		= {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), color};
191		const Vertex4RGBA	lowerRightVertex	= {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), color};
192		const Vertex4RGBA	UpperLeftVertex		= {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), color};
193		const Vertex4RGBA	UpperRightVertex	= {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), color};
194
195		vertices.push_back(lowerLeftVertex);
196		vertices.push_back(lowerRightVertex);
197		vertices.push_back(UpperLeftVertex);
198		vertices.push_back(UpperLeftVertex);
199		vertices.push_back(lowerRightVertex);
200		vertices.push_back(UpperRightVertex);
201	}
202
203	return vertices;
204}
205
206vector<Vertex4Tex4> createTexQuads (deUint32 numQuads, float size)
207{
208	vector<Vertex4Tex4>	vertices;
209
210	for (deUint32 quadNdx = 0; quadNdx < numQuads; quadNdx++)
211	{
212		const float			xOffset				= -0.5f + (float)quadNdx;
213		const Vertex4Tex4	lowerLeftVertex		= {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), tcu::Vec4(-0.2f, -0.2f, 0.0f, 0.0f)};
214		const Vertex4Tex4	lowerRightVertex	= {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), tcu::Vec4(1.2f, -0.2f, 0.0f, 0.0f)};
215		const Vertex4Tex4	UpperLeftVertex		= {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), tcu::Vec4(-0.2f, 1.2f, 0.0f, 0.0f)};
216		const Vertex4Tex4	UpperRightVertex	= {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), tcu::Vec4(1.2f, 1.2f, 0.0f, 0.0f)};
217
218		vertices.push_back(lowerLeftVertex);
219		vertices.push_back(lowerRightVertex);
220		vertices.push_back(UpperLeftVertex);
221		vertices.push_back(UpperLeftVertex);
222		vertices.push_back(lowerRightVertex);
223		vertices.push_back(UpperRightVertex);
224	}
225
226	return vertices;
227}
228
229static const tcu::Vec4 defaultTestColors[] =
230
231{
232	tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
233	tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)
234};
235
236class PushDescriptorBufferGraphicsTestInstance : public vkt::TestInstance
237{
238public:
239								PushDescriptorBufferGraphicsTestInstance	(Context& context, const TestParams& params);
240	virtual						~PushDescriptorBufferGraphicsTestInstance	(void);
241	void						init										(void);
242	virtual tcu::TestStatus		iterate										(void);
243	tcu::TestStatus				verifyImage									(void);
244
245private:
246	const TestParams				m_params;
247	const PlatformInterface&		m_vkp;
248	const Extensions				m_instanceExtensions;
249	const CustomInstance			m_instance;
250	const InstanceDriver&			m_vki;
251	const VkPhysicalDevice			m_physicalDevice;
252	const deUint32					m_queueFamilyIndex;
253	const Extensions				m_deviceExtensions;
254	std::vector<std::string>		m_deviceEnabledExtensions;
255	const Unique<VkDevice>			m_device;
256	const DeviceDriver				m_vkd;
257	const VkQueue					m_queue;
258	SimpleAllocator					m_allocator;
259	const tcu::UVec2				m_renderSize;
260	const VkFormat					m_colorFormat;
261	Move<VkImage>					m_colorImage;
262	de::MovePtr<Allocation>			m_colorImageAlloc;
263	Move<VkImageView>				m_colorAttachmentView;
264	RenderPassWrapper				m_renderPass;
265	Move<VkFramebuffer>				m_framebuffer;
266	ShaderWrapper					m_vertexShaderModule;
267	ShaderWrapper					m_fragmentShaderModule;
268	Move<VkBuffer>					m_vertexBuffer;
269	de::MovePtr<Allocation>			m_vertexBufferAlloc;
270	vector<VkBufferSp>				m_buffers;
271	vector<AllocationSp>			m_bufferAllocs;
272	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
273	PipelineLayoutWrapper			m_preRasterizationStatePipelineLayout;
274	PipelineLayoutWrapper			m_fragmentStatePipelineLayout;
275	GraphicsPipelineWrapper			m_graphicsPipeline;
276	Move<VkCommandPool>				m_cmdPool;
277	Move<VkCommandBuffer>			m_cmdBuffer;
278	vector<Vertex4RGBA>				m_vertices;
279};
280
281PushDescriptorBufferGraphicsTestInstance::PushDescriptorBufferGraphicsTestInstance (Context& context, const TestParams& params)
282	: vkt::TestInstance			(context)
283	, m_params					(params)
284	, m_vkp						(context.getPlatformInterface())
285	, m_instanceExtensions		(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
286	, m_instance				(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
287	, m_vki						(m_instance.getDriver())
288	, m_physicalDevice			(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
289	, m_queueFamilyIndex		(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
290	, m_deviceExtensions		(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
291	, m_device					(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
292	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
293	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
294	, m_allocator				(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
295	, m_renderSize				(32, 32)
296	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
297	, m_graphicsPipeline		(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions, params.pipelineConstructionType)
298	, m_vertices				(createQuads(params.numCalls, 0.25f))
299{
300}
301
302void PushDescriptorBufferGraphicsTestInstance::init (void)
303{
304	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
305
306	// Create color image
307	{
308
309		const VkImageCreateInfo		colorImageParams		=
310		{
311			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
312			DE_NULL,																// const void*				pNext;
313			0u,																		// VkImageCreateFlags		flags;
314			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
315			m_colorFormat,															// VkFormat					format;
316			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
317			1u,																		// deUint32					mipLevels;
318			1u,																		// deUint32					arrayLayers;
319			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
320			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
321			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
322			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
323			1u,																		// deUint32					queueFamilyIndexCount;
324			&m_queueFamilyIndex,													// const deUint32*			pQueueFamilyIndices;
325			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
326		};
327
328		m_colorImage			= createImage(m_vkd, *m_device, &colorImageParams);
329
330		// Allocate and bind color image memory
331		m_colorImageAlloc		= m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
332		VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
333	}
334
335	// Create color attachment view
336	{
337		const VkImageViewCreateInfo colorAttachmentViewParams =
338		{
339			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
340			DE_NULL,										// const void*				pNext;
341			0u,												// VkImageViewCreateFlags	flags;
342			*m_colorImage,									// VkImage					image;
343			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
344			m_colorFormat,									// VkFormat					format;
345			componentMappingRGBA,							// VkChannelMapping			channels;
346			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
347		};
348
349		m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
350	}
351
352	// Create render pass
353	m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, m_colorFormat);
354
355	// Create framebuffer
356	{
357		const VkImageView				attachmentBindInfos[]	=
358		{
359			*m_colorAttachmentView
360		};
361
362		const VkFramebufferCreateInfo	framebufferParams		=
363		{
364			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
365			DE_NULL,									// const void*				pNext;
366			0u,											// VkFramebufferCreateFlags	flags;
367			*m_renderPass,								// VkRenderPass				renderPass;
368			1u,											// deUint32					attachmentCount;
369			attachmentBindInfos,						// const VkImageView*		pAttachments;
370			(deUint32)m_renderSize.x(),					// deUint32					width;
371			(deUint32)m_renderSize.y(),					// deUint32					height;
372			1u											// deUint32					layers;
373		};
374
375		m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
376	}
377
378	// Create pipeline layout
379	{
380		// Create descriptor set layout
381		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
382		{
383			m_params.binding,					// uint32_t				binding;
384			m_params.descriptorType,			// VkDescriptorType		descriptorType;
385			1u,									// uint32_t				descriptorCount;
386			VK_SHADER_STAGE_VERTEX_BIT,			// VkShaderStageFlags	stageFlags;
387			DE_NULL								// const VkSampler*		pImmutableSamplers;
388		};
389
390		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
391		{
392			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
393			DE_NULL,													// const void*							pNext;
394			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
395			1u,															// uint32_t								bindingCount;
396			&descriptorSetLayoutBinding									// const VkDescriptorSetLayoutBinding*	pBindings;
397		};
398
399		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
400
401		// Create pipeline layout
402		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
403		VkPipelineLayoutCreateInfo	pipelineLayoutParams
404		{
405			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
406			DE_NULL,										// const void*					pNext;
407			pipelineLayoutFlags,							// VkPipelineLayoutCreateFlags	flags;
408			1u,												// deUint32						setLayoutCount;
409			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
410			0u,												// deUint32						pushConstantRangeCount;
411			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
412		};
413
414		m_preRasterizationStatePipelineLayout	= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
415		pipelineLayoutParams.setLayoutCount		= 0u;
416		pipelineLayoutParams.pSetLayouts		= DE_NULL;
417		m_fragmentStatePipelineLayout			= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
418	}
419
420	// Create buffers. One color value in each buffer.
421	{
422		VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
423		for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
424		{
425			const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
426
427			VkBufferCreateInfo	bufferCreateInfo
428			{
429				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
430				DE_NULL,								// const void*			pNext;
431				0u,										// VkBufferCreateFlags	flags
432				kSizeofVec4,							// VkDeviceSize			size;
433				usageFlags,								// VkBufferUsageFlags	usage;
434				VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
435				1u,										// deUint32				queueFamilyCount;
436				&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
437			};
438
439			if (m_params.useMaintenance5)
440			{
441				bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)usageFlags;
442				bufferCreateInfo.pNext = &bufferUsageFlags2;
443				bufferCreateInfo.usage = 0;
444			}
445
446			m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
447			m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
448			VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
449
450			deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], static_cast<size_t>(kSizeofVec4));
451			flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
452		}
453	}
454
455	// Create shaders
456	{
457		m_vertexShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
458		m_fragmentShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
459	}
460
461	// Create pipeline
462	{
463		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
464		{
465			0u,							// deUint32					binding;
466			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
467			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
468		};
469
470		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[]	=
471		{
472			{
473				0u,									// deUint32	location;
474				0u,									// deUint32	binding;
475				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
476				0u									// deUint32	offsetInBytes;
477			},
478			{
479				1u,									// deUint32	location;
480				0u,									// deUint32	binding;
481				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
482				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
483			}
484		};
485
486		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
487		{
488			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
489			DE_NULL,													// const void*								pNext;
490			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
491			1u,															// deUint32									bindingCount;
492			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
493			2u,															// deUint32									attributeCount;
494			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
495		};
496
497		const VkPrimitiveTopology					topology							= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
498
499		const vector<VkViewport>					viewports							{ makeViewport(m_renderSize) };
500		const vector<VkRect2D>						scissors							{ makeRect2D(m_renderSize) };
501
502		m_graphicsPipeline.setDefaultRasterizationState()
503						  .setDefaultDepthStencilState()
504						  .setDefaultMultisampleState()
505						  .setDefaultColorBlendState()
506						  .setDefaultTopology(topology)
507						  .setupVertexInputState(&vertexInputStateParams)
508						  .setupPreRasterizationShaderState(viewports,
509															scissors,
510															m_preRasterizationStatePipelineLayout,
511															*m_renderPass,
512															0u,
513															m_vertexShaderModule)
514						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
515						  .setupFragmentOutputState(*m_renderPass)
516						  .setMonolithicPipelineLayout(m_preRasterizationStatePipelineLayout)
517						  .buildPipeline();
518	}
519
520	// Create vertex buffer
521	{
522		const VkBufferCreateInfo vertexBufferParams =
523		{
524			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
525			DE_NULL,													// const void*			pNext;
526			0u,															// VkBufferCreateFlags	flags;
527			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
528			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
529			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
530			1u,															// deUint32				queueFamilyCount;
531			&m_queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
532		};
533
534		m_vertexBuffer		= createBuffer(m_vkd, *m_device, &vertexBufferParams);
535		m_vertexBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
536
537		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
538
539		// Load vertices into vertex buffer
540		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
541		flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
542	}
543
544	// Create command pool
545	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
546
547	// Create command buffer
548	{
549		const VkClearValue	attachmentClearValue	= defaultClearValue(m_colorFormat);
550		const VkDeviceSize	vertexBufferOffset		= 0;
551
552		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
553		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
554		m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
555		m_graphicsPipeline.bind(*m_cmdBuffer);
556		m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
557
558		// Draw quads. Switch input buffer which contains the quad color for each draw call.
559		for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
560		{
561			VkDescriptorBufferInfo descriptorBufferInfo =
562			{
563				**m_buffers[quadNdx],	// VkBuffer			buffer;
564				0u,						// VkDeviceSize		offset;
565				kSizeofVec4,			// VkDeviceSize		range;
566			};
567
568			VkWriteDescriptorSet writeDescriptorSet =
569			{
570				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
571				DE_NULL,								// const void*						pNext;
572				0u,										// VkDescriptorSet					dstSet;
573				m_params.binding,						// uint32_t							dstBinding;
574				0u,										// uint32_t							dstArrayElement;
575				1u,										// uint32_t							descriptorCount;
576				m_params.descriptorType,				// VkDescriptorType					descriptorType;
577				DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
578				&descriptorBufferInfo,					// const VkDescriptorBufferInfo*	pBufferInfo;
579				DE_NULL									// const VkBufferView*				pTexelBufferView;
580			};
581
582			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_preRasterizationStatePipelineLayout, 0, 1, &writeDescriptorSet);
583			m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
584		}
585
586		m_renderPass.end(m_vkd, *m_cmdBuffer);
587		endCommandBuffer(m_vkd, *m_cmdBuffer);
588	}
589}
590
591PushDescriptorBufferGraphicsTestInstance::~PushDescriptorBufferGraphicsTestInstance (void)
592{
593}
594
595tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::iterate (void)
596{
597	init();
598
599	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
600
601	return verifyImage();
602}
603
604tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::verifyImage (void)
605{
606	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
607	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
608	const ColorVertexShader		vertexShader;
609	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
610	const rr::Program			program			(&vertexShader, &fragmentShader);
611	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
612	bool						compareOk		= false;
613
614	// Render reference image
615	{
616		for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
617			for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
618				m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = defaultTestColors[quadIdx];
619
620		refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
621						 rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
622	}
623
624	// Compare result with reference image
625	{
626		de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
627
628		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
629															  "IntImageCompare",
630															  "Image comparison",
631															  refRenderer.getAccess(),
632															  result->getAccess(),
633															  tcu::UVec4(2, 2, 2, 2),
634															  tcu::IVec3(1, 1, 0),
635															  true,
636															  tcu::COMPARE_LOG_RESULT);
637	}
638
639	if (compareOk)
640		return tcu::TestStatus::pass("Result image matches reference");
641	else
642		return tcu::TestStatus::fail("Image mismatch");
643}
644
645class PushDescriptorBufferGraphicsTest : public vkt::TestCase
646{
647public:
648						PushDescriptorBufferGraphicsTest	(tcu::TestContext&	testContext,
649															 const string&		name,
650															 const TestParams&	params);
651						~PushDescriptorBufferGraphicsTest	(void);
652	void				checkSupport						(Context& context) const;
653	void				initPrograms						(SourceCollections& sourceCollections) const;
654	TestInstance*		createInstance						(Context& context) const;
655
656protected:
657	const TestParams	m_params;
658};
659
660PushDescriptorBufferGraphicsTest::PushDescriptorBufferGraphicsTest (tcu::TestContext&	testContext,
661																	const string&		name,
662																	const TestParams&	params)
663	: vkt::TestCase	(testContext, name)
664	, m_params		(params)
665{
666}
667
668PushDescriptorBufferGraphicsTest::~PushDescriptorBufferGraphicsTest (void)
669{
670}
671
672TestInstance* PushDescriptorBufferGraphicsTest::createInstance (Context& context) const
673{
674	return new PushDescriptorBufferGraphicsTestInstance(context, m_params);
675}
676
677void PushDescriptorBufferGraphicsTest::checkSupport(Context& context) const
678{
679	if (m_params.useMaintenance5)
680		context.requireDeviceFunctionality("VK_KHR_maintenance5");
681
682	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
683}
684
685void PushDescriptorBufferGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
686{
687	const string	bufferType	= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "readonly buffer";
688	const string	vertexSrc	=
689		"#version 450\n"
690		"layout(location = 0) in highp vec4 position;\n"
691		"layout(location = 1) in highp vec4 color;\n"
692		"layout(location = 0) out highp vec4 vtxColor;\n"
693		"layout(set = 0, binding = " + de::toString(m_params.binding) + ") " + bufferType + " Block\n"
694		"{\n"
695		"	vec4 color;\n"
696		"} inputData;\n"
697		"\n"
698		"out gl_PerVertex { vec4 gl_Position; };\n"
699		"\n"
700		"void main()\n"
701		"{\n"
702		"	gl_Position = position;\n"
703		"	vtxColor = inputData.color;\n"
704		"}\n";
705
706	const string	fragmentSrc	=
707		"#version 450\n"
708		"layout(location = 0) in highp vec4 vtxColor;\n"
709		"layout(location = 0) out highp vec4 fragColor;\n"
710		"\n"
711		"void main (void)\n"
712		"{\n"
713		"	fragColor = vtxColor;\n"
714		"}\n";
715
716	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
717	sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
718}
719
720class PushDescriptorBufferComputeTestInstance : public vkt::TestInstance
721{
722public:
723								PushDescriptorBufferComputeTestInstance		(Context& context, const TestParams& params);
724	virtual						~PushDescriptorBufferComputeTestInstance	(void);
725	void						init										(void);
726	virtual tcu::TestStatus		iterate										(void);
727	tcu::TestStatus				verifyOutput								(void);
728
729private:
730	const TestParams			m_params;
731	const PlatformInterface&	m_vkp;
732	const Extensions			m_instanceExtensions;
733	const CustomInstance		m_instance;
734	const InstanceDriver&		m_vki;
735	const VkPhysicalDevice		m_physicalDevice;
736	const deUint32				m_queueFamilyIndex;
737	const Extensions			m_deviceExtensions;
738	std::vector<std::string>	m_deviceEnabledExtensions;
739	const Unique<VkDevice>		m_device;
740	const DeviceDriver			m_vkd;
741	const VkQueue				m_queue;
742	const VkDeviceSize			m_itemSize;
743	SimpleAllocator				m_allocator;
744	Move<VkShaderModule>		m_computeShaderModule;
745	vector<VkBufferSp>			m_buffers;
746	vector<AllocationSp>		m_bufferAllocs;
747	Move<VkBuffer>				m_outputBuffer;
748	de::MovePtr<Allocation>		m_outputBufferAlloc;
749	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
750	Move<VkPipelineLayout>		m_pipelineLayout;
751	Move<VkPipeline>			m_computePipeline;
752	Move<VkCommandPool>			m_cmdPool;
753	Move<VkCommandBuffer>		m_cmdBuffer;
754	std::vector<tcu::Vec4>		m_testColors;
755};
756
757PushDescriptorBufferComputeTestInstance::PushDescriptorBufferComputeTestInstance (Context& context, const TestParams& params)
758	: vkt::TestInstance		(context)
759	, m_params				(params)
760	, m_vkp					(context.getPlatformInterface())
761	, m_instanceExtensions	(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
762	, m_instance			(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
763	, m_vki					(m_instance.getDriver())
764	, m_physicalDevice		(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
765	, m_queueFamilyIndex	(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT))
766	, m_deviceExtensions	(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
767	, m_device				(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
768	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
769	, m_queue				(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
770	, m_itemSize			(calcItemSize(m_vki, m_physicalDevice))
771	, m_allocator			(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
772{
773}
774
775void PushDescriptorBufferComputeTestInstance::init (void)
776{
777	// Create pipeline layout
778	{
779		// Create descriptor set layout
780		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindings[]	=
781		{
782			{
783				m_params.binding,				// uint32_t				binding;
784				m_params.descriptorType,		// VkDescriptorType		descriptorType;
785				1u,								// uint32_t				descriptorCount;
786				VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags	stageFlags;
787				DE_NULL							// const VkSampler*		pImmutableSamplers;
788			},
789			{
790				m_params.binding + 1,				// uint32_t				binding;
791				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	// VkDescriptorType		descriptorType;
792				1u,									// uint32_t				descriptorCount;
793				VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
794				DE_NULL								// const VkSampler*		pImmutableSamplers;
795			}
796		};
797
798		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
799		{
800			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
801			DE_NULL,													// const void*							pNext;
802			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
803			2u,															// uint32_t								bindingCount;
804			descriptorSetLayoutBindings									// const VkDescriptorSetLayoutBinding*	pBindings;
805		};
806
807		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
808
809		// Create pipeline layout
810		const VkPipelineLayoutCreateInfo		pipelineLayoutParams			=
811		{
812			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
813			DE_NULL,										// const void*					pNext;
814			0u,												// VkPipelineLayoutCreateFlags	flags;
815			1u,												// deUint32						descriptorSetCount;
816			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
817			0u,												// deUint32						pushConstantRangeCount;
818			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
819		};
820
821		m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
822	}
823
824	// Fill the test colors table
825	m_testColors.resize(m_params.numCalls);
826	for (deUint32 colorIdx = 0; colorIdx < m_params.numCalls; colorIdx++)
827	{
828		if (colorIdx < DE_LENGTH_OF_ARRAY(defaultTestColors))
829			m_testColors[colorIdx] = defaultTestColors[colorIdx];
830		else
831		{
832			const float mix = static_cast<float>(colorIdx) / static_cast<float>(m_params.numCalls - 1);
833
834			// interpolate between first and last color, require these colors to be different
835			DE_ASSERT(defaultTestColors[0] != defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1]);
836			m_testColors[colorIdx] = defaultTestColors[0] * mix + defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1] * (1.0f - mix);
837		}
838	}
839
840	// Create buffers. One color value in each buffer.
841	{
842		for (deUint32 bufIdx = 0; bufIdx <  m_params.numCalls; bufIdx++)
843		{
844			const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
845
846			const VkBufferCreateInfo	bufferCreateInfo	=
847			{
848				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
849				DE_NULL,								// const void*			pNext;
850				0u,										// VkBufferCreateFlags	flags
851				kSizeofVec4,							// VkDeviceSize			size;
852				usageFlags,								// VkBufferUsageFlags	usage;
853				VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
854				1u,										// deUint32				queueFamilyCount;
855				&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
856			};
857
858			m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
859			m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
860			VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
861
862			deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &m_testColors[bufIdx], static_cast<size_t>(kSizeofVec4));
863			flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
864		}
865	}
866
867	// Create output buffer
868	{
869		const VkBufferCreateInfo bufferCreateInfo =
870		{
871			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
872			DE_NULL,								// const void*			pNext;
873			0u,										// VkBufferCreateFlags	flags
874			m_itemSize * m_params.numCalls,			// VkDeviceSize			size;
875			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags	usage;
876			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
877			1u,										// deUint32				queueFamilyCount;
878			&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
879		};
880
881		m_outputBuffer		= createBuffer(m_vkd, *m_device, &bufferCreateInfo);
882		m_outputBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer), MemoryRequirement::HostVisible);
883		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
884	}
885
886	// Create shader
887	{
888		m_computeShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
889	}
890
891	// Create pipeline
892	{
893		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
894		{
895			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
896			DE_NULL,												// const void*						pNext;
897			0u,														// VkPipelineShaderStageCreateFlags	flags;
898			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
899			*m_computeShaderModule,									// VkShaderModule					module;
900			"main",													// const char*						pName;
901			DE_NULL													// const VkSpecializationInfo*		pSpecializationInfo;
902		};
903
904		const VkComputePipelineCreateInfo		createInfo		=
905		{
906			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
907			DE_NULL,												// const void*						pNext;
908			0u,														// VkPipelineCreateFlags			flags;
909			stageCreateInfo,										// VkPipelineShaderStageCreateInfo	stage;
910			*m_pipelineLayout,										// VkPipelineLayout					layout;
911			(VkPipeline)0,											// VkPipeline						basePipelineHandle;
912			0u,														// int32_t							basePipelineIndex;
913		};
914
915		m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
916	}
917
918	// Create command pool
919	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
920
921	// Create command buffer
922	{
923		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
924		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
925		m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
926
927		// Dispatch: Each dispatch switches the input buffer.
928		// Output buffer is exposed as a vec4 sized window.
929		for (deUint32 dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
930		{
931			VkDescriptorBufferInfo descriptorBufferInfoUbo		=
932			{
933				**m_buffers[dispatchNdx],	// VkBuffer			buffer;
934				0u,							// VkDeviceSize		offset;
935				kSizeofVec4,				// VkDeviceSize		range;
936			};
937
938			VkDescriptorBufferInfo descriptorBufferInfoOutput	=
939			{
940				*m_outputBuffer,			// VkBuffer			buffer;
941				m_itemSize * dispatchNdx,	// VkDeviceSize		offset;
942				kSizeofVec4,				// VkDeviceSize		range;
943			};
944
945			VkWriteDescriptorSet writeDescriptorSets[] =
946			{
947				{
948					VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
949					DE_NULL,								// const void*						pNext;
950					0u,										// VkDescriptorSet					dstSet;
951					m_params.binding,						// uint32_t							dstBinding;
952					0u,										// uint32_t							dstArrayElement;
953					1u,										// uint32_t							descriptorCount;
954					m_params.descriptorType,				// VkDescriptorType					descriptorType;
955					DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
956					&descriptorBufferInfoUbo,				// const VkDescriptorBufferInfo*	pBufferInfo;
957					DE_NULL									// const VkBufferView*				pTexelBufferView;
958				},
959				{
960					VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
961					DE_NULL,								// const void*						pNext;
962					0u,										// VkDescriptorSet					dstSet;
963					m_params.binding + 1,					// uint32_t							dstBinding;
964					0u,										// uint32_t							dstArrayElement;
965					1u,										// uint32_t							descriptorCount;
966					VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// VkDescriptorType					descriptorType;
967					DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
968					&descriptorBufferInfoOutput,			// const VkDescriptorBufferInfo*	pBufferInfo;
969					DE_NULL									// const VkBufferView*				pTexelBufferView;
970				}
971			};
972
973			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 2, writeDescriptorSets);
974			m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
975		}
976
977		endCommandBuffer(m_vkd, *m_cmdBuffer);
978	}
979}
980
981PushDescriptorBufferComputeTestInstance::~PushDescriptorBufferComputeTestInstance (void)
982{
983}
984
985tcu::TestStatus PushDescriptorBufferComputeTestInstance::iterate (void)
986{
987	init();
988
989	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
990
991	return verifyOutput();
992}
993
994tcu::TestStatus PushDescriptorBufferComputeTestInstance::verifyOutput (void)
995{
996	invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
997
998	// Verify result
999	auto bufferPtr = reinterpret_cast<const char*>(m_outputBufferAlloc->getHostPtr());
1000	for (deUint32 i = 0; i < m_params.numCalls; ++i)
1001	{
1002		if (deMemCmp(&m_testColors[i], bufferPtr + (i * m_itemSize), static_cast<size_t>(kSizeofVec4)) != 0)
1003			TCU_FAIL("Output mismatch at output item " + de::toString(i));
1004	}
1005
1006	return tcu::TestStatus::pass("Output matches expected values");
1007}
1008
1009class PushDescriptorBufferComputeTest : public vkt::TestCase
1010{
1011public:
1012						PushDescriptorBufferComputeTest		(tcu::TestContext&	testContext,
1013															 const string&		name,
1014															 const TestParams&	params);
1015						~PushDescriptorBufferComputeTest	(void);
1016	void				initPrograms						(SourceCollections& sourceCollections) const;
1017	TestInstance*		createInstance						(Context& context) const;
1018
1019protected:
1020	const TestParams	m_params;
1021};
1022
1023PushDescriptorBufferComputeTest::PushDescriptorBufferComputeTest (tcu::TestContext&	testContext,
1024																  const string&		name,
1025																  const TestParams&	params)
1026	: vkt::TestCase	(testContext, name)
1027	, m_params		(params)
1028{
1029}
1030
1031PushDescriptorBufferComputeTest::~PushDescriptorBufferComputeTest (void)
1032{
1033}
1034
1035TestInstance* PushDescriptorBufferComputeTest::createInstance (Context& context) const
1036{
1037	return new PushDescriptorBufferComputeTestInstance(context, m_params);
1038}
1039
1040void PushDescriptorBufferComputeTest::initPrograms (SourceCollections& sourceCollections) const
1041{
1042	const string	bufferType	= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "buffer";
1043	const string	computeSrc	=
1044		"#version 450\n"
1045		"layout(set = 0, binding = " + de::toString(m_params.binding) + ") " + bufferType + " Block\n"
1046		"{\n"
1047		"	vec4 color;\n"
1048		"} inputData;\n"
1049		"\n"
1050		"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
1051		"{\n"
1052		"	vec4 color;\n"
1053		"} outData;\n"
1054		"\n"
1055		"void main()\n"
1056		"{\n"
1057		"	outData.color = inputData.color;\n"
1058		"}\n";
1059
1060	sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
1061}
1062
1063class PushDescriptorImageGraphicsTestInstance : public vkt::TestInstance
1064{
1065public:
1066								PushDescriptorImageGraphicsTestInstance		(Context& context, const TestParams& params);
1067	virtual						~PushDescriptorImageGraphicsTestInstance	(void);
1068	void						init										(void);
1069	virtual tcu::TestStatus		iterate										(void);
1070	tcu::TestStatus				verifyImage									(void);
1071
1072private:
1073	const TestParams				m_params;
1074	const PlatformInterface&		m_vkp;
1075	const Extensions				m_instanceExtensions;
1076	const CustomInstance			m_instance;
1077	const InstanceDriver&			m_vki;
1078	const VkPhysicalDevice			m_physicalDevice;
1079	const deUint32					m_queueFamilyIndex;
1080	const Extensions				m_deviceExtensions;
1081	std::vector<std::string>		m_deviceEnabledExtensions;
1082	const Unique<VkDevice>			m_device;
1083	const DeviceDriver				m_vkd;
1084	const VkQueue					m_queue;
1085	SimpleAllocator					m_allocator;
1086	const tcu::UVec2				m_renderSize;
1087	const tcu::UVec2				m_textureSize;
1088	const VkFormat					m_colorFormat;
1089	Move<VkImage>					m_colorImage;
1090	de::MovePtr<Allocation>			m_colorImageAlloc;
1091	Move<VkImageView>				m_colorAttachmentView;
1092	vector<VkImageSp>				m_textureImages;
1093	vector<AllocationSp>			m_textureImageAllocs;
1094	vector<VkImageViewSp>			m_textureViews;
1095	Move<VkSampler>					m_whiteBorderSampler;
1096	Move<VkSampler>					m_blackBorderSampler;
1097	RenderPassWrapper				m_renderPass;
1098	Move<VkFramebuffer>				m_framebuffer;
1099	ShaderWrapper					m_vertexShaderModule;
1100	ShaderWrapper					m_fragmentShaderModule;
1101	Move<VkBuffer>					m_vertexBuffer;
1102	de::MovePtr<Allocation>			m_vertexBufferAlloc;
1103	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1104	PipelineLayoutWrapper			m_preRasterizationStatePipelineLayout;
1105	PipelineLayoutWrapper			m_fragmentStatePipelineLayout;
1106	GraphicsPipelineWrapper			m_graphicsPipeline;
1107	Move<VkCommandPool>				m_cmdPool;
1108	Move<VkCommandBuffer>			m_cmdBuffer;
1109	vector<Vertex4Tex4>				m_vertices;
1110};
1111
1112PushDescriptorImageGraphicsTestInstance::PushDescriptorImageGraphicsTestInstance (Context& context, const TestParams& params)
1113	: vkt::TestInstance			(context)
1114	, m_params					(params)
1115	, m_vkp						(context.getPlatformInterface())
1116	, m_instanceExtensions		(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
1117	, m_instance				(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
1118	, m_vki						(m_instance.getDriver())
1119	, m_physicalDevice			(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
1120	, m_queueFamilyIndex		(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
1121	, m_deviceExtensions		(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
1122	, m_device					(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
1123	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
1124	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
1125	, m_allocator				(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
1126	, m_renderSize				(32, 32)
1127	, m_textureSize				(32, 32)
1128	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1129	, m_graphicsPipeline		(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions, params.pipelineConstructionType)
1130	, m_vertices				(createTexQuads(params.numCalls, 0.25f))
1131{
1132}
1133
1134void PushDescriptorImageGraphicsTestInstance::init (void)
1135{
1136	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1137
1138	// Create color image
1139	{
1140
1141		const VkImageCreateInfo		colorImageParams		=
1142		{
1143			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
1144			DE_NULL,																// const void*				pNext;
1145			0u,																		// VkImageCreateFlags		flags;
1146			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
1147			m_colorFormat,															// VkFormat					format;
1148			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
1149			1u,																		// deUint32					mipLevels;
1150			1u,																		// deUint32					arrayLayers;
1151			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
1152			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
1153			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
1154			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
1155			1u,																		// deUint32					queueFamilyIndexCount;
1156			&m_queueFamilyIndex,													// const deUint32*			pQueueFamilyIndices;
1157			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
1158		};
1159
1160		m_colorImage			= createImage(m_vkd, *m_device, &colorImageParams);
1161
1162		// Allocate and bind color image memory
1163		m_colorImageAlloc		= m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
1164		VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1165	}
1166
1167	// Create color attachment view
1168	{
1169		const VkImageViewCreateInfo colorAttachmentViewParams =
1170		{
1171			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1172			DE_NULL,										// const void*				pNext;
1173			0u,												// VkImageViewCreateFlags	flags;
1174			*m_colorImage,									// VkImage					image;
1175			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1176			m_colorFormat,									// VkFormat					format;
1177			componentMappingRGBA,							// VkChannelMapping			channels;
1178			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1179		};
1180
1181		m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
1182	}
1183
1184	// Create texture images
1185	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
1186	{
1187		VkImageUsageFlags			usageFlags			= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1188		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1189			usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
1190		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1191			usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
1192
1193		const VkImageCreateInfo		textureImageParams	=
1194		{
1195			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
1196			DE_NULL,										// const void*				pNext;
1197			0u,												// VkImageCreateFlags		flags;
1198			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
1199			m_colorFormat,									// VkFormat					format;
1200			{ m_textureSize.x(), m_textureSize.y(), 1u },	// VkExtent3D				extent;
1201			1u,												// deUint32					mipLevels;
1202			1u,												// deUint32					arrayLayers;
1203			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
1204			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
1205			usageFlags,										// VkImageUsageFlags		usage;
1206			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
1207			1u,												// deUint32					queueFamilyIndexCount;
1208			&m_queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
1209			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
1210		};
1211
1212		m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
1213
1214		// Allocate and bind texture image memory
1215		m_textureImageAllocs.push_back(AllocationSp(m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()), MemoryRequirement::Any).release()));
1216		VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(), m_textureImageAllocs.back()->getOffset()));
1217	}
1218
1219	// Create texture image views
1220	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
1221	{
1222		const VkImageViewCreateInfo textureViewParams =
1223		{
1224			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1225			DE_NULL,										// const void*				pNext;
1226			0u,												// VkImageViewCreateFlags	flags;
1227			**m_textureImages[texIdx],						// VkImage					image;
1228			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1229			m_colorFormat,									// VkFormat					format;
1230			componentMappingRGBA,							// VkChannelMapping			channels;
1231			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1232		};
1233
1234		m_textureViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
1235	}
1236
1237	VkClearValue	clearValues[2];
1238	clearValues[0].color.float32[0] = 0.0f;
1239	clearValues[0].color.float32[1] = 1.0f;
1240	clearValues[0].color.float32[2] = 0.0f;
1241	clearValues[0].color.float32[3] = 1.0f;
1242	clearValues[1].color.float32[0] = 1.0f;
1243	clearValues[1].color.float32[1] = 0.0f;
1244	clearValues[1].color.float32[2] = 0.0f;
1245	clearValues[1].color.float32[3] = 1.0f;
1246
1247	const VkImageLayout	textureImageLayout	= (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
1248											  VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1249
1250	// Clear textures
1251	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
1252	{
1253		const VkImageAspectFlags	aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1254		Move<VkCommandPool>			cmdPool;
1255		Move<VkCommandBuffer>		cmdBuffer;
1256
1257		cmdPool		= createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
1258		cmdBuffer	= allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1259
1260		const VkImageMemoryBarrier preImageBarrier =
1261		{
1262			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
1263			DE_NULL,								// const void*				pNext;
1264			0u,										// VkAccessFlags			srcAccessMask;
1265			VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1266			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
1267			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
1268			VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
1269			VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
1270			**m_textureImages[texIdx],				// VkImage					image;
1271			{										// VkImageSubresourceRange	subresourceRange;
1272				aspectMask,							// VkImageAspect			aspect;
1273				0u,									// deUint32					baseMipLevel;
1274				1u,									// deUint32					mipLevels;
1275				0u,									// deUint32					baseArraySlice;
1276				1u									// deUint32					arraySize;
1277			}
1278		};
1279
1280		const VkImageMemoryBarrier	postImageBarrier	=
1281		{
1282			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1283			DE_NULL,									// const void*				pNext;
1284			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1285			VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
1286			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1287			textureImageLayout,							// VkImageLayout			newLayout;
1288			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1289			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1290			**m_textureImages[texIdx],					// VkImage					image;
1291			{											// VkImageSubresourceRange	subresourceRange;
1292				aspectMask,								// VkImageAspect			aspect;
1293				0u,										// deUint32					baseMipLevel;
1294				1u,										// deUint32					mipLevels;
1295				0u,										// deUint32					baseArraySlice;
1296				1u										// deUint32					arraySize;
1297			}
1298		};
1299
1300		const VkImageSubresourceRange clearRange	=
1301		{
1302			aspectMask,	// VkImageAspectFlags	aspectMask;
1303			0u,			// deUint32				baseMipLevel;
1304			1u,			// deUint32				levelCount;
1305			0u,			// deUint32				baseArrayLayer;
1306			1u			// deUint32				layerCount;
1307		};
1308
1309		beginCommandBuffer(m_vkd, *cmdBuffer);
1310		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
1311		m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValues[texIdx].color, 1, &clearRange);
1312		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
1313		endCommandBuffer(m_vkd, *cmdBuffer);
1314
1315		submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
1316	}
1317
1318	// Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
1319	{
1320		VkSamplerCreateInfo samplerParams =
1321		{
1322			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
1323			DE_NULL,									// const void*			pNext;
1324			0u,											// VkSamplerCreateFlags	flags;
1325			VK_FILTER_NEAREST,							// VkFilter				magFilter;
1326			VK_FILTER_NEAREST,							// VkFilter				minFilter;
1327			VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
1328			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeU;
1329			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeV;
1330			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeW;
1331			0.0f,										// float				mipLodBias;
1332			VK_FALSE,									// VkBool32				anisotropyEnable;
1333			0.0f,										// float				maxAnisotropy;
1334			VK_FALSE,									// VkBool32				compareEnable;
1335			VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
1336			0.0f,										// float				minLod;
1337			0.0f,										// float				maxLod;
1338			VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,			// VkBorderColor		borderColor;
1339			VK_FALSE									// VkBool32				unnormalizedCoordinates;
1340		};
1341
1342		m_whiteBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
1343		samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
1344		m_blackBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
1345	}
1346
1347	// Create render pass
1348	{
1349		const VkAttachmentDescription	attachmentDescription	=
1350		{
1351			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
1352			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat						format
1353			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
1354			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
1355			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
1356			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
1357			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
1358			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
1359			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
1360		};
1361
1362		const VkAttachmentReference		resultAttachmentRef		=
1363		{
1364			0u,											// deUint32			attachment
1365			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
1366		};
1367
1368		const VkSubpassDescription		subpassDescription		=
1369		{
1370			(VkSubpassDescriptionFlags)0,				// VkSubpassDescriptionFlags	flags
1371			VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint			pipelineBindPoint
1372			0u,											// deUint32						inputAttachmentCount
1373			DE_NULL,									// const VkAttachmentReference*	pInputAttachments
1374			1u,											// deUint32						colorAttachmentCount
1375			&resultAttachmentRef,						// const VkAttachmentReference*	pColorAttachments
1376			DE_NULL,									// const VkAttachmentReference*	pResolveAttachments
1377			DE_NULL,									// const VkAttachmentReference*	pDepthStencilAttachment
1378			0u,											// deUint32						preserveAttachmentCount
1379			DE_NULL										// const deUint32*				pPreserveAttachments
1380		};
1381
1382		const VkRenderPassCreateInfo	renderPassInfo			=
1383		{
1384			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureTypei					sType
1385			DE_NULL,									// const void*						pNext
1386			(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
1387			1u,											// deUint32							attachmentCount
1388			&attachmentDescription,						// const VkAttachmentDescription*	pAttachments
1389			1u,											// deUint32							subpassCount
1390			&subpassDescription,						// const VkSubpassDescription*		pSubpasses
1391			0u,											// deUint32							dependencyCount
1392			DE_NULL										// const VkSubpassDependency*		pDependencies
1393		};
1394
1395		m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &renderPassInfo);
1396	}
1397
1398	// Create framebuffer
1399	{
1400		const VkImageView				attachmentBindInfos[]	=
1401		{
1402			*m_colorAttachmentView
1403		};
1404
1405		const VkFramebufferCreateInfo	framebufferParams		=
1406		{
1407			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
1408			DE_NULL,									// const void*				pNext;
1409			0u,											// VkFramebufferCreateFlags	flags;
1410			*m_renderPass,								// VkRenderPass				renderPass;
1411			1u,											// deUint32					attachmentCount;
1412			attachmentBindInfos,						// const VkImageView*		pAttachments;
1413			(deUint32)m_renderSize.x(),					// deUint32					width;
1414			(deUint32)m_renderSize.y(),					// deUint32					height;
1415			1u											// deUint32					layers;
1416		};
1417
1418		m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
1419	}
1420
1421	// Create pipeline layout
1422	{
1423		// Create descriptor set layout
1424		vector<VkDescriptorSetLayoutBinding>	layoutBindings;
1425
1426		switch(m_params.descriptorType)
1427		{
1428			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1429				{
1430					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
1431					{
1432						m_params.binding,							// uint32_t				binding;
1433						VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	// VkDescriptorType		descriptorType;
1434						1u,											// uint32_t				descriptorCount;
1435						VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlags	stageFlags;
1436						DE_NULL										// const VkSampler*		pImmutableSamplers;
1437					};
1438					layoutBindings.push_back(descriptorSetLayoutBinding);
1439				}
1440				break;
1441
1442			case VK_DESCRIPTOR_TYPE_SAMPLER:
1443				{
1444					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingSampler	=
1445					{
1446						m_params.binding,				// uint32_t				binding;
1447						VK_DESCRIPTOR_TYPE_SAMPLER,		// VkDescriptorType		descriptorType;
1448						1u,								// uint32_t				descriptorCount;
1449						VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
1450						DE_NULL							// const VkSampler*		pImmutableSamplers;
1451					};
1452					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingTex	=
1453					{
1454						m_params.binding + 1,				// uint32_t				binding;
1455						VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	// VkDescriptorType		descriptorType;
1456						1u,									// uint32_t				descriptorCount;
1457						VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags	stageFlags;
1458						DE_NULL								// const VkSampler*		pImmutableSamplers;
1459					};
1460					layoutBindings.push_back(descriptorSetLayoutBindingSampler);
1461					layoutBindings.push_back(descriptorSetLayoutBindingTex);
1462				}
1463				break;
1464
1465			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1466				{
1467					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingSampler	=
1468					{
1469						m_params.binding + 1,			// uint32_t				binding;
1470						VK_DESCRIPTOR_TYPE_SAMPLER,		// VkDescriptorType		descriptorType;
1471						1u,								// uint32_t				descriptorCount;
1472						VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
1473						DE_NULL							// const VkSampler*		pImmutableSamplers;
1474					};
1475					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingTex	=
1476					{
1477						m_params.binding,					// uint32_t				binding;
1478						VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	// VkDescriptorType		descriptorType;
1479						1u,									// uint32_t				descriptorCount;
1480						VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags	stageFlags;
1481						DE_NULL								// const VkSampler*		pImmutableSamplers;
1482					};
1483					layoutBindings.push_back(descriptorSetLayoutBindingSampler);
1484					layoutBindings.push_back(descriptorSetLayoutBindingTex);
1485				}
1486				break;
1487
1488			case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1489				{
1490					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
1491					{
1492						m_params.binding,					// uint32_t				binding;
1493						VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,	// VkDescriptorType		descriptorType;
1494						1u,									// uint32_t				descriptorCount;
1495						VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags	stageFlags;
1496						DE_NULL								// const VkSampler*		pImmutableSamplers;
1497					};
1498					layoutBindings.push_back(descriptorSetLayoutBinding);
1499				}
1500				break;
1501
1502			default:
1503				DE_FATAL("unexpected descriptor type");
1504				break;
1505		}
1506
1507		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
1508		{
1509			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
1510			DE_NULL,													// const void*							pNext;
1511			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
1512			(deUint32)layoutBindings.size(),							// uint32_t								bindingCount;
1513			layoutBindings.data()										// const VkDescriptorSetLayoutBinding*	pBindings;
1514		};
1515
1516		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
1517
1518		// Create pipeline layout
1519		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1520		VkPipelineLayoutCreateInfo	pipelineLayoutParams
1521		{
1522			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
1523			DE_NULL,										// const void*					pNext;
1524			pipelineLayoutFlags,							// VkPipelineLayoutCreateFlags	flags;
1525			0u,												// deUint32						setLayoutCount;
1526			DE_NULL,										// const VkDescriptorSetLayout*	pSetLayouts;
1527			0u,												// deUint32						pushConstantRangeCount;
1528			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
1529		};
1530
1531		m_preRasterizationStatePipelineLayout	= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
1532		pipelineLayoutParams.setLayoutCount		= 1u;
1533		pipelineLayoutParams.pSetLayouts		= &(*m_descriptorSetLayout);
1534		m_fragmentStatePipelineLayout			= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
1535	}
1536
1537	// Create shaders
1538	{
1539		m_vertexShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
1540		m_fragmentShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
1541	}
1542
1543	// Create pipeline
1544	{
1545		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
1546		{
1547			0u,							// deUint32					binding;
1548			sizeof(Vertex4Tex4),		// deUint32					strideInBytes;
1549			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
1550		};
1551
1552		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[]	=
1553		{
1554			{
1555				0u,										// deUint32	location;
1556				0u,										// deUint32	binding;
1557				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
1558				0u										// deUint32	offsetInBytes;
1559			},
1560			{
1561				1u,										// deUint32	location;
1562				0u,										// deUint32	binding;
1563				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
1564				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
1565			}
1566		};
1567
1568		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
1569		{
1570			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1571			DE_NULL,													// const void*								pNext;
1572			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
1573			1u,															// deUint32									bindingCount;
1574			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1575			2u,															// deUint32									attributeCount;
1576			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1577		};
1578
1579		const vector<VkViewport>					viewports		{ makeViewport(m_renderSize) };
1580		const vector<VkRect2D>						scissors		{ makeRect2D(m_renderSize) };
1581
1582		m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
1583						  .setDefaultRasterizationState()
1584						  .setDefaultDepthStencilState()
1585						  .setDefaultMultisampleState()
1586						  .setDefaultColorBlendState()
1587						  .setupVertexInputState(&vertexInputStateParams)
1588						  .setupPreRasterizationShaderState(viewports,
1589															scissors,
1590															m_preRasterizationStatePipelineLayout,
1591															*m_renderPass,
1592															0u,
1593															m_vertexShaderModule)
1594						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
1595						  .setupFragmentOutputState(*m_renderPass)
1596						  .buildPipeline();
1597	}
1598
1599	// Create vertex buffer
1600	{
1601		const VkBufferCreateInfo vertexBufferParams =
1602		{
1603			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
1604			DE_NULL,													// const void*			pNext;
1605			0u,															// VkBufferCreateFlags	flags;
1606			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
1607			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
1608			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
1609			1u,															// deUint32				queueFamilyCount;
1610			&m_queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
1611		};
1612
1613		m_vertexBuffer		= createBuffer(m_vkd, *m_device, &vertexBufferParams);
1614		m_vertexBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1615
1616		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1617
1618		// Load vertices into vertex buffer
1619		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4Tex4));
1620		flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
1621	}
1622
1623	// Create command pool
1624	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
1625
1626	// Create command buffer
1627	{
1628		const VkClearValue	attachmentClearValue	= defaultClearValue(m_colorFormat);
1629		const VkDeviceSize	vertexBufferOffset		= 0;
1630
1631		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1632		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
1633		m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1634		m_graphicsPipeline.bind(*m_cmdBuffer);
1635		m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1636
1637		// Draw quads. Switch sampler or image view depending on the test.
1638		vector<VkSampler>	samplers;
1639		vector<VkImageView> imageViews;
1640
1641		samplers.push_back(*m_whiteBorderSampler);
1642		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1643		{
1644			// Vary sampler between draws
1645			samplers.push_back(*m_blackBorderSampler);
1646		}
1647		else
1648		{
1649			// Usa a single sampler
1650			samplers.push_back(*m_whiteBorderSampler);
1651		}
1652
1653		imageViews.push_back(**m_textureViews[0]);
1654		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1655		{
1656			// Vary image view between draws
1657			imageViews.push_back(**m_textureViews[1]);
1658		}
1659		else
1660		{
1661			// Usa a single image view
1662			imageViews.push_back(**m_textureViews[0]);
1663		}
1664
1665		for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
1666		{
1667			VkDescriptorImageInfo	descriptorImageInfo	=
1668			{
1669				samplers[quadNdx],							// VkSampler		sampler;
1670				imageViews[quadNdx],						// VkImageView		imageView;
1671				textureImageLayout							// VkImageLayout	imageLayout;
1672			};
1673
1674			VkWriteDescriptorSet	writeDescriptorSet	=
1675			{
1676				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
1677				DE_NULL,								// const void*						pNext;
1678				0u,										// VkDescriptorSet					dstSet;
1679				m_params.binding,						// uint32_t							dstBinding;
1680				0u,										// uint32_t							dstArrayElement;
1681				1u,										// uint32_t							descriptorCount;
1682				m_params.descriptorType,				// VkDescriptorType					descriptorType;
1683				&descriptorImageInfo,					// const VkDescriptorImageInfo*		pImageInfo;
1684				DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo;
1685				DE_NULL									// const VkBufferView*				pTexelBufferView;
1686			};
1687
1688			vector<VkWriteDescriptorSet> writeDescriptorSets;
1689			writeDescriptorSets.push_back(writeDescriptorSet);
1690
1691			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1692			{
1693				// Sampler also needs an image.
1694				writeDescriptorSet.dstBinding++;
1695				writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1696				writeDescriptorSets.push_back(writeDescriptorSet);
1697			}
1698			else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1699			{
1700				// Image also needs a sampler.
1701				writeDescriptorSet.dstBinding++;
1702				writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1703				writeDescriptorSets.push_back(writeDescriptorSet);
1704			}
1705
1706			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, (deUint32)writeDescriptorSets.size(), writeDescriptorSets.data());
1707			m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
1708		}
1709
1710		m_renderPass.end(m_vkd, *m_cmdBuffer);
1711		endCommandBuffer(m_vkd, *m_cmdBuffer);
1712	}
1713}
1714
1715PushDescriptorImageGraphicsTestInstance::~PushDescriptorImageGraphicsTestInstance (void)
1716{
1717}
1718
1719tcu::TestStatus PushDescriptorImageGraphicsTestInstance::iterate (void)
1720{
1721	init();
1722
1723	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
1724
1725	return verifyImage();
1726}
1727
1728tcu::TestStatus PushDescriptorImageGraphicsTestInstance::verifyImage (void)
1729{
1730	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
1731	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
1732	const ColorVertexShader		vertexShader;
1733	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
1734	const rr::Program			program			(&vertexShader, &fragmentShader);
1735	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1736	bool						compareOk		= false;
1737
1738	// Render reference image
1739	{
1740		vector<Vertex4RGBA>	refQuadsOuter	= createQuads(m_params.numCalls, 0.25f);
1741		vector<Vertex4RGBA>	refQuadsInner	= createQuads(m_params.numCalls, 0.25f * 0.8f);
1742		tcu::Vec4			outerColor[2];
1743		tcu::Vec4			innerColor[2];
1744		const bool			hasBorder		= m_params.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1745
1746		if (hasBorder)
1747		{
1748			outerColor[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1749			innerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1750			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1751				outerColor[1] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1752			else
1753				outerColor[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1754			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1755				innerColor[1] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1756			else
1757				innerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1758		}
1759		else
1760		{
1761			outerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1762			outerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1763		}
1764
1765		for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
1766			for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
1767			{
1768				const deUint32 idx = quadIdx * 6 + vertexIdx;
1769				refQuadsOuter[idx].color.xyzw() = outerColor[quadIdx];
1770				refQuadsInner[idx].color.xyzw() = innerColor[quadIdx];
1771			}
1772
1773		if (hasBorder)
1774			refQuadsOuter.insert(refQuadsOuter.end(), refQuadsInner.begin(), refQuadsInner.end());
1775
1776		refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
1777						 rr::PRIMITIVETYPE_TRIANGLES, refQuadsOuter);
1778	}
1779
1780	// Compare result with reference image
1781	{
1782		de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
1783
1784		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1785															  "IntImageCompare",
1786															  "Image comparison",
1787															  refRenderer.getAccess(),
1788															  result->getAccess(),
1789															  tcu::UVec4(2, 2, 2, 2),
1790															  tcu::IVec3(1, 1, 0),
1791															  true,
1792															  tcu::COMPARE_LOG_RESULT);
1793	}
1794
1795	if (compareOk)
1796		return tcu::TestStatus::pass("Result image matches reference");
1797	else
1798		return tcu::TestStatus::fail("Image mismatch");
1799}
1800
1801class PushDescriptorImageGraphicsTest : public vkt::TestCase
1802{
1803public:
1804						PushDescriptorImageGraphicsTest		(tcu::TestContext&	testContext,
1805															 const string&		name,
1806															 const TestParams&	params);
1807						~PushDescriptorImageGraphicsTest	(void);
1808
1809	void				checkSupport						(Context& context) const;
1810	void				initPrograms						(SourceCollections& sourceCollections) const;
1811	TestInstance*		createInstance						(Context& context) const;
1812
1813protected:
1814	const TestParams	m_params;
1815};
1816
1817PushDescriptorImageGraphicsTest::PushDescriptorImageGraphicsTest	(tcu::TestContext&	testContext,
1818																	const string&		name,
1819																	const TestParams&	params)
1820	: vkt::TestCase	(testContext, name)
1821	, m_params		(params)
1822{
1823}
1824
1825PushDescriptorImageGraphicsTest::~PushDescriptorImageGraphicsTest (void)
1826{
1827}
1828
1829TestInstance* PushDescriptorImageGraphicsTest::createInstance (Context& context) const
1830{
1831	return new PushDescriptorImageGraphicsTestInstance(context, m_params);
1832}
1833
1834void PushDescriptorImageGraphicsTest::checkSupport(Context& context) const
1835{
1836	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1837}
1838
1839void PushDescriptorImageGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
1840{
1841	const string	vertexSrc	=
1842		"#version 450\n"
1843		"layout(location = 0) in highp vec4 position;\n"
1844		"layout(location = 1) in highp vec4 texcoordVtx;\n"
1845		"layout(location = 0) out highp vec2 texcoordFrag;\n"
1846		"\n"
1847		"out gl_PerVertex { vec4 gl_Position; };\n"
1848		"\n"
1849		"void main()\n"
1850		"{\n"
1851		"	gl_Position = position;\n"
1852		"	texcoordFrag = texcoordVtx.xy;\n"
1853		"}\n";
1854
1855	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
1856
1857	if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1858	{
1859		const string	fragmentSrc	=
1860			"#version 450\n"
1861			"layout(location = 0) in highp vec2 texcoordFrag;\n"
1862			"layout(location = 0) out highp vec4 fragColor;\n"
1863			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler2D combinedSampler;\n"
1864			"\n"
1865			"void main (void)\n"
1866			"{\n"
1867			"	fragColor = texture(combinedSampler, texcoordFrag);\n"
1868			"}\n";
1869
1870		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1871	}
1872	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1873	{
1874		const string	fragmentSrc	=
1875			"#version 450\n"
1876			"layout(location = 0) in highp vec2 texcoordFrag;\n"
1877			"layout(location = 0) out highp vec4 fragColor;\n"
1878			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler texSampler;\n"
1879			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform texture2D texImage;\n"
1880			"\n"
1881			"void main (void)\n"
1882			"{\n"
1883			"	fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
1884			"}\n";
1885
1886		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1887	}
1888	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1889	{
1890		const string	fragmentSrc	=
1891			"#version 450\n"
1892			"layout(location = 0) in highp vec2 texcoordFrag;\n"
1893			"layout(location = 0) out highp vec4 fragColor;\n"
1894			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform sampler texSampler;\n"
1895			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform texture2D texImage;\n"
1896			"\n"
1897			"void main (void)\n"
1898			"{\n"
1899			"	fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
1900			"}\n";
1901
1902		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1903	}
1904	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1905	{
1906		const string	fragmentSrc	=
1907			"#version 450\n"
1908			"layout(location = 0) in highp vec2 texcoordFrag;\n"
1909			"layout(location = 0) out highp vec4 fragColor;\n"
1910			"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba8) uniform readonly image2D storageImage;\n"
1911			"\n"
1912			"void main (void)\n"
1913			"{\n"
1914			"	fragColor = imageLoad(storageImage, ivec2(0));\n"
1915			"}\n";
1916
1917		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1918	}
1919	else
1920	{
1921		DE_FATAL("Unexpected descriptor type");
1922	}
1923}
1924
1925class PushDescriptorImageComputeTestInstance : public vkt::TestInstance
1926{
1927public:
1928								PushDescriptorImageComputeTestInstance	(Context& context, const TestParams& params);
1929	virtual						~PushDescriptorImageComputeTestInstance	(void);
1930	void						init									(void);
1931	virtual tcu::TestStatus		iterate									(void);
1932	tcu::TestStatus				verifyOutput							(void);
1933
1934private:
1935	const TestParams			m_params;
1936	const PlatformInterface&	m_vkp;
1937	const Extensions			m_instanceExtensions;
1938	const CustomInstance		m_instance;
1939	const InstanceDriver&		m_vki;
1940	const VkPhysicalDevice		m_physicalDevice;
1941	const deUint32				m_queueFamilyIndex;
1942	const Extensions			m_deviceExtensions;
1943	std::vector<std::string>	m_deviceEnabledExtensions;
1944	const Unique<VkDevice>		m_device;
1945	const DeviceDriver			m_vkd;
1946	const VkQueue				m_queue;
1947	const VkDeviceSize			m_itemSize;
1948	const VkDeviceSize			m_blockSize;
1949	SimpleAllocator				m_allocator;
1950	const tcu::UVec2			m_textureSize;
1951	const VkFormat				m_colorFormat;
1952	Move<VkShaderModule>		m_computeShaderModule;
1953	vector<VkImageSp>			m_textureImages;
1954	vector<AllocationSp>		m_textureImageAllocs;
1955	vector<VkImageViewSp>		m_textureViews;
1956	Move<VkSampler>				m_whiteBorderSampler;
1957	Move<VkSampler>				m_blackBorderSampler;
1958	Move<VkBuffer>				m_outputBuffer;
1959	de::MovePtr<Allocation>		m_outputBufferAlloc;
1960	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
1961	Move<VkPipelineLayout>		m_pipelineLayout;
1962	Move<VkPipeline>			m_computePipeline;
1963	Move<VkCommandPool>			m_cmdPool;
1964	Move<VkCommandBuffer>		m_cmdBuffer;
1965	deUint32					m_outputBufferBinding;
1966};
1967
1968PushDescriptorImageComputeTestInstance::PushDescriptorImageComputeTestInstance (Context& context, const TestParams& params)
1969	: vkt::TestInstance		(context)
1970	, m_params				(params)
1971	, m_vkp					(context.getPlatformInterface())
1972	, m_instanceExtensions	(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
1973	, m_instance			(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
1974	, m_vki					(m_instance.getDriver())
1975	, m_physicalDevice		(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
1976	, m_queueFamilyIndex	(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT))
1977	, m_deviceExtensions	(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
1978	, m_device				(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
1979	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
1980	, m_queue				(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
1981	, m_itemSize			(calcItemSize(m_vki, m_physicalDevice, 2u))
1982	, m_blockSize			(kSizeofVec4 * 2u)
1983	, m_allocator			(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
1984	, m_textureSize			(32, 32)
1985	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
1986	, m_outputBufferBinding	(0)
1987{
1988}
1989
1990void PushDescriptorImageComputeTestInstance::init (void)
1991{
1992	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1993
1994	// Create texture images
1995	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
1996	{
1997		VkImageUsageFlags			usageFlags			= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1998		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1999			usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
2000		if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2001			usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
2002
2003		const VkImageCreateInfo		textureImageParams	=
2004		{
2005			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
2006			DE_NULL,										// const void*				pNext;
2007			0u,												// VkImageCreateFlags		flags;
2008			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
2009			m_colorFormat,									// VkFormat					format;
2010			{ m_textureSize.x(), m_textureSize.y(), 1u },	// VkExtent3D				extent;
2011			1u,												// deUint32					mipLevels;
2012			1u,												// deUint32					arrayLayers;
2013			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
2014			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
2015			usageFlags,										// VkImageUsageFlags		usage;
2016			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
2017			1u,												// deUint32					queueFamilyIndexCount;
2018			&m_queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
2019			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
2020		};
2021
2022		m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
2023
2024		// Allocate and bind texture image memory
2025		m_textureImageAllocs.push_back(AllocationSp(m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()), MemoryRequirement::Any).release()));
2026		VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(), m_textureImageAllocs.back()->getOffset()));
2027	}
2028
2029	// Create texture image views
2030	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
2031	{
2032		const VkImageViewCreateInfo textureViewParams =
2033		{
2034			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
2035			DE_NULL,										// const void*				pNext;
2036			0u,												// VkImageViewCreateFlags	flags;
2037			**m_textureImages[texIdx],						// VkImage					image;
2038			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
2039			m_colorFormat,									// VkFormat					format;
2040			componentMappingRGBA,							// VkChannelMapping			channels;
2041			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
2042		};
2043
2044		m_textureViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
2045	}
2046
2047	VkClearValue	clearValues[2];
2048	clearValues[0].color.float32[0] = 0.0f;
2049	clearValues[0].color.float32[1] = 1.0f;
2050	clearValues[0].color.float32[2] = 0.0f;
2051	clearValues[0].color.float32[3] = 1.0f;
2052	clearValues[1].color.float32[0] = 1.0f;
2053	clearValues[1].color.float32[1] = 0.0f;
2054	clearValues[1].color.float32[2] = 0.0f;
2055	clearValues[1].color.float32[3] = 1.0f;
2056
2057	const VkImageLayout	textureImageLayout = (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
2058											  VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
2059
2060	// Clear textures
2061	for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
2062	{
2063		const VkImageAspectFlags		aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
2064		Move<VkCommandPool>				cmdPool;
2065		Move<VkCommandBuffer>			cmdBuffer;
2066
2067		cmdPool		= createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
2068		cmdBuffer	= allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2069
2070		const VkImageMemoryBarrier preImageBarrier =
2071		{
2072			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
2073			DE_NULL,								// const void*				pNext;
2074			0u,										// VkAccessFlags			srcAccessMask;
2075			VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
2076			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
2077			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
2078			VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
2079			VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
2080			**m_textureImages[texIdx],				// VkImage					image;
2081			{										// VkImageSubresourceRange	subresourceRange;
2082				aspectMask,							// VkImageAspect			aspect;
2083				0u,									// deUint32					baseMipLevel;
2084				1u,									// deUint32					mipLevels;
2085				0u,									// deUint32					baseArraySlice;
2086				1u									// deUint32					arraySize;
2087			}
2088		};
2089
2090		const VkImageMemoryBarrier postImageBarrier =
2091		{
2092			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2093			DE_NULL,									// const void*				pNext;
2094			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
2095			VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
2096			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
2097			textureImageLayout,							// VkImageLayout			newLayout;
2098			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2099			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2100			**m_textureImages[texIdx],					// VkImage					image;
2101			{											// VkImageSubresourceRange	subresourceRange;
2102				aspectMask,								// VkImageAspect			aspect;
2103				0u,										// deUint32					baseMipLevel;
2104				1u,										// deUint32					mipLevels;
2105				0u,										// deUint32					baseArraySlice;
2106				1u										// deUint32					arraySize;
2107			}
2108		};
2109
2110		const VkImageSubresourceRange clearRange	=
2111		{
2112			aspectMask,	// VkImageAspectFlags	aspectMask;
2113			0u,			// deUint32				baseMipLevel;
2114			1u,			// deUint32				levelCount;
2115			0u,			// deUint32				baseArrayLayer;
2116			1u			// deUint32				layerCount;
2117		};
2118
2119		beginCommandBuffer(m_vkd, *cmdBuffer);
2120		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
2121		m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValues[texIdx].color, 1, &clearRange);
2122		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
2123		endCommandBuffer(m_vkd, *cmdBuffer);
2124
2125		submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
2126	}
2127
2128	// Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
2129	{
2130		VkSamplerCreateInfo samplerParams =
2131		{
2132			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
2133			DE_NULL,									// const void*			pNext;
2134			0u,											// VkSamplerCreateFlags	flags;
2135			VK_FILTER_NEAREST,							// VkFilter				magFilter;
2136			VK_FILTER_NEAREST,							// VkFilter				minFilter;
2137			VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
2138			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeU;
2139			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeV;
2140			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeW;
2141			0.0f,										// float				mipLodBias;
2142			VK_FALSE,									// VkBool32				anisotropyEnable;
2143			0.0f,										// float				maxAnisotropy;
2144			VK_FALSE,									// VkBool32				compareEnable;
2145			VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
2146			0.0f,										// float				minLod;
2147			0.0f,										// float				maxLod;
2148			VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,			// VkBorderColor		borderColor;
2149			VK_FALSE									// VkBool32				unnormalizedCoordinates;
2150		};
2151
2152		m_whiteBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
2153		samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
2154		m_blackBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
2155	}
2156
2157	// Create pipeline layout
2158	{
2159		// Create descriptor set layout
2160		vector<VkDescriptorSetLayoutBinding>	layoutBindings;
2161
2162		switch(m_params.descriptorType)
2163		{
2164			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2165				{
2166					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
2167					{
2168						m_params.binding,							// uint32_t				binding;
2169						VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	// VkDescriptorType		descriptorType;
2170						1u,											// uint32_t				descriptorCount;
2171						VK_SHADER_STAGE_COMPUTE_BIT,				// VkShaderStageFlags	stageFlags;
2172						DE_NULL										// const VkSampler*		pImmutableSamplers;
2173					};
2174					layoutBindings.push_back(descriptorSetLayoutBinding);
2175					m_outputBufferBinding = m_params.binding + 1;
2176				}
2177				break;
2178
2179			case VK_DESCRIPTOR_TYPE_SAMPLER:
2180				{
2181					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingSampler	=
2182					{
2183						m_params.binding,				// uint32_t				binding;
2184						VK_DESCRIPTOR_TYPE_SAMPLER,		// VkDescriptorType		descriptorType;
2185						1u,								// uint32_t				descriptorCount;
2186						VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags	stageFlags;
2187						DE_NULL							// const VkSampler*		pImmutableSamplers;
2188					};
2189					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingTex	=
2190					{
2191						m_params.binding + 1,				// uint32_t				binding;
2192						VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	// VkDescriptorType		descriptorType;
2193						1u,									// uint32_t				descriptorCount;
2194						VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
2195						DE_NULL								// const VkSampler*		pImmutableSamplers;
2196					};
2197					layoutBindings.push_back(descriptorSetLayoutBindingSampler);
2198					layoutBindings.push_back(descriptorSetLayoutBindingTex);
2199					m_outputBufferBinding = m_params.binding + 2;
2200				}
2201				break;
2202
2203			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2204				{
2205					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingSampler	=
2206					{
2207						m_params.binding + 1,			// uint32_t				binding;
2208						VK_DESCRIPTOR_TYPE_SAMPLER,		// VkDescriptorType		descriptorType;
2209						1u,								// uint32_t				descriptorCount;
2210						VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags	stageFlags;
2211						DE_NULL							// const VkSampler*		pImmutableSamplers;
2212					};
2213					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingTex	=
2214					{
2215						m_params.binding,					// uint32_t				binding;
2216						VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	// VkDescriptorType		descriptorType;
2217						1u,									// uint32_t				descriptorCount;
2218						VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
2219						DE_NULL								// const VkSampler*		pImmutableSamplers;
2220					};
2221					layoutBindings.push_back(descriptorSetLayoutBindingSampler);
2222					layoutBindings.push_back(descriptorSetLayoutBindingTex);
2223					m_outputBufferBinding = m_params.binding + 2;
2224				}
2225				break;
2226
2227			case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2228				{
2229					const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
2230					{
2231						m_params.binding,					// uint32_t				binding;
2232						VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,	// VkDescriptorType		descriptorType;
2233						1u,									// uint32_t				descriptorCount;
2234						VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
2235						DE_NULL								// const VkSampler*		pImmutableSamplers;
2236					};
2237					layoutBindings.push_back(descriptorSetLayoutBinding);
2238					m_outputBufferBinding = m_params.binding + 1;
2239				}
2240				break;
2241
2242			default:
2243				DE_FATAL("unexpected descriptor type");
2244				break;
2245		}
2246
2247		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindingOutputBuffer	=
2248		{
2249			m_outputBufferBinding,				// uint32_t				binding;
2250			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	// VkDescriptorType		descriptorType;
2251			1u,									// uint32_t				descriptorCount;
2252			VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
2253			DE_NULL								// const VkSampler*		pImmutableSamplers;
2254		};
2255
2256		layoutBindings.push_back(descriptorSetLayoutBindingOutputBuffer);
2257
2258		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
2259		{
2260			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
2261			DE_NULL,													// const void*							pNext;
2262			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
2263			(deUint32)layoutBindings.size(),							// uint32_t								bindingCount;
2264			layoutBindings.data()										// const VkDescriptorSetLayoutBinding*	pBindings;
2265		};
2266
2267		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
2268
2269		// Create pipeline layout
2270		const VkPipelineLayoutCreateInfo		pipelineLayoutParams			=
2271		{
2272			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
2273			DE_NULL,										// const void*					pNext;
2274			0u,												// VkPipelineLayoutCreateFlags	flags;
2275			1u,												// deUint32						descriptorSetCount;
2276			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
2277			0u,												// deUint32						pushConstantRangeCount;
2278			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
2279		};
2280
2281		m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
2282	}
2283
2284	// Create output buffer
2285	{
2286		DE_ASSERT(m_params.numCalls <= 2u);
2287
2288		const VkBufferCreateInfo bufferCreateInfo =
2289		{
2290			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
2291			DE_NULL,								// const void*			pNext;
2292			0u,										// VkBufferCreateFlags	flags
2293			m_itemSize * 2u,						// VkDeviceSize			size;
2294			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags	usage;
2295			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2296			1u,										// deUint32				queueFamilyCount;
2297			&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
2298		};
2299
2300		m_outputBuffer		= createBuffer(m_vkd, *m_device, &bufferCreateInfo);
2301		m_outputBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer), MemoryRequirement::HostVisible);
2302		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
2303	}
2304
2305	// Create shader
2306	{
2307		m_computeShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
2308	}
2309
2310	// Create pipeline
2311	{
2312		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
2313		{
2314			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
2315			DE_NULL,												// const void*						pNext;
2316			0u,														// VkPipelineShaderStageCreateFlags	flags;
2317			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
2318			*m_computeShaderModule,									// VkShaderModule					module;
2319			"main",													// const char*						pName;
2320			DE_NULL													// const VkSpecializationInfo*		pSpecializationInfo;
2321		};
2322
2323		const VkComputePipelineCreateInfo		createInfo		=
2324		{
2325			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
2326			DE_NULL,												// const void*						pNext;
2327			0u,														// VkPipelineCreateFlags			flags;
2328			stageCreateInfo,										// VkPipelineShaderStageCreateInfo	stage;
2329			*m_pipelineLayout,										// VkPipelineLayout					layout;
2330			(VkPipeline)0,											// VkPipeline						basePipelineHandle;
2331			0u,														// int32_t							basePipelineIndex;
2332		};
2333
2334		m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
2335	}
2336
2337	// Create command pool
2338	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
2339
2340	// Create command buffer
2341	{
2342		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2343		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
2344		m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
2345
2346		// Dispatch: Each dispatch switches the input image.
2347		// Output buffer is exposed as a 2 x vec4 sized window.
2348		for (deUint32 dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
2349		{
2350			vector<VkSampler>	samplers;
2351			vector<VkImageView> imageViews;
2352
2353			samplers.push_back(*m_whiteBorderSampler);
2354			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2355			{
2356				// Vary sampler between draws
2357				samplers.push_back(*m_blackBorderSampler);
2358			}
2359			else
2360			{
2361				// Usa a single sampler
2362				samplers.push_back(*m_whiteBorderSampler);
2363			}
2364
2365			imageViews.push_back(**m_textureViews[0]);
2366			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2367			{
2368				// Vary image view between draws
2369				imageViews.push_back(**m_textureViews[1]);
2370			}
2371			else
2372			{
2373				// Usa a single image view
2374				imageViews.push_back(**m_textureViews[0]);
2375			}
2376
2377			const VkDescriptorImageInfo	descriptorImageInfo	=
2378			{
2379				samplers[dispatchNdx],					// VkSampler		sampler;
2380				imageViews[dispatchNdx],				// VkImageView		imageView;
2381				textureImageLayout						// VkImageLayout	imageLayout;
2382			};
2383
2384			VkWriteDescriptorSet	writeDescriptorSet		=
2385			{
2386				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
2387				DE_NULL,								// const void*						pNext;
2388				0u,										// VkDescriptorSet					dstSet;
2389				m_params.binding,						// uint32_t							dstBinding;
2390				0u,										// uint32_t							dstArrayElement;
2391				1u,										// uint32_t							descriptorCount;
2392				m_params.descriptorType,				// VkDescriptorType					descriptorType;
2393				&descriptorImageInfo,					// const VkDescriptorImageInfo*		pImageInfo;
2394				DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo;
2395				DE_NULL									// const VkBufferView*				pTexelBufferView;
2396			};
2397
2398			vector<VkWriteDescriptorSet> writeDescriptorSets;
2399			writeDescriptorSets.push_back(writeDescriptorSet);
2400
2401			if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
2402			{
2403				// Sampler also needs an image.
2404				writeDescriptorSet.dstBinding++;
2405				writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2406				writeDescriptorSets.push_back(writeDescriptorSet);
2407			}
2408			else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
2409			{
2410				// Image also needs a sampler.
2411				writeDescriptorSet.dstBinding++;
2412				writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
2413				writeDescriptorSets.push_back(writeDescriptorSet);
2414			}
2415
2416			const VkDescriptorBufferInfo descriptorBufferInfoOutput	=
2417			{
2418				*m_outputBuffer,			// VkBuffer		buffer;
2419				m_itemSize * dispatchNdx,	// VkDeviceSize	offset;
2420				m_blockSize,				// VkDeviceSize	range;
2421			};
2422
2423			// Write output buffer descriptor set
2424			const VkWriteDescriptorSet	writeDescriptorSetOutput	=
2425			{
2426				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
2427				DE_NULL,								// const void*						pNext;
2428				0u,										// VkDescriptorSet					dstSet;
2429				m_outputBufferBinding,					// uint32_t							dstBinding;
2430				0u,										// uint32_t							dstArrayElement;
2431				1u,										// uint32_t							descriptorCount;
2432				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// VkDescriptorType					descriptorType;
2433				DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
2434				&descriptorBufferInfoOutput,			// const VkDescriptorBufferInfo*	pBufferInfo;
2435				DE_NULL									// const VkBufferView*				pTexelBufferView;
2436			};
2437
2438			writeDescriptorSets.push_back(writeDescriptorSetOutput);
2439
2440			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, (deUint32)writeDescriptorSets.size(), writeDescriptorSets.data());
2441			m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
2442		}
2443
2444		endCommandBuffer(m_vkd, *m_cmdBuffer);
2445	}
2446}
2447
2448PushDescriptorImageComputeTestInstance::~PushDescriptorImageComputeTestInstance (void)
2449{
2450}
2451
2452tcu::TestStatus PushDescriptorImageComputeTestInstance::iterate (void)
2453{
2454	init();
2455
2456	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
2457
2458	return verifyOutput();
2459}
2460
2461tcu::TestStatus PushDescriptorImageComputeTestInstance::verifyOutput (void)
2462{
2463	const auto			floatsPerDispatch	= 8u; // 8 floats (2 vec4s) per dispatch.
2464	std::vector<float>	ref					(floatsPerDispatch * 2u);
2465
2466	invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
2467
2468	switch(m_params.descriptorType)
2469	{
2470		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2471			// Dispatch 1: inner & outer = green
2472			ref[0] = ref[4] = 0.0f;
2473			ref[1] = ref[5] = 1.0f;
2474			ref[2] = ref[6] = 0.0f;
2475			ref[3] = ref[7] = 1.0f;
2476
2477			// Dispatch 2: inner & outer = red
2478			ref[8] = ref[12] = 1.0f;
2479			ref[9] = ref[13] = 0.0f;
2480			ref[10] = ref[14] = 0.0f;
2481			ref[11] = ref[15] = 1.0f;
2482			break;
2483
2484		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2485			// Dispatch 1: inner = green, outer = white
2486			ref[0] = 0.0f;
2487			ref[1] = 1.0f;
2488			ref[2] = 0.0f;
2489			ref[3] = 1.0f;
2490
2491			ref[4] = 1.0f;
2492			ref[5] = 1.0f;
2493			ref[6] = 1.0f;
2494			ref[7] = 1.0f;
2495
2496			// Dispatch 2: inner = red, outer = black
2497			ref[8] = 1.0f;
2498			ref[9] = 0.0f;
2499			ref[10] = 0.0f;
2500			ref[11] = 1.0f;
2501
2502			ref[12] = 0.0f;
2503			ref[13] = 0.0f;
2504			ref[14] = 0.0f;
2505			ref[15] = 1.0f;
2506			break;
2507
2508		case VK_DESCRIPTOR_TYPE_SAMPLER:
2509			// Dispatch 1: inner = green, outer = white
2510			ref[0] = 0.0f;
2511			ref[1] = 1.0f;
2512			ref[2] = 0.0f;
2513			ref[3] = 1.0f;
2514
2515			ref[4] = 1.0f;
2516			ref[5] = 1.0f;
2517			ref[6] = 1.0f;
2518			ref[7] = 1.0f;
2519
2520			// Dispatch 2: inner = green, outer = black
2521			ref[8] = 0.0f;
2522			ref[9] = 1.0f;
2523			ref[10] = 0.0f;
2524			ref[11] = 1.0f;
2525
2526			ref[12] = 0.0f;
2527			ref[13] = 0.0f;
2528			ref[14] = 0.0f;
2529			ref[15] = 1.0f;
2530			break;
2531
2532		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2533			// Dispatch 1: inner = green, outer = white
2534			ref[0] = 0.0f;
2535			ref[1] = 1.0f;
2536			ref[2] = 0.0f;
2537			ref[3] = 1.0f;
2538
2539			ref[4] = 1.0f;
2540			ref[5] = 1.0f;
2541			ref[6] = 1.0f;
2542			ref[7] = 1.0f;
2543
2544			// Dispatch 2: inner = red, outer = white
2545			ref[8] = 1.0f;
2546			ref[9] = 0.0f;
2547			ref[10] = 0.0f;
2548			ref[11] = 1.0f;
2549
2550			ref[12] = 1.0f;
2551			ref[13] = 1.0f;
2552			ref[14] = 1.0f;
2553			ref[15] = 1.0f;
2554			break;
2555
2556		default:
2557			DE_FATAL("unexpected descriptor type");
2558			break;
2559	}
2560
2561	// Verify result
2562	const auto			bufferDataPtr		= reinterpret_cast<const char*>(m_outputBufferAlloc->getHostPtr());
2563	const auto			blockSize			= static_cast<size_t>(m_blockSize);
2564
2565	for (deUint32 dispatchNdx = 0u; dispatchNdx < m_params.numCalls; ++dispatchNdx)
2566	{
2567		const auto refIdx		= floatsPerDispatch * dispatchNdx;
2568		const auto bufferOffset	= m_itemSize * dispatchNdx;	// Each dispatch uses m_itemSize bytes in the buffer to meet alignment reqs.
2569
2570		if (deMemCmp(&ref[refIdx], bufferDataPtr + bufferOffset, blockSize) != 0)
2571		{
2572			std::vector<float> buffferValues	(floatsPerDispatch);
2573			std::vector<float> refValues		(floatsPerDispatch);
2574
2575			deMemcpy(refValues.data(), &ref[refIdx], blockSize);
2576			deMemcpy(buffferValues.data(), bufferDataPtr + bufferOffset, blockSize);
2577
2578			std::ostringstream msg;
2579			msg << "Output mismatch at dispatch " << dispatchNdx << ": Reference ";
2580			for (deUint32 i = 0; i < floatsPerDispatch; ++i)
2581				msg << ((i == 0) ? "[" : ", ") << refValues[i];
2582			msg << "]; Buffer ";
2583			for (deUint32 i = 0; i < floatsPerDispatch; ++i)
2584				msg << ((i == 0) ? "[" : ", ") << buffferValues[i];
2585			msg << "]";
2586
2587			m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2588			return tcu::TestStatus::fail("Output mismatch");
2589		}
2590	}
2591
2592	return tcu::TestStatus::pass("Output matches expected values");
2593}
2594
2595class PushDescriptorImageComputeTest : public vkt::TestCase
2596{
2597public:
2598						PushDescriptorImageComputeTest	(tcu::TestContext&	testContext,
2599														 const string&		name,
2600														 const TestParams&	params);
2601						~PushDescriptorImageComputeTest	(void);
2602	void				initPrograms					(SourceCollections& sourceCollections) const;
2603	TestInstance*		createInstance					(Context& context) const;
2604
2605protected:
2606	const TestParams	m_params;
2607};
2608
2609PushDescriptorImageComputeTest::PushDescriptorImageComputeTest	(tcu::TestContext&	testContext,
2610																 const string&		name,
2611																 const TestParams&	params)
2612	: vkt::TestCase	(testContext, name)
2613	, m_params		(params)
2614{
2615}
2616
2617PushDescriptorImageComputeTest::~PushDescriptorImageComputeTest (void)
2618{
2619}
2620
2621TestInstance* PushDescriptorImageComputeTest::createInstance (Context& context) const
2622{
2623	return new PushDescriptorImageComputeTestInstance(context, m_params);
2624}
2625
2626void PushDescriptorImageComputeTest::initPrograms (SourceCollections& sourceCollections) const
2627{
2628	if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2629	{
2630		const string	computeSrc	=
2631			"#version 450\n"
2632			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler2D combinedSampler;\n"
2633			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
2634			"{\n"
2635			"	vec4 innerColor;\n"
2636			"	vec4 outerColor;\n"
2637			"} outData;\n"
2638			"\n"
2639			"void main()\n"
2640			"{\n"
2641			"	outData.innerColor = texture(combinedSampler, vec2(0.5));\n"
2642			"	outData.outerColor = texture(combinedSampler, vec2(-0.1));\n"
2643			"}\n";
2644
2645		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2646	}
2647	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
2648	{
2649		const string	computeSrc	=
2650			"#version 450\n"
2651			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler texSampler;\n"
2652			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform texture2D texImage;\n"
2653			"layout(set = 0, binding = " + de::toString(m_params.binding + 2) + ") writeonly buffer Output\n"
2654			"{\n"
2655			"	vec4 innerColor;\n"
2656			"	vec4 outerColor;\n"
2657			"} outData;\n"
2658			"\n"
2659			"void main()\n"
2660			"{\n"
2661			"	outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
2662			"	outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
2663			"}\n";
2664
2665		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2666	}
2667	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
2668	{
2669		const string	computeSrc	=
2670			"#version 450\n"
2671			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform sampler texSampler;\n"
2672			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform texture2D texImage;\n"
2673			"layout(set = 0, binding = " + de::toString(m_params.binding + 2) + ") writeonly buffer Output\n"
2674			"{\n"
2675			"	vec4 innerColor;\n"
2676			"	vec4 outerColor;\n"
2677			"} outData;\n"
2678			"\n"
2679			"void main()\n"
2680			"{\n"
2681			"	outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
2682			"	outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
2683			"}\n";
2684
2685		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2686	}
2687	else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2688	{
2689		const string	computeSrc	=
2690			"#version 450\n"
2691			"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba8) uniform readonly image2D storageImage;\n"
2692			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
2693			"{\n"
2694			"	vec4 innerColor;\n"
2695			"	vec4 outerColor;\n"
2696			"} outData;\n"
2697			"\n"
2698			"void main()\n"
2699			"{\n"
2700			"	outData.innerColor = imageLoad(storageImage, ivec2(0));\n"
2701			"	outData.outerColor = imageLoad(storageImage, ivec2(0));\n"
2702			"}\n";
2703
2704		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2705	}
2706	else
2707	{
2708		DE_FATAL("Unexpected descriptor type");
2709	}
2710}
2711
2712class PushDescriptorTexelBufferGraphicsTestInstance : public vkt::TestInstance
2713{
2714public:
2715								PushDescriptorTexelBufferGraphicsTestInstance	(Context& context, const TestParams& params);
2716	virtual						~PushDescriptorTexelBufferGraphicsTestInstance	(void);
2717	void						init											(void);
2718	virtual tcu::TestStatus		iterate											(void);
2719	tcu::TestStatus				verifyImage										(void);
2720
2721private:
2722	const TestParams				m_params;
2723	const PlatformInterface&		m_vkp;
2724	const Extensions				m_instanceExtensions;
2725	const CustomInstance			m_instance;
2726	const InstanceDriver&			m_vki;
2727	const VkPhysicalDevice			m_physicalDevice;
2728	const deUint32					m_queueFamilyIndex;
2729	const Extensions				m_deviceExtensions;
2730	std::vector<std::string>		m_deviceEnabledExtensions;
2731	const Unique<VkDevice>			m_device;
2732	const DeviceDriver				m_vkd;
2733	const VkQueue					m_queue;
2734	SimpleAllocator					m_allocator;
2735	const tcu::UVec2				m_renderSize;
2736	const VkFormat					m_colorFormat;
2737	Move<VkImage>					m_colorImage;
2738	de::MovePtr<Allocation>			m_colorImageAlloc;
2739	Move<VkImageView>				m_colorAttachmentView;
2740	vector<VkBufferSp>				m_buffers;
2741	vector<AllocationSp>			m_bufferAllocs;
2742	vector<VkBufferViewSp>			m_bufferViews;
2743	const VkFormat					m_bufferFormat;
2744	RenderPassWrapper				m_renderPass;
2745	Move<VkFramebuffer>				m_framebuffer;
2746	ShaderWrapper					m_vertexShaderModule;
2747	ShaderWrapper					m_fragmentShaderModule;
2748	Move<VkBuffer>					m_vertexBuffer;
2749	de::MovePtr<Allocation>			m_vertexBufferAlloc;
2750	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
2751	PipelineLayoutWrapper			m_preRasterizationStatePipelineLayout;
2752	PipelineLayoutWrapper			m_fragmentStatePipelineLayout;
2753	GraphicsPipelineWrapper			m_graphicsPipeline;
2754	Move<VkCommandPool>				m_cmdPool;
2755	Move<VkCommandBuffer>			m_cmdBuffer;
2756	vector<Vertex4RGBA>				m_vertices;
2757};
2758
2759PushDescriptorTexelBufferGraphicsTestInstance::PushDescriptorTexelBufferGraphicsTestInstance (Context& context, const TestParams& params)
2760	: vkt::TestInstance			(context)
2761	, m_params					(params)
2762	, m_vkp						(context.getPlatformInterface())
2763	, m_instanceExtensions		(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
2764	, m_instance				(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
2765	, m_vki						(m_instance.getDriver())
2766	, m_physicalDevice			(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
2767	, m_queueFamilyIndex		(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
2768	, m_deviceExtensions		(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
2769	, m_device					(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
2770	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
2771	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
2772	, m_allocator				(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
2773	, m_renderSize				(32, 32)
2774	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2775	, m_bufferFormat			(VK_FORMAT_R32G32B32A32_SFLOAT)
2776	, m_graphicsPipeline		(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions, params.pipelineConstructionType)
2777	, m_vertices				(createQuads(params.numCalls, 0.25f))
2778{
2779}
2780
2781void PushDescriptorTexelBufferGraphicsTestInstance::init (void)
2782{
2783	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
2784
2785	// Create color image
2786	{
2787
2788		const VkImageCreateInfo		colorImageParams		=
2789		{
2790			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
2791			DE_NULL,																// const void*				pNext;
2792			0u,																		// VkImageCreateFlags		flags;
2793			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
2794			m_colorFormat,															// VkFormat					format;
2795			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
2796			1u,																		// deUint32					mipLevels;
2797			1u,																		// deUint32					arrayLayers;
2798			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
2799			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
2800			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
2801			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
2802			1u,																		// deUint32					queueFamilyIndexCount;
2803			&m_queueFamilyIndex,													// const deUint32*			pQueueFamilyIndices;
2804			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
2805		};
2806
2807		m_colorImage			= createImage(m_vkd, *m_device, &colorImageParams);
2808
2809		// Allocate and bind color image memory
2810		m_colorImageAlloc		= m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
2811		VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
2812	}
2813
2814	// Create color attachment view
2815	{
2816		const VkImageViewCreateInfo colorAttachmentViewParams =
2817		{
2818			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType				sType;
2819			DE_NULL,										// const void*					pNext;
2820			0u,												// VkImageViewCreateFlags		flags;
2821			*m_colorImage,									// VkImage						image;
2822			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType				viewType;
2823			m_colorFormat,									// VkFormat						format;
2824			componentMappingRGBA,							// VkChannelMapping				channels;
2825			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange		subresourceRange;
2826		};
2827
2828		m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
2829	}
2830
2831	// Create buffers
2832	VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
2833	for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
2834	{
2835		const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
2836
2837		VkBufferCreateInfo	bufferCreateInfo
2838		{
2839			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
2840			DE_NULL,								// const void*			pNext;
2841			0u,										// VkBufferCreateFlags	flags
2842			kSizeofVec4,							// VkDeviceSize			size;
2843			usageFlags,								// VkBufferUsageFlags	usage;
2844			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2845			1u,										// deUint32				queueFamilyCount;
2846			&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
2847		};
2848
2849		if (m_params.useMaintenance5)
2850		{
2851			bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)usageFlags;
2852			bufferCreateInfo.pNext = &bufferUsageFlags2;
2853			bufferCreateInfo.usage = 0;
2854		}
2855
2856		m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
2857		m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
2858		VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
2859
2860		deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], static_cast<size_t>(kSizeofVec4));
2861		flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
2862	}
2863
2864	// Create buffer views
2865	for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
2866	{
2867		const VkBufferViewCreateInfo bufferViewParams =
2868		{
2869			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType;
2870			DE_NULL,									// const void*				pNext;
2871			0u,											// VkBufferViewCreateFlags	flags;
2872			**m_buffers[bufIdx],						// VkBuffer					buffer;
2873			m_bufferFormat,								// VkFormat					format;
2874			0u,											// VkDeviceSize				offset;
2875			VK_WHOLE_SIZE								// VkDeviceSize				range;
2876		};
2877
2878		m_bufferViews.push_back(VkBufferViewSp(new Unique<VkBufferView>(createBufferView(m_vkd, *m_device, &bufferViewParams))));
2879	}
2880
2881	// Create render pass
2882	m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, m_colorFormat);
2883
2884	// Create framebuffer
2885	{
2886		const VkImageView				attachmentBindInfos[]	=
2887		{
2888			*m_colorAttachmentView
2889		};
2890
2891		const VkFramebufferCreateInfo	framebufferParams		=
2892		{
2893			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
2894			DE_NULL,									// const void*				pNext;
2895			0u,											// VkFramebufferCreateFlags	flags;
2896			*m_renderPass,								// VkRenderPass				renderPass;
2897			1u,											// deUint32					attachmentCount;
2898			attachmentBindInfos,						// const VkImageView*		pAttachments;
2899			(deUint32)m_renderSize.x(),					// deUint32					width;
2900			(deUint32)m_renderSize.y(),					// deUint32					height;
2901			1u											// deUint32					layers;
2902		};
2903
2904		m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
2905	}
2906
2907	// Create pipeline layout
2908	{
2909		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
2910		{
2911			m_params.binding,				// uint32_t				binding;
2912			m_params.descriptorType,		// VkDescriptorType		descriptorType;
2913			1u,								// uint32_t				descriptorCount;
2914			VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
2915			DE_NULL							// const VkSampler*		pImmutableSamplers;
2916		};
2917
2918		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
2919		{
2920			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
2921			DE_NULL,													// const void*							pNext;
2922			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
2923			1u,															// uint32_t								bindingCount;
2924			&descriptorSetLayoutBinding									// const VkDescriptorSetLayoutBinding*	pBindings;
2925		};
2926
2927		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
2928
2929		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
2930		VkPipelineLayoutCreateInfo	pipelineLayoutParams
2931		{
2932			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
2933			DE_NULL,										// const void*					pNext;
2934			pipelineLayoutFlags,							// VkPipelineLayoutCreateFlags	flags;
2935			0u,												// deUint32						setLayoutCount;
2936			DE_NULL,										// const VkDescriptorSetLayout*	pSetLayouts;
2937			0u,												// deUint32						pushConstantRangeCount;
2938			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
2939		};
2940
2941		m_preRasterizationStatePipelineLayout	= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
2942		pipelineLayoutParams.setLayoutCount		= 1u;
2943		pipelineLayoutParams.pSetLayouts		= &(*m_descriptorSetLayout);
2944		m_fragmentStatePipelineLayout			= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
2945	}
2946
2947	// Create shaders
2948	{
2949		m_vertexShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
2950		m_fragmentShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
2951	}
2952
2953	// Create pipeline
2954	{
2955		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
2956		{
2957			0u,							// deUint32					binding;
2958			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
2959			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
2960		};
2961
2962		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[]	=
2963		{
2964			{
2965				0u,									// deUint32	location;
2966				0u,									// deUint32	binding;
2967				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2968				0u									// deUint32	offsetInBytes;
2969			},
2970			{
2971				1u,									// deUint32	location;
2972				0u,									// deUint32	binding;
2973				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2974				DE_OFFSET_OF(Vertex4RGBA, color)	// deUint32	offset;
2975			}
2976		};
2977
2978		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
2979		{
2980			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
2981			DE_NULL,													// const void*								pNext;
2982			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
2983			1u,															// deUint32									bindingCount;
2984			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2985			2u,															// deUint32									attributeCount;
2986			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2987		};
2988
2989		const vector<VkViewport>					viewports			{ makeViewport(m_renderSize) };
2990		const vector<VkRect2D>						scissors			{ makeRect2D(m_renderSize) };
2991
2992		m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
2993						  .setDefaultRasterizationState()
2994						  .setDefaultDepthStencilState()
2995						  .setDefaultMultisampleState()
2996						  .setDefaultColorBlendState()
2997						  .setupVertexInputState(&vertexInputStateParams)
2998						  .setupPreRasterizationShaderState(viewports,
2999															scissors,
3000															m_preRasterizationStatePipelineLayout,
3001															*m_renderPass,
3002															0u,
3003															m_vertexShaderModule)
3004						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
3005						  .setupFragmentOutputState(*m_renderPass)
3006						  .buildPipeline();
3007	}
3008
3009	// Create vertex buffer
3010	{
3011		const VkBufferCreateInfo vertexBufferParams =
3012		{
3013			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
3014			DE_NULL,													// const void*			pNext;
3015			0u,															// VkBufferCreateFlags	flags;
3016			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
3017			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
3018			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
3019			1u,															// deUint32				queueFamilyCount;
3020			&m_queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
3021		};
3022
3023		m_vertexBuffer		= createBuffer(m_vkd, *m_device, &vertexBufferParams);
3024		m_vertexBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
3025
3026		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
3027
3028		// Load vertices into vertex buffer
3029		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
3030		flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
3031	}
3032
3033	// Create command pool
3034	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3035
3036	// Create command buffer
3037	{
3038		const VkClearValue	attachmentClearValue	= defaultClearValue(m_colorFormat);
3039		const VkDeviceSize	vertexBufferOffset		= 0;
3040
3041		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3042		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
3043		m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
3044		m_graphicsPipeline.bind(*m_cmdBuffer);
3045		m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
3046
3047		// Draw quads. Switch buffer view between draws.
3048		for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
3049		{
3050			VkWriteDescriptorSet	writeDescriptorSet	=
3051			{
3052				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
3053				DE_NULL,								// const void*						pNext;
3054				0u,										// VkDescriptorSet					dstSet;
3055				m_params.binding,						// uint32_t							dstBinding;
3056				0u,										// uint32_t							dstArrayElement;
3057				1u,										// uint32_t							descriptorCount;
3058				m_params.descriptorType,				// VkDescriptorType					descriptorType;
3059				DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
3060				DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo;
3061				&m_bufferViews[quadNdx]->get()			// const VkBufferView*				pTexelBufferView;
3062			};
3063
3064			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1u, &writeDescriptorSet);
3065			m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
3066		}
3067
3068		m_renderPass.end(m_vkd, *m_cmdBuffer);
3069		endCommandBuffer(m_vkd, *m_cmdBuffer);
3070	}
3071}
3072
3073PushDescriptorTexelBufferGraphicsTestInstance::~PushDescriptorTexelBufferGraphicsTestInstance (void)
3074{
3075}
3076
3077tcu::TestStatus PushDescriptorTexelBufferGraphicsTestInstance::iterate (void)
3078{
3079	init();
3080
3081	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
3082
3083	return verifyImage();
3084}
3085
3086tcu::TestStatus PushDescriptorTexelBufferGraphicsTestInstance::verifyImage (void)
3087{
3088	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
3089	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
3090	const ColorVertexShader		vertexShader;
3091	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
3092	const rr::Program			program			(&vertexShader, &fragmentShader);
3093	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
3094	bool						compareOk		= false;
3095
3096	// Render reference image
3097	{
3098		for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
3099			for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
3100				m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = defaultTestColors[quadIdx];
3101
3102		refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
3103						 rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
3104	}
3105
3106	// Compare result with reference image
3107	{
3108		de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
3109
3110		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
3111															  "IntImageCompare",
3112															  "Image comparison",
3113															  refRenderer.getAccess(),
3114															  result->getAccess(),
3115															  tcu::UVec4(2, 2, 2, 2),
3116															  tcu::IVec3(1, 1, 0),
3117															  true,
3118															  tcu::COMPARE_LOG_RESULT);
3119	}
3120
3121	if (compareOk)
3122		return tcu::TestStatus::pass("Result image matches reference");
3123	else
3124		return tcu::TestStatus::fail("Image mismatch");
3125}
3126
3127class PushDescriptorTexelBufferGraphicsTest : public vkt::TestCase
3128{
3129public:
3130						PushDescriptorTexelBufferGraphicsTest	(tcu::TestContext&	testContext,
3131																 const string&		name,
3132																 const TestParams&	params);
3133						~PushDescriptorTexelBufferGraphicsTest	(void);
3134
3135	void				checkSupport						(Context& context) const;
3136	void				initPrograms						(SourceCollections& sourceCollections) const;
3137	TestInstance*		createInstance						(Context& context) const;
3138
3139protected:
3140	const TestParams	m_params;
3141};
3142
3143PushDescriptorTexelBufferGraphicsTest::PushDescriptorTexelBufferGraphicsTest	(tcu::TestContext&	testContext,
3144																				 const string&		name,
3145																				 const TestParams&	params)
3146	: vkt::TestCase	(testContext, name)
3147	, m_params		(params)
3148{
3149}
3150
3151PushDescriptorTexelBufferGraphicsTest::~PushDescriptorTexelBufferGraphicsTest (void)
3152{
3153}
3154
3155TestInstance* PushDescriptorTexelBufferGraphicsTest::createInstance (Context& context) const
3156{
3157	return new PushDescriptorTexelBufferGraphicsTestInstance(context, m_params);
3158}
3159
3160void PushDescriptorTexelBufferGraphicsTest::checkSupport(Context& context) const
3161{
3162	if (m_params.useMaintenance5)
3163		context.requireDeviceFunctionality("VK_KHR_maintenance5");
3164
3165	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
3166}
3167
3168void PushDescriptorTexelBufferGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
3169{
3170	const string	vertexSrc	=
3171		"#version 450\n"
3172		"layout(location = 0) in highp vec4 position;\n"
3173		"layout(location = 1) in highp vec4 texcoordVtx;\n"
3174		"layout(location = 0) out highp vec2 texcoordFrag;\n"
3175		"\n"
3176		"out gl_PerVertex { vec4 gl_Position; };\n"
3177		"\n"
3178		"void main()\n"
3179		"{\n"
3180		"	gl_Position = position;\n"
3181		"	texcoordFrag = texcoordVtx.xy;\n"
3182		"}\n";
3183
3184	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
3185
3186	if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
3187	{
3188		const string	fragmentSrc	=
3189			"#version 450\n"
3190			"layout(location = 0) in highp vec2 texcoordFrag;\n"
3191			"layout(location = 0) out highp vec4 fragColor;\n"
3192			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform textureBuffer texelBuffer;\n"
3193			"\n"
3194			"void main (void)\n"
3195			"{\n"
3196			"	fragColor = texelFetch(texelBuffer, 0);\n"
3197			"}\n";
3198
3199		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
3200	}
3201	else
3202	{
3203		DE_ASSERT(m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
3204		const string	fragmentSrc	=
3205			"#version 450\n"
3206			"layout(location = 0) in highp vec2 texcoordFrag;\n"
3207			"layout(location = 0) out highp vec4 fragColor;\n"
3208			"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba32f) uniform readonly imageBuffer texelBuffer;\n"
3209			"\n"
3210			"void main (void)\n"
3211			"{\n"
3212			"	fragColor = imageLoad(texelBuffer, 0);\n"
3213			"}\n";
3214
3215		sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
3216	}
3217}
3218
3219class PushDescriptorTexelBufferComputeTestInstance : public vkt::TestInstance
3220{
3221public:
3222								PushDescriptorTexelBufferComputeTestInstance	(Context& context, const TestParams& params);
3223	virtual						~PushDescriptorTexelBufferComputeTestInstance	(void);
3224	void						init											(void);
3225	virtual tcu::TestStatus		iterate											(void);
3226	tcu::TestStatus				verifyOutput									(void);
3227
3228private:
3229	const TestParams			m_params;
3230	const PlatformInterface&	m_vkp;
3231	const Extensions			m_instanceExtensions;
3232	const CustomInstance		m_instance;
3233	const InstanceDriver&		m_vki;
3234	const VkPhysicalDevice		m_physicalDevice;
3235	const deUint32				m_queueFamilyIndex;
3236	const Extensions			m_deviceExtensions;
3237	std::vector<std::string>	m_deviceEnabledExtensions;
3238	const Unique<VkDevice>		m_device;
3239	const DeviceDriver			m_vkd;
3240	const VkQueue				m_queue;
3241	const VkDeviceSize			m_itemSize;
3242	SimpleAllocator				m_allocator;
3243	vector<VkBufferSp>			m_buffers;
3244	vector<AllocationSp>		m_bufferAllocs;
3245	vector<VkBufferViewSp>		m_bufferViews;
3246	const VkFormat				m_bufferFormat;
3247	Move<VkShaderModule>		m_computeShaderModule;
3248	Move<VkBuffer>				m_outputBuffer;
3249	de::MovePtr<Allocation>		m_outputBufferAlloc;
3250	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
3251	Move<VkPipelineLayout>		m_pipelineLayout;
3252	Move<VkPipeline>			m_computePipeline;
3253	Move<VkCommandPool>			m_cmdPool;
3254	Move<VkCommandBuffer>		m_cmdBuffer;
3255};
3256
3257PushDescriptorTexelBufferComputeTestInstance::PushDescriptorTexelBufferComputeTestInstance (Context& context, const TestParams& params)
3258	: vkt::TestInstance		(context)
3259	, m_params				(params)
3260	, m_vkp					(context.getPlatformInterface())
3261	, m_instanceExtensions	(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
3262	, m_instance			(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
3263	, m_vki					(m_instance.getDriver())
3264	, m_physicalDevice		(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
3265	, m_queueFamilyIndex	(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT))
3266	, m_deviceExtensions	(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
3267	, m_device				(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
3268	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
3269	, m_queue				(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
3270	, m_itemSize			(calcItemSize(m_vki, m_physicalDevice))
3271	, m_allocator			(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
3272	, m_bufferFormat		(VK_FORMAT_R32G32B32A32_SFLOAT)
3273{
3274}
3275
3276void PushDescriptorTexelBufferComputeTestInstance::init (void)
3277{
3278	// Create buffers
3279	for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
3280	{
3281		const VkBufferUsageFlags	usageFlags			= m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
3282
3283		const VkBufferCreateInfo	bufferCreateInfo	=
3284		{
3285			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
3286			DE_NULL,								// const void*			pNext;
3287			0u,										// VkBufferCreateFlags	flags
3288			kSizeofVec4,							// VkDeviceSize			size;
3289			usageFlags,								// VkBufferUsageFlags	usage;
3290			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
3291			1u,										// deUint32				queueFamilyCount;
3292			&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
3293		};
3294
3295		m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
3296		m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
3297		VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
3298
3299		deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], static_cast<size_t>(kSizeofVec4));
3300		flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
3301	}
3302
3303	// Create buffer views
3304	for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
3305	{
3306		const VkBufferViewCreateInfo bufferViewParams =
3307		{
3308			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType;
3309			DE_NULL,									// const void*				pNext;
3310			0u,											// VkBufferViewCreateFlags	flags;
3311			**m_buffers[bufIdx],						// VkBuffer					buffer;
3312			m_bufferFormat,								// VkFormat					format;
3313			0u,											// VkDeviceSize				offset;
3314			VK_WHOLE_SIZE								// VkDeviceSize				range;
3315		};
3316
3317		m_bufferViews.push_back(VkBufferViewSp(new Unique<VkBufferView>(createBufferView(m_vkd, *m_device, &bufferViewParams))));
3318	}
3319
3320	// Create pipeline layout
3321	{
3322		vector<VkDescriptorSetLayoutBinding>	layoutBindings;
3323
3324		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBindings[]		=
3325		{
3326			{
3327				m_params.binding,				// uint32_t				binding;
3328				m_params.descriptorType,		// VkDescriptorType		descriptorType;
3329				1u,								// uint32_t				descriptorCount;
3330				VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags	stageFlags;
3331				DE_NULL							// const VkSampler*		pImmutableSamplers;
3332			},
3333			{
3334				m_params.binding + 1,				// uint32_t				binding;
3335				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	// VkDescriptorType		descriptorType;
3336				1u,									// uint32_t				descriptorCount;
3337				VK_SHADER_STAGE_COMPUTE_BIT,		// VkShaderStageFlags	stageFlags;
3338				DE_NULL								// const VkSampler*		pImmutableSamplers;
3339			}
3340		};
3341
3342		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
3343		{
3344			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
3345			DE_NULL,													// const void*							pNext;
3346			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
3347			2u,															// uint32_t								bindingCount;
3348			descriptorSetLayoutBindings									// const VkDescriptorSetLayoutBinding*	pBindings;
3349		};
3350
3351		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
3352
3353		const VkPipelineLayoutCreateInfo		pipelineLayoutParams			=
3354		{
3355			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
3356			DE_NULL,										// const void*					pNext;
3357			0u,												// VkPipelineLayoutCreateFlags	flags;
3358			1u,												// deUint32						descriptorSetCount;
3359			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
3360			0u,												// deUint32						pushConstantRangeCount;
3361			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
3362		};
3363
3364		m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
3365	}
3366
3367	// Create output buffer
3368	{
3369		DE_ASSERT(m_params.numCalls <= 2u);
3370
3371		const VkBufferCreateInfo bufferCreateInfo =
3372		{
3373			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
3374			DE_NULL,								// const void*			pNext;
3375			0u,										// VkBufferCreateFlags	flags
3376			m_itemSize * m_params.numCalls,			// VkDeviceSize			size;
3377			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags	usage;
3378			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
3379			1u,										// deUint32				queueFamilyCount;
3380			&m_queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
3381		};
3382
3383		m_outputBuffer		= createBuffer(m_vkd, *m_device, &bufferCreateInfo);
3384		m_outputBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer), MemoryRequirement::HostVisible);
3385		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
3386	}
3387
3388	// Create shader
3389	{
3390		m_computeShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
3391	}
3392
3393	// Create pipeline
3394	{
3395		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
3396		{
3397			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
3398			DE_NULL,												// const void*						pNext;
3399			0u,														// VkPipelineShaderStageCreateFlags	flags;
3400			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
3401			*m_computeShaderModule,									// VkShaderModule					module;
3402			"main",													// const char*						pName;
3403			DE_NULL													// const VkSpecializationInfo*		pSpecializationInfo;
3404		};
3405
3406		const VkComputePipelineCreateInfo		createInfo		=
3407		{
3408			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
3409			DE_NULL,												// const void*						pNext;
3410			0u,														// VkPipelineCreateFlags			flags;
3411			stageCreateInfo,										// VkPipelineShaderStageCreateInfo	stage;
3412			*m_pipelineLayout,										// VkPipelineLayout					layout;
3413			(VkPipeline)0,											// VkPipeline						basePipelineHandle;
3414			0u,														// int32_t							basePipelineIndex;
3415		};
3416
3417		m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
3418	}
3419
3420	// Create command pool
3421	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3422
3423	// Create command buffer
3424	{
3425		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3426		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
3427		m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
3428
3429		// Dispatch: Each dispatch switches the input image.
3430		// Output buffer is exposed as a vec4 sized window.
3431		for (deUint32 dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
3432		{
3433			VkWriteDescriptorSet	writeDescriptorSet	=
3434			{
3435				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
3436				DE_NULL,								// const void*						pNext;
3437				0u,										// VkDescriptorSet					dstSet;
3438				m_params.binding,						// uint32_t							dstBinding;
3439				0u,										// uint32_t							dstArrayElement;
3440				1u,										// uint32_t							descriptorCount;
3441				m_params.descriptorType,				// VkDescriptorType					descriptorType;
3442				DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
3443				DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo;
3444				&m_bufferViews[dispatchNdx]->get()		// const VkBufferView*				pTexelBufferView;
3445			};
3446
3447			vector<VkWriteDescriptorSet> writeDescriptorSets;
3448			writeDescriptorSets.push_back(writeDescriptorSet);
3449
3450			const VkDescriptorBufferInfo descriptorBufferInfoOutput	=
3451			{
3452				*m_outputBuffer,			// VkBuffer			buffer;
3453				m_itemSize * dispatchNdx,	// VkDeviceSize		offset;
3454				kSizeofVec4,				// VkDeviceSize		range;
3455			};
3456
3457			// Write output buffer descriptor set
3458			const VkWriteDescriptorSet	writeDescriptorSetOutput	=
3459			{
3460				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
3461				DE_NULL,								// const void*						pNext;
3462				0u,										// VkDescriptorSet					dstSet;
3463				m_params.binding + 1,					// uint32_t							dstBinding;
3464				0u,										// uint32_t							dstArrayElement;
3465				1u,										// uint32_t							descriptorCount;
3466				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// VkDescriptorType					descriptorType;
3467				DE_NULL,								// const VkDescriptorImageInfo*		pImageInfo;
3468				&descriptorBufferInfoOutput,			// const VkDescriptorBufferInfo*	pBufferInfo;
3469				DE_NULL									// const VkBufferView*				pTexelBufferView;
3470			};
3471
3472			writeDescriptorSets.push_back(writeDescriptorSetOutput);
3473
3474			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, (deUint32)writeDescriptorSets.size(), writeDescriptorSets.data());
3475			m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
3476		}
3477
3478		endCommandBuffer(m_vkd, *m_cmdBuffer);
3479	}
3480}
3481
3482PushDescriptorTexelBufferComputeTestInstance::~PushDescriptorTexelBufferComputeTestInstance (void)
3483{
3484}
3485
3486tcu::TestStatus PushDescriptorTexelBufferComputeTestInstance::iterate (void)
3487{
3488	init();
3489
3490	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
3491
3492	return verifyOutput();
3493}
3494
3495tcu::TestStatus PushDescriptorTexelBufferComputeTestInstance::verifyOutput (void)
3496{
3497	const tcu::Vec4 ref[2] = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
3498	invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
3499
3500	// Verify result
3501	DE_ASSERT(m_params.numCalls <= 2u);
3502
3503	auto bufferPtr = reinterpret_cast<const char*>(m_outputBufferAlloc->getHostPtr());
3504	for (deUint32 i = 0; i < m_params.numCalls; ++i)
3505	{
3506		tcu::Vec4 bufferColor;
3507		deMemcpy(&bufferColor, bufferPtr + (i * m_itemSize), static_cast<size_t>(kSizeofVec4));
3508
3509		if (bufferColor != ref[i])
3510		{
3511			std::ostringstream msg;
3512			msg << "Output mismatch at item " << i << ": expected " << ref[i] << " but found " << bufferColor;
3513			TCU_FAIL(msg.str());
3514		}
3515	}
3516
3517	return tcu::TestStatus::pass("Output matches expected values");
3518}
3519
3520class PushDescriptorTexelBufferComputeTest : public vkt::TestCase
3521{
3522public:
3523						PushDescriptorTexelBufferComputeTest	(tcu::TestContext&	testContext,
3524																 const string&		name,
3525																 const TestParams&	params);
3526						~PushDescriptorTexelBufferComputeTest	(void);
3527	void				initPrograms							(SourceCollections& sourceCollections) const;
3528	TestInstance*		createInstance							(Context& context) const;
3529
3530protected:
3531	const TestParams	m_params;
3532};
3533
3534PushDescriptorTexelBufferComputeTest::PushDescriptorTexelBufferComputeTest	(tcu::TestContext&	testContext,
3535																			 const string&		name,
3536																			 const TestParams&	params)
3537	: vkt::TestCase	(testContext, name)
3538	, m_params		(params)
3539{
3540}
3541
3542PushDescriptorTexelBufferComputeTest::~PushDescriptorTexelBufferComputeTest (void)
3543{
3544}
3545
3546TestInstance* PushDescriptorTexelBufferComputeTest::createInstance (Context& context) const
3547{
3548	return new PushDescriptorTexelBufferComputeTestInstance(context, m_params);
3549}
3550
3551void PushDescriptorTexelBufferComputeTest::initPrograms (SourceCollections& sourceCollections) const
3552{
3553	if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
3554	{
3555		const string	computeSrc	=
3556			"#version 450\n"
3557			"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform textureBuffer texelBuffer;\n"
3558			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
3559			"{\n"
3560			"	vec4 color;\n"
3561			"} outData;\n"
3562			"\n"
3563			"void main()\n"
3564			"{\n"
3565			"	outData.color = texelFetch(texelBuffer, 0);\n"
3566			"}\n";
3567
3568		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
3569	}
3570	else
3571	{
3572		DE_ASSERT(m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
3573
3574		const string	computeSrc	=
3575			"#version 450\n"
3576			"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba32f) uniform readonly imageBuffer texelBuffer;\n"
3577			"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
3578			"{\n"
3579			"	vec4 color;\n"
3580			"} outData;\n"
3581			"\n"
3582			"void main()\n"
3583			"{\n"
3584			"	outData.color = imageLoad(texelBuffer, 0);\n"
3585			"}\n";
3586
3587		sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
3588	}
3589}
3590
3591class PushDescriptorInputAttachmentGraphicsTestInstance : public vkt::TestInstance
3592{
3593public:
3594								PushDescriptorInputAttachmentGraphicsTestInstance	(Context& context, const TestParams& params);
3595	virtual						~PushDescriptorInputAttachmentGraphicsTestInstance	(void);
3596	void						init												(void);
3597	virtual tcu::TestStatus		iterate												(void);
3598	tcu::TestStatus				verifyImage											(void);
3599
3600private:
3601	const TestParams				m_params;
3602	const PlatformInterface&		m_vkp;
3603	const Extensions				m_instanceExtensions;
3604	const CustomInstance			m_instance;
3605	const InstanceDriver&			m_vki;
3606	const VkPhysicalDevice			m_physicalDevice;
3607	const deUint32					m_queueFamilyIndex;
3608	const Extensions				m_deviceExtensions;
3609	std::vector<std::string>		m_deviceEnabledExtensions;
3610	const Unique<VkDevice>			m_device;
3611	const DeviceDriver				m_vkd;
3612	const VkQueue					m_queue;
3613	SimpleAllocator					m_allocator;
3614	const tcu::UVec2				m_renderSize;
3615	const tcu::UVec2				m_textureSize;
3616	const VkFormat					m_colorFormat;
3617	Move<VkImage>					m_colorImage;
3618	de::MovePtr<Allocation>			m_colorImageAlloc;
3619	Move<VkImageView>				m_colorAttachmentView;
3620	vector<VkImageSp>				m_inputImages;
3621	vector<AllocationSp>			m_inputImageAllocs;
3622	vector<VkImageViewSp>			m_inputImageViews;
3623	vector<VkRenderPassSp>			m_renderPasses;
3624	ShaderWrapper					m_vertexShaderModule;
3625	ShaderWrapper					m_fragmentShaderModule;
3626	Move<VkBuffer>					m_vertexBuffer;
3627	de::MovePtr<Allocation>			m_vertexBufferAlloc;
3628	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
3629	PipelineLayoutWrapper			m_preRasterizationStatePipelineLayout;
3630	PipelineLayoutWrapper			m_fragmentStatePipelineLayout;
3631	vector<GraphicsPipelineWrapper>	m_graphicsPipelines;
3632	Move<VkCommandPool>				m_cmdPool;
3633	Move<VkCommandBuffer>			m_cmdBuffer;
3634	vector<Vertex4Tex4>				m_vertices;
3635};
3636
3637PushDescriptorInputAttachmentGraphicsTestInstance::PushDescriptorInputAttachmentGraphicsTestInstance (Context& context, const TestParams& params)
3638	: vkt::TestInstance			(context)
3639	, m_params					(params)
3640	, m_vkp						(context.getPlatformInterface())
3641	, m_instanceExtensions		(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
3642	, m_instance				(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
3643	, m_vki						(m_instance.getDriver())
3644	, m_physicalDevice			(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
3645	, m_queueFamilyIndex		(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
3646	, m_deviceExtensions		(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
3647	, m_device					(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, params, m_deviceEnabledExtensions))
3648	, m_vkd					(m_vkp, m_instance, *m_device, context.getUsedApiVersion())
3649	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
3650	, m_allocator				(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
3651	, m_renderSize				(32, 32)
3652	, m_textureSize				(32, 32)
3653	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
3654	, m_vertices				(createTexQuads(params.numCalls, 0.25f))
3655{
3656}
3657
3658void PushDescriptorInputAttachmentGraphicsTestInstance::init (void)
3659{
3660	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
3661
3662	// Create color image
3663	{
3664
3665		const VkImageCreateInfo		colorImageParams		=
3666		{
3667			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
3668			DE_NULL,																// const void*				pNext;
3669			0u,																		// VkImageCreateFlags		flags;
3670			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
3671			m_colorFormat,															// VkFormat					format;
3672			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
3673			1u,																		// deUint32					mipLevels;
3674			1u,																		// deUint32					arrayLayers;
3675			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
3676			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
3677			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
3678			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
3679			1u,																		// deUint32					queueFamilyIndexCount;
3680			&m_queueFamilyIndex,													// const deUint32*			pQueueFamilyIndices;
3681			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
3682		};
3683
3684		m_colorImage		= createImage(m_vkd, *m_device, &colorImageParams);
3685
3686		// Allocate and bind color image memory
3687		m_colorImageAlloc	= m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
3688		VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
3689	}
3690
3691	// Create color attachment view
3692	{
3693		const VkImageViewCreateInfo colorAttachmentViewParams =
3694		{
3695			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
3696			DE_NULL,										// const void*				pNext;
3697			0u,												// VkImageViewCreateFlags	flags;
3698			*m_colorImage,									// VkImage					image;
3699			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
3700			m_colorFormat,									// VkFormat					format;
3701			componentMappingRGBA,							// VkChannelMapping			channels;
3702			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3703		};
3704
3705		m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
3706	}
3707
3708	// Create input images
3709	for (deUint32 imageIdx = 0; imageIdx < 2; imageIdx++)
3710	{
3711		const VkImageUsageFlags		usageFlags			= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3712
3713		const VkImageCreateInfo		inputImageParams	=
3714		{
3715			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
3716			DE_NULL,										// const void*				pNext;
3717			0u,												// VkImageCreateFlags		flags;
3718			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
3719			m_colorFormat,									// VkFormat					format;
3720			{ m_textureSize.x(), m_textureSize.y(), 1u },	// VkExtent3D				extent;
3721			1u,												// deUint32					mipLevels;
3722			1u,												// deUint32					arrayLayers;
3723			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
3724			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
3725			usageFlags,										// VkImageUsageFlags		usage;
3726			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
3727			1u,												// deUint32					queueFamilyIndexCount;
3728			&m_queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
3729			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
3730		};
3731
3732		m_inputImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &inputImageParams))));
3733
3734		// Allocate and bind image memory
3735		m_inputImageAllocs.push_back(AllocationSp(m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_inputImages.back()), MemoryRequirement::Any).release()));
3736		VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_inputImages.back(), m_inputImageAllocs.back()->getMemory(), m_inputImageAllocs.back()->getOffset()));
3737	}
3738
3739	// Create texture image views
3740	for (deUint32 imageIdx = 0; imageIdx < 2; imageIdx++)
3741	{
3742		const VkImageViewCreateInfo textureViewParams =
3743		{
3744			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
3745			DE_NULL,										// const void*				pNext;
3746			0u,												// VkImageViewCreateFlags	flags;
3747			**m_inputImages[imageIdx],						// VkImage					image;
3748			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
3749			m_colorFormat,									// VkFormat					format;
3750			componentMappingRGBA,							// VkChannelMapping			channels;
3751			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3752		};
3753
3754		m_inputImageViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
3755	}
3756
3757	VkClearValue clearValues[2];
3758	clearValues[0].color.float32[0] = 0.0f;
3759	clearValues[0].color.float32[1] = 1.0f;
3760	clearValues[0].color.float32[2] = 0.0f;
3761	clearValues[0].color.float32[3] = 1.0f;
3762	clearValues[1].color.float32[0] = 1.0f;
3763	clearValues[1].color.float32[1] = 0.0f;
3764	clearValues[1].color.float32[2] = 0.0f;
3765	clearValues[1].color.float32[3] = 1.0f;
3766
3767	// Clear input images
3768	for (deUint32 imageIdx = 0; imageIdx < 2; imageIdx++)
3769	{
3770		const VkImageAspectFlags	aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3771		Move<VkCommandPool>			cmdPool;
3772		Move<VkCommandBuffer>		cmdBuffer;
3773		const VkAccessFlags			accessFlags	= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
3774
3775		cmdPool		= createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3776		cmdBuffer	= allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3777
3778		const VkImageMemoryBarrier preImageBarrier =
3779		{
3780			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
3781			DE_NULL,								// const void*				pNext;
3782			0u,										// VkAccessFlags			srcAccessMask;
3783			VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
3784			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
3785			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
3786			VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
3787			VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
3788			**m_inputImages[imageIdx],				// VkImage					image;
3789			{										// VkImageSubresourceRange	subresourceRange;
3790				aspectMask,							// VkImageAspect			aspect;
3791				0u,									// deUint32					baseMipLevel;
3792				1u,									// deUint32					mipLevels;
3793				0u,									// deUint32					baseArraySlice;
3794				1u									// deUint32					arraySize;
3795			}
3796		};
3797
3798		const VkImageMemoryBarrier postImageBarrier =
3799		{
3800			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
3801			DE_NULL,									// const void*				pNext;
3802			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
3803			accessFlags,								// VkAccessFlags			dstAccessMask;
3804			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
3805			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout			newLayout;
3806			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
3807			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
3808			**m_inputImages[imageIdx],					// VkImage					image;
3809			{											// VkImageSubresourceRange	subresourceRange;
3810				aspectMask,								// VkImageAspect			aspect;
3811				0u,										// deUint32					baseMipLevel;
3812				1u,										// deUint32					mipLevels;
3813				0u,										// deUint32					baseArraySlice;
3814				1u										// deUint32					arraySize;
3815			}
3816		};
3817
3818		const VkImageSubresourceRange clearRange	=
3819		{
3820			aspectMask,	// VkImageAspectFlags	aspectMask;
3821			0u,			// deUint32				baseMipLevel;
3822			1u,			// deUint32				levelCount;
3823			0u,			// deUint32				baseArrayLayer;
3824			1u			// deUint32				layerCount;
3825		};
3826
3827		beginCommandBuffer(m_vkd, *cmdBuffer);
3828		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
3829		m_vkd.cmdClearColorImage(*cmdBuffer, **m_inputImages[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValues[imageIdx].color, 1, &clearRange);
3830		m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3831		endCommandBuffer(m_vkd, *cmdBuffer);
3832
3833		submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
3834	}
3835
3836	// Create render passes
3837	for (deUint32 renderPassIdx = 0; renderPassIdx < 2; renderPassIdx++)
3838	{
3839		// The first pass clears the output image, and the second one draws on top of the first pass.
3840		const VkAttachmentLoadOp		loadOps[]					=
3841		{
3842			VK_ATTACHMENT_LOAD_OP_CLEAR,
3843			VK_ATTACHMENT_LOAD_OP_LOAD
3844		};
3845
3846		const VkImageLayout				initialLayouts[]			=
3847		{
3848			VK_IMAGE_LAYOUT_UNDEFINED,
3849			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
3850		};
3851
3852		const VkAttachmentDescription	attachmentDescriptions[]	=
3853		{
3854			// Result attachment
3855			{
3856				(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
3857				VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat						format
3858				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
3859				loadOps[renderPassIdx],						// VkAttachmentLoadOp			loadOp
3860				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
3861				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
3862				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
3863				initialLayouts[renderPassIdx],				// VkImageLayout				initialLayout
3864				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
3865			},
3866			// Input attachment
3867			{
3868				(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
3869				VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat						format
3870				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
3871				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp			loadOp
3872				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
3873				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
3874				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
3875				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout				initialLayout
3876				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout				finalLayout
3877			}
3878		};
3879
3880		const VkAttachmentReference		resultAttachmentRef		=
3881		{
3882			0u,											// deUint32			attachment
3883			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
3884		};
3885
3886		const VkAttachmentReference		inputAttachmentRef		=
3887		{
3888			1u,											// deUint32			attachment
3889			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	layout
3890		};
3891
3892		const VkSubpassDescription		subpassDescription		=
3893		{
3894			(VkSubpassDescriptionFlags)0,				// VkSubpassDescriptionFlags	flags
3895			VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint			pipelineBindPoint
3896			1u,											// deUint32						inputAttachmentCount
3897			&inputAttachmentRef,							// const VkAttachmentReference*	pInputAttachments
3898			1u,											// deUint32						colorAttachmentCount
3899			&resultAttachmentRef,						// const VkAttachmentReference*	pColorAttachments
3900			DE_NULL,									// const VkAttachmentReference*	pResolveAttachments
3901			DE_NULL,									// const VkAttachmentReference*	pDepthStencilAttachment
3902			0u,											// deUint32						preserveAttachmentCount
3903			DE_NULL										// const deUint32*				pPreserveAttachments
3904		};
3905
3906		const VkSubpassDependency		subpassDependency		=
3907		{
3908			VK_SUBPASS_EXTERNAL,							// deUint32				srcSubpass
3909			0,												// deUint32				dstSubpass
3910			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags	srcStageMask
3911			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags	dstStageMask
3912			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags		srcAccessMask
3913			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT,	//	dstAccessMask
3914			VK_DEPENDENCY_BY_REGION_BIT						// VkDependencyFlags	dependencyFlags
3915		};
3916
3917		const VkRenderPassCreateInfo	renderPassInfo			=
3918		{
3919			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureTypei					sType
3920			DE_NULL,									// const void*						pNext
3921			(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
3922			2u,											// deUint32							attachmentCount
3923			attachmentDescriptions,						// const VkAttachmentDescription*	pAttachments
3924			1u,											// deUint32							subpassCount
3925			&subpassDescription,						// const VkSubpassDescription*		pSubpasses
3926			1u,											// deUint32							dependencyCount
3927			&subpassDependency							// const VkSubpassDependency*		pDependencies
3928		};
3929
3930		m_renderPasses.push_back(VkRenderPassSp(new RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &renderPassInfo)));
3931
3932		std::vector<VkImage>			images					=
3933		{
3934			*m_colorImage,
3935			**m_inputImages[renderPassIdx],
3936		};
3937
3938		const VkImageView				attachmentBindInfos[]	=
3939		{
3940			*m_colorAttachmentView,
3941			**m_inputImageViews[renderPassIdx],
3942		};
3943
3944		const VkFramebufferCreateInfo	framebufferParams		=
3945		{
3946			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
3947			DE_NULL,									// const void*				pNext;
3948			0u,											// VkFramebufferCreateFlags	flags;
3949			**m_renderPasses[renderPassIdx],			// VkRenderPass				renderPass;
3950			2u,											// deUint32					attachmentCount;
3951			attachmentBindInfos,						// const VkImageView*		pAttachments;
3952			(deUint32)m_renderSize.x(),					// deUint32					width;
3953			(deUint32)m_renderSize.y(),					// deUint32					height;
3954			1u											// deUint32					layers;
3955		};
3956
3957		m_renderPasses[renderPassIdx]->createFramebuffer(m_vkd, *m_device, &framebufferParams, images);
3958	}
3959
3960	// Create pipeline layout
3961	{
3962		// Create descriptor set layout
3963		const VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding		=
3964		{
3965			m_params.binding,						// uint32_t				binding;
3966			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		descriptorType;
3967			1u,										// uint32_t				descriptorCount;
3968			VK_SHADER_STAGE_FRAGMENT_BIT,			// VkShaderStageFlags	stageFlags;
3969			DE_NULL									// const VkSampler*		pImmutableSamplers;
3970		};
3971
3972		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutCreateInfo	=
3973		{
3974			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType;
3975			DE_NULL,													// const void*							pNext;
3976			VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,	// VkDescriptorSetLayoutCreateFlags		flags;
3977			1u,															// uint32_t								bindingCount;
3978			&descriptorSetLayoutBinding									// const VkDescriptorSetLayoutBinding*	pBindings;
3979		};
3980
3981		m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
3982
3983		// Create pipeline layout
3984		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
3985		VkPipelineLayoutCreateInfo	pipelineLayoutParams
3986		{
3987			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
3988			DE_NULL,										// const void*					pNext;
3989			pipelineLayoutFlags,							// VkPipelineLayoutCreateFlags	flags;
3990			0u,												// deUint32						setLayoutCount;
3991			DE_NULL,										// const VkDescriptorSetLayout*	pSetLayouts;
3992			0u,												// deUint32						pushConstantRangeCount;
3993			DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
3994		};
3995
3996		m_preRasterizationStatePipelineLayout	= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
3997		pipelineLayoutParams.setLayoutCount		= 1u;
3998		pipelineLayoutParams.pSetLayouts		= &(*m_descriptorSetLayout);
3999		m_fragmentStatePipelineLayout			= PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
4000	}
4001
4002	// Create shaders
4003	{
4004		m_vertexShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
4005		m_fragmentShaderModule	= ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
4006	}
4007
4008	m_graphicsPipelines.reserve(2);
4009
4010	// Create pipelines
4011	for (deUint32 pipelineIdx = 0; pipelineIdx < 2; pipelineIdx++)
4012	{
4013		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
4014		{
4015			0u,							// deUint32					binding;
4016			sizeof(Vertex4Tex4),		// deUint32					strideInBytes;
4017			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
4018		};
4019
4020		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[]	=
4021		{
4022			{
4023				0u,										// deUint32	location;
4024				0u,										// deUint32	binding;
4025				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
4026				0u										// deUint32	offsetInBytes;
4027			},
4028			{
4029				1u,										// deUint32	location;
4030				0u,										// deUint32	binding;
4031				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
4032				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
4033			}
4034		};
4035
4036		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
4037		{
4038			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
4039			DE_NULL,													// const void*								pNext;
4040			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
4041			1u,															// deUint32									bindingCount;
4042			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
4043			2u,															// deUint32									attributeCount;
4044			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4045		};
4046
4047		const vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
4048		const vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
4049
4050		m_graphicsPipelines.emplace_back(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions, m_params.pipelineConstructionType);
4051		m_graphicsPipelines.back().setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
4052								  .setDefaultRasterizationState()
4053								  .setDefaultDepthStencilState()
4054								  .setDefaultMultisampleState()
4055								  .setDefaultColorBlendState()
4056								  .setupVertexInputState(&vertexInputStateParams)
4057								  .setupPreRasterizationShaderState(viewports,
4058																	scissors,
4059																	m_preRasterizationStatePipelineLayout,
4060																	**m_renderPasses[pipelineIdx],
4061																	0u,
4062																	m_vertexShaderModule)
4063								  .setupFragmentShaderState(m_fragmentStatePipelineLayout, **m_renderPasses[pipelineIdx], 0u, m_fragmentShaderModule)
4064								  .setupFragmentOutputState(**m_renderPasses[pipelineIdx])
4065								  .buildPipeline();
4066	}
4067
4068	// Create vertex buffer
4069	{
4070		const VkBufferCreateInfo vertexBufferParams =
4071		{
4072			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
4073			DE_NULL,													// const void*			pNext;
4074			0u,															// VkBufferCreateFlags	flags;
4075			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
4076			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
4077			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
4078			1u,															// deUint32				queueFamilyCount;
4079			&m_queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
4080		};
4081
4082		m_vertexBuffer		= createBuffer(m_vkd, *m_device, &vertexBufferParams);
4083		m_vertexBufferAlloc	= m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
4084
4085		VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
4086
4087		// Load vertices into vertex buffer
4088		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4Tex4));
4089		flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
4090	}
4091
4092	// Create command pool
4093	m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
4094
4095	// Create command buffer
4096	{
4097		const VkClearValue	attachmentClearValue	= defaultClearValue(m_colorFormat);
4098		const VkDeviceSize	vertexBufferOffset		= 0;
4099
4100		m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4101		beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
4102		for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
4103		{
4104			(*m_renderPasses[quadNdx]).begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
4105			m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
4106			m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4107
4108			VkDescriptorImageInfo	descriptorImageInfo	=
4109			{
4110				0,											// VkSampler		sampler;
4111				**m_inputImageViews[quadNdx],				// VkImageView		imageView;
4112				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
4113			};
4114
4115			VkWriteDescriptorSet	writeDescriptorSet	=
4116			{
4117				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType;
4118				DE_NULL,								// const void*						pNext;
4119				0u,										// VkDescriptorSet					dstSet;
4120				m_params.binding,						// uint32_t							dstBinding;
4121				0u,										// uint32_t							dstArrayElement;
4122				1u,										// uint32_t							descriptorCount;
4123				m_params.descriptorType,				// VkDescriptorType					descriptorType;
4124				&descriptorImageInfo,					// const VkDescriptorImageInfo*		pImageInfo;
4125				DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo;
4126				DE_NULL									// const VkBufferView*				pTexelBufferView;
4127			};
4128
4129			m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1, &writeDescriptorSet);
4130			m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
4131
4132			(*m_renderPasses[quadNdx]).end(m_vkd, *m_cmdBuffer);
4133		}
4134
4135		endCommandBuffer(m_vkd, *m_cmdBuffer);
4136	}
4137}
4138
4139PushDescriptorInputAttachmentGraphicsTestInstance::~PushDescriptorInputAttachmentGraphicsTestInstance (void)
4140{
4141}
4142
4143tcu::TestStatus PushDescriptorInputAttachmentGraphicsTestInstance::iterate (void)
4144{
4145	init();
4146
4147	submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
4148
4149	return verifyImage();
4150}
4151
4152tcu::TestStatus PushDescriptorInputAttachmentGraphicsTestInstance::verifyImage (void)
4153{
4154	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
4155	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
4156	const ColorVertexShader		vertexShader;
4157	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
4158	const rr::Program			program			(&vertexShader, &fragmentShader);
4159	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
4160	bool						compareOk		= false;
4161
4162	// Render reference image
4163	{
4164		vector<Vertex4RGBA>	refQuads = createQuads(m_params.numCalls, 0.25f);
4165		tcu::Vec4			colors[2];
4166
4167		colors[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
4168		colors[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
4169
4170		for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
4171			for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
4172			{
4173				const deUint32 idx = quadIdx * 6 + vertexIdx;
4174				refQuads[idx].color.xyzw() = colors[quadIdx];
4175			}
4176
4177		refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
4178						 rr::PRIMITIVETYPE_TRIANGLES, refQuads);
4179	}
4180
4181	// Compare result with reference image
4182	{
4183		de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
4184
4185		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
4186															  "IntImageCompare",
4187															  "Image comparison",
4188															  refRenderer.getAccess(),
4189															  result->getAccess(),
4190															  tcu::UVec4(2, 2, 2, 2),
4191															  tcu::IVec3(1, 1, 0),
4192															  true,
4193															  tcu::COMPARE_LOG_RESULT);
4194	}
4195
4196	if (compareOk)
4197		return tcu::TestStatus::pass("Result image matches reference");
4198	else
4199		return tcu::TestStatus::fail("Image mismatch");
4200}
4201
4202class PushDescriptorInputAttachmentGraphicsTest : public vkt::TestCase
4203{
4204public:
4205						PushDescriptorInputAttachmentGraphicsTest		(tcu::TestContext&	testContext,
4206															 const string&		name,
4207															 const TestParams&	params);
4208						~PushDescriptorInputAttachmentGraphicsTest	(void);
4209
4210	void				checkSupport						(Context& context) const;
4211	void				initPrograms						(SourceCollections& sourceCollections) const;
4212	TestInstance*		createInstance						(Context& context) const;
4213
4214protected:
4215	const TestParams	m_params;
4216};
4217
4218PushDescriptorInputAttachmentGraphicsTest::PushDescriptorInputAttachmentGraphicsTest	(tcu::TestContext&	testContext,
4219																	const string&		name,
4220																	const TestParams&	params)
4221	: vkt::TestCase	(testContext, name)
4222	, m_params		(params)
4223{
4224}
4225
4226PushDescriptorInputAttachmentGraphicsTest::~PushDescriptorInputAttachmentGraphicsTest (void)
4227{
4228}
4229
4230TestInstance* PushDescriptorInputAttachmentGraphicsTest::createInstance (Context& context) const
4231{
4232	return new PushDescriptorInputAttachmentGraphicsTestInstance(context, m_params);
4233}
4234
4235void PushDescriptorInputAttachmentGraphicsTest::checkSupport(Context& context) const
4236{
4237	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
4238}
4239
4240void PushDescriptorInputAttachmentGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
4241{
4242	const string	vertexSrc	=
4243		"#version 450\n"
4244		"layout(location = 0) in highp vec4 position;\n"
4245		"layout(location = 1) in highp vec4 texcoordVtx;\n"
4246		"layout(location = 0) out highp vec2 texcoordFrag;\n"
4247		"\n"
4248		"out gl_PerVertex { vec4 gl_Position; };\n"
4249		"\n"
4250		"void main()\n"
4251		"{\n"
4252		"	gl_Position = position;\n"
4253		"	texcoordFrag = texcoordVtx.xy;\n"
4254		"}\n";
4255
4256	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
4257
4258	const string	fragmentSrc	=
4259		"#version 450\n"
4260		"layout(location = 0) in highp vec2 texcoordFrag;\n"
4261		"layout(location = 0) out highp vec4 fragColor;\n"
4262		"layout(input_attachment_index = 0, set = 0, binding = " + de::toString(m_params.binding) + ") uniform subpassInput inputColor;\n"
4263		"\n"
4264		"void main (void)\n"
4265		"{\n"
4266		"	fragColor = subpassLoad(inputColor);\n"
4267		"}\n";
4268
4269	sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
4270}
4271
4272} // anonymous
4273
4274tcu::TestCaseGroup* createPushDescriptorTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineType)
4275{
4276	const TestParams params[]
4277	{
4278		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,				0u, 1u,		false },
4279		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,				0u, 2u,		false },
4280		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,				1u, 2u,		false },
4281		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,				3u, 2u,		false },
4282		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,				0u, 1u,		false },
4283		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,				0u, 2u,		false },
4284		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,				1u, 2u,		false },
4285		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,				3u, 2u,		false },
4286		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,				1u, 128u,	false },
4287		{ pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,		0u, 1u,		false },
4288		{ pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,		0u, 2u,		false },
4289		{ pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,		1u, 2u,		false },
4290		{ pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,		3u, 2u,		false },
4291		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER,						0u, 1u,		false },
4292		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER,						0u, 2u,		false },
4293		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER,						1u, 2u,		false },
4294		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER,						3u, 2u,		false },
4295		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				0u, 1u,		false },
4296		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				0u, 2u,		false },
4297		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				1u, 2u,		false },
4298		{ pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				3u, 2u,		false },
4299		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				0u, 1u,		false },
4300		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				0u, 2u,		false },
4301		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				1u, 2u,		false },
4302		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				3u, 2u,		false },
4303		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		0u, 1u,		false },
4304		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		0u, 2u,		false },
4305		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		1u, 2u,		false },
4306		{ pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		3u, 2u,		false },
4307		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		0u, 1u,		false },
4308		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		0u, 2u,		false },
4309		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		1u, 2u,		false },
4310		{ pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		3u, 2u,		false },
4311		{ pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			0u, 1u,		false },
4312		{ pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			0u, 2u,		false },
4313		{ pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			1u, 2u,		false },
4314		{ pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			3u, 2u,		false }
4315	};
4316
4317	de::MovePtr<tcu::TestCaseGroup>	pushDescriptorTests	(new tcu::TestCaseGroup(testCtx, "push_descriptor"));
4318
4319	de::MovePtr<tcu::TestCaseGroup>	graphicsTests		(new tcu::TestCaseGroup(testCtx, "graphics"));
4320	de::MovePtr<tcu::TestCaseGroup>	computeTests		(new tcu::TestCaseGroup(testCtx, "compute"));
4321
4322	for (deUint32 testIdx = 0; testIdx < DE_LENGTH_OF_ARRAY(params); testIdx++)
4323	{
4324		string testName;
4325		testName += "binding" + de::toString(params[testIdx].binding) + "_numcalls" + de::toString(params[testIdx].numCalls);
4326		switch(params[testIdx].descriptorType)
4327		{
4328			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
4329				testName += "_uniform_buffer";
4330				if (params[testIdx].numCalls <= 2)
4331					graphicsTests->addChild(new PushDescriptorBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4332				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4333					computeTests->addChild(new PushDescriptorBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4334				break;
4335
4336			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4337				testName += "_storage_buffer";
4338				if (params[testIdx].numCalls <= 2)
4339					graphicsTests->addChild(new PushDescriptorBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4340				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4341					computeTests->addChild(new PushDescriptorBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4342				break;
4343
4344			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4345				testName += "_combined_image_sampler";
4346				graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4347				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4348					computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4349				break;
4350
4351			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4352				testName += "_sampled_image";
4353				graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4354				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4355					computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4356				break;
4357
4358			case VK_DESCRIPTOR_TYPE_SAMPLER:
4359				testName += "_sampler";
4360				graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4361				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4362					computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4363				break;
4364
4365			case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4366				testName += "_storage_image";
4367				graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4368				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4369					computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4370				break;
4371
4372			case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4373				testName += "_uniform_texel_buffer";
4374				graphicsTests->addChild(new PushDescriptorTexelBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4375				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4376					computeTests->addChild(new PushDescriptorTexelBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4377				break;
4378
4379			case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4380				testName += "_storage_texel_buffer";
4381				graphicsTests->addChild(new PushDescriptorTexelBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4382				if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4383					computeTests->addChild(new PushDescriptorTexelBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4384				break;
4385
4386			case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
4387				// Input attachments are not supported with dynamic rendering
4388				if (!vk::isConstructionTypeShaderObject(pipelineType))
4389				{
4390					testName += "_input_attachment";
4391					graphicsTests->addChild(new PushDescriptorInputAttachmentGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4392				}
4393				break;
4394
4395			default:
4396				DE_FATAL("Unexpected descriptor type");
4397				break;
4398		}
4399	}
4400
4401	if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4402	{
4403		TestParams testParams = { pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0u, 1u, true };
4404		graphicsTests->addChild(new PushDescriptorTexelBufferGraphicsTest(testCtx, "maintenance5_uniform_texel_buffer", testParams));
4405		testParams.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
4406		graphicsTests->addChild(new PushDescriptorTexelBufferGraphicsTest(testCtx, "maintenance5_storage_texel_buffer", testParams));
4407		testParams.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4408		graphicsTests->addChild(new PushDescriptorBufferGraphicsTest(testCtx, "maintenance5_uniform_buffer", testParams));
4409	}
4410
4411	pushDescriptorTests->addChild(graphicsTests.release());
4412	if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4413		pushDescriptorTests->addChild(computeTests.release());
4414
4415	return pushDescriptorTests.release();
4416}
4417
4418} // pipeline
4419} // vkt
4420