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