1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 ARM Limited.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief PushConstant Tests
25 *//*--------------------------------------------------------------------*/
26
27#include "vktPipelinePushConstantTests.hpp"
28#include "vktPipelineClearUtil.hpp"
29#include "vktPipelineImageUtil.hpp"
30#include "vktPipelineVertexUtil.hpp"
31#include "vktPipelineReferenceRenderer.hpp"
32
33#include "vktTestCase.hpp"
34#include "vkImageUtil.hpp"
35#include "vkMemUtil.hpp"
36#include "vkPrograms.hpp"
37#include "vkQueryUtil.hpp"
38#include "vkRef.hpp"
39#include "vkRefUtil.hpp"
40#include "vkBuilderUtil.hpp"
41#include "vkTypeUtil.hpp"
42#include "vkCmdUtil.hpp"
43#include "vkObjUtil.hpp"
44#include "vkImageWithMemory.hpp"
45#include "vkBufferWithMemory.hpp"
46#include "vkBarrierUtil.hpp"
47
48#include "tcuImageCompare.hpp"
49#include "tcuTestLog.hpp"
50
51#include "deMemory.h"
52#include "deRandom.hpp"
53#include "deStringUtil.hpp"
54#include "deUniquePtr.hpp"
55
56#include <algorithm>
57#include <sstream>
58#include <vector>
59
60namespace vkt
61{
62namespace pipeline
63{
64
65using namespace vk;
66
67namespace
68{
69
70enum
71{
72	TRIANGLE_COUNT	= 2,
73	MAX_RANGE_COUNT	= 5
74};
75
76enum RangeSizeCase
77{
78	SIZE_CASE_4	= 0,
79	SIZE_CASE_8,
80	SIZE_CASE_12,
81	SIZE_CASE_16,
82	SIZE_CASE_32,
83	SIZE_CASE_36,
84	SIZE_CASE_48,
85	SIZE_CASE_128,
86	SIZE_CASE_UNSUPPORTED
87};
88
89enum CommandType
90{
91	CMD_BIND_PIPELINE_GRAPHICS = 0,
92	CMD_BIND_PIPELINE_COMPUTE,
93	CMD_PUSH_CONSTANT,
94	CMD_DRAW,
95	CMD_DISPATCH,
96	CMD_UNSUPPORTED
97};
98
99struct CommandData
100{
101	CommandType cType;
102	deInt32 rangeNdx;
103};
104
105struct PushConstantData
106{
107	struct PushConstantRange
108	{
109		VkShaderStageFlags		shaderStage;
110		deUint32				offset;
111		deUint32				size;
112	} range;
113	struct PushConstantUpdate
114	{
115		deUint32				offset;
116		deUint32				size;
117	} update;
118};
119
120// These values will be loaded from push constants and used as an index
121static const deUint32 DYNAMIC_VEC_INDEX = 2u;
122static const deUint32 DYNAMIC_MAT_INDEX = 0u;
123static const deUint32 DYNAMIC_ARR_INDEX = 3u;
124
125// These reference values will be compared in the shader to ensure the correct index was read
126static const float DYNAMIC_VEC_CONSTANT = 0.25f;
127static const float DYNAMIC_MAT_CONSTANT = 0.50f;
128static const float DYNAMIC_ARR_CONSTANT = 0.75f;
129
130enum IndexType
131{
132	INDEX_TYPE_CONST_LITERAL = 0,
133	INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR,
134
135	INDEX_TYPE_LAST
136};
137
138enum ComputeTestType
139{
140	CTT_SIMPLE = 0,
141	CTT_UNINITIALIZED,
142
143	CTT_LAST
144};
145
146std::string getShaderStageNameStr (VkShaderStageFlags stageFlags)
147{
148	const VkShaderStageFlags	shaderStages[]		=
149	{
150		VK_SHADER_STAGE_VERTEX_BIT,
151		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
152		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
153		VK_SHADER_STAGE_GEOMETRY_BIT,
154		VK_SHADER_STAGE_FRAGMENT_BIT
155	};
156
157	const char*					shaderStageNames[]	=
158	{
159		"VK_SHADER_STAGE_VERTEX_BIT",
160		"VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT",
161		"VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT",
162		"VK_SHADER_STAGE_GEOMETRY_BIT",
163		"VK_SHADER_STAGE_FRAGMENT_BIT",
164	};
165
166	std::stringstream			shaderStageStr;
167
168	for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
169	{
170		if (stageFlags & shaderStages[stageNdx])
171		{
172			if (!(shaderStageStr.str().empty()))
173				shaderStageStr << " | ";
174
175			shaderStageStr << shaderStageNames[stageNdx];
176		}
177	}
178
179	return shaderStageStr.str();
180}
181
182std::vector<Vertex4RGBA> createQuad(const float size, const tcu::Vec4 &color)
183{
184	std::vector<Vertex4RGBA>	vertices;
185
186	const Vertex4RGBA			lowerLeftVertex		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
187	const Vertex4RGBA			lowerRightVertex	= {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
188	const Vertex4RGBA			UpperLeftVertex		= {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
189	const Vertex4RGBA			UpperRightVertex	= {tcu::Vec4(size, size, 0.0f, 1.0f), color};
190
191	vertices.push_back(lowerLeftVertex);
192	vertices.push_back(lowerRightVertex);
193	vertices.push_back(UpperLeftVertex);
194	vertices.push_back(UpperLeftVertex);
195	vertices.push_back(lowerRightVertex);
196	vertices.push_back(UpperRightVertex);
197
198	return vertices;
199}
200
201class PushConstantGraphicsTestInstance : public vkt::TestInstance {
202public:
203												PushConstantGraphicsTestInstance	(Context&							context,
204																					 const PipelineConstructionType		pipelineConstructionType,
205																					 const deUint32						rangeCount,
206																					 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
207																					 const deBool						multipleUpdate,
208																					 const IndexType					indexType);
209	virtual										~PushConstantGraphicsTestInstance	(void);
210	void										init								(void);
211	virtual tcu::TestStatus						iterate								(void);
212	virtual std::vector<VkPushConstantRange>	getPushConstantRanges				(void) = 0;
213	virtual void								updatePushConstants					(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout) = 0;
214	virtual void								setReferenceColor					(tcu::Vec4 initColor) = 0;
215	void										createShaderModule					(const DeviceInterface&		vk,
216																					 VkDevice					device,
217																					 const BinaryCollection&	programCollection,
218																					 const char*				name,
219																					 ShaderWrapper*				module);
220	tcu::TestStatus								verifyImage							(void);
221
222protected:
223	const PipelineConstructionType					m_pipelineConstructionType;
224	std::vector<Vertex4RGBA>						m_vertices;
225	const deUint32									m_rangeCount;
226	PushConstantData								m_pushConstantRange[MAX_RANGE_COUNT];
227	const IndexType									m_indexType;
228
229private:
230	const tcu::UVec2								m_renderSize;
231	const VkFormat									m_colorFormat;
232	const deBool									m_multipleUpdate;
233
234	VkImageCreateInfo								m_colorImageCreateInfo;
235	Move<VkImage>									m_colorImage;
236	de::MovePtr<Allocation>							m_colorImageAlloc;
237	Move<VkImageView>								m_colorAttachmentView;
238	RenderPassWrapper								m_renderPass;
239	Move<VkFramebuffer>								m_framebuffer;
240
241	ShaderWrapper									m_vertexShaderModule;
242	ShaderWrapper									m_fragmentShaderModule;
243	ShaderWrapper									m_geometryShaderModule;
244	ShaderWrapper									m_tessControlShaderModule;
245	ShaderWrapper									m_tessEvaluationShaderModule;
246
247	VkShaderStageFlags								m_shaderFlags;
248	std::vector<VkPipelineShaderStageCreateInfo>	m_shaderStage;
249
250	Move<VkBuffer>									m_vertexBuffer;
251	de::MovePtr<Allocation>							m_vertexBufferAlloc;
252
253	Move<VkBuffer>									m_uniformBuffer;
254	de::MovePtr<Allocation>							m_uniformBufferAlloc;
255	Move<VkDescriptorPool>							m_descriptorPool;
256	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
257	Move<VkDescriptorSet>							m_descriptorSet;
258
259	PipelineLayoutWrapper							m_preRasterizationStatePipelineLayout;
260	PipelineLayoutWrapper							m_fragmentStatePipelineLayout;
261	GraphicsPipelineWrapper							m_graphicsPipeline;
262
263	Move<VkCommandPool>								m_cmdPool;
264	Move<VkCommandBuffer>							m_cmdBuffer;
265};
266
267void PushConstantGraphicsTestInstance::createShaderModule (const DeviceInterface&	vk,
268														   VkDevice					device,
269														   const BinaryCollection&	programCollection,
270														   const char*				name,
271														   ShaderWrapper*	module)
272{
273	*module = ShaderWrapper(vk, device, programCollection.get(name), 0);
274}
275
276PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context&						context,
277																	const PipelineConstructionType	pipelineConstructionType,
278																	const deUint32					rangeCount,
279																	const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
280																	deBool							multipleUpdate,
281																	IndexType						indexType)
282	: vkt::TestInstance				(context)
283	, m_pipelineConstructionType	(pipelineConstructionType)
284	, m_rangeCount					(rangeCount)
285	, m_indexType					(indexType)
286	, m_renderSize					(32, 32)
287	, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
288	, m_multipleUpdate				(multipleUpdate)
289	, m_shaderFlags					(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
290	, m_graphicsPipeline			(m_context.getInstanceInterface(), m_context.getDeviceInterface(), m_context.getPhysicalDevice(), m_context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType)
291{
292	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
293}
294
295void PushConstantGraphicsTestInstance::init (void)
296{
297	const DeviceInterface&					vk						= m_context.getDeviceInterface();
298	const VkDevice							vkDevice				= m_context.getDevice();
299	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
300	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
301	const VkComponentMapping				componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
302	const std::vector<VkPushConstantRange>	pushConstantRanges		= getPushConstantRanges();
303	bool									useTessellation			= false;
304	bool									useGeometry				= false;
305
306	// Create color image
307	{
308		const VkImageCreateInfo colorImageParams =
309		{
310			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
311			DE_NULL,																// const void*				pNext;
312			0u,																		// VkImageCreateFlags		flags;
313			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
314			m_colorFormat,															// VkFormat					format;
315			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
316			1u,																		// deUint32					mipLevels;
317			1u,																		// deUint32					arrayLayers;
318			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
319			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
320			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
321			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
322			1u,																		// deUint32					queueFamilyIndexCount;
323			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
324			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
325		};
326
327		m_colorImageCreateInfo	= colorImageParams;
328		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
329
330		// Allocate and bind color image memory
331		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
332		VK_CHECK(vk.bindImageMemory(vkDevice, *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(vk, vkDevice, &colorAttachmentViewParams);
350	}
351
352	// Create render pass
353	m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, m_colorFormat);
354
355	// Create framebuffer
356	{
357		const VkImageView attachmentBindInfos[1] =
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(vk, vkDevice, &framebufferParams, *m_colorImage);
376	}
377
378	// Create pipeline layout
379	{
380		// create descriptor set layout
381		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
382
383		// create descriptor pool
384		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
385
386		// create uniform buffer
387		const VkBufferCreateInfo			uniformBufferCreateInfo	=
388		{
389			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
390			DE_NULL,								// const void*			pNext;
391			0u,										// VkBufferCreateFlags	flags
392			16u,									// VkDeviceSize			size;
393			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,		// VkBufferUsageFlags	usage;
394			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
395			1u,										// deUint32				queueFamilyCount;
396			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
397		};
398
399		m_uniformBuffer			= createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
400		m_uniformBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
401		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
402
403		const tcu::Vec4						value					= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
404		deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
405		flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
406
407		// create and update descriptor set
408		const VkDescriptorSetAllocateInfo	allocInfo				=
409		{
410			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType                             sType;
411			DE_NULL,										// const void*                                 pNext;
412			*m_descriptorPool,								// VkDescriptorPool                            descriptorPool;
413			1u,												// deUint32                                    setLayoutCount;
414			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*                pSetLayouts;
415		};
416		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
417
418		const VkDescriptorBufferInfo		descriptorInfo			= makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
419
420		DescriptorSetUpdateBuilder()
421			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
422			.update(vk, vkDevice);
423
424		// create pipeline layout
425#ifndef CTS_USES_VULKANSC
426		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = (vk::isConstructionTypeLibrary(m_pipelineConstructionType)) ? deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT) : 0u;
427#else
428		VkPipelineLayoutCreateFlags	pipelineLayoutFlags = 0u;
429#endif // CTS_USES_VULKANSC
430		VkPipelineLayoutCreateInfo	pipelineLayoutParams
431		{
432			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
433			DE_NULL,										// const void*					pNext;
434			pipelineLayoutFlags,							// VkPipelineLayoutCreateFlags	flags;
435			1u,												// deUint32						setLayoutCount;
436			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
437			(deUint32)pushConstantRanges.size(),			// deUint32						pushConstantRangeCount;
438			&pushConstantRanges.front()						// const VkPushConstantRange*	pPushConstantRanges;
439		};
440
441		m_preRasterizationStatePipelineLayout		= PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
442		pipelineLayoutParams.setLayoutCount			= 0u;
443		pipelineLayoutParams.pSetLayouts			= DE_NULL;
444		m_fragmentStatePipelineLayout				= PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
445	}
446
447	// Create shaders
448	{
449		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
450		{
451			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
452			{
453				m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
454			}
455			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
456			{
457				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
458			}
459			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
460			{
461				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
462			}
463		}
464
465		VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
466
467		createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", &m_vertexShaderModule);
468		if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
469		{
470			if (features.tessellationShader == VK_FALSE)
471			{
472				TCU_THROW(NotSupportedError, "Tessellation Not Supported");
473			}
474			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", &m_tessControlShaderModule);
475			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", &m_tessEvaluationShaderModule);
476			useTessellation = true;
477		}
478		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
479		{
480			if (features.geometryShader == VK_FALSE)
481			{
482				TCU_THROW(NotSupportedError, "Geometry Not Supported");
483			}
484			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", &m_geometryShaderModule);
485			useGeometry = true;
486		}
487		createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", &m_fragmentShaderModule);
488	}
489
490	// Create pipeline
491	{
492		const VkVertexInputBindingDescription			vertexInputBindingDescription		=
493		{
494			0u,							// deUint32					binding;
495			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
496			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
497		};
498
499		const VkVertexInputAttributeDescription			vertexInputAttributeDescriptions[]	=
500		{
501			{
502				0u,								// deUint32	location;
503				0u,								// deUint32	binding;
504				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
505				0u								// deUint32	offsetInBytes;
506			},
507			{
508				1u,									// deUint32	location;
509				0u,									// deUint32	binding;
510				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
511				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
512			}
513		};
514
515		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
516		{
517			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
518			DE_NULL,													// const void*								pNext;
519			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
520			1u,															// deUint32									bindingCount;
521			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
522			2u,															// deUint32									attributeCount;
523			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
524		};
525
526		const VkPrimitiveTopology		topology	= (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
527
528		const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
529		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
530
531		m_graphicsPipeline.setMonolithicPipelineLayout(m_preRasterizationStatePipelineLayout)
532						  .setDefaultRasterizationState()
533						  .setDefaultDepthStencilState()
534						  .setDefaultMultisampleState()
535						  .setDefaultColorBlendState()
536						  .setDefaultTopology(topology)
537						  .setupVertexInputState(&vertexInputStateParams)
538						  .setupPreRasterizationShaderState(viewports,
539															scissors,
540															m_preRasterizationStatePipelineLayout,
541															*m_renderPass,
542															0u,
543															m_vertexShaderModule,
544															DE_NULL,
545															useTessellation ? m_tessControlShaderModule : ShaderWrapper(),
546															useTessellation ? m_tessEvaluationShaderModule : ShaderWrapper(),
547															useGeometry ? m_geometryShaderModule : ShaderWrapper())
548						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
549						  .setupFragmentOutputState(*m_renderPass)
550						  .buildPipeline();
551	}
552
553	// Create vertex buffer
554	{
555		m_vertices			= createQuad(1.0f, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
556
557		const VkBufferCreateInfo vertexBufferParams =
558		{
559			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
560			DE_NULL,													// const void*			pNext;
561			0u,															// VkBufferCreateFlags	flags;
562			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
563			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
564			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
565			1u,															// deUint32				queueFamilyCount;
566			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
567		};
568
569		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
570		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
571
572		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
573
574		// Load vertices into vertex buffer
575		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
576		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
577	}
578
579	// Create command pool
580	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
581
582	// Create command buffer
583	{
584		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
585
586		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
587
588		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
589
590		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
591
592		// Update push constant values
593		updatePushConstants(*m_cmdBuffer, *m_preRasterizationStatePipelineLayout);
594
595		// draw quad
596		const VkDeviceSize				triangleOffset			= (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
597
598		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
599		{
600			VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
601
602			if (m_multipleUpdate)
603				vk.cmdPushConstants(*m_cmdBuffer, *m_preRasterizationStatePipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
604
605			m_graphicsPipeline.bind(*m_cmdBuffer);
606			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
607			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_preRasterizationStatePipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
608
609			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
610		}
611
612		m_renderPass.end(vk, *m_cmdBuffer);
613		endCommandBuffer(vk, *m_cmdBuffer);
614	}
615}
616
617PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
618{
619}
620
621tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
622{
623	init();
624
625	const DeviceInterface&		vk			= m_context.getDeviceInterface();
626	const VkDevice				vkDevice	= m_context.getDevice();
627	const VkQueue				queue		= m_context.getUniversalQueue();
628
629	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
630
631	return verifyImage();
632}
633
634tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
635{
636	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
637	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
638	const ColorVertexShader		vertexShader;
639	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
640	const rr::Program			program			(&vertexShader, &fragmentShader);
641	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
642	bool						compareOk		= false;
643
644	// Render reference image
645	{
646		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
647		{
648			m_vertices = createQuad(0.5f, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
649		}
650
651		setReferenceColor(m_vertices[0].color);
652
653		if (m_multipleUpdate)
654		{
655			for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
656			{
657				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
658			}
659			for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
660			{
661				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
662			}
663		}
664
665		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
666		{
667			rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
668
669			refRenderer.draw(renderState,
670							 rr::PRIMITIVETYPE_TRIANGLES,
671							 std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
672													  m_vertices.begin() + (triangleNdx + 1) * 3));
673		}
674	}
675
676	// Compare result with reference image
677	{
678		const DeviceInterface&			vk					= m_context.getDeviceInterface();
679		const VkDevice					vkDevice			= m_context.getDevice();
680		const VkQueue					queue				= m_context.getUniversalQueue();
681		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
682		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
683		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
684
685		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
686															  "IntImageCompare",
687															  "Image comparison",
688															  refRenderer.getAccess(),
689															  result->getAccess(),
690															  tcu::UVec4(2, 2, 2, 2),
691															  tcu::IVec3(1, 1, 0),
692															  true,
693															  tcu::COMPARE_LOG_RESULT);
694	}
695
696	if (compareOk)
697		return tcu::TestStatus::pass("Result image matches reference");
698	else
699		return tcu::TestStatus::fail("Image mismatch");
700}
701
702class PushConstantGraphicsDisjointInstance : public PushConstantGraphicsTestInstance
703{
704public:
705										PushConstantGraphicsDisjointInstance	(Context&							context,
706																				 const PipelineConstructionType		pipelineConstructionType,
707																				 const deUint32						rangeCount,
708																				 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
709																				 const deBool						multipleUpdate,
710																				 const IndexType					indexType);
711	virtual								~PushConstantGraphicsDisjointInstance	(void);
712	std::vector<VkPushConstantRange>	getPushConstantRanges					(void);
713	void								updatePushConstants						(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
714	void								setReferenceColor						(tcu::Vec4 initColor);
715};
716
717PushConstantGraphicsDisjointInstance::PushConstantGraphicsDisjointInstance (Context&						context,
718																			const PipelineConstructionType	pipelineConstructionType,
719																			const deUint32					rangeCount,
720																			const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
721																			deBool							multipleUpdate,
722																			IndexType						indexType)
723	: PushConstantGraphicsTestInstance (context, pipelineConstructionType, rangeCount, pushConstantRange, multipleUpdate, indexType)
724{
725	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
726}
727
728PushConstantGraphicsDisjointInstance::~PushConstantGraphicsDisjointInstance(void)
729{
730}
731
732std::vector<VkPushConstantRange> PushConstantGraphicsDisjointInstance::getPushConstantRanges (void)
733{
734	std::vector<VkPushConstantRange> pushConstantRanges;
735
736	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
737	{
738		const VkPushConstantRange pushConstantRange =
739		{
740			m_pushConstantRange[rangeNdx].range.shaderStage,
741			m_pushConstantRange[rangeNdx].range.offset,
742			m_pushConstantRange[rangeNdx].range.size
743		};
744
745		pushConstantRanges.push_back(pushConstantRange);
746	}
747
748	return pushConstantRanges;
749}
750
751void PushConstantGraphicsDisjointInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
752{
753	const DeviceInterface&	vk		= m_context.getDeviceInterface();
754	std::vector<tcu::Vec4>	color	(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
755	std::vector<tcu::Vec4>	allOnes	(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
756
757	switch (m_indexType)
758	{
759		case INDEX_TYPE_CONST_LITERAL:
760			// Do nothing
761			break;
762		case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
763			// Stick our dynamic index at the beginning of a vector
764			color[0] = tcu::Vec4(	float(DYNAMIC_VEC_INDEX),
765									float(DYNAMIC_MAT_INDEX),
766									float(DYNAMIC_ARR_INDEX),
767									1.0f);
768
769			// Place our reference values at each type offset
770
771			// vec4[i]
772			DE_ASSERT(DYNAMIC_VEC_INDEX <= 3);
773			color[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
774			color[1][DYNAMIC_VEC_INDEX] = DYNAMIC_VEC_CONSTANT;
775
776			// mat2[i][0]
777			DE_ASSERT(DYNAMIC_MAT_INDEX <= 1);
778			color[2] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
779			color[2][DYNAMIC_MAT_INDEX * 2] = DYNAMIC_MAT_CONSTANT;
780
781			// float[i]
782			DE_ASSERT(DYNAMIC_ARR_INDEX <= 3);
783			color[3] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
784			color[3][DYNAMIC_ARR_INDEX] = DYNAMIC_ARR_CONSTANT;
785			break;
786		default:
787			DE_FATAL("Unhandled IndexType");
788			break;
789	}
790
791	const deUint32			kind	= 2u;
792	const void*				value	= DE_NULL;
793
794	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
795	{
796		value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
797
798		vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
799
800		if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
801		{
802			value = (void*)(&allOnes[0]);
803			vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
804		}
805	}
806}
807
808void PushConstantGraphicsDisjointInstance::setReferenceColor (tcu::Vec4 initColor)
809{
810	DE_UNREF(initColor);
811
812	const tcu::Vec4 color = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
813
814	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
815	{
816		if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
817		{
818			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
819			{
820				m_vertices[vertexNdx].color.xyzw() = color;
821			}
822		}
823	}
824}
825
826class PushConstantGraphicsOverlapTestInstance : public PushConstantGraphicsTestInstance
827{
828public:
829										PushConstantGraphicsOverlapTestInstance		(Context&							context,
830																					 const PipelineConstructionType		pipelineConstructionType,
831																					 const deUint32						rangeCount,
832																					 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
833																					 const deBool						multipleUpdate,
834																					 const IndexType					indexType);
835	virtual								~PushConstantGraphicsOverlapTestInstance	(void);
836	std::vector<VkPushConstantRange>	getPushConstantRanges					(void);
837	std::vector<VkPushConstantRange>	getPushConstantUpdates					(void);
838	void								updatePushConstants						(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
839	void								setReferenceColor						(tcu::Vec4 initColor);
840
841private:
842	const std::vector<float>			m_colorData;
843	std::vector<float>					m_referenceData;
844};
845
846std::vector<float> generateColorData (deUint32 numBytes)
847{
848	DE_ASSERT(numBytes % 4u == 0u);
849
850	std::vector<float> colorData;
851
852	deRandom random;
853	deRandom_init(&random, numBytes);
854
855	for (deUint32 elementNdx = 0u; elementNdx < numBytes / 4u; elementNdx++)
856		colorData.push_back(deRandom_getFloat(&random));
857
858	return colorData;
859}
860
861PushConstantGraphicsOverlapTestInstance::PushConstantGraphicsOverlapTestInstance (Context&							context,
862																				  const PipelineConstructionType	pipelineConstructionType,
863																				  const deUint32					rangeCount,
864																				  const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
865																				  deBool							multipleUpdate,
866																				  IndexType							indexType)
867	: PushConstantGraphicsTestInstance	(context, pipelineConstructionType, rangeCount, pushConstantRange, multipleUpdate, indexType)
868	, m_colorData						(generateColorData(256u))
869{
870	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
871}
872
873PushConstantGraphicsOverlapTestInstance::~PushConstantGraphicsOverlapTestInstance(void)
874{
875}
876
877std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantRanges (void)
878{
879	// Find push constant ranges for each shader stage
880	const VkShaderStageFlags			shaderStages[]		=
881	{
882		VK_SHADER_STAGE_VERTEX_BIT,
883		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
884		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
885		VK_SHADER_STAGE_GEOMETRY_BIT,
886		VK_SHADER_STAGE_FRAGMENT_BIT,
887	};
888
889	std::vector<VkPushConstantRange>	pushConstantRanges;
890
891	m_context.getTestContext().getLog() << tcu::TestLog::Section("Ranges", "Push constant ranges");
892
893	for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
894	{
895		deUint32 firstByte	= ~0u;
896		deUint32 lastByte	= 0u;
897
898		for (deUint32 rangeNdx = 0u; rangeNdx < m_rangeCount; rangeNdx++)
899		{
900			if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStages[stageNdx])
901			{
902				firstByte	= deMinu32(firstByte, m_pushConstantRange[rangeNdx].range.offset);
903				lastByte	= deMaxu32(lastByte, m_pushConstantRange[rangeNdx].range.offset + m_pushConstantRange[rangeNdx].range.size);
904			}
905		}
906
907		if (firstByte != ~0u)
908		{
909			const VkPushConstantRange pushConstantRange =
910			{
911				shaderStages[stageNdx],	// VkShaderStageFlags    stageFlags
912				firstByte,				// deUint32              offset
913				lastByte - firstByte	// deUint32              size
914			};
915
916			pushConstantRanges.push_back(pushConstantRange);
917
918			m_context.getTestContext().getLog()
919				<< tcu::TestLog::Message
920				<< "VkShaderStageFlags    stageFlags    " << getShaderStageNameStr(shaderStages[stageNdx]) << ",\n"
921				<< "deUint32              offset        " << pushConstantRange.offset << ",\n"
922				<< "deUint32              size          " << pushConstantRange.size << "\n"
923				<< tcu::TestLog::EndMessage;
924		}
925	}
926
927	m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
928
929	return pushConstantRanges;
930}
931
932std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantUpdates (void)
933{
934	VkShaderStageFlags					lastStageFlags		= (VkShaderStageFlags)~0u;
935	std::vector<VkPushConstantRange>	pushConstantUpdates;
936
937	// Find matching shader stages for every 4 byte chunk
938	for (deUint32 offset = 0u; offset < 128u; offset += 4u)
939	{
940		VkShaderStageFlags	stageFlags	= (VkShaderStageFlags)0u;
941		bool				updateRange	= false;
942
943		// For each byte in the range specified by offset and size and for each push constant range that overlaps that byte,
944		// stageFlags must include all stages in that push constant range's VkPushConstantRange::stageFlags
945		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
946		{
947			const deUint32 rangeStart	= m_pushConstantRange[rangeNdx].range.offset;
948			const deUint32 rangeEnd		= rangeStart + m_pushConstantRange[rangeNdx].range.size;
949
950			const deUint32 updateStart	= m_pushConstantRange[rangeNdx].update.offset;
951			const deUint32 updateEnd	= updateStart + m_pushConstantRange[rangeNdx].update.size;
952
953			updateRange |= (updateStart <= offset && updateEnd >= offset + 4u);
954
955			DE_ASSERT(rangeEnd <= 128u);
956
957			if (rangeStart <= offset && rangeEnd >= offset + 4u)
958				stageFlags |= m_pushConstantRange[rangeNdx].range.shaderStage;
959		}
960
961		// Skip chunks with no updates
962		if (!stageFlags || !updateRange)
963			continue;
964
965		// Add new update entry
966		if (stageFlags != lastStageFlags)
967		{
968			const VkPushConstantRange update =
969			{
970				stageFlags,	// VkShaderStageFlags    stageFlags;
971				offset,		// deUint32              offset;
972				4u			// deUint32              size;
973			};
974
975			pushConstantUpdates.push_back(update);
976			lastStageFlags = stageFlags;
977		}
978		// Increase current update entry size
979		else
980		{
981			DE_ASSERT(pushConstantUpdates.size() > 0u);
982			pushConstantUpdates.back().size += 4u;
983		}
984	}
985
986	return pushConstantUpdates;
987}
988
989void PushConstantGraphicsOverlapTestInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
990{
991	const DeviceInterface&				vk = m_context.getDeviceInterface();
992	const std::vector<VkPushConstantRange> pushConstantUpdates = getPushConstantUpdates();
993
994	m_referenceData.resize(m_colorData.size(), 0.0f);
995
996	m_context.getTestContext().getLog() << tcu::TestLog::Section("Updates", "Push constant updates");
997
998	for (deUint32 pushNdx = 0u; pushNdx < pushConstantUpdates.size(); pushNdx++)
999	{
1000		m_context.getTestContext().getLog()
1001			<< tcu::TestLog::Message
1002			<< "VkShaderStageFlags    stageFlags    " << getShaderStageNameStr(pushConstantUpdates[pushNdx].stageFlags) << ",\n"
1003			<< "deUint32              offset        " << pushConstantUpdates[pushNdx].offset << ",\n"
1004			<< "deUint32              size          " << pushConstantUpdates[pushNdx].size << ",\n"
1005			<< "const void*           pValues       " << &m_colorData[pushConstantUpdates[pushNdx].offset / 2u] << "\n"
1006			<< tcu::TestLog::EndMessage;
1007
1008		vk.cmdPushConstants(cmdBuffer, pipelineLayout, pushConstantUpdates[pushNdx].stageFlags, pushConstantUpdates[pushNdx].offset, pushConstantUpdates[pushNdx].size, &m_colorData[pushConstantUpdates[pushNdx].offset / 2u]);
1009
1010		// Copy push constant values to reference buffer
1011		DE_ASSERT((pushConstantUpdates[pushNdx].offset / 2u + pushConstantUpdates[pushNdx].size) < 4u * m_colorData.size());
1012		deMemcpy(&m_referenceData.at(pushConstantUpdates[pushNdx].offset / 4u), &m_colorData.at(pushConstantUpdates[pushNdx].offset / 2u), pushConstantUpdates[pushNdx].size);
1013	}
1014
1015	m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
1016}
1017
1018void PushConstantGraphicsOverlapTestInstance::setReferenceColor (tcu::Vec4 initColor)
1019{
1020	tcu::Vec4 expectedColor = initColor;
1021
1022	// Calculate reference color
1023	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1024	{
1025		const deUint32	offset = m_pushConstantRange[rangeNdx].range.offset / 4u;
1026		const deUint32	size = m_pushConstantRange[rangeNdx].range.size / 4u;
1027		const deUint32	numComponents = (size < 4u) ? size : 4u;
1028		const deUint32	colorNdx = (offset + size - numComponents);
1029
1030		for (deUint32 componentNdx = 0u; componentNdx < numComponents; componentNdx++)
1031			expectedColor[componentNdx] += m_referenceData[colorNdx + componentNdx];
1032	}
1033
1034	expectedColor = tcu::min(tcu::mod(expectedColor, tcu::Vec4(2.0f)), 2.0f - tcu::mod(expectedColor, tcu::Vec4(2.0f)));
1035
1036	for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1037	{
1038		m_vertices[vertexNdx].color.xyzw() = expectedColor;
1039	}
1040}
1041
1042class PushConstantGraphicsTest : public vkt::TestCase
1043{
1044public:
1045							PushConstantGraphicsTest	(tcu::TestContext&					testContext,
1046														 const std::string&					name,
1047														 const PipelineConstructionType		pipelineConstructionType,
1048														 const deUint32						rangeCount,
1049														 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
1050														 const deBool						multipleUpdate,
1051														 const IndexType					indexType);
1052	virtual					~PushConstantGraphicsTest	(void);
1053
1054
1055	virtual void			checkSupport				(Context &context) const;
1056	virtual void			initPrograms				(SourceCollections& sourceCollections) const = 0;
1057	virtual TestInstance*	createInstance				(Context& context) const = 0;
1058	RangeSizeCase			getRangeSizeCase			(deUint32 rangeSize) const;
1059
1060protected:
1061	const PipelineConstructionType	m_pipelineConstructionType;
1062	const deUint32					m_rangeCount;
1063	PushConstantData				m_pushConstantRange[MAX_RANGE_COUNT];
1064	const deBool					m_multipleUpdate;
1065	const IndexType					m_indexType;
1066};
1067
1068PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext&					testContext,
1069													const std::string&					name,
1070													const PipelineConstructionType		pipelineConstructionType,
1071													const deUint32						rangeCount,
1072													const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
1073													const deBool						multipleUpdate,
1074													const IndexType						indexType)
1075	: vkt::TestCase					(testContext, name)
1076	, m_pipelineConstructionType	(pipelineConstructionType)
1077	, m_rangeCount					(rangeCount)
1078	, m_multipleUpdate				(multipleUpdate)
1079	, m_indexType					(indexType)
1080{
1081	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
1082}
1083
1084PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
1085{
1086}
1087
1088void PushConstantGraphicsTest::checkSupport(Context &context) const
1089{
1090	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
1091}
1092
1093RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
1094{
1095	switch (rangeSize)
1096	{
1097		case 8:
1098			return SIZE_CASE_8;
1099		case 4:
1100			return SIZE_CASE_4;
1101		case 12:
1102			return SIZE_CASE_12;
1103		case 16:
1104			return SIZE_CASE_16;
1105		case 32:
1106			return SIZE_CASE_32;
1107		case 36:
1108			return SIZE_CASE_36;
1109		case 48:
1110			return SIZE_CASE_48;
1111		case 128:
1112			return SIZE_CASE_128;
1113		default:
1114			DE_FATAL("Range size unsupported yet");
1115			return SIZE_CASE_UNSUPPORTED;
1116	}
1117}
1118
1119class PushConstantGraphicsDisjointTest : public PushConstantGraphicsTest
1120{
1121public:
1122							PushConstantGraphicsDisjointTest	(tcu::TestContext&					testContext,
1123																 const std::string&					name,
1124																 const PipelineConstructionType		pipelineConstructionType,
1125																 const deUint32						rangeCount,
1126																 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
1127																 const deBool						multipleUpdate,
1128																 const IndexType					indexType);
1129	virtual					~PushConstantGraphicsDisjointTest	(void);
1130
1131	virtual void			initPrograms						(SourceCollections& sourceCollections) const;
1132	virtual TestInstance*	createInstance						(Context& context) const;
1133};
1134
1135PushConstantGraphicsDisjointTest::PushConstantGraphicsDisjointTest (tcu::TestContext&				testContext,
1136																	const std::string&				name,
1137																	const PipelineConstructionType	pipelineConstructionType,
1138																	const deUint32					rangeCount,
1139																	const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
1140																	const deBool					multipleUpdate,
1141																	const IndexType					indexType)
1142	: PushConstantGraphicsTest (testContext, name, pipelineConstructionType, rangeCount, pushConstantRange, multipleUpdate, indexType)
1143{
1144}
1145
1146PushConstantGraphicsDisjointTest::~PushConstantGraphicsDisjointTest (void)
1147{
1148}
1149
1150void PushConstantGraphicsDisjointTest::initPrograms (SourceCollections& sourceCollections) const
1151{
1152	std::ostringstream	vertexSrc;
1153	std::ostringstream	fragmentSrc;
1154	std::ostringstream	geometrySrc;
1155	std::ostringstream	tessControlSrc;
1156	std::ostringstream	tessEvaluationSrc;
1157
1158	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1159	{
1160		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1161		{
1162			vertexSrc << "#version 450\n"
1163					  << "layout(location = 0) in highp vec4 position;\n"
1164					  << "layout(location = 1) in highp vec4 color;\n"
1165					  << "layout(location = 0) out highp vec4 vtxColor;\n"
1166					  << "out gl_PerVertex { vec4 gl_Position; };\n"
1167					  << "layout(push_constant) uniform Material {\n";
1168
1169			switch (m_indexType)
1170			{
1171				case INDEX_TYPE_CONST_LITERAL:
1172					switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1173					{
1174						case SIZE_CASE_4:
1175							vertexSrc << "int kind;\n"
1176									  << "} matInst;\n";
1177							break;
1178						case SIZE_CASE_16:
1179							vertexSrc << "vec4 color;\n"
1180									  << "} matInst;\n"
1181									  << "layout(std140, binding = 0) uniform UniformBuf {\n"
1182									  << "vec4 element;\n"
1183									  << "} uniformBuf;\n";
1184							break;
1185						case SIZE_CASE_32:
1186							vertexSrc << "vec4 color[2];\n"
1187									  << "} matInst;\n";
1188							break;
1189						case SIZE_CASE_48:
1190							vertexSrc << "int unused1;\n"
1191									  << "vec4 unused2;\n"
1192									  << "vec4 color;\n"
1193									  << "} matInst;\n";
1194							break;
1195						case SIZE_CASE_128:
1196							vertexSrc << "vec4 color[8];\n"
1197									  << "} matInst;\n";
1198							break;
1199						default:
1200							DE_FATAL("Not implemented yet");
1201							break;
1202					}
1203					break;
1204				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1205					vertexSrc << "    layout(offset = 0)  vec4 index; \n"
1206							  << "    layout(offset = 16) vec4 vecType; \n"
1207							  << "    layout(offset = 32) mat2 matType; \n"
1208							  << "    layout(offset = 48) float[4] arrType; \n"
1209							  << "} matInst;\n";
1210					break;
1211				default:
1212					DE_FATAL("Unhandled IndexType");
1213					break;
1214			}
1215
1216			vertexSrc << "void main()\n"
1217					  << "{\n"
1218					  << "	gl_Position = position;\n";
1219
1220			switch (m_indexType)
1221			{
1222				case INDEX_TYPE_CONST_LITERAL:
1223					switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1224					{
1225						case SIZE_CASE_4:
1226							vertexSrc << "switch (matInst.kind) {\n"
1227									  << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
1228									  << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
1229									  << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
1230									  << "default: vtxColor = color; break;}\n"
1231									  << "}\n";
1232							break;
1233						case SIZE_CASE_16:
1234							vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
1235									  << "}\n";
1236							break;
1237						case SIZE_CASE_32:
1238							vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
1239									  << "}\n";
1240							break;
1241						case SIZE_CASE_48:
1242							vertexSrc << "vtxColor = matInst.color;\n"
1243									  << "}\n";
1244							break;
1245						case SIZE_CASE_128:
1246							vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
1247									  << "for (int i = 0; i < 8; i++)\n"
1248									  << "{\n"
1249									  << "  color = color + matInst.color[i];\n"
1250									  << "}\n"
1251									  << "vtxColor = color * 0.125;\n"
1252									  << "}\n";
1253							break;
1254						default:
1255							DE_FATAL("Not implemented yet");
1256							break;
1257					}
1258					break;
1259				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1260					{
1261						vertexSrc << "    vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1262								  // Mix in gl_Position to (hopefully) prevent optimizing our index away
1263								  << "    int vec_selector = int(abs(gl_Position.x) * 0.0000001 + 0);\n"
1264								  << "    int mat_selector = int(abs(gl_Position.x) * 0.0000001 + 1);\n"
1265								  << "    int arr_selector = int(abs(gl_Position.x) * 0.0000001 + 2);\n";
1266
1267						// Use the dynamic index to pull our real index value from push constants
1268						// Then use that value to index into three variable types
1269						std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1270						std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1271						std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1272
1273						// Test vector indexing
1274						vertexSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1275								  << "        vtxColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1276
1277						// Test matrix indexing
1278						vertexSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1279								  << "        vtxColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1280
1281						// Test array indexing
1282						vertexSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1283								  << "        vtxColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1284
1285						vertexSrc << "}\n";
1286					}
1287					break;
1288				default:
1289					DE_FATAL("Unhandled IndexType");
1290					break;
1291			}
1292
1293			sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
1294		}
1295
1296		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1297		{
1298			tessControlSrc << "#version 450\n"
1299						   << "layout (vertices = 3) out;\n"
1300						   << "layout(push_constant) uniform TessLevel {\n"
1301						   << "    layout(offset = 24) int level;\n"
1302						   << "} tessLevel;\n"
1303						   << "layout(location = 0) in highp vec4 color[];\n"
1304						   << "layout(location = 0) out highp vec4 vtxColor[];\n"
1305						   << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1306						   << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
1307						   << "void main()\n"
1308						   << "{\n"
1309						   << "  gl_TessLevelInner[0] = tessLevel.level;\n"
1310						   << "  gl_TessLevelOuter[0] = tessLevel.level;\n"
1311						   << "  gl_TessLevelOuter[1] = tessLevel.level;\n"
1312						   << "  gl_TessLevelOuter[2] = tessLevel.level;\n"
1313						   << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1314						   << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1315						   << "}\n";
1316
1317			sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
1318		}
1319
1320		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1321		{
1322			tessEvaluationSrc << "#version 450\n"
1323							  << "layout (triangles) in;\n"
1324							  << "layout(push_constant) uniform Material {\n"
1325							  << "    layout(offset = 32) vec4 color;\n"
1326							  << "} matInst;\n"
1327							  << "layout(location = 0) in highp vec4 color[];\n"
1328							  << "layout(location = 0) out highp vec4 vtxColor;\n"
1329							  << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1330							  << "out gl_PerVertex { vec4 gl_Position; };\n"
1331							  << "void main()\n"
1332							  << "{\n"
1333							  << "  gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
1334							  << "  vtxColor = matInst.color;\n"
1335							  << "}\n";
1336
1337			sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
1338		}
1339
1340		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1341		{
1342			geometrySrc << "#version 450\n"
1343						<< "layout(triangles) in;\n"
1344						<< "layout(triangle_strip, max_vertices=3) out;\n"
1345						<< "layout(push_constant) uniform Material {\n"
1346						<< "    layout(offset = 20) int kind;\n"
1347						<< "} matInst;\n"
1348						<< "layout(location = 0) in highp vec4 color[];\n"
1349						<< "layout(location = 0) out highp vec4 vtxColor;\n"
1350						<< "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
1351						<< "out gl_PerVertex { vec4 gl_Position; };\n"
1352						<< "void main()\n"
1353						<< "{\n"
1354						<< "  for(int i=0; i<3; i++)\n"
1355						<< "  {\n"
1356						<< "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
1357						<< "    gl_Position.w = gl_in[i].gl_Position.w;\n"
1358						<< "    vtxColor = color[i];\n"
1359						<< "    EmitVertex();\n"
1360						<< "  }\n"
1361						<< "  EndPrimitive();\n"
1362						<< "}\n";
1363
1364			sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
1365		}
1366
1367		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1368		{
1369			fragmentSrc << "#version 450\n"
1370						<< "layout(location = 0) in highp vec4 vtxColor;\n"
1371						<< "layout(location = 0) out highp vec4 fragColor;\n"
1372						<< "layout(push_constant) uniform Material {\n";
1373
1374			switch (m_indexType)
1375			{
1376				case INDEX_TYPE_CONST_LITERAL:
1377					if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1378					{
1379						fragmentSrc << "    layout(offset = 0) int kind; \n"
1380									<< "} matInst;\n";
1381					}
1382					else
1383					{
1384						fragmentSrc << "    layout(offset = 16) int kind;\n"
1385									<< "} matInst;\n";
1386					}
1387
1388					fragmentSrc << "void main (void)\n"
1389						<< "{\n"
1390						<< "    switch (matInst.kind) {\n"
1391						<< "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
1392						<< "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
1393						<< "    case 2: fragColor = vtxColor; break;\n"
1394						<< "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
1395						<< "}\n";
1396					break;
1397				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1398					{
1399						fragmentSrc << "    layout(offset = 0)  vec4 index; \n"
1400									<< "    layout(offset = 16) vec4 vecType; \n"
1401									<< "    layout(offset = 32) mat2 matType; \n"
1402									<< "    layout(offset = 48) float[4] arrType; \n"
1403									<< "} matInst;\n";
1404
1405						fragmentSrc << "void main (void)\n"
1406									<< "{\n"
1407									<< "    fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1408
1409									// Mix in gl_FragCoord to (hopefully) prevent optimizing our index away
1410									<< "    int vec_selector = int(gl_FragCoord.x * 0.0000001 + 0);\n"
1411									<< "    int mat_selector = int(gl_FragCoord.x * 0.0000001 + 1);\n"
1412									<< "    int arr_selector = int(gl_FragCoord.x * 0.0000001 + 2);\n";
1413
1414						// Use the dynamic index to pull our real index value from push constants
1415						// Then use that value to index into three variable types
1416						std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1417						std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1418						std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1419
1420						// Test vector indexing
1421						fragmentSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1422									<< "        fragColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1423
1424						// Test matrix indexing
1425						fragmentSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1426									<< "        fragColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1427
1428						// Test array indexing
1429						fragmentSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1430									<< "        fragColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1431
1432						fragmentSrc << "}\n";
1433					}
1434					break;
1435				default:
1436					DE_FATAL("Unhandled IndexType");
1437					break;
1438			}
1439
1440			sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1441		}
1442	}
1443
1444	// add a pass through fragment shader if it's not activated in push constant ranges
1445	if (fragmentSrc.str().empty())
1446	{
1447		fragmentSrc << "#version 450\n"
1448					<< "layout(location = 0) in highp vec4 vtxColor;\n"
1449					<< "layout(location = 0) out highp vec4 fragColor;\n"
1450					<< "void main (void)\n"
1451					<< "{\n"
1452					<< "	fragColor = vtxColor;\n"
1453					<< "}\n";
1454
1455		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1456	}
1457}
1458
1459TestInstance* PushConstantGraphicsDisjointTest::createInstance (Context& context) const
1460{
1461	return new PushConstantGraphicsDisjointInstance(context, m_pipelineConstructionType, m_rangeCount, m_pushConstantRange, m_multipleUpdate, m_indexType);
1462}
1463
1464class PushConstantGraphicsOverlapTest : public PushConstantGraphicsTest
1465{
1466public:
1467							PushConstantGraphicsOverlapTest		(tcu::TestContext&					testContext,
1468																 const std::string&					name,
1469																 const PipelineConstructionType		pipelineConstructionType,
1470																 const deUint32						rangeCount,
1471																 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT]);
1472	virtual					~PushConstantGraphicsOverlapTest	(void);
1473	std::string				getPushConstantDeclarationStr		(VkShaderStageFlags shaderStage) const;
1474	virtual void			initPrograms						(SourceCollections& sourceCollections) const;
1475	virtual TestInstance*	createInstance						(Context& context) const;
1476};
1477
1478PushConstantGraphicsOverlapTest::PushConstantGraphicsOverlapTest (tcu::TestContext&					testContext,
1479																  const std::string&				name,
1480																  const PipelineConstructionType	pipelineConstructionType,
1481																  const deUint32					rangeCount,
1482																  const PushConstantData			pushConstantRange[MAX_RANGE_COUNT])
1483	: PushConstantGraphicsTest (testContext, name, pipelineConstructionType, rangeCount, pushConstantRange, false, INDEX_TYPE_CONST_LITERAL)
1484{
1485}
1486
1487PushConstantGraphicsOverlapTest::~PushConstantGraphicsOverlapTest (void)
1488{
1489}
1490
1491std::string PushConstantGraphicsOverlapTest::getPushConstantDeclarationStr (VkShaderStageFlags shaderStage) const
1492{
1493	std::stringstream src;
1494
1495	src	<< "layout(push_constant) uniform Material\n"
1496		<< "{\n";
1497
1498	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1499	{
1500		if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStage)
1501		{
1502			switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1503			{
1504				case SIZE_CASE_4:
1505					src	<< "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") float color;\n";
1506					break;
1507				case SIZE_CASE_8:
1508					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec2 color;\n";
1509					break;
1510				case SIZE_CASE_12:
1511					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec3 color;\n";
1512					break;
1513				case SIZE_CASE_16:
1514					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color;\n";
1515					break;
1516				case SIZE_CASE_32:
1517					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[2];\n";
1518					break;
1519				case SIZE_CASE_36:
1520					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") int unused1;\n"
1521						<< "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 4) << ") vec4 unused2;\n"
1522						<< "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 20) << ") vec4 color;\n";
1523					break;
1524				case SIZE_CASE_128:
1525					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[8];\n";
1526					break;
1527				default:
1528					DE_FATAL("Not implemented");
1529					break;
1530			}
1531		}
1532	}
1533
1534	src	<< "} matInst;\n";
1535
1536	return src.str();
1537}
1538
1539std::string getSwizzleStr (deUint32 size)
1540{
1541	switch (size)
1542	{
1543		case 4:		return ".x";
1544		case 8:		return ".xy";
1545		case 12:	return ".xyz";
1546		case 16:
1547		case 32:
1548		case 36:
1549		case 128:	return "";
1550		default:	DE_FATAL("Not implemented");
1551					return "";
1552	}
1553}
1554
1555std::string getColorReadStr (deUint32 size)
1556{
1557	// Always read the last element from array types
1558	const std::string	arrayNdx		= (size == 128u)	? "[7]"
1559										: (size == 32u)		? "[1]"
1560										: "";
1561	const std::string	colorReadStr	= getSwizzleStr(size) + " += matInst.color" + arrayNdx + ";\n";
1562
1563	return colorReadStr;
1564}
1565
1566void PushConstantGraphicsOverlapTest::initPrograms (SourceCollections& sourceCollections) const
1567{
1568	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1569	{
1570		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1571		{
1572			const std::string source =
1573				"#version 450\n"
1574				"layout(location = 0) in highp vec4 position;\n"
1575				"layout(location = 1) in highp vec4 inColor;\n"
1576				"layout(location = 0) out highp vec4 vtxColor;\n"
1577				"out gl_PerVertex\n"
1578				"{\n"
1579				"    vec4 gl_Position;\n"
1580				"};\n"
1581				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_VERTEX_BIT) +
1582				"void main()\n"
1583				"{\n"
1584				"    gl_Position = position;\n"
1585				"    vec4 color = inColor;\n"
1586				"    color" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1587				"    vtxColor = color;\n"
1588				"}\n";
1589
1590			sourceCollections.glslSources.add("color_vert") << glu::VertexSource(source);
1591		}
1592
1593		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1594		{
1595			const std::string source =
1596				"#version 450\n"
1597				"layout (vertices = 3) out;\n"
1598				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) +
1599				"layout(location = 0) in highp vec4 color[];\n"
1600				"layout(location = 0) out highp vec4 vtxColor[];\n"
1601				"in gl_PerVertex\n"
1602				"{\n"
1603				"    vec4 gl_Position;\n"
1604				"} gl_in[gl_MaxPatchVertices];\n"
1605				"out gl_PerVertex\n"
1606				"{\n"
1607				"    vec4 gl_Position;\n"
1608				"} gl_out[];\n"
1609				"void main()\n"
1610				"{\n"
1611				"    gl_TessLevelInner[0] = 2.0;\n"
1612				"    gl_TessLevelOuter[0] = 2.0;\n"
1613				"    gl_TessLevelOuter[1] = 2.0;\n"
1614				"    gl_TessLevelOuter[2] = 2.0;\n"
1615				"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1616				"    vec4 outColor = color[gl_InvocationID];\n"
1617				"    outColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1618				"    vtxColor[gl_InvocationID] = outColor;\n"
1619				"}\n";
1620
1621			sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(source);
1622		}
1623
1624		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1625		{
1626			const std::string source =
1627				"#version 450\n"
1628				"layout (triangles) in;\n"
1629				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) +
1630				"layout(location = 0) in highp vec4 color[];\n"
1631				"layout(location = 0) out highp vec4 vtxColor;\n"
1632				"in gl_PerVertex\n"
1633				"{\n"
1634				"    vec4 gl_Position;\n"
1635				"} gl_in[gl_MaxPatchVertices];\n"
1636				"out gl_PerVertex\n"
1637				"{\n"
1638				"    vec4 gl_Position;\n"
1639				"};\n"
1640				"void main()\n"
1641				"{\n"
1642				"    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
1643				"    vtxColor = gl_TessCoord.x * color[0] + gl_TessCoord.y * color[1] + gl_TessCoord.z * color[2];\n"
1644				"    vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1645				"}\n";
1646
1647			sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(source);
1648		}
1649
1650		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1651		{
1652			const std::string source =
1653				"#version 450\n"
1654				"layout(triangles) in;\n"
1655				"layout(triangle_strip, max_vertices=3) out;\n"
1656				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_GEOMETRY_BIT) +
1657				"layout(location = 0) in highp vec4 color[];\n"
1658				"layout(location = 0) out highp vec4 vtxColor;\n"
1659				"in gl_PerVertex\n"
1660				"{\n"
1661				"    vec4 gl_Position;\n"
1662				"} gl_in[];\n"
1663				"out gl_PerVertex\n"
1664				"{\n"
1665				"    vec4 gl_Position;\n"
1666				"};\n"
1667				"void main()\n"
1668				"{\n"
1669				"    for(int i = 0; i < 3; i++)\n"
1670				"    {\n"
1671				"        gl_Position.xyz = gl_in[i].gl_Position.xyz / 2.0;\n"
1672				"        gl_Position.w = gl_in[i].gl_Position.w;\n"
1673				"        vtxColor = color[i];\n"
1674				"        vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1675				"        EmitVertex();\n"
1676				"    }\n"
1677				"    EndPrimitive();\n"
1678				"}\n";
1679
1680			sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(source);
1681		}
1682
1683		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1684		{
1685			const std::string source =
1686				"#version 450\n"
1687				"layout(location = 0) in highp vec4 vtxColor;\n"
1688				"layout(location = 0) out highp vec4 fragColor;\n"
1689				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_FRAGMENT_BIT) +
1690				"void main (void)\n"
1691				"{\n"
1692				"    fragColor = vtxColor;\n"
1693				"    fragColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1694				"    fragColor = min(mod(fragColor, 2.0), 2.0 - mod(fragColor, 2.0));\n"
1695				"}\n";
1696
1697			sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(source);
1698		}
1699	}
1700}
1701
1702TestInstance* PushConstantGraphicsOverlapTest::createInstance (Context& context) const
1703{
1704	return new PushConstantGraphicsOverlapTestInstance(context, m_pipelineConstructionType, m_rangeCount, m_pushConstantRange, false, INDEX_TYPE_CONST_LITERAL);
1705}
1706
1707class PushConstantComputeTest : public vkt::TestCase
1708{
1709public:
1710							PushConstantComputeTest		(tcu::TestContext&		testContext,
1711														 const std::string&		name,
1712														 const ComputeTestType	testType,
1713														 const PushConstantData	pushConstantRange);
1714	virtual					~PushConstantComputeTest	(void);
1715	virtual void			initPrograms				(SourceCollections& sourceCollections) const;
1716	virtual TestInstance*	createInstance				(Context& context) const;
1717	virtual void			checkSupport				(Context& context) const;
1718
1719private:
1720	const ComputeTestType	m_testType;
1721	const PushConstantData	m_pushConstantRange;
1722};
1723
1724class PushConstantComputeTestInstance : public vkt::TestInstance
1725{
1726public:
1727							PushConstantComputeTestInstance		(Context&				context,
1728																 const ComputeTestType	testType,
1729																 const PushConstantData	pushConstantRange);
1730	virtual					~PushConstantComputeTestInstance	(void);
1731	virtual tcu::TestStatus	iterate								(void);
1732
1733private:
1734	const ComputeTestType			m_testType;
1735	const PushConstantData			m_pushConstantRange;
1736
1737	Move<VkBuffer>					m_outBuffer;
1738	de::MovePtr<Allocation>			m_outBufferAlloc;
1739	Move<VkDescriptorPool>			m_descriptorPool;
1740	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1741	Move<VkDescriptorSet>			m_descriptorSet;
1742
1743	Move<VkPipelineLayout>			m_pipelineLayout;
1744	Move<VkPipeline>				m_computePipelines;
1745
1746	Move<VkShaderModule>			m_computeShaderModule;
1747
1748	Move<VkCommandPool>				m_cmdPool;
1749	Move<VkCommandBuffer>			m_cmdBuffer;
1750};
1751
1752PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext&			testContext,
1753												  const std::string&		name,
1754												  const ComputeTestType		testType,
1755												  const PushConstantData	pushConstantRange)
1756	: vkt::TestCase			(testContext, name)
1757	, m_testType			(testType)
1758	, m_pushConstantRange	(pushConstantRange)
1759{
1760}
1761
1762PushConstantComputeTest::~PushConstantComputeTest (void)
1763{
1764}
1765
1766TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1767{
1768	return new PushConstantComputeTestInstance(context, m_testType, m_pushConstantRange);
1769}
1770
1771void PushConstantComputeTest::checkSupport(Context& context) const
1772{
1773	if (CTT_UNINITIALIZED == m_testType)
1774		context.requireDeviceFunctionality("VK_KHR_maintenance4");
1775}
1776
1777void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1778{
1779	std::ostringstream	computeSrc;
1780
1781	computeSrc << "#version 450\n"
1782			   << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1783			   << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1784			   << "  vec4 elements[];\n"
1785			   << "} outData;\n"
1786			   << "layout(push_constant) uniform Material{\n"
1787			   << "  vec4 element;\n"
1788			   << "} matInst;\n"
1789			   << "void main (void)\n"
1790			   << "{\n"
1791			   << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1792			   << "}\n";
1793
1794	sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1795}
1796
1797PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context&					context,
1798																  const ComputeTestType		testType,
1799																  const PushConstantData	pushConstantRange)
1800	: vkt::TestInstance		(context)
1801	, m_testType			(testType)
1802	, m_pushConstantRange	(pushConstantRange)
1803{
1804	const DeviceInterface&		vk					= context.getDeviceInterface();
1805	const VkDevice				vkDevice			= context.getDevice();
1806	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1807	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1808
1809	// Create pipeline layout
1810	{
1811		// create push constant range
1812		VkPushConstantRange	pushConstantRanges;
1813		pushConstantRanges.stageFlags	= m_pushConstantRange.range.shaderStage;
1814		pushConstantRanges.offset		= m_pushConstantRange.range.offset;
1815		pushConstantRanges.size			= m_pushConstantRange.range.size;
1816
1817		// create descriptor set layout
1818		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1819
1820		// create descriptor pool
1821		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1822
1823		// create uniform buffer
1824		const VkDeviceSize			bufferSize			= sizeof(tcu::Vec4) * 8;
1825		const VkBufferCreateInfo	bufferCreateInfo	=
1826		{
1827			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
1828			DE_NULL,													// const void*			pNext;
1829			0u,															// VkBufferCreateFlags	flags
1830			bufferSize,													// VkDeviceSize			size;
1831			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,							// VkBufferUsageFlags	usage;
1832			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
1833			1u,															// deUint32				queueFamilyCount;
1834			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
1835		};
1836
1837		m_outBuffer			= createBuffer(vk, vkDevice, &bufferCreateInfo);
1838		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1839		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1840
1841		// create and update descriptor set
1842		const VkDescriptorSetAllocateInfo allocInfo =
1843		{
1844			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                             sType;
1845			DE_NULL,													// const void*                                 pNext;
1846			*m_descriptorPool,											// VkDescriptorPool                            descriptorPool;
1847			1u,															// uint32_t                                    setLayoutCount;
1848			&(*m_descriptorSetLayout),									// const VkDescriptorSetLayout*                pSetLayouts;
1849		};
1850		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
1851
1852		const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1853
1854		DescriptorSetUpdateBuilder()
1855			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1856			.update(vk, vkDevice);
1857
1858		// create pipeline layout
1859		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
1860		{
1861			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1862			DE_NULL,											// const void*					pNext;
1863			0u,													// VkPipelineLayoutCreateFlags	flags;
1864			1u,													// deUint32						descriptorSetCount;
1865			&(*m_descriptorSetLayout),							// const VkDescriptorSetLayout*	pSetLayouts;
1866			1u,													// deUint32						pushConstantRangeCount;
1867			&pushConstantRanges									// const VkPushConstantRange*	pPushConstantRanges;
1868		};
1869
1870		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1871	}
1872
1873	// create pipeline
1874	{
1875		m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1876
1877		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
1878		{
1879			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1880			DE_NULL,												// const void*							pNext;
1881			0u,														// VkPipelineShaderStageCreateFlags		flags;
1882			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1883			*m_computeShaderModule,									// VkShaderModule						module;
1884			"main",													// const char*							pName;
1885			DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
1886		};
1887
1888		const VkComputePipelineCreateInfo		createInfo	=
1889		{
1890			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType                             sType;
1891			DE_NULL,												// const void*                                 pNext;
1892			0u,														// VkPipelineCreateFlags                       flags;
1893			stageCreateInfo,										// VkPipelineShaderStageCreateInfo             stage;
1894			*m_pipelineLayout,										// VkPipelineLayout                            layout;
1895			(VkPipeline)0,											// VkPipeline                                  basePipelineHandle;
1896			0u,														// int32_t                                     basePipelineIndex;
1897		};
1898
1899		m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1900	}
1901
1902	// Create command pool
1903	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1904
1905	// Create command buffer
1906	{
1907		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1908
1909		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1910
1911		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1912		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1913
1914		// update push constant
1915		if (CTT_UNINITIALIZED != m_testType)
1916		{
1917			tcu::Vec4	value	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1918			vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1919		}
1920
1921		vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1922
1923		const VkBufferMemoryBarrier buf_barrier =
1924		{
1925			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,				//    VkStructureType    sType;
1926			DE_NULL,												//    const void*        pNext;
1927			VK_ACCESS_SHADER_WRITE_BIT,								//    VkAccessFlags      srcAccessMask;
1928			VK_ACCESS_HOST_READ_BIT,								//    VkAccessFlags      dstAccessMask;
1929			VK_QUEUE_FAMILY_IGNORED,								//    uint32_t           srcQueueFamilyIndex;
1930			VK_QUEUE_FAMILY_IGNORED,								//    uint32_t           dstQueueFamilyIndex;
1931			*m_outBuffer,											//    VkBuffer           buffer;
1932			0,														//    VkDeviceSize       offset;
1933			VK_WHOLE_SIZE											//    VkDeviceSize       size;
1934		};
1935
1936		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, DE_NULL, 1, &buf_barrier, 0, DE_NULL);
1937
1938		endCommandBuffer(vk, *m_cmdBuffer);
1939	}
1940}
1941
1942PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1943{
1944}
1945
1946tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1947{
1948	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1949	const VkDevice				vkDevice	= m_context.getDevice();
1950	const VkQueue				queue		= m_context.getUniversalQueue();
1951
1952	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1953
1954	// The test should run without crashing when reading that undefined value.
1955	// The actual value is not important, test just shouldn't crash.
1956	if (CTT_UNINITIALIZED == m_testType)
1957		return tcu::TestStatus::pass("pass");
1958
1959	invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
1960
1961	// verify result
1962	std::vector<tcu::Vec4>	expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1963	if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1964	{
1965		return tcu::TestStatus::fail("Image mismatch");
1966	}
1967	return tcu::TestStatus::pass("result image matches with reference");
1968}
1969
1970class PushConstantLifetimeTest : public vkt::TestCase
1971{
1972public:
1973	PushConstantLifetimeTest(tcu::TestContext&					testContext,
1974							 const std::string&					name,
1975							 const PipelineConstructionType		pipelineConstructionType,
1976							 const PushConstantData				pushConstantRange[MAX_RANGE_COUNT],
1977							 const std::vector<CommandData>&	cmdList);
1978
1979	virtual ~PushConstantLifetimeTest(void);
1980
1981	virtual void checkSupport(Context &context) const;
1982
1983	virtual void initPrograms(SourceCollections &sourceCollections) const;
1984
1985	virtual TestInstance *createInstance(Context &context) const;
1986
1987private:
1988	const PipelineConstructionType	m_pipelineConstructionType;
1989	PushConstantData				m_pushConstantRange[MAX_RANGE_COUNT];
1990	std::vector<CommandData>		m_cmdList;
1991};
1992
1993class PushConstantLifetimeTestInstance : public vkt::TestInstance {
1994public:
1995	PushConstantLifetimeTestInstance(Context &context,
1996			const PipelineConstructionType pipelineConstructionType,
1997			const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
1998			const std::vector<CommandData> &cmdList);
1999
2000	virtual ~PushConstantLifetimeTestInstance(void);
2001
2002	virtual tcu::TestStatus iterate(void);
2003
2004	void init(void);
2005
2006	tcu::TestStatus verify(deBool verifyGraphics, deBool verifyCompute);
2007
2008private:
2009	PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
2010	PipelineConstructionType m_pipelineConstructionType;
2011	std::vector<CommandData> m_cmdList;
2012
2013	std::vector<Vertex4RGBA> m_vertices;
2014
2015	const tcu::UVec2 m_renderSize;
2016	const VkFormat m_colorFormat;
2017
2018	VkImageCreateInfo m_colorImageCreateInfo;
2019	Move<VkImage> m_colorImage;
2020	de::MovePtr<Allocation> m_colorImageAlloc;
2021	Move<VkImageView> m_colorAttachmentView;
2022	RenderPassWrapper m_renderPass;
2023	Move<VkFramebuffer> m_framebuffer;
2024
2025	ShaderWrapper m_vertexShaderModule;
2026	ShaderWrapper m_fragmentShaderModule;
2027	ShaderWrapper m_computeShaderModule;
2028
2029	std::vector<VkPipelineShaderStageCreateInfo> m_shaderStage;
2030
2031	Move<VkBuffer> m_vertexBuffer;
2032	de::MovePtr<Allocation> m_vertexBufferAlloc;
2033
2034	Move<VkBuffer> m_outBuffer;
2035	de::MovePtr<Allocation> m_outBufferAlloc;
2036	Move<VkDescriptorPool> m_descriptorPool;
2037	Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2038	Move<VkDescriptorSet> m_descriptorSet;
2039
2040	PipelineLayoutWrapper m_pipelineLayout[3];
2041	GraphicsPipelineWrapper m_graphicsPipeline[3];
2042	Move<VkPipeline> m_computePipeline[3];
2043
2044	Move<VkCommandPool> m_cmdPool;
2045	Move<VkCommandBuffer> m_cmdBuffer;
2046};
2047
2048PushConstantLifetimeTest::PushConstantLifetimeTest(tcu::TestContext&				testContext,
2049												   const std::string&				name,
2050												   const PipelineConstructionType	pipelineConstructionType,
2051												   const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
2052												   const std::vector<CommandData>&	cmdList)
2053	: vkt::TestCase					(testContext, name)
2054	, m_pipelineConstructionType	(pipelineConstructionType)
2055	, m_cmdList						(cmdList)
2056{
2057	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
2058}
2059
2060PushConstantLifetimeTest::~PushConstantLifetimeTest(void)
2061{
2062}
2063
2064void PushConstantLifetimeTest::checkSupport(Context &context) const
2065{
2066	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
2067}
2068
2069void PushConstantLifetimeTest::initPrograms(SourceCollections &sourceCollections) const
2070{
2071	std::ostringstream	vertexSrc;
2072
2073	vertexSrc	<< "#version 450\n"
2074				<< "layout(location = 0) in highp vec4 position;\n"
2075				<< "layout(location = 1) in highp vec4 inColor;\n"
2076				<< "layout(location = 0) out highp vec4 vtxColor;\n"
2077				<< "out gl_PerVertex\n"
2078				<< "{\n"
2079				<< "  vec4 gl_Position;\n"
2080				<< "};\n"
2081				<< "layout(push_constant) uniform Material {\n"
2082				<< "    layout(offset = 16) vec4 color;\n"
2083				<< "}matInst;\n"
2084				<< "void main()\n"
2085				<< "{\n"
2086				<< "    gl_Position = position;\n"
2087				<< "    vtxColor = vec4(inColor.x + matInst.color.x,\n"
2088				<< "                    inColor.y - matInst.color.y,\n"
2089				<< "                    inColor.z + matInst.color.z,\n"
2090				<< "					inColor.w + matInst.color.w);\n"
2091				<< "}\n";
2092
2093	sourceCollections.glslSources.add("color_vert_lt") << glu::VertexSource(vertexSrc.str());
2094
2095	std::ostringstream	fragmentSrc;
2096
2097	fragmentSrc << "#version 450\n"
2098				<< "layout(location = 0) in highp vec4 vtxColor;\n"
2099				<< "layout(location = 0) out highp vec4 fragColor;\n"
2100				<< "void main (void)\n"
2101				<< "{\n"
2102				<< "    fragColor = vtxColor;\n"
2103				<< "}\n";
2104
2105	sourceCollections.glslSources.add("color_frag_lt") << glu::FragmentSource(fragmentSrc.str());
2106
2107	std::ostringstream	computeSrc;
2108
2109	computeSrc  << "#version 450\n"
2110				<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2111				<< "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
2112				<< "  vec4 elements[];\n"
2113				<< "} outData;\n"
2114				<< "layout(push_constant) uniform Material{\n"
2115				<< "    layout(offset = 16) vec4 element;\n"
2116				<< "} matInst;\n"
2117				<< "void main (void)\n"
2118				<< "{\n"
2119				<< "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
2120				<< "}\n";
2121
2122	sourceCollections.glslSources.add("compute_lt") << glu::ComputeSource(computeSrc.str());
2123}
2124
2125TestInstance* PushConstantLifetimeTest::createInstance (Context& context) const
2126{
2127	return new PushConstantLifetimeTestInstance(context, m_pipelineConstructionType, m_pushConstantRange, m_cmdList);
2128}
2129
2130PushConstantLifetimeTestInstance::PushConstantLifetimeTestInstance (Context&						context,
2131																	const PipelineConstructionType	pipelineConstructionType,
2132																	const PushConstantData			pushConstantRange[MAX_RANGE_COUNT],
2133																	const std::vector<CommandData>&	cmdList)
2134	: vkt::TestInstance				(context)
2135	, m_pipelineConstructionType	(pipelineConstructionType)
2136	, m_cmdList						(cmdList)
2137	, m_renderSize					(32, 32)
2138	, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
2139	, m_graphicsPipeline
2140	{
2141		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType },
2142		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType },
2143		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType }
2144	}
2145{
2146	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
2147}
2148
2149void PushConstantLifetimeTestInstance::init (void)
2150{
2151	const DeviceInterface		&vk = m_context.getDeviceInterface();
2152	const VkDevice				vkDevice = m_context.getDevice();
2153	const deUint32				queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2154	SimpleAllocator				memAlloc(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2155	const VkComponentMapping	componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
2156
2157	// Create color image
2158	{
2159		const VkImageCreateInfo colorImageParams =
2160			{
2161				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
2162				DE_NULL,																// const void*				pNext;
2163				0u,																		// VkImageCreateFlags		flags;
2164				VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
2165				m_colorFormat,															// VkFormat					format;
2166				{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
2167				1u,																		// deUint32					mipLevels;
2168				1u,																		// deUint32					arrayLayers;
2169				VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
2170				VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
2171				VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
2172				VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
2173				1u,																		// deUint32					queueFamilyIndexCount;
2174				&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
2175				VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
2176			};
2177
2178		m_colorImageCreateInfo = colorImageParams;
2179		m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
2180
2181		// Allocate and bind color image memory
2182		m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
2183		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
2184	}
2185
2186	// Create color attachment view
2187	{
2188		const VkImageViewCreateInfo colorAttachmentViewParams =
2189			{
2190				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType				sType;
2191				DE_NULL,										// const void*					pNext;
2192				0u,												// VkImageViewCreateFlags		flags;
2193				*m_colorImage,									// VkImage						image;
2194				VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType				viewType;
2195				m_colorFormat,									// VkFormat						format;
2196				componentMappingRGBA,							// VkChannelMapping				channels;
2197				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange		subresourceRange;
2198			};
2199
2200		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
2201	}
2202
2203	// Create render pass
2204	m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, m_colorFormat);
2205
2206	// Create framebuffer
2207	{
2208		const VkImageView attachmentBindInfos[1] =
2209			{
2210				*m_colorAttachmentView
2211			};
2212
2213		const VkFramebufferCreateInfo framebufferParams =
2214			{
2215				VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType				sType;
2216				DE_NULL,									// const void*					pNext;
2217				0u,											// VkFramebufferCreateFlags		flags;
2218				*m_renderPass,								// VkRenderPass					renderPass;
2219				1u,											// deUint32						attachmentCount;
2220				attachmentBindInfos,						// const VkImageView*			pAttachments;
2221				(deUint32)m_renderSize.x(),					// deUint32						width;
2222				(deUint32)m_renderSize.y(),					// deUint32						height;
2223				1u											// deUint32						layers;
2224			};
2225
2226		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
2227	}
2228
2229	// Create data for pipeline layout
2230	{
2231		// create descriptor set layout
2232		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
2233
2234		// create descriptor pool
2235		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2236
2237		// create storage buffer
2238		const VkDeviceSize			bufferSize			= sizeof(tcu::Vec4) * 8;
2239		const VkBufferCreateInfo	bufferCreateInfo	=
2240		{
2241			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType					sType;
2242			DE_NULL,													// const void*						pNext;
2243			0u,															// VkBufferCreateFlags				flags
2244			bufferSize,													// VkDeviceSize						size;
2245			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,							// VkBufferUsageFlags				usage;
2246			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode					sharingMode;
2247			1u,															// deUint32							queueFamilyCount;
2248			&queueFamilyIndex											// const deUint32*					pQueueFamilyIndices;
2249		};
2250
2251		m_outBuffer			= createBuffer(vk, vkDevice, &bufferCreateInfo);
2252		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
2253		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
2254
2255		// create and update descriptor set
2256		const VkDescriptorSetAllocateInfo	allocInfo				=
2257			{
2258				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// VkStructureType					sType;
2259				DE_NULL,												// const void*						pNext;
2260				*m_descriptorPool,										// VkDescriptorPool					descriptorPool;
2261				1u,														// deUint32							setLayoutCount;
2262				&(*m_descriptorSetLayout),								// const VkDescriptorSetLayout*		pSetLayouts;
2263			};
2264		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
2265
2266		const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
2267
2268		DescriptorSetUpdateBuilder()
2269				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
2270				.update(vk, vkDevice);
2271
2272		// create push constant ranges
2273		const VkPushConstantRange	pushConstantRanges[]
2274		{
2275			{
2276					m_pushConstantRange[0].range.shaderStage,
2277					m_pushConstantRange[0].range.offset,
2278					m_pushConstantRange[0].range.size
2279			},
2280			{
2281					m_pushConstantRange[1].range.shaderStage,
2282					m_pushConstantRange[1].range.offset,
2283					m_pushConstantRange[1].range.size
2284			}
2285		};
2286
2287		const VkPipelineLayoutCreateInfo pipelineLayoutParams[]
2288		{
2289			{
2290				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
2291				DE_NULL,										// const void*					pNext;
2292				0u,												// VkPipelineLayoutCreateFlags	flags;
2293				1u,												// deUint32						descriptorSetCount;
2294				&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
2295				1u,												// deUint32						pushConstantRangeCount;
2296				&(pushConstantRanges[0])
2297			},
2298			{
2299				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
2300				DE_NULL,										// const void*					pNext;
2301				0u,												// VkPipelineLayoutCreateFlags	flags;
2302				1u,												// deUint32						descriptorSetCount;
2303				&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
2304				1u,												// deUint32						pushConstantRangeCount;
2305				&(pushConstantRanges[1])
2306			}
2307		};
2308
2309		m_pipelineLayout[0] = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &(pipelineLayoutParams[0]));
2310		m_pipelineLayout[1] = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &(pipelineLayoutParams[1]));
2311	}
2312
2313	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert_lt"), 0);
2314	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_lt"), 0);
2315
2316	// Create graphics pipelines
2317	{
2318		const VkVertexInputBindingDescription vertexInputBindingDescription
2319		{
2320			0u,								// deUint32					binding;
2321			sizeof(Vertex4RGBA),			// deUint32					strideInBytes;
2322			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
2323		};
2324
2325		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[]
2326		{
2327			{
2328				0u,									// deUint32	location;
2329				0u,									// deUint32	binding;
2330				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2331				0u									// deUint32	offsetInBytes;
2332			},
2333			{
2334				1u,									// deUint32	location;
2335				0u,									// deUint32	binding;
2336				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2337				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
2338			}
2339		};
2340
2341		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
2342		{
2343			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
2344			DE_NULL,														// const void*								pNext;
2345			0u,																// vkPipelineVertexInputStateCreateFlags	flags;
2346			1u,																// deUint32									bindingCount;
2347			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2348			2u,																// deUint32									attributeCount;
2349			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2350		};
2351
2352		const VkPrimitiveTopology		topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
2353
2354		const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
2355		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
2356
2357		m_graphicsPipeline[0].setDefaultRasterizationState()
2358							 .setDefaultDepthStencilState()
2359							 .setDefaultMultisampleState()
2360							 .setDefaultColorBlendState()
2361							 .setDefaultTopology(topology)
2362							 .setupVertexInputState(&vertexInputStateParams)
2363							 .setupPreRasterizationShaderState(viewports,
2364															   scissors,
2365															   (m_pipelineLayout[0]),
2366															   *m_renderPass,
2367															   0u,
2368															   m_vertexShaderModule)
2369							 .setupFragmentShaderState((m_pipelineLayout[0]), *m_renderPass, 0u, m_fragmentShaderModule)
2370							 .setupFragmentOutputState(*m_renderPass)
2371							 .setMonolithicPipelineLayout((m_pipelineLayout[0]))
2372							 .buildPipeline();
2373
2374		m_graphicsPipeline[1].setDefaultRasterizationState()
2375							 .setDefaultDepthStencilState()
2376							 .setDefaultMultisampleState()
2377							 .setDefaultColorBlendState()
2378							 .setDefaultTopology(topology)
2379							 .setupVertexInputState(&vertexInputStateParams)
2380							 .setupPreRasterizationShaderState(viewports,
2381															   scissors,
2382															   (m_pipelineLayout[1]),
2383															   *m_renderPass,
2384															   0u,
2385															   m_vertexShaderModule)
2386							 .setupFragmentShaderState((m_pipelineLayout[1]), *m_renderPass, 0u, m_fragmentShaderModule)
2387							 .setupFragmentOutputState(*m_renderPass)
2388							 .setMonolithicPipelineLayout((m_pipelineLayout[1]))
2389							 .buildPipeline();
2390	}
2391
2392	// Create vertex buffer
2393	{
2394		m_vertices			= createQuad(1.0f, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
2395
2396		const VkBufferCreateInfo vertexBufferParams =
2397		{
2398			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
2399			DE_NULL,													// const void*			pNext;
2400			0u,															// VkBufferCreateFlags	flags;
2401			(VkDeviceSize) (sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
2402			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
2403			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
2404			1u,															// deUint32				queueFamilyCount;
2405			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
2406		};
2407
2408		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
2409		m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),	MemoryRequirement::HostVisible);
2410
2411		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
2412
2413		// Load vertices into vertex buffer
2414		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
2415		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
2416	}
2417
2418	// Create compute pipelines
2419	{
2420		m_computeShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("compute_lt"), 0);
2421
2422		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
2423			{
2424				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
2425				DE_NULL,												// const void*							pNext;
2426				0u,														// VkPipelineShaderStageCreateFlags		flags;
2427				VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
2428				m_computeShaderModule.getModule(),						// VkShaderModule						module;
2429				"main",													// const char*							pName;
2430				DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
2431			};
2432
2433		if (m_pushConstantRange[0].range.shaderStage & VK_SHADER_STAGE_COMPUTE_BIT)
2434		{
2435			const VkComputePipelineCreateInfo computePipelineLayoutParams =
2436				{
2437					VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType								sType;
2438					DE_NULL,												// const void*									pNext;
2439					0u,														// VkPipelineCreateFlags						flags;
2440					stageCreateInfo,										// VkPipelineShaderStageCreateInfo				stage;
2441					*m_pipelineLayout[0],									// VkPipelineLayout								layout;
2442					(VkPipeline) 0,											// VkPipeline									basePipelineHandle;
2443					0u,														// int32_t										basePipelineIndex;
2444				};
2445
2446			m_computePipeline[0] = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache) 0u, &computePipelineLayoutParams);
2447		}
2448		if (m_pushConstantRange[1].range.shaderStage & VK_SHADER_STAGE_COMPUTE_BIT)
2449		{
2450			const VkComputePipelineCreateInfo computePipelineLayoutParams =
2451				{
2452					VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType								sType;
2453					DE_NULL,												// const void*									pNext;
2454					0u,														// VkPipelineCreateFlags						flags;
2455					stageCreateInfo,										// VkPipelineShaderStageCreateInfo				stage;
2456					*m_pipelineLayout[1],									// VkPipelineLayout								layout;
2457					(VkPipeline) 0,											// VkPipeline									basePipelineHandle;
2458					0u,														// int32_t										basePipelineIndex;
2459				};
2460
2461			m_computePipeline[1] = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache) 0u, &computePipelineLayoutParams);
2462		}
2463	}
2464}
2465
2466PushConstantLifetimeTestInstance::~PushConstantLifetimeTestInstance (void)
2467{
2468
2469}
2470
2471tcu::TestStatus PushConstantLifetimeTestInstance::iterate (void)
2472{
2473	const DeviceInterface		&vk				 = m_context.getDeviceInterface();
2474	const VkDevice				vkDevice		 = m_context.getDevice();
2475	const deUint32				queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2476	const VkQueue				queue			 = m_context.getUniversalQueue();
2477
2478	deBool						verifyGraphics	 = false;
2479	deBool						verifyCompute	 = false;
2480
2481	init();
2482
2483	// Create command pool
2484	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2485
2486	// Create command buffer
2487	{
2488		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
2489
2490		// Set push constant value
2491		tcu::Vec4	value[2] =
2492				{
2493					{0.25f, 0.75f, 0.75f, 1.0f},
2494					{0.25f, 0.75f, 0.75f, 1.0f}
2495				};
2496
2497		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2498
2499		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2500
2501		for (size_t ndx = 0; ndx < m_cmdList.size(); ndx++)
2502		{
2503			const VkPushConstantRange pushConstantRange
2504				{
2505					m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.shaderStage,
2506					m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.offset,
2507					m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.size
2508				};
2509
2510			switch (m_cmdList[ndx].cType)
2511			{
2512				case CMD_PUSH_CONSTANT:
2513				{
2514					vk.cmdPushConstants(*m_cmdBuffer,
2515										*m_pipelineLayout[m_cmdList[ndx].rangeNdx],
2516										 pushConstantRange.stageFlags,
2517										 pushConstantRange.offset,
2518										 pushConstantRange.size,
2519										 &value);
2520					break;
2521				}
2522				case CMD_BIND_PIPELINE_COMPUTE:
2523				{
2524					vk.cmdBindDescriptorSets(*m_cmdBuffer,
2525											  VK_PIPELINE_BIND_POINT_COMPUTE,
2526											 *m_pipelineLayout[m_cmdList[ndx].rangeNdx],
2527											  0,
2528											  1u,
2529											  &(*m_descriptorSet),
2530											  0,
2531											  DE_NULL);
2532
2533					vk.cmdBindPipeline(*m_cmdBuffer,
2534										VK_PIPELINE_BIND_POINT_COMPUTE,
2535										*m_computePipeline[m_cmdList[ndx].rangeNdx]);
2536					break;
2537				}
2538				case CMD_BIND_PIPELINE_GRAPHICS:
2539				{
2540					m_graphicsPipeline[m_cmdList[ndx].rangeNdx].bind(*m_cmdBuffer);
2541					break;
2542				}
2543				case CMD_DRAW:
2544				{
2545					const VkDeviceSize bufferOffset = 0;
2546
2547					const VkImageMemoryBarrier prePassBarrier =
2548						{
2549							VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					//		VkStructureType			sType;
2550							DE_NULL,												//		const void*				pNext;
2551							0,														//		VkAccessFlags			srcAccessMask;
2552							VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					//		VkAccessFlags			dstAccessMask;
2553							VK_IMAGE_LAYOUT_UNDEFINED,								//		VkImageLayout			oldLayout;
2554							VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				//		VkImageLayout			newLayout;
2555							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				srcQueueFamilyIndex;
2556							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				dstQueueFamilyIndex;
2557							*m_colorImage,											//		VkImage					image;
2558							{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }			//		VkImageSubresourceRange	subresourceRange;
2559						};
2560
2561					vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &prePassBarrier);
2562
2563					m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
2564
2565					vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &bufferOffset);
2566					vk.cmdDraw(*m_cmdBuffer, (deUint32) m_vertices.size(), 1, 0, 0);
2567
2568					m_renderPass.end(vk, *m_cmdBuffer);
2569
2570					const VkImageMemoryBarrier postPassBarrier =
2571						{
2572							VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					//		VkStructureType			sType;
2573							DE_NULL,												//		const void*				pNext;
2574							VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					//		VkAccessFlags			srcAccessMask;
2575							VK_ACCESS_TRANSFER_WRITE_BIT,							//		VkAccessFlags			dstAccessMask;
2576							VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				//		VkImageLayout			oldLayout;
2577							VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				//		VkImageLayout			newLayout;
2578							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				srcQueueFamilyIndex;
2579							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				dstQueueFamilyIndex;
2580							*m_colorImage,											//		VkImage					image;
2581							{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }			//		VkImageSubresourceRange	subresourceRange;
2582						};
2583
2584					vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &postPassBarrier);
2585
2586					verifyGraphics = true;
2587					break;
2588				}
2589				case CMD_DISPATCH:
2590				{
2591
2592					vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
2593
2594					const VkBufferMemoryBarrier outputBarrier =
2595						{
2596							VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,				//		VkStructureType			sType;
2597							DE_NULL,												//		const void*				pNext;
2598							VK_ACCESS_SHADER_WRITE_BIT,								//		VkAccessFlags			srcAccessMask;
2599							VK_ACCESS_HOST_READ_BIT,								//		VkAccessFlags			dstAccessMask;
2600							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				srcQueueFamilyIndex;
2601							VK_QUEUE_FAMILY_IGNORED,								//		uint32_t				dstQueueFamilyIndex;
2602							*m_outBuffer,											//		VkBuffer				buffer;
2603							0,														//		VkDeviceSize			offset;
2604							VK_WHOLE_SIZE											//		VkDeviceSize			size;
2605						};
2606
2607					vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, DE_NULL, 1, &outputBarrier, 0, DE_NULL);
2608
2609					verifyCompute = true;
2610					break;
2611				}
2612				case CMD_UNSUPPORTED:
2613					break;
2614				default:
2615					break;
2616			}
2617		}
2618
2619		endCommandBuffer(vk, *m_cmdBuffer);
2620	}
2621
2622	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2623
2624	return verify(verifyGraphics, verifyCompute);
2625}
2626
2627tcu::TestStatus PushConstantLifetimeTestInstance::verify (deBool verifyGraphics, deBool verifyCompute)
2628{
2629	const DeviceInterface&		vk				= m_context.getDeviceInterface();
2630	const VkDevice				vkDevice		= m_context.getDevice();
2631
2632	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
2633	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
2634	const ColorVertexShader		vertexShader;
2635	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
2636	const rr::Program			program			(&vertexShader, &fragmentShader);
2637	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
2638
2639	deBool						graphicsOk		= !verifyGraphics;
2640	deBool						computeOk		= !verifyCompute;
2641
2642	// Compare result with reference image
2643	if (verifyGraphics)
2644	{
2645		// Render reference image
2646		{
2647			rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
2648			refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
2649		}
2650
2651		const VkQueue					queue				= m_context.getUniversalQueue();
2652		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
2653		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2654		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
2655
2656		graphicsOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
2657															  "IntImageCompare",
2658															  "Image comparison",
2659															  refRenderer.getAccess(),
2660															  result->getAccess(),
2661															  tcu::UVec4(2, 2, 2, 2),
2662															  tcu::IVec3(1, 1, 0),
2663															  true,
2664															  tcu::COMPARE_LOG_RESULT);
2665	}
2666
2667	// Compare compute output
2668	if (verifyCompute)
2669	{
2670		invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
2671
2672		// verify result
2673		std::vector<tcu::Vec4>	expectValue(8, tcu::Vec4(0.25f, 0.75f, 0.75f, 1.0f));
2674		if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
2675			computeOk = false;
2676		else
2677			computeOk = true;
2678	}
2679
2680	if (!graphicsOk)
2681		return tcu::TestStatus::fail("Image mismatch");
2682
2683	if (!computeOk)
2684		return tcu::TestStatus::fail("Wrong output value");
2685
2686	return tcu::TestStatus::pass("Result image matches reference");
2687}
2688
2689// The overwrite-values cases will use a 2x2 storage image and 4 separate draws or dispatches to store the color of each pixel in
2690// the image. The color will be calculated as baseColor*multiplier+colorOffset, and the base color, multiplier, color component
2691// offsets and coords will be changed with multiple push commands before each draw/dispatch, to verify overwriting multiple ranges
2692// works as expected.
2693
2694struct OverwritePushConstants
2695{
2696	tcu::IVec4	coords;				// We will only use the first two components, but an IVec4 eases matching alignments.
2697	tcu::UVec4	baseColor;
2698	tcu::UVec4	multiplier;
2699	deUint32	colorOffsets[4];
2700	tcu::UVec4	transparentGreen;
2701};
2702
2703struct OverwriteTestParams
2704{
2705	PipelineConstructionType	pipelineConstructionType;
2706	OverwritePushConstants		pushConstantValues[4];
2707	VkPipelineBindPoint			bindPoint;
2708};
2709
2710class OverwriteTestCase : public vkt::TestCase
2711{
2712public:
2713							OverwriteTestCase		(tcu::TestContext& testCtx, const std::string& name, const OverwriteTestParams& params);
2714	virtual					~OverwriteTestCase		(void) {}
2715
2716	virtual void			checkSupport			(Context &context) const;
2717	virtual void			initPrograms			(vk::SourceCollections& programCollection) const;
2718	virtual TestInstance*	createInstance			(Context& context) const;
2719
2720protected:
2721	OverwriteTestParams		m_params;
2722};
2723
2724class OverwriteTestInstance : public vkt::TestInstance
2725{
2726public:
2727								OverwriteTestInstance	(Context& context, const OverwriteTestParams& params);
2728	virtual						~OverwriteTestInstance	(void) {}
2729
2730	virtual tcu::TestStatus		iterate					(void);
2731
2732protected:
2733	OverwriteTestParams			m_params;
2734};
2735
2736OverwriteTestCase::OverwriteTestCase (tcu::TestContext& testCtx, const std::string& name, const OverwriteTestParams& params)
2737	: vkt::TestCase	(testCtx, name)
2738	, m_params		(params)
2739{}
2740
2741void OverwriteTestCase::checkSupport(Context &context) const
2742{
2743	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
2744}
2745
2746void OverwriteTestCase::initPrograms (vk::SourceCollections& programCollection) const
2747{
2748	std::ostringstream shader;
2749
2750	shader
2751		<< "#version 450\n"
2752		<< "layout (push_constant, std430) uniform PushConstants {\n"
2753		<< "    ivec4   coords;\n" // Note we will only use the .xy swizzle.
2754		<< "    uvec4   baseColor;\n"
2755		<< "    uvec4   multiplier;\n"
2756		<< "    uint    colorOffsets[4];\n"
2757		<< "    uvec4   transparentGreen;\n"
2758		<< "} pc;\n"
2759		<< "layout(rgba8ui, set=0, binding=0) uniform uimage2D simage;\n"
2760		<< "void main() {\n"
2761		<< "    uvec4   colorOffsets = uvec4(pc.colorOffsets[0], pc.colorOffsets[1], pc.colorOffsets[2], pc.colorOffsets[3]);\n"
2762		<< "    uvec4   finalColor   = pc.baseColor * pc.multiplier + colorOffsets + pc.transparentGreen;\n"
2763		<< "    imageStore(simage, pc.coords.xy, finalColor);\n"
2764		<< "}\n"
2765		;
2766
2767	if (m_params.bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE)
2768	{
2769		programCollection.glslSources.add("comp") << glu::ComputeSource(shader.str());
2770	}
2771	else if (m_params.bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
2772	{
2773		std::ostringstream vert;
2774		vert
2775			<< "#version 450\n"
2776			<< "\n"
2777			<< "void main()\n"
2778			<< "{\n"
2779			// Full-screen clockwise triangle strip with 4 vertices.
2780			<< "	const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
2781			<< "	const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
2782			<< "	gl_Position = vec4(x, y, 0.0, 1.0);\n"
2783			<< "}\n"
2784			;
2785
2786		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2787		programCollection.glslSources.add("frag") << glu::FragmentSource(shader.str());
2788	}
2789	else
2790		DE_ASSERT(false);
2791}
2792
2793TestInstance* OverwriteTestCase::createInstance (Context& context) const
2794{
2795	return new OverwriteTestInstance(context, m_params);
2796}
2797
2798OverwriteTestInstance::OverwriteTestInstance (Context& context, const OverwriteTestParams& params)
2799	: vkt::TestInstance	(context)
2800	, m_params			(params)
2801{}
2802
2803tcu::TestStatus OverwriteTestInstance::iterate (void)
2804{
2805	const auto& vki			= m_context.getInstanceInterface();
2806	const auto&	vkd			= m_context.getDeviceInterface();
2807	const auto	physDevice	= m_context.getPhysicalDevice();
2808	const auto	device		= m_context.getDevice();
2809	auto&		alloc		= m_context.getDefaultAllocator();
2810	const auto	queue		= m_context.getUniversalQueue();
2811	const auto	qIndex		= m_context.getUniversalQueueFamilyIndex();
2812	const bool	isComp		= (m_params.bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE);
2813
2814	const VkShaderStageFlags	stageFlags	= (isComp ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT);
2815	const VkPipelineStageFlags	writeStages	= (isComp ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
2816	const auto					imageFormat	= VK_FORMAT_R8G8B8A8_UINT;
2817	const auto					imageExtent	= makeExtent3D(2u, 2u, 1u);
2818
2819	// Storage image.
2820	const VkImageCreateInfo imageCreateInfo =
2821	{
2822		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							//	VkStructureType			sType;
2823		nullptr,														//	const void*				pNext;
2824		0u,																//	VkImageCreateFlags		flags;
2825		VK_IMAGE_TYPE_2D,												//	VkImageType				imageType;
2826		imageFormat,													//	VkFormat				format;
2827		imageExtent,													//	VkExtent3D				extent;
2828		1u,																//	deUint32				mipLevels;
2829		1u,																//	deUint32				arrayLayers;
2830		VK_SAMPLE_COUNT_1_BIT,											//	VkSampleCountFlagBits	samples;
2831		VK_IMAGE_TILING_OPTIMAL,										//	VkImageTiling			tiling;
2832		(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),	//	VkImageUsageFlags		usage;
2833		VK_SHARING_MODE_EXCLUSIVE,										//	VkSharingMode			sharingMode;
2834		0u,																//	deUint32				queueFamilyIndexCount;
2835		nullptr,														//	const deUint32*			pQueueFamilyIndices;
2836		VK_IMAGE_LAYOUT_UNDEFINED,										//	VkImageLayout			initialLayout;
2837	};
2838	ImageWithMemory storageImage (vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any);
2839	const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2840	const auto storageImageView = makeImageView(vkd, device, storageImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
2841
2842	// Buffer to copy output pixels to.
2843	const auto tcuFormat	= mapVkFormat(imageFormat);
2844	const auto pixelSize	= static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat));
2845	const auto bufferSize	= pixelSize * imageExtent.width * imageExtent.height * imageExtent.depth;
2846
2847	const auto bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2848	BufferWithMemory transferBuffer (vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
2849
2850	// Descriptor set layout and pipeline layout.
2851	DescriptorSetLayoutBuilder layoutBuilder;
2852	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags);
2853	const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
2854
2855	const VkPushConstantRange pcRange =
2856	{
2857		stageFlags,												//	VkShaderStageFlags	stageFlags;
2858		0u,														//	deUint32			offset;
2859		static_cast<deUint32>(sizeof(OverwritePushConstants)),	//	deUint32			size;
2860	};
2861	const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vkd, device, 1u, &descriptorSetLayout.get(), 1u, &pcRange);
2862
2863	// Descriptor pool and set.
2864	DescriptorPoolBuilder poolBuilder;
2865	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
2866	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2867	const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
2868
2869	DescriptorSetUpdateBuilder updateBuilder;
2870	const auto descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, storageImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
2871	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo);
2872	updateBuilder.update(vkd, device);
2873
2874	// Command pool and set.
2875	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
2876	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2877	const auto cmdBuffer	= cmdBufferPtr.get();
2878
2879	// Pipeline.
2880	const std::vector<VkViewport>	viewports	(1, makeViewport(imageExtent));
2881	const std::vector<VkRect2D>		scissors	(1, makeRect2D(imageExtent));
2882
2883	ShaderWrapper			vertModule;
2884	ShaderWrapper			fragModule;
2885	ShaderWrapper			compModule;
2886
2887	RenderPassWrapper		renderPass;
2888	Move<VkFramebuffer>		framebuffer;
2889	Move<VkPipeline>		pipeline;
2890	GraphicsPipelineWrapper	pipelineWrapper(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
2891
2892	if (isComp)
2893	{
2894		compModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
2895		pipeline	= makeComputePipeline(vkd, device, pipelineLayout.get(), compModule.getModule());
2896	}
2897	else
2898	{
2899		vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
2900		fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
2901
2902		const VkPipelineVertexInputStateCreateInfo inputState =
2903		{
2904			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType
2905			nullptr,													// const void*                                 pNext
2906			0u,															// VkPipelineVertexInputStateCreateFlags       flags
2907			0u,															// deUint32                                    vertexBindingDescriptionCount
2908			nullptr,													// const VkVertexInputBindingDescription*      pVertexBindingDescriptions
2909			0u,															// deUint32                                    vertexAttributeDescriptionCount
2910			nullptr,													// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
2911		};
2912		renderPass	= RenderPassWrapper(m_params.pipelineConstructionType, vkd, device);
2913		renderPass.createFramebuffer(vkd, device, 0u, DE_NULL, DE_NULL, imageExtent.width, imageExtent.height);
2914
2915		const VkPipelineColorBlendStateCreateInfo colorBlendState
2916		{
2917			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
2918			DE_NULL,													// const void*									pNext
2919			0u,															// VkPipelineColorBlendStateCreateFlags			flags
2920			VK_FALSE,													// VkBool32										logicOpEnable
2921			VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp
2922			0u,															// deUint32										attachmentCount
2923			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments
2924			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4]
2925		};
2926
2927		pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2928					   .setDefaultRasterizationState()
2929					   .setDefaultDepthStencilState()
2930					   .setDefaultMultisampleState()
2931					   .setupVertexInputState(&inputState)
2932					   .setupPreRasterizationShaderState(viewports,
2933														 scissors,
2934														 pipelineLayout,
2935														 *renderPass,
2936														 0u,
2937														 vertModule)
2938					   .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
2939					   .setupFragmentOutputState(*renderPass, 0u, &colorBlendState)
2940					   .setMonolithicPipelineLayout(pipelineLayout)
2941					   .buildPipeline();
2942	}
2943
2944	// Offsets and sizes.
2945	const struct
2946	{
2947		size_t offset;
2948		size_t size;
2949	} pcPush[] =
2950	{
2951		// Push members doing some back-and-forth in the range.
2952		{	offsetof(OverwritePushConstants, baseColor),		sizeof(OverwritePushConstants::baseColor)			},
2953		{	offsetof(OverwritePushConstants, coords),			sizeof(OverwritePushConstants::coords)				},
2954		{	offsetof(OverwritePushConstants, colorOffsets),		sizeof(OverwritePushConstants::colorOffsets)		},
2955		{	offsetof(OverwritePushConstants, multiplier),		sizeof(OverwritePushConstants::multiplier)			},
2956		{	offsetof(OverwritePushConstants, transparentGreen),	sizeof(OverwritePushConstants::transparentGreen)	},
2957	};
2958
2959	beginCommandBuffer(vkd, cmdBuffer);
2960
2961	// Transition layout for storage image.
2962	const auto preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), subresourceRange);
2963	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, writeStages, 0u, 0u, nullptr, 0u, nullptr, 1u, &preImageBarrier);
2964
2965	vkd.cmdBindDescriptorSets(cmdBuffer, m_params.bindPoint, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2966
2967	if (!isComp)
2968	{
2969		pipelineWrapper.bind(cmdBuffer);
2970		renderPass.begin(vkd, cmdBuffer, scissors[0]);
2971	}
2972	else
2973		vkd.cmdBindPipeline(cmdBuffer, m_params.bindPoint, pipeline.get());
2974
2975	for (int pcIndex = 0; pcIndex < DE_LENGTH_OF_ARRAY(m_params.pushConstantValues); ++pcIndex)
2976	{
2977		const auto& pc = m_params.pushConstantValues[pcIndex];
2978
2979		// Push all structure members separately.
2980		for (int pushIdx = 0; pushIdx < DE_LENGTH_OF_ARRAY(pcPush); ++pushIdx)
2981		{
2982			const auto&	push	= pcPush[pushIdx];
2983			const void*	dataPtr	= reinterpret_cast<const void*>(reinterpret_cast<const char*>(&pc) + push.offset);
2984			vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), stageFlags, static_cast<deUint32>(push.offset), static_cast<deUint32>(push.size), dataPtr);
2985		}
2986
2987		// Draw or dispatch.
2988		if (isComp)
2989			vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
2990		else
2991			vkd.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
2992	}
2993
2994	if (!isComp)
2995		renderPass.end(vkd, cmdBuffer);
2996
2997	// Copy storage image to output buffer.
2998	const auto postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, storageImage.get(), subresourceRange);
2999	vkd.cmdPipelineBarrier(cmdBuffer, writeStages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postImageBarrier);
3000
3001	const auto copyRegion = makeBufferImageCopy(imageExtent, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
3002	vkd.cmdCopyImageToBuffer(cmdBuffer, storageImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transferBuffer.get(), 1u, &copyRegion);
3003
3004	const auto bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, transferBuffer.get(), 0ull, bufferSize);
3005	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
3006
3007	endCommandBuffer(vkd, cmdBuffer);
3008	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3009
3010	// Verify output colors match.
3011	auto&		bufferAlloc		= transferBuffer.getAllocation();
3012	const void*	bufferHostPtr	= bufferAlloc.getHostPtr();
3013	invalidateAlloc(vkd, device, bufferAlloc);
3014
3015	const int iWidth	= static_cast<int>(imageExtent.width);
3016	const int iHeight	= static_cast<int>(imageExtent.height);
3017	const int iDepth	= static_cast<int>(imageExtent.depth);
3018
3019	tcu::ConstPixelBufferAccess outputAccess (tcuFormat, iWidth, iHeight, iDepth, bufferHostPtr);
3020
3021	for (int pixelIdx = 0; pixelIdx < DE_LENGTH_OF_ARRAY(m_params.pushConstantValues); ++pixelIdx)
3022	{
3023		const auto&			pc				= m_params.pushConstantValues[pixelIdx];
3024		const tcu::UVec4	expectedValue	= pc.baseColor * pc.multiplier + tcu::UVec4(pc.colorOffsets[0], pc.colorOffsets[1], pc.colorOffsets[2], pc.colorOffsets[3]) + pc.transparentGreen;
3025		const tcu::UVec4	outputValue		= outputAccess.getPixelUint(pc.coords.x(), pc.coords.y());
3026
3027		if (expectedValue != outputValue)
3028		{
3029			std::ostringstream msg;
3030			msg << "Unexpected value in output image at coords " << pc.coords << ": found " << outputValue << " and expected " << expectedValue;
3031			TCU_FAIL(msg.str());
3032		}
3033	}
3034
3035	return tcu::TestStatus::pass("Pass");
3036}
3037
3038void addOverwriteCase (tcu::TestCaseGroup* group, tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, VkPipelineBindPoint bindPoint)
3039{
3040	const OverwritePushConstants pushConstants[4] =
3041	{
3042	//	coords						baseColor					multiplier							colorOffsets				transparentGreen
3043		{ tcu::IVec4(0, 0, 0, 0),	tcu::UVec4(1u, 0u, 0u, 0u),	tcu::UVec4( 2u,  2u,  2u,  2u),		{ 128u, 129u, 130u, 131u },	tcu::UVec4(0u, 1u, 0u, 0u) },
3044		{ tcu::IVec4(0, 1, 0, 0),	tcu::UVec4(0u, 1u, 0u, 0u),	tcu::UVec4( 4u,  4u,  4u,  4u),		{ 132u, 133u, 134u, 135u },	tcu::UVec4(0u, 1u, 0u, 0u) },
3045		{ tcu::IVec4(1, 0, 0, 0),	tcu::UVec4(0u, 0u, 1u, 0u),	tcu::UVec4( 8u,  8u,  8u,  8u),		{ 136u, 137u, 138u, 139u },	tcu::UVec4(0u, 1u, 0u, 0u) },
3046		{ tcu::IVec4(1, 1, 0, 0),	tcu::UVec4(0u, 0u, 0u, 1u),	tcu::UVec4(16u, 16u, 16u, 16u),		{ 140u, 141u, 142u, 143u },	tcu::UVec4(0u, 1u, 0u, 0u) },
3047	};
3048
3049	OverwriteTestParams testParams;
3050
3051	DE_ASSERT(DE_LENGTH_OF_ARRAY(pushConstants) == DE_LENGTH_OF_ARRAY(testParams.pushConstantValues));
3052	for (int pixelIdx = 0; pixelIdx < DE_LENGTH_OF_ARRAY(pushConstants); ++pixelIdx)
3053		testParams.pushConstantValues[pixelIdx] = pushConstants[pixelIdx];
3054
3055	testParams.pipelineConstructionType = pipelineConstructionType;
3056	testParams.bindPoint				= bindPoint;
3057
3058	// Test push constant range overwrites
3059	group->addChild(new OverwriteTestCase(testCtx, "overwrite", testParams));
3060}
3061
3062} // anonymous
3063
3064tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
3065{
3066	static const struct
3067	{
3068		const char*			name;
3069		deUint32			count;
3070		PushConstantData	range[MAX_RANGE_COUNT];
3071		deBool				hasMultipleUpdates;
3072		IndexType			indexType;
3073	} graphicsParams[] =
3074	{
3075		// test range size is 4 bytes(minimum valid size)
3076		{
3077			"range_size_4",
3078			1u,
3079			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
3080			false,
3081			INDEX_TYPE_CONST_LITERAL
3082		},
3083		// test range size is 16 bytes, and together with a normal uniform
3084		{
3085			"range_size_16",
3086			1u,
3087			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
3088			false,
3089			INDEX_TYPE_CONST_LITERAL
3090		},
3091		// test range size is 128 bytes(maximum valid size)
3092		{
3093			"range_size_128",
3094			1u,
3095			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
3096			false,
3097			INDEX_TYPE_CONST_LITERAL
3098		},
3099		// test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
3100		{
3101			"count_2_shaders_vert_frag",
3102			2u,
3103			{
3104				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
3105				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
3106			},
3107			false,
3108			INDEX_TYPE_CONST_LITERAL
3109		},
3110		// test range count is 3, use vertex, geometry and fragment shaders
3111		{
3112			"count_3_shaders_vert_geom_frag",
3113			3u,
3114			{
3115				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
3116				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
3117				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
3118			},
3119			false,
3120			INDEX_TYPE_CONST_LITERAL
3121		},
3122		// test range count is 5, use vertex, tessellation, geometry and fragment shaders
3123		{
3124			"count_5_shaders_vert_tess_geom_frag",
3125			5u,
3126			{
3127				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
3128				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
3129				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
3130				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
3131				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
3132			},
3133			false,
3134			INDEX_TYPE_CONST_LITERAL
3135		},
3136		// test range count is 1, vertex and fragment shaders share one range
3137		{
3138			"count_1_shader_vert_frag",
3139			1u,
3140			{ { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
3141			false,
3142			INDEX_TYPE_CONST_LITERAL
3143		},
3144		// test data partial update and multiple times update
3145		{
3146			"data_update_partial_1",
3147			1u,
3148			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
3149			false,
3150			INDEX_TYPE_CONST_LITERAL
3151		},
3152		// test partial update of the values
3153		{
3154			"data_update_partial_2",
3155			1u,
3156			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
3157			false,
3158			INDEX_TYPE_CONST_LITERAL
3159		},
3160		// test multiple times update of the values
3161		{
3162			"data_update_multiple",
3163			1u,
3164			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
3165			true,
3166			INDEX_TYPE_CONST_LITERAL
3167		},
3168		// dynamically uniform indexing of vertex, matrix, and array in vertex shader
3169		{
3170			"dynamic_index_vert",
3171			1u,
3172			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 64 }, { 0, 64 } } },
3173			false,
3174			INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
3175		},
3176		// dynamically uniform indexing of vertex, matrix, and array in fragment shader
3177		{
3178			"dynamic_index_frag",
3179			1u,
3180			{ { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 64 }, { 0, 64 } } },
3181			false,
3182			INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
3183		}
3184	};
3185
3186	static const struct
3187	{
3188		const char*			name;
3189		deUint32			count;
3190		PushConstantData	range[MAX_RANGE_COUNT];
3191	} overlapGraphicsParams[] =
3192	{
3193		// overlapping range count is 2, use vertex and fragment shaders
3194		{
3195			"overlap_2_shaders_vert_frag",
3196			2u,
3197			{
3198				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
3199				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36 }, { 12, 36 } },
3200			}
3201		},
3202		// overlapping range count is 3, use vertex, geometry and fragment shaders
3203		{
3204			"overlap_3_shaders_vert_geom_frag",
3205			3u,
3206			{
3207				{ { VK_SHADER_STAGE_VERTEX_BIT, 12, 36 }, { 12, 36 } },
3208				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32 }, { 16, 16 } },
3209				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4 }, { 20, 4 } }
3210			}
3211		},
3212		// overlapping range count is 4, use vertex, tessellation and fragment shaders
3213		{
3214			"overlap_4_shaders_vert_tess_frag",
3215			4u,
3216			{
3217				{ { VK_SHADER_STAGE_VERTEX_BIT, 8, 4 }, { 8, 4 } },
3218				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 128 }, { 52, 76 } },
3219				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 56, 8 }, { 56, 8 } },
3220				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 60, 36 }, { 60, 36 } }
3221			}
3222		},
3223		// overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders
3224		{
3225			"overlap_5_shaders_vert_tess_geom_frag",
3226			5u,
3227			{
3228				{ { VK_SHADER_STAGE_VERTEX_BIT, 40, 8 }, { 40, 8 } },
3229				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12 }, { 32, 12 } },
3230				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16 }, { 48, 16 } },
3231				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36 }, { 28, 36 } },
3232				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8 }, { 60, 4 } }
3233			}
3234		}
3235	};
3236
3237	static const struct
3238	{
3239		const char*			name;
3240		ComputeTestType		type;
3241		PushConstantData	range;
3242	} computeParams[] =
3243	{
3244		// test compute pipeline
3245		{
3246			"simple_test",
3247			CTT_SIMPLE,
3248			{ { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
3249		},
3250		// test push constant that is dynamically unused
3251		{
3252			"uninitialized",
3253			CTT_UNINITIALIZED,
3254			{ { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
3255		},
3256	};
3257
3258	static const struct
3259	{
3260		const char*						name;
3261		PushConstantData				range[MAX_RANGE_COUNT];
3262		std::vector<CommandData>		cmdList;
3263	} lifetimeParams[] =
3264	{
3265		// bind different layout with the same range
3266		{
3267			"push_range0_bind_layout1",
3268			{
3269				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3270				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}
3271			},
3272			{
3273				{ CMD_PUSH_CONSTANT, 0 },
3274				{ CMD_BIND_PIPELINE_GRAPHICS, 1 },
3275				{ CMD_DRAW, -1 },
3276			}
3277		},
3278		// bind layout with same range then push different range
3279		{
3280			"push_range1_bind_layout1_push_range0",
3281			{
3282				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3283				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}
3284			},
3285			{
3286				{ CMD_PUSH_CONSTANT, 1 },
3287				{ CMD_BIND_PIPELINE_GRAPHICS, 1 },
3288				{ CMD_DRAW, -1 },
3289				{ CMD_PUSH_CONSTANT, 0 },
3290				{ CMD_DRAW, -1 },
3291			}
3292		},
3293		// same range same layout then same range from a different layout and same range from the same layout
3294		{
3295			"push_range0_bind_layout0_push_range1_push_range0",
3296			{
3297				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3298				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}
3299			},
3300			{
3301				{ CMD_PUSH_CONSTANT, 0 },
3302				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3303				{ CMD_PUSH_CONSTANT, 1 },
3304				{ CMD_PUSH_CONSTANT, 0 },
3305				{ CMD_DRAW, -1 },
3306			}
3307		},
3308		// same range same layout then diff range and same range update
3309		{
3310			"push_range0_bind_layout0_push_diff_overlapping_range1_push_range0",
3311			{
3312				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3313				{{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}
3314			},
3315			{
3316				{ CMD_PUSH_CONSTANT, 0 },
3317				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3318				{ CMD_PUSH_CONSTANT, 1 },
3319				{ CMD_PUSH_CONSTANT, 0 },
3320				{ CMD_DRAW, -1 },
3321			}
3322		},
3323		// update push constant bind different layout with the same range then bind correct layout
3324		{
3325			"push_range0_bind_layout1_bind_layout0",
3326			{
3327				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3328				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}
3329			},
3330			{
3331				{ CMD_PUSH_CONSTANT, 0 },
3332				{ CMD_BIND_PIPELINE_GRAPHICS, 1 },
3333				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3334				{ CMD_DRAW, -1 },
3335			}
3336		},
3337		// update push constant then bind different layout with overlapping range then bind correct layout
3338		{
3339			"push_range0_bind_layout1_overlapping_range_bind_layout0",
3340			{
3341				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3342				{{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}
3343			},
3344			{
3345				{ CMD_PUSH_CONSTANT, 0 },
3346				{ CMD_BIND_PIPELINE_GRAPHICS, 1 },
3347				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3348				{ CMD_DRAW, -1 },
3349			}
3350		},
3351		// bind different layout with different range then update push constant and bind correct layout
3352		{
3353			"bind_layout1_push_range0_bind_layout0",
3354			{
3355				{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}},
3356				{{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}
3357			},
3358			{
3359				{ CMD_BIND_PIPELINE_GRAPHICS, 1 },
3360				{ CMD_PUSH_CONSTANT, 0 },
3361				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3362				{ CMD_DRAW, -1 },
3363			}
3364		},
3365		// change pipeline same range, bind then push, stages vertex and compute
3366		{
3367			"pipeline_change_same_range_bind_push_vert_and_comp",
3368			{
3369				{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}},
3370				{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}}
3371			},
3372			{
3373				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3374				{ CMD_BIND_PIPELINE_COMPUTE, 1 },
3375				{ CMD_PUSH_CONSTANT, 0 },
3376				{ CMD_DRAW, -1 },
3377				{ CMD_PUSH_CONSTANT, 1 },
3378				{ CMD_DISPATCH, -1 },
3379			}
3380		},
3381		// change pipeline different range overlapping, bind then push, stages vertex and compute
3382		{
3383			"pipeline_change_diff_range_bind_push_vert_and_comp",
3384			{
3385				{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}},
3386				{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 16, 32}, {16, 32}}
3387			},
3388			{
3389				{ CMD_BIND_PIPELINE_GRAPHICS, 0 },
3390				{ CMD_BIND_PIPELINE_COMPUTE, 1 },
3391				{ CMD_PUSH_CONSTANT, 0 },
3392				{ CMD_DRAW, -1 },
3393				{ CMD_PUSH_CONSTANT, 1 },
3394				{ CMD_DISPATCH, -1 },
3395			}
3396		}
3397	};
3398
3399	de::MovePtr<tcu::TestCaseGroup>	pushConstantTests	(new tcu::TestCaseGroup(testCtx, "push_constant"));
3400
3401	de::MovePtr<tcu::TestCaseGroup>	graphicsTests	(new tcu::TestCaseGroup(testCtx, "graphics_pipeline"));
3402	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
3403	{
3404		graphicsTests->addChild(new PushConstantGraphicsDisjointTest(testCtx, graphicsParams[ndx].name, pipelineConstructionType, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates, graphicsParams[ndx].indexType));
3405	}
3406
3407	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(overlapGraphicsParams); ndx++)
3408	{
3409		graphicsTests->addChild(new PushConstantGraphicsOverlapTest(testCtx, overlapGraphicsParams[ndx].name, pipelineConstructionType, overlapGraphicsParams[ndx].count, overlapGraphicsParams[ndx].range));
3410	}
3411	addOverwriteCase(graphicsTests.get(), testCtx, pipelineConstructionType, VK_PIPELINE_BIND_POINT_GRAPHICS);
3412	pushConstantTests->addChild(graphicsTests.release());
3413
3414	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3415	{
3416		de::MovePtr<tcu::TestCaseGroup>	computeTests	(new tcu::TestCaseGroup(testCtx, "compute_pipeline"));
3417		for (const auto& params : computeParams)
3418		{
3419			computeTests->addChild(new PushConstantComputeTest(testCtx, params.name, params.type, params.range));
3420		}
3421		addOverwriteCase(computeTests.get(), testCtx, pipelineConstructionType, VK_PIPELINE_BIND_POINT_COMPUTE);
3422		pushConstantTests->addChild(computeTests.release());
3423	}
3424
3425	de::MovePtr<tcu::TestCaseGroup>	lifetimeTests	(new tcu::TestCaseGroup(testCtx, "lifetime"));
3426	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(lifetimeParams); ndx++)
3427	{
3428		lifetimeTests->addChild(new PushConstantLifetimeTest(testCtx, lifetimeParams[ndx].name, pipelineConstructionType, lifetimeParams[ndx].range, lifetimeParams[ndx].cmdList));
3429	}
3430	pushConstantTests->addChild(lifetimeTests.release());
3431
3432	return pushConstantTests.release();
3433}
3434
3435} // pipeline
3436} // vkt
3437