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