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