• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
52 namespace vkt
53 {
54 namespace pipeline
55 {
56 
57 using namespace vk;
58 using namespace std;
59 
60 namespace
61 {
62 typedef vector<VkExtensionProperties>			Extensions;
63 typedef de::SharedPtr<Unique<VkBuffer> >		VkBufferSp;
64 typedef de::SharedPtr<Unique<VkImage> >			VkImageSp;
65 typedef de::SharedPtr<Unique<VkImageView> >		VkImageViewSp;
66 typedef de::SharedPtr<Unique<VkBufferView> >	VkBufferViewSp;
67 typedef de::SharedPtr<Allocation>				AllocationSp;
68 typedef de::SharedPtr<RenderPassWrapper>		VkRenderPassSp;
69 
70 constexpr VkDeviceSize kSizeofVec4 = static_cast<VkDeviceSize>(sizeof(tcu::Vec4));
71 
72 struct 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 
calcItemSize(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 numElements=1u)81 VkDeviceSize 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 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)88 void 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 
createInstanceWithGetPhysicalDeviceProperties2(Context & context,const Extensions & supportedExtensions)97 CustomInstance 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 
innerCString(const string & str)106 const char *innerCString(const string &str)
107 {
108 	return str.c_str();
109 }
110 
createDeviceWithPushDescriptor(const Context & context,const PlatformInterface & vkp,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,const TestParams & params,std::vector<std::string> & enabledExtensions)111 Move<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 
createQuads(deUint32 numQuads,float size)182 vector<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 
createTexQuads(deUint32 numQuads,float size)206 vector<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 
229 static 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 
236 class PushDescriptorBufferGraphicsTestInstance : public vkt::TestInstance
237 {
238 public:
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 
245 private:
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 
PushDescriptorBufferGraphicsTestInstance(Context & context,const TestParams & params)281 PushDescriptorBufferGraphicsTestInstance::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 
init(void)302 void 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 
~PushDescriptorBufferGraphicsTestInstance(void)591 PushDescriptorBufferGraphicsTestInstance::~PushDescriptorBufferGraphicsTestInstance (void)
592 {
593 }
594 
iterate(void)595 tcu::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 
verifyImage(void)604 tcu::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 
645 class PushDescriptorBufferGraphicsTest : public vkt::TestCase
646 {
647 public:
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 
656 protected:
657 	const TestParams	m_params;
658 };
659 
PushDescriptorBufferGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)660 PushDescriptorBufferGraphicsTest::PushDescriptorBufferGraphicsTest (tcu::TestContext&	testContext,
661 																	const string&		name,
662 																	const TestParams&	params)
663 	: vkt::TestCase	(testContext, name)
664 	, m_params		(params)
665 {
666 }
667 
~PushDescriptorBufferGraphicsTest(void)668 PushDescriptorBufferGraphicsTest::~PushDescriptorBufferGraphicsTest (void)
669 {
670 }
671 
createInstance(Context & context) const672 TestInstance* PushDescriptorBufferGraphicsTest::createInstance (Context& context) const
673 {
674 	return new PushDescriptorBufferGraphicsTestInstance(context, m_params);
675 }
676 
checkSupport(Context & context) const677 void 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 
initPrograms(SourceCollections & sourceCollections) const685 void 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 
720 class PushDescriptorBufferComputeTestInstance : public vkt::TestInstance
721 {
722 public:
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 
729 private:
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 
PushDescriptorBufferComputeTestInstance(Context & context,const TestParams & params)757 PushDescriptorBufferComputeTestInstance::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 
init(void)775 void 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 
~PushDescriptorBufferComputeTestInstance(void)981 PushDescriptorBufferComputeTestInstance::~PushDescriptorBufferComputeTestInstance (void)
982 {
983 }
984 
iterate(void)985 tcu::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 
verifyOutput(void)994 tcu::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 
1009 class PushDescriptorBufferComputeTest : public vkt::TestCase
1010 {
1011 public:
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 
1019 protected:
1020 	const TestParams	m_params;
1021 };
1022 
PushDescriptorBufferComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)1023 PushDescriptorBufferComputeTest::PushDescriptorBufferComputeTest (tcu::TestContext&	testContext,
1024 																  const string&		name,
1025 																  const TestParams&	params)
1026 	: vkt::TestCase	(testContext, name)
1027 	, m_params		(params)
1028 {
1029 }
1030 
~PushDescriptorBufferComputeTest(void)1031 PushDescriptorBufferComputeTest::~PushDescriptorBufferComputeTest (void)
1032 {
1033 }
1034 
createInstance(Context & context) const1035 TestInstance* PushDescriptorBufferComputeTest::createInstance (Context& context) const
1036 {
1037 	return new PushDescriptorBufferComputeTestInstance(context, m_params);
1038 }
1039 
initPrograms(SourceCollections & sourceCollections) const1040 void 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 
1063 class PushDescriptorImageGraphicsTestInstance : public vkt::TestInstance
1064 {
1065 public:
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 
1072 private:
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 
PushDescriptorImageGraphicsTestInstance(Context & context,const TestParams & params)1112 PushDescriptorImageGraphicsTestInstance::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 
init(void)1134 void 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 
~PushDescriptorImageGraphicsTestInstance(void)1715 PushDescriptorImageGraphicsTestInstance::~PushDescriptorImageGraphicsTestInstance (void)
1716 {
1717 }
1718 
iterate(void)1719 tcu::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 
verifyImage(void)1728 tcu::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 
1801 class PushDescriptorImageGraphicsTest : public vkt::TestCase
1802 {
1803 public:
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 
1813 protected:
1814 	const TestParams	m_params;
1815 };
1816 
PushDescriptorImageGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)1817 PushDescriptorImageGraphicsTest::PushDescriptorImageGraphicsTest	(tcu::TestContext&	testContext,
1818 																	const string&		name,
1819 																	const TestParams&	params)
1820 	: vkt::TestCase	(testContext, name)
1821 	, m_params		(params)
1822 {
1823 }
1824 
~PushDescriptorImageGraphicsTest(void)1825 PushDescriptorImageGraphicsTest::~PushDescriptorImageGraphicsTest (void)
1826 {
1827 }
1828 
createInstance(Context & context) const1829 TestInstance* PushDescriptorImageGraphicsTest::createInstance (Context& context) const
1830 {
1831 	return new PushDescriptorImageGraphicsTestInstance(context, m_params);
1832 }
1833 
checkSupport(Context & context) const1834 void PushDescriptorImageGraphicsTest::checkSupport(Context& context) const
1835 {
1836 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1837 }
1838 
initPrograms(SourceCollections & sourceCollections) const1839 void 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 
1925 class PushDescriptorImageComputeTestInstance : public vkt::TestInstance
1926 {
1927 public:
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 
1934 private:
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 
PushDescriptorImageComputeTestInstance(Context & context,const TestParams & params)1968 PushDescriptorImageComputeTestInstance::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 
init(void)1990 void 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 
~PushDescriptorImageComputeTestInstance(void)2448 PushDescriptorImageComputeTestInstance::~PushDescriptorImageComputeTestInstance (void)
2449 {
2450 }
2451 
iterate(void)2452 tcu::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 
verifyOutput(void)2461 tcu::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 
2595 class PushDescriptorImageComputeTest : public vkt::TestCase
2596 {
2597 public:
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 
2605 protected:
2606 	const TestParams	m_params;
2607 };
2608 
PushDescriptorImageComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)2609 PushDescriptorImageComputeTest::PushDescriptorImageComputeTest	(tcu::TestContext&	testContext,
2610 																 const string&		name,
2611 																 const TestParams&	params)
2612 	: vkt::TestCase	(testContext, name)
2613 	, m_params		(params)
2614 {
2615 }
2616 
~PushDescriptorImageComputeTest(void)2617 PushDescriptorImageComputeTest::~PushDescriptorImageComputeTest (void)
2618 {
2619 }
2620 
createInstance(Context & context) const2621 TestInstance* PushDescriptorImageComputeTest::createInstance (Context& context) const
2622 {
2623 	return new PushDescriptorImageComputeTestInstance(context, m_params);
2624 }
2625 
initPrograms(SourceCollections & sourceCollections) const2626 void 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 
2712 class PushDescriptorTexelBufferGraphicsTestInstance : public vkt::TestInstance
2713 {
2714 public:
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 
2721 private:
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 
PushDescriptorTexelBufferGraphicsTestInstance(Context & context,const TestParams & params)2759 PushDescriptorTexelBufferGraphicsTestInstance::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 
init(void)2781 void 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 
~PushDescriptorTexelBufferGraphicsTestInstance(void)3073 PushDescriptorTexelBufferGraphicsTestInstance::~PushDescriptorTexelBufferGraphicsTestInstance (void)
3074 {
3075 }
3076 
iterate(void)3077 tcu::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 
verifyImage(void)3086 tcu::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 
3127 class PushDescriptorTexelBufferGraphicsTest : public vkt::TestCase
3128 {
3129 public:
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 
3139 protected:
3140 	const TestParams	m_params;
3141 };
3142 
PushDescriptorTexelBufferGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)3143 PushDescriptorTexelBufferGraphicsTest::PushDescriptorTexelBufferGraphicsTest	(tcu::TestContext&	testContext,
3144 																				 const string&		name,
3145 																				 const TestParams&	params)
3146 	: vkt::TestCase	(testContext, name)
3147 	, m_params		(params)
3148 {
3149 }
3150 
~PushDescriptorTexelBufferGraphicsTest(void)3151 PushDescriptorTexelBufferGraphicsTest::~PushDescriptorTexelBufferGraphicsTest (void)
3152 {
3153 }
3154 
createInstance(Context & context) const3155 TestInstance* PushDescriptorTexelBufferGraphicsTest::createInstance (Context& context) const
3156 {
3157 	return new PushDescriptorTexelBufferGraphicsTestInstance(context, m_params);
3158 }
3159 
checkSupport(Context & context) const3160 void 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 
initPrograms(SourceCollections & sourceCollections) const3168 void 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 
3219 class PushDescriptorTexelBufferComputeTestInstance : public vkt::TestInstance
3220 {
3221 public:
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 
3228 private:
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 
PushDescriptorTexelBufferComputeTestInstance(Context & context,const TestParams & params)3257 PushDescriptorTexelBufferComputeTestInstance::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 
init(void)3276 void 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 
~PushDescriptorTexelBufferComputeTestInstance(void)3482 PushDescriptorTexelBufferComputeTestInstance::~PushDescriptorTexelBufferComputeTestInstance (void)
3483 {
3484 }
3485 
iterate(void)3486 tcu::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 
verifyOutput(void)3495 tcu::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 
3520 class PushDescriptorTexelBufferComputeTest : public vkt::TestCase
3521 {
3522 public:
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 
3530 protected:
3531 	const TestParams	m_params;
3532 };
3533 
PushDescriptorTexelBufferComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)3534 PushDescriptorTexelBufferComputeTest::PushDescriptorTexelBufferComputeTest	(tcu::TestContext&	testContext,
3535 																			 const string&		name,
3536 																			 const TestParams&	params)
3537 	: vkt::TestCase	(testContext, name)
3538 	, m_params		(params)
3539 {
3540 }
3541 
~PushDescriptorTexelBufferComputeTest(void)3542 PushDescriptorTexelBufferComputeTest::~PushDescriptorTexelBufferComputeTest (void)
3543 {
3544 }
3545 
createInstance(Context & context) const3546 TestInstance* PushDescriptorTexelBufferComputeTest::createInstance (Context& context) const
3547 {
3548 	return new PushDescriptorTexelBufferComputeTestInstance(context, m_params);
3549 }
3550 
initPrograms(SourceCollections & sourceCollections) const3551 void 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 
3591 class PushDescriptorInputAttachmentGraphicsTestInstance : public vkt::TestInstance
3592 {
3593 public:
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 
3600 private:
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 
PushDescriptorInputAttachmentGraphicsTestInstance(Context & context,const TestParams & params)3637 PushDescriptorInputAttachmentGraphicsTestInstance::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 
init(void)3658 void 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 
~PushDescriptorInputAttachmentGraphicsTestInstance(void)4139 PushDescriptorInputAttachmentGraphicsTestInstance::~PushDescriptorInputAttachmentGraphicsTestInstance (void)
4140 {
4141 }
4142 
iterate(void)4143 tcu::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 
verifyImage(void)4152 tcu::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 
4202 class PushDescriptorInputAttachmentGraphicsTest : public vkt::TestCase
4203 {
4204 public:
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 
4214 protected:
4215 	const TestParams	m_params;
4216 };
4217 
PushDescriptorInputAttachmentGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)4218 PushDescriptorInputAttachmentGraphicsTest::PushDescriptorInputAttachmentGraphicsTest	(tcu::TestContext&	testContext,
4219 																	const string&		name,
4220 																	const TestParams&	params)
4221 	: vkt::TestCase	(testContext, name)
4222 	, m_params		(params)
4223 {
4224 }
4225 
~PushDescriptorInputAttachmentGraphicsTest(void)4226 PushDescriptorInputAttachmentGraphicsTest::~PushDescriptorInputAttachmentGraphicsTest (void)
4227 {
4228 }
4229 
createInstance(Context & context) const4230 TestInstance* PushDescriptorInputAttachmentGraphicsTest::createInstance (Context& context) const
4231 {
4232 	return new PushDescriptorInputAttachmentGraphicsTestInstance(context, m_params);
4233 }
4234 
checkSupport(Context & context) const4235 void PushDescriptorInputAttachmentGraphicsTest::checkSupport(Context& context) const
4236 {
4237 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
4238 }
4239 
initPrograms(SourceCollections & sourceCollections) const4240 void 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 
createPushDescriptorTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineType)4274 tcu::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