1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Limited.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief PushConstant Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelinePushConstantTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "deMemory.h"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "tcuTestLog.hpp"
47 
48 #include <algorithm>
49 #include <sstream>
50 #include <vector>
51 
52 namespace vkt
53 {
54 namespace pipeline
55 {
56 
57 using namespace vk;
58 
59 namespace
60 {
61 
62 enum
63 {
64 	TRIANGLE_COUNT	= 2,
65 	MAX_RANGE_COUNT	= 5
66 };
67 
68 enum RangeSizeCase
69 {
70 	SIZE_CASE_4	= 0,
71 	SIZE_CASE_8,
72 	SIZE_CASE_12,
73 	SIZE_CASE_16,
74 	SIZE_CASE_32,
75 	SIZE_CASE_36,
76 	SIZE_CASE_48,
77 	SIZE_CASE_128,
78 	SIZE_CASE_UNSUPPORTED
79 };
80 
81 struct PushConstantData
82 {
83 	struct PushConstantRange
84 	{
85 		VkShaderStageFlags		shaderStage;
86 		deUint32				offset;
87 		deUint32				size;
88 	} range;
89 	struct PushConstantUpdate
90 	{
91 		deUint32				offset;
92 		deUint32				size;
93 	} update;
94 };
95 
96 // These values will be loaded from push constants and used as an index
97 static const deUint32 DYNAMIC_VEC_INDEX = 2u;
98 static const deUint32 DYNAMIC_MAT_INDEX = 0u;
99 static const deUint32 DYNAMIC_ARR_INDEX = 3u;
100 
101 // These reference values will be compared in the shader to ensure the correct index was read
102 static const float DYNAMIC_VEC_CONSTANT = 0.25f;
103 static const float DYNAMIC_MAT_CONSTANT = 0.50f;
104 static const float DYNAMIC_ARR_CONSTANT = 0.75f;
105 
106 enum IndexType
107 {
108 	INDEX_TYPE_CONST_LITERAL = 0,
109 	INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR,
110 
111 	INDEX_TYPE_LAST
112 };
113 
getShaderStageNameStr(VkShaderStageFlags stageFlags)114 std::string getShaderStageNameStr (VkShaderStageFlags stageFlags)
115 {
116 	const VkShaderStageFlags	shaderStages[]		=
117 	{
118 		VK_SHADER_STAGE_VERTEX_BIT,
119 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
120 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
121 		VK_SHADER_STAGE_GEOMETRY_BIT,
122 		VK_SHADER_STAGE_FRAGMENT_BIT
123 	};
124 
125 	const char*					shaderStageNames[]	=
126 	{
127 		"VK_SHADER_STAGE_VERTEX_BIT",
128 		"VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT",
129 		"VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT",
130 		"VK_SHADER_STAGE_GEOMETRY_BIT",
131 		"VK_SHADER_STAGE_FRAGMENT_BIT",
132 	};
133 
134 	std::stringstream			shaderStageStr;
135 
136 	for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
137 	{
138 		if (stageFlags & shaderStages[stageNdx])
139 		{
140 			if (!(shaderStageStr.str().empty()))
141 				shaderStageStr << " | ";
142 
143 			shaderStageStr << shaderStageNames[stageNdx];
144 		}
145 	}
146 
147 	return shaderStageStr.str();
148 }
149 
150 class PushConstantGraphicsTestInstance : public vkt::TestInstance
151 {
152 public:
153 												PushConstantGraphicsTestInstance	(Context&					context,
154 																					 const deUint32				rangeCount,
155 																					 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
156 																					 const deBool				multipleUpdate,
157 																					 const IndexType			indexType);
158 	virtual										~PushConstantGraphicsTestInstance	(void);
159 	void										init								(void);
160 	virtual tcu::TestStatus						iterate								(void);
161 	virtual std::vector<VkPushConstantRange>	getPushConstantRanges				(void) = 0;
162 	virtual void								updatePushConstants					(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout) = 0;
163 	virtual void								setReferenceColor					(tcu::Vec4 initColor) = 0;
164 	void										createShaderModule					(const DeviceInterface&		vk,
165 																					 VkDevice					device,
166 																					 const BinaryCollection&	programCollection,
167 																					 const char*				name,
168 																					 Move<VkShaderModule>*		module);
169 	std::vector<Vertex4RGBA>					createQuad							(const float size);
170 	tcu::TestStatus								verifyImage							(void);
171 
172 protected:
173 	std::vector<Vertex4RGBA>						m_vertices;
174 	const deUint32									m_rangeCount;
175 	PushConstantData								m_pushConstantRange[MAX_RANGE_COUNT];
176 	const IndexType									m_indexType;
177 
178 private:
179 	const tcu::UVec2								m_renderSize;
180 	const VkFormat									m_colorFormat;
181 	const deBool									m_multipleUpdate;
182 
183 	VkImageCreateInfo								m_colorImageCreateInfo;
184 	Move<VkImage>									m_colorImage;
185 	de::MovePtr<Allocation>							m_colorImageAlloc;
186 	Move<VkImageView>								m_colorAttachmentView;
187 	Move<VkRenderPass>								m_renderPass;
188 	Move<VkFramebuffer>								m_framebuffer;
189 
190 	Move<VkShaderModule>							m_vertexShaderModule;
191 	Move<VkShaderModule>							m_fragmentShaderModule;
192 	Move<VkShaderModule>							m_geometryShaderModule;
193 	Move<VkShaderModule>							m_tessControlShaderModule;
194 	Move<VkShaderModule>							m_tessEvaluationShaderModule;
195 
196 	VkShaderStageFlags								m_shaderFlags;
197 	std::vector<VkPipelineShaderStageCreateInfo>	m_shaderStage;
198 
199 	Move<VkBuffer>									m_vertexBuffer;
200 	de::MovePtr<Allocation>							m_vertexBufferAlloc;
201 
202 	Move<VkBuffer>									m_uniformBuffer;
203 	de::MovePtr<Allocation>							m_uniformBufferAlloc;
204 	Move<VkDescriptorPool>							m_descriptorPool;
205 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
206 	Move<VkDescriptorSet>							m_descriptorSet;
207 
208 	Move<VkPipelineLayout>							m_pipelineLayout;
209 	Move<VkPipeline>								m_graphicsPipelines;
210 
211 	Move<VkCommandPool>								m_cmdPool;
212 	Move<VkCommandBuffer>							m_cmdBuffer;
213 };
214 
createShaderModule(const DeviceInterface & vk,VkDevice device,const BinaryCollection & programCollection,const char * name,Move<VkShaderModule> * module)215 void PushConstantGraphicsTestInstance::createShaderModule (const DeviceInterface&	vk,
216 														   VkDevice					device,
217 														   const BinaryCollection&	programCollection,
218 														   const char*				name,
219 														   Move<VkShaderModule>*	module)
220 {
221 	*module = vk::createShaderModule(vk, device, programCollection.get(name), 0);
222 }
223 
createQuad(const float size)224 std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
225 {
226 	std::vector<Vertex4RGBA>	vertices;
227 
228 	const tcu::Vec4				color				= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
229 	const Vertex4RGBA			lowerLeftVertex		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
230 	const Vertex4RGBA			lowerRightVertex	= {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
231 	const Vertex4RGBA			UpperLeftVertex		= {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
232 	const Vertex4RGBA			UpperRightVertex	= {tcu::Vec4(size, size, 0.0f, 1.0f), color};
233 
234 	vertices.push_back(lowerLeftVertex);
235 	vertices.push_back(lowerRightVertex);
236 	vertices.push_back(UpperLeftVertex);
237 	vertices.push_back(UpperLeftVertex);
238 	vertices.push_back(lowerRightVertex);
239 	vertices.push_back(UpperRightVertex);
240 
241 	return vertices;
242 }
243 
PushConstantGraphicsTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)244 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context&				context,
245 																	const deUint32			rangeCount,
246 																	const PushConstantData	pushConstantRange[MAX_RANGE_COUNT],
247 																	deBool					multipleUpdate,
248 																	IndexType				indexType)
249 	: vkt::TestInstance	(context)
250 	, m_rangeCount		(rangeCount)
251 	, m_indexType		(indexType)
252 	, m_renderSize		(32, 32)
253 	, m_colorFormat		(VK_FORMAT_R8G8B8A8_UNORM)
254 	, m_multipleUpdate	(multipleUpdate)
255 	, m_shaderFlags		(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
256 {
257 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
258 }
259 
init(void)260 void PushConstantGraphicsTestInstance::init (void)
261 {
262 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
263 	const VkDevice							vkDevice				= m_context.getDevice();
264 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
265 	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
266 	const VkComponentMapping				componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
267 	const std::vector<VkPushConstantRange>	pushConstantRanges		= getPushConstantRanges();
268 	bool									useTessellation			= false;
269 	bool									useGeometry				= false;
270 
271 	// Create color image
272 	{
273 		const VkImageCreateInfo colorImageParams =
274 		{
275 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
276 			DE_NULL,																// const void*				pNext;
277 			0u,																		// VkImageCreateFlags		flags;
278 			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
279 			m_colorFormat,															// VkFormat					format;
280 			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
281 			1u,																		// deUint32					mipLevels;
282 			1u,																		// deUint32					arrayLayers;
283 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
284 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
285 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
286 			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
287 			1u,																		// deUint32					queueFamilyIndexCount;
288 			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
289 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
290 		};
291 
292 		m_colorImageCreateInfo	= colorImageParams;
293 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
294 
295 		// Allocate and bind color image memory
296 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
297 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
298 	}
299 
300 	// Create color attachment view
301 	{
302 		const VkImageViewCreateInfo colorAttachmentViewParams =
303 		{
304 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType				sType;
305 			DE_NULL,										// const void*					pNext;
306 			0u,												// VkImageViewCreateFlags		flags;
307 			*m_colorImage,									// VkImage						image;
308 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType				viewType;
309 			m_colorFormat,									// VkFormat						format;
310 			componentMappingRGBA,							// VkChannelMapping				channels;
311 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange		subresourceRange;
312 		};
313 
314 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
315 	}
316 
317 	// Create render pass
318 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
319 
320 	// Create framebuffer
321 	{
322 		const VkImageView attachmentBindInfos[1] =
323 		{
324 		  *m_colorAttachmentView
325 		};
326 
327 		const VkFramebufferCreateInfo framebufferParams =
328 		{
329 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType				sType;
330 			DE_NULL,									// const void*					pNext;
331 			0u,											// VkFramebufferCreateFlags		flags;
332 			*m_renderPass,								// VkRenderPass					renderPass;
333 			1u,											// deUint32						attachmentCount;
334 			attachmentBindInfos,						// const VkImageView*			pAttachments;
335 			(deUint32)m_renderSize.x(),					// deUint32						width;
336 			(deUint32)m_renderSize.y(),					// deUint32						height;
337 			1u											// deUint32						layers;
338 		};
339 
340 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
341 	}
342 
343 	// Create pipeline layout
344 	{
345 		// create descriptor set layout
346 		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
347 
348 		// create descriptor pool
349 		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
350 
351 		// create uniform buffer
352 		const VkBufferCreateInfo			uniformBufferCreateInfo	=
353 		{
354 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
355 			DE_NULL,								// const void*			pNext;
356 			0u,										// VkBufferCreateFlags	flags
357 			16u,									// VkDeviceSize			size;
358 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,		// VkBufferUsageFlags	usage;
359 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
360 			1u,										// deUint32				queueFamilyCount;
361 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
362 		};
363 
364 		m_uniformBuffer			= createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
365 		m_uniformBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
366 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
367 
368 		const tcu::Vec4						value					= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
369 		deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
370 		flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
371 
372 		// create and update descriptor set
373 		const VkDescriptorSetAllocateInfo	allocInfo				=
374 		{
375 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType                             sType;
376 			DE_NULL,										// const void*                                 pNext;
377 			*m_descriptorPool,								// VkDescriptorPool                            descriptorPool;
378 			1u,												// deUint32                                    setLayoutCount;
379 			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*                pSetLayouts;
380 		};
381 		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
382 
383 		const VkDescriptorBufferInfo		descriptorInfo			= makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
384 
385 		DescriptorSetUpdateBuilder()
386 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
387 			.update(vk, vkDevice);
388 
389 		// create pipeline layout
390 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
391 		{
392 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
393 			DE_NULL,										// const void*					pNext;
394 			0u,												// VkPipelineLayoutCreateFlags	flags;
395 			1u,												// deUint32						descriptorSetCount;
396 			&(*m_descriptorSetLayout),						// const VkDescriptorSetLayout*	pSetLayouts;
397 			(deUint32)pushConstantRanges.size(),			// deUint32						pushConstantRangeCount;
398 			&pushConstantRanges.front()						// const VkPushConstantRange*	pPushConstantRanges;
399 		};
400 
401 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
402 	}
403 
404 	// Create shaders
405 	{
406 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
407 		{
408 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
409 			{
410 				m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
411 			}
412 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
413 			{
414 				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
415 			}
416 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
417 			{
418 				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
419 			}
420 		}
421 
422 		VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
423 
424 		createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", &m_vertexShaderModule);
425 		if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
426 		{
427 			if (features.tessellationShader == VK_FALSE)
428 			{
429 				TCU_THROW(NotSupportedError, "Tessellation Not Supported");
430 			}
431 			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", &m_tessControlShaderModule);
432 			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", &m_tessEvaluationShaderModule);
433 			useTessellation = true;
434 		}
435 		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
436 		{
437 			if (features.geometryShader == VK_FALSE)
438 			{
439 				TCU_THROW(NotSupportedError, "Geometry Not Supported");
440 			}
441 			createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", &m_geometryShaderModule);
442 			useGeometry = true;
443 		}
444 		createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", &m_fragmentShaderModule);
445 	}
446 
447 	// Create pipeline
448 	{
449 		const VkVertexInputBindingDescription			vertexInputBindingDescription		=
450 		{
451 			0u,							// deUint32					binding;
452 			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
453 			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	stepRate;
454 		};
455 
456 		const VkVertexInputAttributeDescription			vertexInputAttributeDescriptions[]	=
457 		{
458 			{
459 				0u,								// deUint32	location;
460 				0u,								// deUint32	binding;
461 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
462 				0u								// deUint32	offsetInBytes;
463 			},
464 			{
465 				1u,									// deUint32	location;
466 				0u,									// deUint32	binding;
467 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
468 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
469 			}
470 		};
471 
472 		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams				=
473 		{
474 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
475 			DE_NULL,													// const void*								pNext;
476 			0u,															// vkPipelineVertexInputStateCreateFlags	flags;
477 			1u,															// deUint32									bindingCount;
478 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
479 			2u,															// deUint32									attributeCount;
480 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
481 		};
482 
483 		const VkPrimitiveTopology						topology							= (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
484 
485 		const std::vector<VkViewport>					viewports							(1, makeViewport(m_renderSize));
486 		const std::vector<VkRect2D>						scissors							(1, makeRect2D(m_renderSize));
487 
488 		m_graphicsPipelines = makeGraphicsPipeline(vk,															// const DeviceInterface&                        vk
489 												   vkDevice,													// const VkDevice                                device
490 												   *m_pipelineLayout,											// const VkPipelineLayout                        pipelineLayout
491 												   *m_vertexShaderModule,										// const VkShaderModule                          vertexShaderModule
492 												   useTessellation ? *m_tessControlShaderModule : DE_NULL,		// const VkShaderModule                          tessellationControlShaderModule
493 												   useTessellation ? *m_tessEvaluationShaderModule : DE_NULL,	// const VkShaderModule                          tessellationEvalShaderModule
494 												   useGeometry ? *m_geometryShaderModule : DE_NULL,				// const VkShaderModule                          geometryShaderModule
495 												   *m_fragmentShaderModule,										// const VkShaderModule                          fragmentShaderModule
496 												   *m_renderPass,												// const VkRenderPass                            renderPass
497 												   viewports,													// const std::vector<VkViewport>&                viewports
498 												   scissors,													// const std::vector<VkRect2D>&                  scissors
499 												   topology,													// const VkPrimitiveTopology                     topology
500 												   0u,															// const deUint32                                subpass
501 												   3u,															// const deUint32                                patchControlPoints
502 												   &vertexInputStateParams);									// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
503 	}
504 
505 	// Create vertex buffer
506 	{
507 		m_vertices			= createQuad(1.0f);
508 
509 		const VkBufferCreateInfo vertexBufferParams =
510 		{
511 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
512 			DE_NULL,													// const void*			pNext;
513 			0u,															// VkBufferCreateFlags	flags;
514 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
515 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
516 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
517 			1u,															// deUint32				queueFamilyCount;
518 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
519 		};
520 
521 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
522 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
523 
524 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
525 
526 		// Load vertices into vertex buffer
527 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
528 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
529 	}
530 
531 	// Create command pool
532 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
533 
534 	// Create command buffer
535 	{
536 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
537 
538 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
539 
540 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
541 
542 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
543 
544 		// Update push constant values
545 		updatePushConstants(*m_cmdBuffer, *m_pipelineLayout);
546 
547 		// draw quad
548 		const VkDeviceSize				triangleOffset			= (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
549 
550 		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
551 		{
552 			VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
553 
554 			if (m_multipleUpdate)
555 				vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
556 
557 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
558 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
559 			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
560 
561 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
562 		}
563 
564 		endRenderPass(vk, *m_cmdBuffer);
565 		endCommandBuffer(vk, *m_cmdBuffer);
566 	}
567 }
568 
~PushConstantGraphicsTestInstance(void)569 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
570 {
571 }
572 
iterate(void)573 tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
574 {
575 	init();
576 
577 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
578 	const VkDevice				vkDevice	= m_context.getDevice();
579 	const VkQueue				queue		= m_context.getUniversalQueue();
580 
581 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
582 
583 	return verifyImage();
584 }
585 
verifyImage(void)586 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
587 {
588 	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
589 	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
590 	const ColorVertexShader		vertexShader;
591 	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
592 	const rr::Program			program			(&vertexShader, &fragmentShader);
593 	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
594 	bool						compareOk		= false;
595 
596 	// Render reference image
597 	{
598 		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
599 		{
600 			m_vertices = createQuad(0.5f);
601 		}
602 
603 		setReferenceColor(m_vertices[0].color);
604 
605 		if (m_multipleUpdate)
606 		{
607 			for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
608 			{
609 				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
610 			}
611 			for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
612 			{
613 				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
614 			}
615 		}
616 
617 		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
618 		{
619 			rr::RenderState renderState(refRenderer.getViewportState());
620 
621 			refRenderer.draw(renderState,
622 							 rr::PRIMITIVETYPE_TRIANGLES,
623 							 std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
624 													  m_vertices.begin() + (triangleNdx + 1) * 3));
625 		}
626 	}
627 
628 	// Compare result with reference image
629 	{
630 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
631 		const VkDevice					vkDevice			= m_context.getDevice();
632 		const VkQueue					queue				= m_context.getUniversalQueue();
633 		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
634 		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
635 		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
636 
637 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
638 															  "IntImageCompare",
639 															  "Image comparison",
640 															  refRenderer.getAccess(),
641 															  result->getAccess(),
642 															  tcu::UVec4(2, 2, 2, 2),
643 															  tcu::IVec3(1, 1, 0),
644 															  true,
645 															  tcu::COMPARE_LOG_RESULT);
646 	}
647 
648 	if (compareOk)
649 		return tcu::TestStatus::pass("Result image matches reference");
650 	else
651 		return tcu::TestStatus::fail("Image mismatch");
652 }
653 
654 class PushConstantGraphicsDisjointInstance : public PushConstantGraphicsTestInstance
655 {
656 public:
657 										PushConstantGraphicsDisjointInstance	(Context&					context,
658 																				 const deUint32				rangeCount,
659 																				 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
660 																				 const deBool				multipleUpdate,
661 																				 const IndexType			indexType);
662 	virtual								~PushConstantGraphicsDisjointInstance	(void);
663 	std::vector<VkPushConstantRange>	getPushConstantRanges					(void);
664 	void								updatePushConstants						(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
665 	void								setReferenceColor						(tcu::Vec4 initColor);
666 };
667 
668 
PushConstantGraphicsDisjointInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)669 PushConstantGraphicsDisjointInstance::PushConstantGraphicsDisjointInstance (Context&					context,
670 																			const deUint32				rangeCount,
671 																			const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
672 																			deBool						multipleUpdate,
673 																			IndexType					indexType)
674 	: PushConstantGraphicsTestInstance (context, rangeCount, pushConstantRange, multipleUpdate, indexType)
675 {
676 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
677 }
678 
~PushConstantGraphicsDisjointInstance(void)679 PushConstantGraphicsDisjointInstance::~PushConstantGraphicsDisjointInstance(void)
680 {
681 }
682 
getPushConstantRanges(void)683 std::vector<VkPushConstantRange> PushConstantGraphicsDisjointInstance::getPushConstantRanges (void)
684 {
685 	std::vector<VkPushConstantRange> pushConstantRanges;
686 
687 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
688 	{
689 		const VkPushConstantRange pushConstantRange =
690 		{
691 			m_pushConstantRange[rangeNdx].range.shaderStage,
692 			m_pushConstantRange[rangeNdx].range.offset,
693 			m_pushConstantRange[rangeNdx].range.size
694 		};
695 
696 		pushConstantRanges.push_back(pushConstantRange);
697 	}
698 
699 	return pushConstantRanges;
700 }
701 
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)702 void PushConstantGraphicsDisjointInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
703 {
704 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
705 	std::vector<tcu::Vec4>	color	(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
706 	std::vector<tcu::Vec4>	allOnes	(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
707 
708 	switch (m_indexType)
709 	{
710 		case INDEX_TYPE_CONST_LITERAL:
711 			// Do nothing
712 			break;
713 		case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
714 			// Stick our dynamic index at the beginning of a vector
715 			color[0] = tcu::Vec4(	float(DYNAMIC_VEC_INDEX),
716 									float(DYNAMIC_MAT_INDEX),
717 									float(DYNAMIC_ARR_INDEX),
718 									1.0f);
719 
720 			// Place our reference values at each type offset
721 
722 			// vec4[i]
723 			DE_ASSERT(DYNAMIC_VEC_INDEX <= 3);
724 			color[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
725 			color[1][DYNAMIC_VEC_INDEX] = DYNAMIC_VEC_CONSTANT;
726 
727 			// mat2[i][0]
728 			DE_ASSERT(DYNAMIC_MAT_INDEX <= 1);
729 			color[2] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
730 			color[2][DYNAMIC_MAT_INDEX * 2] = DYNAMIC_MAT_CONSTANT;
731 
732 			// float[i]
733 			DE_ASSERT(DYNAMIC_ARR_INDEX <= 3);
734 			color[3] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
735 			color[3][DYNAMIC_ARR_INDEX] = DYNAMIC_ARR_CONSTANT;
736 			break;
737 		default:
738 			DE_FATAL("Unhandled IndexType");
739 			break;
740 	}
741 
742 	const deUint32			kind	= 2u;
743 	const void*				value	= DE_NULL;
744 
745 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
746 	{
747 		value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
748 
749 		vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
750 
751 		if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
752 		{
753 			value = (void*)(&allOnes[0]);
754 			vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
755 		}
756 	}
757 }
758 
setReferenceColor(tcu::Vec4 initColor)759 void PushConstantGraphicsDisjointInstance::setReferenceColor (tcu::Vec4 initColor)
760 {
761 	DE_UNREF(initColor);
762 
763 	const tcu::Vec4 color = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
764 
765 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
766 	{
767 		if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
768 		{
769 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
770 			{
771 				m_vertices[vertexNdx].color.xyzw() = color;
772 			}
773 		}
774 	}
775 }
776 
777 class PushConstantGraphicsOverlapTestInstance : public PushConstantGraphicsTestInstance
778 {
779 public:
780 										PushConstantGraphicsOverlapTestInstance		(Context&					context,
781 																				const deUint32				rangeCount,
782 																				const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
783 																				const deBool				multipleUpdate,
784 																				const IndexType			indexType);
785 	virtual								~PushConstantGraphicsOverlapTestInstance	(void);
786 	std::vector<VkPushConstantRange>	getPushConstantRanges					(void);
787 	std::vector<VkPushConstantRange>	getPushConstantUpdates					(void);
788 	void								updatePushConstants						(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
789 	void								setReferenceColor						(tcu::Vec4 initColor);
790 
791 private:
792 	const std::vector<float>			m_colorData;
793 	std::vector<float>					m_referenceData;
794 };
795 
generateColorData(deUint32 numBytes)796 std::vector<float> generateColorData (deUint32 numBytes)
797 {
798 	DE_ASSERT(numBytes % 4u == 0u);
799 
800 	std::vector<float> colorData;
801 
802 	deRandom random;
803 	deRandom_init(&random, numBytes);
804 
805 	for (deUint32 elementNdx = 0u; elementNdx < numBytes / 4u; elementNdx++)
806 		colorData.push_back(deRandom_getFloat(&random));
807 
808 	return colorData;
809 }
810 
PushConstantGraphicsOverlapTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)811 PushConstantGraphicsOverlapTestInstance::PushConstantGraphicsOverlapTestInstance (Context&					context,
812 																				  const deUint32			rangeCount,
813 																				  const PushConstantData	pushConstantRange[MAX_RANGE_COUNT],
814 																				  deBool					multipleUpdate,
815 																				  IndexType					indexType)
816 	: PushConstantGraphicsTestInstance	(context, rangeCount, pushConstantRange, multipleUpdate, indexType)
817 	, m_colorData						(generateColorData(256u))
818 {
819 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
820 }
821 
~PushConstantGraphicsOverlapTestInstance(void)822 PushConstantGraphicsOverlapTestInstance::~PushConstantGraphicsOverlapTestInstance(void)
823 {
824 }
825 
getPushConstantRanges(void)826 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantRanges (void)
827 {
828 	// Find push constant ranges for each shader stage
829 	const VkShaderStageFlags			shaderStages[]		=
830 	{
831 		VK_SHADER_STAGE_VERTEX_BIT,
832 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
833 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
834 		VK_SHADER_STAGE_GEOMETRY_BIT,
835 		VK_SHADER_STAGE_FRAGMENT_BIT,
836 	};
837 
838 	std::vector<VkPushConstantRange>	pushConstantRanges;
839 
840 	m_context.getTestContext().getLog() << tcu::TestLog::Section("Ranges", "Push constant ranges");
841 
842 	for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
843 	{
844 		deUint32 firstByte	= ~0u;
845 		deUint32 lastByte	= 0u;
846 
847 		for (deUint32 rangeNdx = 0u; rangeNdx < m_rangeCount; rangeNdx++)
848 		{
849 			if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStages[stageNdx])
850 			{
851 				firstByte	= deMinu32(firstByte, m_pushConstantRange[rangeNdx].range.offset);
852 				lastByte	= deMaxu32(lastByte, m_pushConstantRange[rangeNdx].range.offset + m_pushConstantRange[rangeNdx].range.size);
853 			}
854 		}
855 
856 		if (firstByte != ~0u)
857 		{
858 			const VkPushConstantRange pushConstantRange =
859 			{
860 				shaderStages[stageNdx],	// VkShaderStageFlags    stageFlags
861 				firstByte,				// deUint32              offset
862 				lastByte - firstByte	// deUint32              size
863 			};
864 
865 			pushConstantRanges.push_back(pushConstantRange);
866 
867 			m_context.getTestContext().getLog()
868 				<< tcu::TestLog::Message
869 				<< "VkShaderStageFlags    stageFlags    " << getShaderStageNameStr(shaderStages[stageNdx]) << ",\n"
870 				<< "deUint32              offset        " << pushConstantRange.offset << ",\n"
871 				<< "deUint32              size          " << pushConstantRange.size << "\n"
872 				<< tcu::TestLog::EndMessage;
873 		}
874 	}
875 
876 	m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
877 
878 	return pushConstantRanges;
879 }
880 
getPushConstantUpdates(void)881 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantUpdates (void)
882 {
883 	VkShaderStageFlags					lastStageFlags		= (VkShaderStageFlags)~0u;
884 	std::vector<VkPushConstantRange>	pushConstantUpdates;
885 
886 	// Find matching shader stages for every 4 byte chunk
887 	for (deUint32 offset = 0u; offset < 128u; offset += 4u)
888 	{
889 		VkShaderStageFlags	stageFlags	= (VkShaderStageFlags)0u;
890 		bool				updateRange	= false;
891 
892 		// For each byte in the range specified by offset and size and for each push constant range that overlaps that byte,
893 		// stageFlags must include all stages in that push constant range's VkPushConstantRange::stageFlags
894 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
895 		{
896 			const deUint32 rangeStart	= m_pushConstantRange[rangeNdx].range.offset;
897 			const deUint32 rangeEnd		= rangeStart + m_pushConstantRange[rangeNdx].range.size;
898 
899 			const deUint32 updateStart	= m_pushConstantRange[rangeNdx].update.offset;
900 			const deUint32 updateEnd	= updateStart + m_pushConstantRange[rangeNdx].update.size;
901 
902 			updateRange |= (updateStart <= offset && updateEnd >= offset + 4u);
903 
904 			DE_ASSERT(rangeEnd <= 128u);
905 
906 			if (rangeStart <= offset && rangeEnd >= offset + 4u)
907 				stageFlags |= m_pushConstantRange[rangeNdx].range.shaderStage;
908 		}
909 
910 		// Skip chunks with no updates
911 		if (!stageFlags || !updateRange)
912 			continue;
913 
914 		// Add new update entry
915 		if (stageFlags != lastStageFlags)
916 		{
917 			const VkPushConstantRange update =
918 			{
919 				stageFlags,	// VkShaderStageFlags    stageFlags;
920 				offset,		// deUint32              offset;
921 				4u			// deUint32              size;
922 			};
923 
924 			pushConstantUpdates.push_back(update);
925 			lastStageFlags = stageFlags;
926 		}
927 		// Increase current update entry size
928 		else
929 		{
930 			DE_ASSERT(pushConstantUpdates.size() > 0u);
931 			pushConstantUpdates.back().size += 4u;
932 		}
933 	}
934 
935 	return pushConstantUpdates;
936 }
937 
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)938 void PushConstantGraphicsOverlapTestInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
939 {
940 	const DeviceInterface&				vk = m_context.getDeviceInterface();
941 	const std::vector<VkPushConstantRange> pushConstantUpdates = getPushConstantUpdates();
942 
943 	m_referenceData.resize(m_colorData.size(), 0.0f);
944 
945 	m_context.getTestContext().getLog() << tcu::TestLog::Section("Updates", "Push constant updates");
946 
947 	for (deUint32 pushNdx = 0u; pushNdx < pushConstantUpdates.size(); pushNdx++)
948 	{
949 		m_context.getTestContext().getLog()
950 			<< tcu::TestLog::Message
951 			<< "VkShaderStageFlags    stageFlags    " << getShaderStageNameStr(pushConstantUpdates[pushNdx].stageFlags) << ",\n"
952 			<< "deUint32              offset        " << pushConstantUpdates[pushNdx].offset << ",\n"
953 			<< "deUint32              size          " << pushConstantUpdates[pushNdx].size << ",\n"
954 			<< "const void*           pValues       " << &m_colorData[pushConstantUpdates[pushNdx].offset / 2u] << "\n"
955 			<< tcu::TestLog::EndMessage;
956 
957 		vk.cmdPushConstants(cmdBuffer, pipelineLayout, pushConstantUpdates[pushNdx].stageFlags, pushConstantUpdates[pushNdx].offset, pushConstantUpdates[pushNdx].size, &m_colorData[pushConstantUpdates[pushNdx].offset / 2u]);
958 
959 		// Copy push constant values to reference buffer
960 		DE_ASSERT((pushConstantUpdates[pushNdx].offset / 2u + pushConstantUpdates[pushNdx].size) < 4u * m_colorData.size());
961 		deMemcpy(&m_referenceData.at(pushConstantUpdates[pushNdx].offset / 4u), &m_colorData.at(pushConstantUpdates[pushNdx].offset / 2u), pushConstantUpdates[pushNdx].size);
962 	}
963 
964 	m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
965 }
966 
setReferenceColor(tcu::Vec4 initColor)967 void PushConstantGraphicsOverlapTestInstance::setReferenceColor (tcu::Vec4 initColor)
968 {
969 	tcu::Vec4 expectedColor = initColor;
970 
971 	// Calculate reference color
972 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
973 	{
974 		const deUint32	offset = m_pushConstantRange[rangeNdx].range.offset / 4u;
975 		const deUint32	size = m_pushConstantRange[rangeNdx].range.size / 4u;
976 		const deUint32	numComponents = (size < 4u) ? size : 4u;
977 		const deUint32	colorNdx = (offset + size - numComponents);
978 
979 		for (deUint32 componentNdx = 0u; componentNdx < numComponents; componentNdx++)
980 			expectedColor[componentNdx] += m_referenceData[colorNdx + componentNdx];
981 	}
982 
983 	expectedColor = tcu::min(tcu::mod(expectedColor, tcu::Vec4(2.0f)), 2.0f - tcu::mod(expectedColor, tcu::Vec4(2.0f)));
984 
985 	for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
986 	{
987 		m_vertices[vertexNdx].color.xyzw() = expectedColor;
988 	}
989 }
990 
991 class PushConstantGraphicsTest : public vkt::TestCase
992 {
993 public:
994 							PushConstantGraphicsTest	(tcu::TestContext&			testContext,
995 														 const std::string&			name,
996 														 const std::string&			description,
997 														 const deUint32				rangeCount,
998 														 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
999 														 const deBool				multipleUpdate,
1000 														 const IndexType			indexType);
1001 	virtual					~PushConstantGraphicsTest	(void);
1002 	virtual void			initPrograms				(SourceCollections& sourceCollections) const = 0;
1003 	virtual TestInstance*	createInstance				(Context& context) const = 0;
1004 	RangeSizeCase			getRangeSizeCase			(deUint32 rangeSize) const;
1005 
1006 protected:
1007 	const deUint32			m_rangeCount;
1008 	PushConstantData		m_pushConstantRange[MAX_RANGE_COUNT];
1009 	const deBool			m_multipleUpdate;
1010 	const IndexType			m_indexType;
1011 };
1012 
PushConstantGraphicsTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const deBool multipleUpdate,const IndexType indexType)1013 PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext&			testContext,
1014 													const std::string&			name,
1015 													const std::string&			description,
1016 													const deUint32				rangeCount,
1017 													const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
1018 													const deBool				multipleUpdate,
1019 													const IndexType				indexType)
1020 	: vkt::TestCase		(testContext, name, description)
1021 	, m_rangeCount		(rangeCount)
1022 	, m_multipleUpdate	(multipleUpdate)
1023 	, m_indexType		(indexType)
1024 {
1025 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
1026 }
1027 
~PushConstantGraphicsTest(void)1028 PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
1029 {
1030 }
1031 
getRangeSizeCase(deUint32 rangeSize) const1032 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
1033 {
1034 	switch (rangeSize)
1035 	{
1036 		case 8:
1037 			return SIZE_CASE_8;
1038 		case 4:
1039 			return SIZE_CASE_4;
1040 		case 12:
1041 			return SIZE_CASE_12;
1042 		case 16:
1043 			return SIZE_CASE_16;
1044 		case 32:
1045 			return SIZE_CASE_32;
1046 		case 36:
1047 			return SIZE_CASE_36;
1048 		case 48:
1049 			return SIZE_CASE_48;
1050 		case 128:
1051 			return SIZE_CASE_128;
1052 		default:
1053 			DE_FATAL("Range size unsupported yet");
1054 			return SIZE_CASE_UNSUPPORTED;
1055 	}
1056 }
1057 
1058 class PushConstantGraphicsDisjointTest : public PushConstantGraphicsTest
1059 {
1060 public:
1061 							PushConstantGraphicsDisjointTest	(tcu::TestContext&			testContext,
1062 																 const std::string&			name,
1063 																 const std::string&			description,
1064 																 const deUint32				rangeCount,
1065 																 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
1066 																 const deBool				multipleUpdate,
1067 																 const IndexType			indexType);
1068 	virtual					~PushConstantGraphicsDisjointTest	(void);
1069 	virtual void			initPrograms						(SourceCollections& sourceCollections) const;
1070 	virtual TestInstance*	createInstance						(Context& context) const;
1071 };
1072 
PushConstantGraphicsDisjointTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const deBool multipleUpdate,const IndexType indexType)1073 PushConstantGraphicsDisjointTest::PushConstantGraphicsDisjointTest (tcu::TestContext&		testContext,
1074 																	const std::string&		name,
1075 																	const std::string&		description,
1076 																	const deUint32			rangeCount,
1077 																	const PushConstantData	pushConstantRange[MAX_RANGE_COUNT],
1078 																	const deBool			multipleUpdate,
1079 																	const IndexType			indexType)
1080 	: PushConstantGraphicsTest (testContext, name, description, rangeCount, pushConstantRange, multipleUpdate, indexType)
1081 {
1082 }
1083 
~PushConstantGraphicsDisjointTest(void)1084 PushConstantGraphicsDisjointTest::~PushConstantGraphicsDisjointTest (void)
1085 {
1086 }
1087 
initPrograms(SourceCollections & sourceCollections) const1088 void PushConstantGraphicsDisjointTest::initPrograms (SourceCollections& sourceCollections) const
1089 {
1090 	std::ostringstream	vertexSrc;
1091 	std::ostringstream	fragmentSrc;
1092 	std::ostringstream	geometrySrc;
1093 	std::ostringstream	tessControlSrc;
1094 	std::ostringstream	tessEvaluationSrc;
1095 
1096 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1097 	{
1098 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1099 		{
1100 			vertexSrc << "#version 450\n"
1101 					  << "layout(location = 0) in highp vec4 position;\n"
1102 					  << "layout(location = 1) in highp vec4 color;\n"
1103 					  << "layout(location = 0) out highp vec4 vtxColor;\n"
1104 					  << "out gl_PerVertex { vec4 gl_Position; };\n"
1105 					  << "layout(push_constant) uniform Material {\n";
1106 
1107 			switch (m_indexType)
1108 			{
1109 				case INDEX_TYPE_CONST_LITERAL:
1110 					switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1111 					{
1112 						case SIZE_CASE_4:
1113 							vertexSrc << "int kind;\n"
1114 									  << "} matInst;\n";
1115 							break;
1116 						case SIZE_CASE_16:
1117 							vertexSrc << "vec4 color;\n"
1118 									  << "} matInst;\n"
1119 									  << "layout(std140, binding = 0) uniform UniformBuf {\n"
1120 									  << "vec4 element;\n"
1121 									  << "} uniformBuf;\n";
1122 							break;
1123 						case SIZE_CASE_32:
1124 							vertexSrc << "vec4 color[2];\n"
1125 									  << "} matInst;\n";
1126 							break;
1127 						case SIZE_CASE_48:
1128 							vertexSrc << "int dummy1;\n"
1129 									  << "vec4 dummy2;\n"
1130 									  << "vec4 color;\n"
1131 									  << "} matInst;\n";
1132 							break;
1133 						case SIZE_CASE_128:
1134 							vertexSrc << "vec4 color[8];\n"
1135 									  << "} matInst;\n";
1136 							break;
1137 						default:
1138 							DE_FATAL("Not implemented yet");
1139 							break;
1140 					}
1141 					break;
1142 				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1143 					vertexSrc << "    layout(offset = 0)  vec4 index; \n"
1144 							  << "    layout(offset = 16) vec4 vecType; \n"
1145 							  << "    layout(offset = 32) mat2 matType; \n"
1146 							  << "    layout(offset = 48) float[4] arrType; \n"
1147 							  << "} matInst;\n";
1148 					break;
1149 				default:
1150 					DE_FATAL("Unhandled IndexType");
1151 					break;
1152 			}
1153 
1154 			vertexSrc << "void main()\n"
1155 					  << "{\n"
1156 					  << "	gl_Position = position;\n";
1157 
1158 			switch (m_indexType)
1159 			{
1160 				case INDEX_TYPE_CONST_LITERAL:
1161 					switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1162 					{
1163 						case SIZE_CASE_4:
1164 							vertexSrc << "switch (matInst.kind) {\n"
1165 									  << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
1166 									  << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
1167 									  << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
1168 									  << "default: vtxColor = color; break;}\n"
1169 									  << "}\n";
1170 							break;
1171 						case SIZE_CASE_16:
1172 							vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
1173 									  << "}\n";
1174 							break;
1175 						case SIZE_CASE_32:
1176 							vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
1177 									  << "}\n";
1178 							break;
1179 						case SIZE_CASE_48:
1180 							vertexSrc << "vtxColor = matInst.color;\n"
1181 									  << "}\n";
1182 							break;
1183 						case SIZE_CASE_128:
1184 							vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
1185 									  << "for (int i = 0; i < 8; i++)\n"
1186 									  << "{\n"
1187 									  << "  color = color + matInst.color[i];\n"
1188 									  << "}\n"
1189 									  << "vtxColor = color * 0.125;\n"
1190 									  << "}\n";
1191 							break;
1192 						default:
1193 							DE_FATAL("Not implemented yet");
1194 							break;
1195 					}
1196 					break;
1197 				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1198 					{
1199 						vertexSrc << "    vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1200 								  // Mix in gl_Position to (hopefully) prevent optimizing our index away
1201 								  << "    int vec_selector = int(abs(gl_Position.x) * 0.0000001 + 0);\n"
1202 								  << "    int mat_selector = int(abs(gl_Position.x) * 0.0000001 + 1);\n"
1203 								  << "    int arr_selector = int(abs(gl_Position.x) * 0.0000001 + 2);\n";
1204 
1205 						// Use the dynamic index to pull our real index value from push constants
1206 						// Then use that value to index into three variable types
1207 						std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1208 						std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1209 						std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1210 
1211 						// Test vector indexing
1212 						vertexSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1213 								  << "        vtxColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1214 
1215 						// Test matrix indexing
1216 						vertexSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1217 								  << "        vtxColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1218 
1219 						// Test array indexing
1220 						vertexSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1221 								  << "        vtxColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1222 
1223 						vertexSrc << "}\n";
1224 					}
1225 					break;
1226 				default:
1227 					DE_FATAL("Unhandled IndexType");
1228 					break;
1229 			}
1230 
1231 			sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
1232 		}
1233 
1234 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1235 		{
1236 			tessControlSrc << "#version 450\n"
1237 						   << "layout (vertices = 3) out;\n"
1238 						   << "layout(push_constant) uniform TessLevel {\n"
1239 						   << "    layout(offset = 24) int level;\n"
1240 						   << "} tessLevel;\n"
1241 						   << "layout(location = 0) in highp vec4 color[];\n"
1242 						   << "layout(location = 0) out highp vec4 vtxColor[];\n"
1243 						   << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1244 						   << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
1245 						   << "void main()\n"
1246 						   << "{\n"
1247 						   << "  gl_TessLevelInner[0] = tessLevel.level;\n"
1248 						   << "  gl_TessLevelOuter[0] = tessLevel.level;\n"
1249 						   << "  gl_TessLevelOuter[1] = tessLevel.level;\n"
1250 						   << "  gl_TessLevelOuter[2] = tessLevel.level;\n"
1251 						   << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1252 						   << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1253 						   << "}\n";
1254 
1255 			sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
1256 		}
1257 
1258 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1259 		{
1260 			tessEvaluationSrc << "#version 450\n"
1261 							  << "layout (triangles) in;\n"
1262 							  << "layout(push_constant) uniform Material {\n"
1263 							  << "    layout(offset = 32) vec4 color;\n"
1264 							  << "} matInst;\n"
1265 							  << "layout(location = 0) in highp vec4 color[];\n"
1266 							  << "layout(location = 0) out highp vec4 vtxColor;\n"
1267 							  << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1268 							  << "out gl_PerVertex { vec4 gl_Position; };\n"
1269 							  << "void main()\n"
1270 							  << "{\n"
1271 							  << "  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"
1272 							  << "  vtxColor = matInst.color;\n"
1273 							  << "}\n";
1274 
1275 			sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
1276 		}
1277 
1278 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1279 		{
1280 			geometrySrc << "#version 450\n"
1281 						<< "layout(triangles) in;\n"
1282 						<< "layout(triangle_strip, max_vertices=3) out;\n"
1283 						<< "layout(push_constant) uniform Material {\n"
1284 						<< "    layout(offset = 20) int kind;\n"
1285 						<< "} matInst;\n"
1286 						<< "layout(location = 0) in highp vec4 color[];\n"
1287 						<< "layout(location = 0) out highp vec4 vtxColor;\n"
1288 						<< "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
1289 						<< "out gl_PerVertex { vec4 gl_Position; };\n"
1290 						<< "void main()\n"
1291 						<< "{\n"
1292 						<< "  for(int i=0; i<3; i++)\n"
1293 						<< "  {\n"
1294 						<< "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
1295 						<< "    gl_Position.w = gl_in[i].gl_Position.w;\n"
1296 						<< "    vtxColor = color[i];\n"
1297 						<< "    EmitVertex();\n"
1298 						<< "  }\n"
1299 						<< "  EndPrimitive();\n"
1300 						<< "}\n";
1301 
1302 			sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
1303 		}
1304 
1305 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1306 		{
1307 			fragmentSrc << "#version 450\n"
1308 						<< "layout(location = 0) in highp vec4 vtxColor;\n"
1309 						<< "layout(location = 0) out highp vec4 fragColor;\n"
1310 						<< "layout(push_constant) uniform Material {\n";
1311 
1312 			switch (m_indexType)
1313 			{
1314 				case INDEX_TYPE_CONST_LITERAL:
1315 					if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1316 					{
1317 						fragmentSrc << "    layout(offset = 0) int kind; \n"
1318 									<< "} matInst;\n";
1319 					}
1320 					else
1321 					{
1322 						fragmentSrc << "    layout(offset = 16) int kind;\n"
1323 									<< "} matInst;\n";
1324 					}
1325 
1326 					fragmentSrc << "void main (void)\n"
1327 						<< "{\n"
1328 						<< "    switch (matInst.kind) {\n"
1329 						<< "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
1330 						<< "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
1331 						<< "    case 2: fragColor = vtxColor; break;\n"
1332 						<< "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
1333 						<< "}\n";
1334 					break;
1335 				case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1336 					{
1337 						fragmentSrc << "    layout(offset = 0)  vec4 index; \n"
1338 									<< "    layout(offset = 16) vec4 vecType; \n"
1339 									<< "    layout(offset = 32) mat2 matType; \n"
1340 									<< "    layout(offset = 48) float[4] arrType; \n"
1341 									<< "} matInst;\n";
1342 
1343 						fragmentSrc << "void main (void)\n"
1344 									<< "{\n"
1345 									<< "    fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1346 
1347 									// Mix in gl_FragCoord to (hopefully) prevent optimizing our index away
1348 									<< "    int vec_selector = int(gl_FragCoord.x * 0.0000001 + 0);\n"
1349 									<< "    int mat_selector = int(gl_FragCoord.x * 0.0000001 + 1);\n"
1350 									<< "    int arr_selector = int(gl_FragCoord.x * 0.0000001 + 2);\n";
1351 
1352 						// Use the dynamic index to pull our real index value from push constants
1353 						// Then use that value to index into three variable types
1354 						std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1355 						std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1356 						std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1357 
1358 						// Test vector indexing
1359 						fragmentSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1360 									<< "        fragColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1361 
1362 						// Test matrix indexing
1363 						fragmentSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1364 									<< "        fragColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1365 
1366 						// Test array indexing
1367 						fragmentSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1368 									<< "        fragColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1369 
1370 						fragmentSrc << "}\n";
1371 					}
1372 					break;
1373 				default:
1374 					DE_FATAL("Unhandled IndexType");
1375 					break;
1376 			}
1377 
1378 			sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1379 		}
1380 	}
1381 
1382 	// add a pass through fragment shader if it's not activated in push constant ranges
1383 	if (fragmentSrc.str().empty())
1384 	{
1385 		fragmentSrc << "#version 450\n"
1386 					<< "layout(location = 0) in highp vec4 vtxColor;\n"
1387 					<< "layout(location = 0) out highp vec4 fragColor;\n"
1388 					<< "void main (void)\n"
1389 					<< "{\n"
1390 					<< "	fragColor = vtxColor;\n"
1391 					<< "}\n";
1392 
1393 		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1394 	}
1395 }
1396 
createInstance(Context & context) const1397 TestInstance* PushConstantGraphicsDisjointTest::createInstance (Context& context) const
1398 {
1399 	return new PushConstantGraphicsDisjointInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate, m_indexType);
1400 }
1401 
1402 class PushConstantGraphicsOverlapTest : public PushConstantGraphicsTest
1403 {
1404 public:
1405 							PushConstantGraphicsOverlapTest		(tcu::TestContext&			testContext,
1406 																 const std::string&			name,
1407 																 const std::string&			description,
1408 																 const deUint32				rangeCount,
1409 																 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT]);
1410 	virtual					~PushConstantGraphicsOverlapTest	(void);
1411 	std::string				getPushConstantDeclarationStr		(VkShaderStageFlags shaderStage) const;
1412 	virtual void			initPrograms						(SourceCollections& sourceCollections) const;
1413 	virtual TestInstance*	createInstance						(Context& context) const;
1414 };
1415 
PushConstantGraphicsOverlapTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT])1416 PushConstantGraphicsOverlapTest::PushConstantGraphicsOverlapTest (tcu::TestContext&			testContext,
1417 																  const std::string&		name,
1418 																  const std::string&		description,
1419 																  const deUint32			rangeCount,
1420 																  const PushConstantData	pushConstantRange[MAX_RANGE_COUNT])
1421 	: PushConstantGraphicsTest (testContext, name, description, rangeCount, pushConstantRange, false, INDEX_TYPE_CONST_LITERAL)
1422 {
1423 }
1424 
~PushConstantGraphicsOverlapTest(void)1425 PushConstantGraphicsOverlapTest::~PushConstantGraphicsOverlapTest (void)
1426 {
1427 }
1428 
getPushConstantDeclarationStr(VkShaderStageFlags shaderStage) const1429 std::string PushConstantGraphicsOverlapTest::getPushConstantDeclarationStr (VkShaderStageFlags shaderStage) const
1430 {
1431 	std::stringstream src;
1432 
1433 	src	<< "layout(push_constant) uniform Material\n"
1434 		<< "{\n";
1435 
1436 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1437 	{
1438 		if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStage)
1439 		{
1440 			switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1441 			{
1442 				case SIZE_CASE_4:
1443 					src	<< "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") float color;\n";
1444 					break;
1445 				case SIZE_CASE_8:
1446 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec2 color;\n";
1447 					break;
1448 				case SIZE_CASE_12:
1449 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec3 color;\n";
1450 					break;
1451 				case SIZE_CASE_16:
1452 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color;\n";
1453 					break;
1454 				case SIZE_CASE_32:
1455 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[2];\n";
1456 					break;
1457 				case SIZE_CASE_36:
1458 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") int dummy1;\n"
1459 						<< "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 4) << ") vec4 dummy2;\n"
1460 						<< "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 20) << ") vec4 color;\n";
1461 					break;
1462 				case SIZE_CASE_128:
1463 					src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[8];\n";
1464 					break;
1465 				default:
1466 					DE_FATAL("Not implemented");
1467 					break;
1468 			}
1469 		}
1470 	}
1471 
1472 	src	<< "} matInst;\n";
1473 
1474 	return src.str();
1475 }
1476 
getSwizzleStr(deUint32 size)1477 std::string getSwizzleStr (deUint32 size)
1478 {
1479 	switch (size)
1480 	{
1481 		case 4:		return ".x";
1482 		case 8:		return ".xy";
1483 		case 12:	return ".xyz";
1484 		case 16:
1485 		case 32:
1486 		case 36:
1487 		case 128:	return "";
1488 		default:	DE_FATAL("Not implemented");
1489 					return "";
1490 	}
1491 }
1492 
getColorReadStr(deUint32 size)1493 std::string getColorReadStr (deUint32 size)
1494 {
1495 	// Always read the last element from array types
1496 	const std::string	arrayNdx		= (size == 128u)	? "[7]"
1497 										: (size == 32u)		? "[1]"
1498 										: "";
1499 	const std::string	colorReadStr	= getSwizzleStr(size) + " += matInst.color" + arrayNdx + ";\n";;
1500 
1501 	return colorReadStr;
1502 }
1503 
initPrograms(SourceCollections & sourceCollections) const1504 void PushConstantGraphicsOverlapTest::initPrograms (SourceCollections& sourceCollections) const
1505 {
1506 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1507 	{
1508 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1509 		{
1510 			const std::string source =
1511 				"#version 450\n"
1512 				"layout(location = 0) in highp vec4 position;\n"
1513 				"layout(location = 1) in highp vec4 inColor;\n"
1514 				"layout(location = 0) out highp vec4 vtxColor;\n"
1515 				"out gl_PerVertex\n"
1516 				"{\n"
1517 				"    vec4 gl_Position;\n"
1518 				"};\n"
1519 				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_VERTEX_BIT) +
1520 				"void main()\n"
1521 				"{\n"
1522 				"    gl_Position = position;\n"
1523 				"    vec4 color = inColor;\n"
1524 				"    color" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1525 				"    vtxColor = color;\n"
1526 				"}\n";
1527 
1528 			sourceCollections.glslSources.add("color_vert") << glu::VertexSource(source);
1529 		}
1530 
1531 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1532 		{
1533 			const std::string source =
1534 				"#version 450\n"
1535 				"layout (vertices = 3) out;\n"
1536 				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) +
1537 				"layout(location = 0) in highp vec4 color[];\n"
1538 				"layout(location = 0) out highp vec4 vtxColor[];\n"
1539 				"in gl_PerVertex\n"
1540 				"{\n"
1541 				"    vec4 gl_Position;\n"
1542 				"} gl_in[gl_MaxPatchVertices];\n"
1543 				"out gl_PerVertex\n"
1544 				"{\n"
1545 				"    vec4 gl_Position;\n"
1546 				"} gl_out[];\n"
1547 				"void main()\n"
1548 				"{\n"
1549 				"    gl_TessLevelInner[0] = 2.0;\n"
1550 				"    gl_TessLevelOuter[0] = 2.0;\n"
1551 				"    gl_TessLevelOuter[1] = 2.0;\n"
1552 				"    gl_TessLevelOuter[2] = 2.0;\n"
1553 				"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1554 				"    vec4 outColor = color[gl_InvocationID];\n"
1555 				"    outColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1556 				"    vtxColor[gl_InvocationID] = outColor;\n"
1557 				"}\n";
1558 
1559 			sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(source);
1560 		}
1561 
1562 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1563 		{
1564 			const std::string source =
1565 				"#version 450\n"
1566 				"layout (triangles) in;\n"
1567 				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) +
1568 				"layout(location = 0) in highp vec4 color[];\n"
1569 				"layout(location = 0) out highp vec4 vtxColor;\n"
1570 				"in gl_PerVertex\n"
1571 				"{\n"
1572 				"    vec4 gl_Position;\n"
1573 				"} gl_in[gl_MaxPatchVertices];\n"
1574 				"out gl_PerVertex\n"
1575 				"{\n"
1576 				"    vec4 gl_Position;\n"
1577 				"};\n"
1578 				"void main()\n"
1579 				"{\n"
1580 				"    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"
1581 				"    vtxColor = gl_TessCoord.x * color[0] + gl_TessCoord.y * color[1] + gl_TessCoord.z * color[2];\n"
1582 				"    vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1583 				"}\n";
1584 
1585 			sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(source);
1586 		}
1587 
1588 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1589 		{
1590 			const std::string source =
1591 				"#version 450\n"
1592 				"layout(triangles) in;\n"
1593 				"layout(triangle_strip, max_vertices=3) out;\n"
1594 				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_GEOMETRY_BIT) +
1595 				"layout(location = 0) in highp vec4 color[];\n"
1596 				"layout(location = 0) out highp vec4 vtxColor;\n"
1597 				"in gl_PerVertex\n"
1598 				"{\n"
1599 				"    vec4 gl_Position;\n"
1600 				"} gl_in[];\n"
1601 				"out gl_PerVertex\n"
1602 				"{\n"
1603 				"    vec4 gl_Position;\n"
1604 				"};\n"
1605 				"void main()\n"
1606 				"{\n"
1607 				"    for(int i = 0; i < 3; i++)\n"
1608 				"    {\n"
1609 				"        gl_Position.xyz = gl_in[i].gl_Position.xyz / 2.0;\n"
1610 				"        gl_Position.w = gl_in[i].gl_Position.w;\n"
1611 				"        vtxColor = color[i];\n"
1612 				"        vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1613 				"        EmitVertex();\n"
1614 				"    }\n"
1615 				"    EndPrimitive();\n"
1616 				"}\n";
1617 
1618 			sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(source);
1619 		}
1620 
1621 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1622 		{
1623 			const std::string source =
1624 				"#version 450\n"
1625 				"layout(location = 0) in highp vec4 vtxColor;\n"
1626 				"layout(location = 0) out highp vec4 fragColor;\n"
1627 				+ getPushConstantDeclarationStr(VK_SHADER_STAGE_FRAGMENT_BIT) +
1628 				"void main (void)\n"
1629 				"{\n"
1630 				"    fragColor = vtxColor;\n"
1631 				"    fragColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1632 				"    fragColor = min(mod(fragColor, 2.0), 2.0 - mod(fragColor, 2.0));\n"
1633 				"}\n";
1634 
1635 			sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(source);
1636 		}
1637 	}
1638 }
1639 
createInstance(Context & context) const1640 TestInstance* PushConstantGraphicsOverlapTest::createInstance (Context& context) const
1641 {
1642 	return new PushConstantGraphicsOverlapTestInstance(context, m_rangeCount, m_pushConstantRange, false, INDEX_TYPE_CONST_LITERAL);
1643 }
1644 
1645 class PushConstantComputeTest : public vkt::TestCase
1646 {
1647 public:
1648 							PushConstantComputeTest		(tcu::TestContext&		testContext,
1649 														 const std::string&		name,
1650 														 const std::string&		description,
1651 														 const PushConstantData	pushConstantRange);
1652 	virtual					~PushConstantComputeTest	(void);
1653 	virtual void			initPrograms				(SourceCollections& sourceCollections) const;
1654 	virtual TestInstance*	createInstance				(Context& context) const;
1655 
1656 private:
1657 	const PushConstantData	m_pushConstantRange;
1658 };
1659 
1660 class PushConstantComputeTestInstance : public vkt::TestInstance
1661 {
1662 public:
1663 							PushConstantComputeTestInstance		(Context&				context,
1664 																 const PushConstantData	pushConstantRange);
1665 	virtual					~PushConstantComputeTestInstance	(void);
1666 	virtual tcu::TestStatus	iterate								(void);
1667 
1668 private:
1669 	const PushConstantData			m_pushConstantRange;
1670 
1671 	Move<VkBuffer>					m_outBuffer;
1672 	de::MovePtr<Allocation>			m_outBufferAlloc;
1673 	Move<VkDescriptorPool>			m_descriptorPool;
1674 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1675 	Move<VkDescriptorSet>			m_descriptorSet;
1676 
1677 	Move<VkPipelineLayout>			m_pipelineLayout;
1678 	Move<VkPipeline>				m_computePipelines;
1679 
1680 	Move<VkShaderModule>			m_computeShaderModule;
1681 
1682 	Move<VkCommandPool>				m_cmdPool;
1683 	Move<VkCommandBuffer>			m_cmdBuffer;
1684 };
1685 
PushConstantComputeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const PushConstantData pushConstantRange)1686 PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext&			testContext,
1687 												  const std::string&		name,
1688 												  const std::string&		description,
1689 												  const PushConstantData	pushConstantRange)
1690 	: vkt::TestCase			(testContext, name, description)
1691 	, m_pushConstantRange	(pushConstantRange)
1692 {
1693 }
1694 
~PushConstantComputeTest(void)1695 PushConstantComputeTest::~PushConstantComputeTest (void)
1696 {
1697 }
1698 
createInstance(Context & context) const1699 TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1700 {
1701 	return new PushConstantComputeTestInstance(context, m_pushConstantRange);
1702 }
1703 
initPrograms(SourceCollections & sourceCollections) const1704 void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1705 {
1706 	std::ostringstream	computeSrc;
1707 
1708 	computeSrc << "#version 450\n"
1709 			   << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1710 			   << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1711 			   << "  vec4 elements[];\n"
1712 			   << "} outData;\n"
1713 			   << "layout(push_constant) uniform Material{\n"
1714 			   << "  vec4 element;\n"
1715 			   << "} matInst;\n"
1716 			   << "void main (void)\n"
1717 			   << "{\n"
1718 			   << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1719 			   << "}\n";
1720 
1721 	sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1722 }
1723 
PushConstantComputeTestInstance(Context & context,const PushConstantData pushConstantRange)1724 PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context&					context,
1725 																  const PushConstantData	pushConstantRange)
1726 	: vkt::TestInstance		(context)
1727 	, m_pushConstantRange	(pushConstantRange)
1728 {
1729 	const DeviceInterface&		vk					= context.getDeviceInterface();
1730 	const VkDevice				vkDevice			= context.getDevice();
1731 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1732 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1733 
1734 	// Create pipeline layout
1735 	{
1736 		// create push constant range
1737 		VkPushConstantRange	pushConstantRanges;
1738 		pushConstantRanges.stageFlags	= m_pushConstantRange.range.shaderStage;
1739 		pushConstantRanges.offset		= m_pushConstantRange.range.offset;
1740 		pushConstantRanges.size			= m_pushConstantRange.range.size;
1741 
1742 		// create descriptor set layout
1743 		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1744 
1745 		// create descriptor pool
1746 		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1747 
1748 		// create uniform buffer
1749 		const VkDeviceSize			bufferSize			= sizeof(tcu::Vec4) * 8;
1750 		const VkBufferCreateInfo	bufferCreateInfo	=
1751 		{
1752 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
1753 			DE_NULL,													// const void*			pNext;
1754 			0u,															// VkBufferCreateFlags	flags
1755 			bufferSize,													// VkDeviceSize			size;
1756 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,							// VkBufferUsageFlags	usage;
1757 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
1758 			1u,															// deUint32				queueFamilyCount;
1759 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
1760 		};
1761 
1762 		m_outBuffer			= createBuffer(vk, vkDevice, &bufferCreateInfo);
1763 		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1764 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1765 
1766 		// create and update descriptor set
1767 		const VkDescriptorSetAllocateInfo allocInfo =
1768 		{
1769 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                             sType;
1770 			DE_NULL,													// const void*                                 pNext;
1771 			*m_descriptorPool,											// VkDescriptorPool                            descriptorPool;
1772 			1u,															// uint32_t                                    setLayoutCount;
1773 			&(*m_descriptorSetLayout),									// const VkDescriptorSetLayout*                pSetLayouts;
1774 		};
1775 		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
1776 
1777 		const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1778 
1779 		DescriptorSetUpdateBuilder()
1780 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1781 			.update(vk, vkDevice);
1782 
1783 		// create pipeline layout
1784 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
1785 		{
1786 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1787 			DE_NULL,											// const void*					pNext;
1788 			0u,													// VkPipelineLayoutCreateFlags	flags;
1789 			1u,													// deUint32						descriptorSetCount;
1790 			&(*m_descriptorSetLayout),							// const VkDescriptorSetLayout*	pSetLayouts;
1791 			1u,													// deUint32						pushConstantRangeCount;
1792 			&pushConstantRanges									// const VkPushConstantRange*	pPushConstantRanges;
1793 		};
1794 
1795 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1796 	}
1797 
1798 	// create pipeline
1799 	{
1800 		m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1801 
1802 		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
1803 		{
1804 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1805 			DE_NULL,												// const void*							pNext;
1806 			0u,														// VkPipelineShaderStageCreateFlags		flags;
1807 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1808 			*m_computeShaderModule,									// VkShaderModule						module;
1809 			"main",													// const char*							pName;
1810 			DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
1811 		};
1812 
1813 		const VkComputePipelineCreateInfo		createInfo	=
1814 		{
1815 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType                             sType;
1816 			DE_NULL,												// const void*                                 pNext;
1817 			0u,														// VkPipelineCreateFlags                       flags;
1818 			stageCreateInfo,										// VkPipelineShaderStageCreateInfo             stage;
1819 			*m_pipelineLayout,										// VkPipelineLayout                            layout;
1820 			(VkPipeline)0,											// VkPipeline                                  basePipelineHandle;
1821 			0u,														// int32_t                                     basePipelineIndex;
1822 		};
1823 
1824 		m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1825 	}
1826 
1827 	// Create command pool
1828 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1829 
1830 	// Create command buffer
1831 	{
1832 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1833 
1834 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1835 
1836 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1837 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1838 
1839 		// update push constant
1840 		tcu::Vec4	value	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1841 		vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1842 
1843 		vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1844 
1845 		endCommandBuffer(vk, *m_cmdBuffer);
1846 	}
1847 }
1848 
~PushConstantComputeTestInstance(void)1849 PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1850 {
1851 }
1852 
iterate(void)1853 tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1854 {
1855 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1856 	const VkDevice				vkDevice	= m_context.getDevice();
1857 	const VkQueue				queue		= m_context.getUniversalQueue();
1858 
1859 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1860 
1861 	invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
1862 
1863 	// verify result
1864 	std::vector<tcu::Vec4>	expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1865 	if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1866 	{
1867 		return tcu::TestStatus::fail("Image mismatch");
1868 	}
1869 	return tcu::TestStatus::pass("result image matches with reference");
1870 }
1871 
1872 } // anonymous
1873 
createPushConstantTests(tcu::TestContext & testCtx)1874 tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
1875 {
1876 	static const struct
1877 	{
1878 		const char*			name;
1879 		const char*			description;
1880 		deUint32			count;
1881 		PushConstantData	range[MAX_RANGE_COUNT];
1882 		deBool				hasMultipleUpdates;
1883 		IndexType			indexType;
1884 	} graphicsParams[] =
1885 	{
1886 		// test range size from minimum valid size to maximum
1887 		{
1888 			"range_size_4",
1889 			"test range size is 4 bytes(minimum valid size)",
1890 			1u,
1891 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
1892 			false,
1893 			INDEX_TYPE_CONST_LITERAL
1894 		},
1895 		{
1896 			"range_size_16",
1897 			"test range size is 16 bytes, and together with a normal uniform",
1898 			1u,
1899 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
1900 			false,
1901 			INDEX_TYPE_CONST_LITERAL
1902 		},
1903 		{
1904 			"range_size_128",
1905 			"test range size is 128 bytes(maximum valid size)",
1906 			1u,
1907 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
1908 			false,
1909 			INDEX_TYPE_CONST_LITERAL
1910 		},
1911 		// test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
1912 		{
1913 			"count_2_shaders_vert_frag",
1914 			"test range count is 2, use vertex and fragment shaders",
1915 			2u,
1916 			{
1917 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1918 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1919 			},
1920 			false,
1921 			INDEX_TYPE_CONST_LITERAL
1922 		},
1923 		{
1924 			"count_3_shaders_vert_geom_frag",
1925 			"test range count is 3, use vertex, geometry and fragment shaders",
1926 			3u,
1927 			{
1928 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1929 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1930 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1931 			},
1932 			false,
1933 			INDEX_TYPE_CONST_LITERAL
1934 		},
1935 		{
1936 			"count_5_shaders_vert_tess_geom_frag",
1937 			"test range count is 5, use vertex, tessellation, geometry and fragment shaders",
1938 			5u,
1939 			{
1940 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1941 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1942 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1943 				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
1944 				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
1945 			},
1946 			false,
1947 			INDEX_TYPE_CONST_LITERAL
1948 		},
1949 		{
1950 			"count_1_shader_vert_frag",
1951 			"test range count is 1, vertex and fragment shaders share one range",
1952 			1u,
1953 			{ { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
1954 			false,
1955 			INDEX_TYPE_CONST_LITERAL
1956 		},
1957 		// test data partial update and multiple times update
1958 		{
1959 			"data_update_partial_1",
1960 			"test partial update of the values",
1961 			1u,
1962 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
1963 			false,
1964 			INDEX_TYPE_CONST_LITERAL
1965 		},
1966 		{
1967 			"data_update_partial_2",
1968 			"test partial update of the values",
1969 			1u,
1970 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
1971 			false,
1972 			INDEX_TYPE_CONST_LITERAL
1973 		},
1974 		{
1975 			"data_update_multiple",
1976 			"test multiple times update of the values",
1977 			1u,
1978 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
1979 			true,
1980 			INDEX_TYPE_CONST_LITERAL
1981 		},
1982 		{
1983 			"dynamic_index_vert",
1984 			"dynamically uniform indexing of vertex, matrix, and array in vertex shader",
1985 			1u,
1986 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 64 }, { 0, 64 } } },
1987 			false,
1988 			INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
1989 		},
1990 		{
1991 			"dynamic_index_frag",
1992 			"dynamically uniform indexing of vertex, matrix, and array in fragment shader",
1993 			1u,
1994 			{ { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 64 }, { 0, 64 } } },
1995 			false,
1996 			INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
1997 		}
1998 	};
1999 
2000 	static const struct
2001 	{
2002 		const char*			name;
2003 		const char*			description;
2004 		deUint32			count;
2005 		PushConstantData	range[MAX_RANGE_COUNT];
2006 	} overlapGraphicsParams[] =
2007 	{
2008 		// test ranges with multiple overlapping stages
2009 		{
2010 			"overlap_2_shaders_vert_frag",
2011 			"overlapping range count is 2, use vertex and fragment shaders",
2012 			2u,
2013 			{
2014 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
2015 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36 }, { 12, 36 } },
2016 			}
2017 		},
2018 		{
2019 			"overlap_3_shaders_vert_geom_frag",
2020 			"overlapping range count is 3, use vertex, geometry and fragment shaders",
2021 			3u,
2022 			{
2023 				{ { VK_SHADER_STAGE_VERTEX_BIT, 12, 36 }, { 12, 36 } },
2024 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32 }, { 16, 16 } },
2025 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4 }, { 20, 4 } }
2026 			}
2027 		},
2028 		{
2029 			"overlap_4_shaders_vert_tess_frag",
2030 			"overlapping range count is 4, use vertex, tessellation and fragment shaders",
2031 			4u,
2032 			{
2033 				{ { VK_SHADER_STAGE_VERTEX_BIT, 8, 4 }, { 8, 4 } },
2034 				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 128 }, { 52, 76 } },
2035 				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 56, 8 }, { 56, 8 } },
2036 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 60, 36 }, { 60, 36 } }
2037 			}
2038 		},
2039 		{
2040 			"overlap_5_shaders_vert_tess_geom_frag",
2041 			"overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders",
2042 			5u,
2043 			{
2044 				{ { VK_SHADER_STAGE_VERTEX_BIT, 40, 8 }, { 40, 8 } },
2045 				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12 }, { 32, 12 } },
2046 				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16 }, { 48, 16 } },
2047 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36 }, { 28, 36 } },
2048 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8 }, { 60, 4 } }
2049 			}
2050 		}
2051 	};
2052 
2053 	static const struct
2054 	{
2055 		const char*			name;
2056 		const char*			description;
2057 		PushConstantData	range;
2058 	} computeParams[] =
2059 	{
2060 		{
2061 			"simple_test",
2062 			"test compute pipeline",
2063 			{ { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
2064 		},
2065 	};
2066 
2067 	de::MovePtr<tcu::TestCaseGroup>	pushConstantTests	(new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
2068 
2069 	de::MovePtr<tcu::TestCaseGroup>	graphicsTests	(new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
2070 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
2071 	{
2072 		graphicsTests->addChild(new PushConstantGraphicsDisjointTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates, graphicsParams[ndx].indexType));
2073 	}
2074 
2075 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(overlapGraphicsParams); ndx++)
2076 	{
2077 		graphicsTests->addChild(new PushConstantGraphicsOverlapTest(testCtx, overlapGraphicsParams[ndx].name, overlapGraphicsParams[ndx].description, overlapGraphicsParams[ndx].count, overlapGraphicsParams[ndx].range));
2078 	}
2079 	pushConstantTests->addChild(graphicsTests.release());
2080 
2081 	de::MovePtr<tcu::TestCaseGroup>	computeTests	(new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
2082 	computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
2083 	pushConstantTests->addChild(computeTests.release());
2084 
2085 	return pushConstantTests.release();
2086 }
2087 
2088 } // pipeline
2089 } // vkt
2090