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