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 "tcuImageCompare.hpp"
40 #include "deMemory.h"
41 #include "deRandom.hpp"
42 #include "deStringUtil.hpp"
43 #include "deUniquePtr.hpp"
44 
45 #include <algorithm>
46 #include <sstream>
47 #include <vector>
48 
49 namespace vkt
50 {
51 namespace pipeline
52 {
53 
54 using namespace vk;
55 
56 namespace
57 {
58 
59 enum
60 {
61 	TRIANGLE_COUNT	= 2,
62 	MAX_RANGE_COUNT	= 5
63 };
64 
65 enum RangeSizeCase
66 {
67 	SIZE_CASE_4	= 0,
68 	SIZE_CASE_16,
69 	SIZE_CASE_32,
70 	SIZE_CASE_48,
71 	SIZE_CASE_128,
72 	SIZE_CASE_UNSUPPORTED
73 };
74 
75 struct PushConstantData
76 {
77 	struct PushConstantRange
78 	{
79 		VkShaderStageFlags		shaderStage;
80 		deUint32				offset;
81 		deUint32				size;
82 	} range;
83 	struct PushConstantUpdate
84 	{
85 		deUint32				offset;
86 		deUint32				size;
87 	} update;
88 };
89 
90 class PushConstantGraphicsTest : public vkt::TestCase
91 {
92 public:
93 							PushConstantGraphicsTest	(tcu::TestContext&			testContext,
94 														 const std::string&			name,
95 														 const std::string&			description,
96 														 const deUint32				rangeCount,
97 														 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
98 														 const deBool				multipleUpdate);
99 	virtual					~PushConstantGraphicsTest	(void);
100 	virtual void			initPrograms				(SourceCollections& sourceCollections) const;
101 	virtual TestInstance*	createInstance				(Context& context) const;
102 	RangeSizeCase			getRangeSizeCase			(deUint32 rangeSize) const;
103 
104 private:
105 	const deUint32			m_rangeCount;
106 	PushConstantData		m_pushConstantRange[MAX_RANGE_COUNT];
107 	const deBool			m_multipleUpdate;
108 };
109 
110 class PushConstantGraphicsTestInstance : public vkt::TestInstance
111 {
112 public:
113 								PushConstantGraphicsTestInstance	(Context&					context,
114 																	 const deUint32				rangeCount,
115 																	 const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
116 																	 const deBool				multipleUpdate);
117 	virtual						~PushConstantGraphicsTestInstance	(void);
118 	virtual tcu::TestStatus		iterate								(void);
119 
120 	void						createShaderStage					(const DeviceInterface&		vk,
121 																	 VkDevice					device,
122 																	 const BinaryCollection&	programCollection,
123 																	 const char*				name,
124 																	 VkShaderStageFlagBits		stage,
125 																	 Move<VkShaderModule>*		module);
126 	std::vector<Vertex4RGBA>	createQuad							(const float size);
127 
128 private:
129 	tcu::TestStatus				verifyImage							(void);
130 
131 private:
132 	const tcu::UVec2								m_renderSize;
133 	const VkFormat									m_colorFormat;
134 	const deUint32									m_rangeCount;
135 	PushConstantData								m_pushConstantRange[MAX_RANGE_COUNT];
136 	const deBool									m_multipleUpdate;
137 
138 	VkImageCreateInfo								m_colorImageCreateInfo;
139 	Move<VkImage>									m_colorImage;
140 	de::MovePtr<Allocation>							m_colorImageAlloc;
141 	Move<VkImageView>								m_colorAttachmentView;
142 	Move<VkRenderPass>								m_renderPass;
143 	Move<VkFramebuffer>								m_framebuffer;
144 
145 	Move<VkShaderModule>							m_vertexShaderModule;
146 	Move<VkShaderModule>							m_fragmentShaderModule;
147 	Move<VkShaderModule>							m_geometryShaderModule;
148 	Move<VkShaderModule>							m_tessControlShaderModule;
149 	Move<VkShaderModule>							m_tessEvaluationShaderModule;
150 
151 	VkShaderStageFlags								m_shaderFlags;
152 	std::vector<VkPipelineShaderStageCreateInfo>	m_shaderStage;
153 
154 	Move<VkBuffer>									m_vertexBuffer;
155 	std::vector<Vertex4RGBA>						m_vertices;
156 	de::MovePtr<Allocation>							m_vertexBufferAlloc;
157 
158 	Move<VkBuffer>									m_uniformBuffer;
159 	de::MovePtr<Allocation>							m_uniformBufferAlloc;
160 	Move<VkDescriptorPool>							m_descriptorPool;
161 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
162 	Move<VkDescriptorSet>							m_descriptorSet;
163 
164 	Move<VkPipelineLayout>							m_pipelineLayout;
165 	Move<VkPipeline>								m_graphicsPipelines;
166 
167 	Move<VkCommandPool>								m_cmdPool;
168 	Move<VkCommandBuffer>							m_cmdBuffer;
169 
170 	Move<VkFence>									m_fence;
171 };
172 
PushConstantGraphicsTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const deBool multipleUpdate)173 PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext&			testContext,
174 													const std::string&			name,
175 													const std::string&			description,
176 													const deUint32				rangeCount,
177 													const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
178 													const deBool				multipleUpdate)
179 	: vkt::TestCase		(testContext, name, description)
180 	, m_rangeCount		(rangeCount)
181 	, m_multipleUpdate	(multipleUpdate)
182 {
183 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
184 }
185 
~PushConstantGraphicsTest(void)186 PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
187 {
188 }
189 
createInstance(Context & context) const190 TestInstance* PushConstantGraphicsTest::createInstance (Context& context) const
191 {
192 	return new PushConstantGraphicsTestInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate);
193 }
194 
getRangeSizeCase(deUint32 rangeSize) const195 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
196 {
197 	switch (rangeSize)
198 	{
199 		case 4:
200 			return SIZE_CASE_4;
201 		case 16:
202 			return SIZE_CASE_16;
203 		case 32:
204 			return SIZE_CASE_32;
205 		case 48:
206 			return SIZE_CASE_48;
207 		case 128:
208 			return SIZE_CASE_128;
209 		default:
210 			DE_FATAL("Range size unsupported yet");
211 			return SIZE_CASE_UNSUPPORTED;
212 	}
213 }
214 
initPrograms(SourceCollections & sourceCollections) const215 void PushConstantGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
216 {
217 	std::ostringstream	vertexSrc;
218 	std::ostringstream	fragmentSrc;
219 	std::ostringstream	geometrySrc;
220 	std::ostringstream	tessControlSrc;
221 	std::ostringstream	tessEvaluationSrc;
222 
223 	for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
224 	{
225 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
226 		{
227 			vertexSrc << "#version 450\n"
228 					  << "layout(location = 0) in highp vec4 position;\n"
229 					  << "layout(location = 1) in highp vec4 color;\n"
230 					  << "layout(location = 0) out highp vec4 vtxColor;\n"
231 					  << "layout(push_constant) uniform Material {\n";
232 
233 			switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
234 			{
235 				case SIZE_CASE_4:
236 					vertexSrc << "int kind;\n"
237 							  << "} matInst;\n";
238 					break;
239 				case SIZE_CASE_16:
240 					vertexSrc << "vec4 color;\n"
241 							  << "} matInst;\n"
242 							  << "layout(std140, binding = 0) uniform UniformBuf {\n"
243 							  << "vec4 element;\n"
244 							  << "} uniformBuf;\n";
245 					break;
246 				case SIZE_CASE_32:
247 					vertexSrc << "vec4 color[2];\n"
248 							  << "} matInst;\n";
249 					break;
250 				case SIZE_CASE_48:
251 					vertexSrc << "int dummy1;\n"
252 							  << "vec4 dummy2;\n"
253 							  << "vec4 color;\n"
254 							  << "} matInst;\n";
255 					break;
256 				case SIZE_CASE_128:
257 					vertexSrc << "vec4 color[8];\n"
258 							  << "} matInst;\n";
259 					break;
260 				default:
261 					DE_FATAL("Not implemented yet");
262 					break;
263 			}
264 
265 			vertexSrc << "void main()\n"
266 					  << "{\n"
267 					  << "	gl_Position = position;\n";
268 
269 			switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
270 			{
271 				case SIZE_CASE_4:
272 					vertexSrc << "switch (matInst.kind) {\n"
273 							  << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
274 							  << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
275 							  << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
276 							  << "default: vtxColor = color; break;}\n"
277 							  << "}\n";
278 					break;
279 				case SIZE_CASE_16:
280 					vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
281 							  << "}\n";
282 					break;
283 				case SIZE_CASE_32:
284 					vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
285 							  << "}\n";
286 					break;
287 				case SIZE_CASE_48:
288 					vertexSrc << "vtxColor = matInst.color;\n"
289 							  << "}\n";
290 					break;
291 				case SIZE_CASE_128:
292 					vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
293 							  << "for (int i = 0; i < 8; i++)\n"
294 							  << "{\n"
295 							  << "  color = color + matInst.color[i];\n"
296 							  << "}\n"
297 							  << "vtxColor = color * 0.125;\n"
298 							  << "}\n";
299 					break;
300 				default:
301 					DE_FATAL("Not implemented yet");
302 					break;
303 			}
304 
305 			sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
306 		}
307 
308 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
309 		{
310 			tessControlSrc << "#version 450\n"
311 						   << "layout (vertices = 3) out;\n"
312 						   << "layout(push_constant) uniform TessLevel {\n"
313 						   << "    layout(offset = 24) int level;\n"
314 						   << "} tessLevel;\n"
315 						   << "layout(location = 0) in highp vec4 color[];\n"
316 						   << "layout(location = 0) out highp vec4 vtxColor[];\n"
317 						   << "void main()\n"
318 						   << "{\n"
319 						   << "  gl_TessLevelInner[0] = tessLevel.level;\n"
320 						   << "  gl_TessLevelOuter[0] = tessLevel.level;\n"
321 						   << "  gl_TessLevelOuter[1] = tessLevel.level;\n"
322 						   << "  gl_TessLevelOuter[2] = tessLevel.level;\n"
323 						   << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
324 						   << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
325 						   << "}\n";
326 
327 			sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
328 		}
329 
330 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
331 		{
332 			tessEvaluationSrc << "#version 450\n"
333 							  << "layout (triangles) in;\n"
334 							  << "layout(push_constant) uniform Material {\n"
335 							  << "    layout(offset = 32) vec4 color;\n"
336 							  << "} matInst;\n"
337 							  << "layout(location = 0) in highp vec4 color[];\n"
338 							  << "layout(location = 0) out highp vec4 vtxColor;\n"
339 							  << "void main()\n"
340 							  << "{\n"
341 							  << "  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"
342 							  << "  vtxColor = matInst.color;\n"
343 							  << "}\n";
344 
345 			sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
346 		}
347 
348 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
349 		{
350 			geometrySrc << "#version 450\n"
351 						<< "layout(triangles) in;\n"
352 						<< "layout(triangle_strip, max_vertices=3) out;\n"
353 						<< "layout(push_constant) uniform Material {\n"
354 						<< "    layout(offset = 20) int kind;\n"
355 						<< "} matInst;\n"
356 						<< "layout(location = 0) in highp vec4 color[];\n"
357 						<< "layout(location = 0) out highp vec4 vtxColor;\n"
358 						<< "void main()\n"
359 						<< "{\n"
360 						<< "  for(int i=0; i<3; i++)\n"
361 						<< "  {\n"
362 						<< "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
363 						<< "    gl_Position.w = gl_in[i].gl_Position.w;\n"
364 						<< "    vtxColor = color[i];\n"
365 						<< "    EmitVertex();\n"
366 						<< "  }\n"
367 						<< "  EndPrimitive();\n"
368 						<< "}\n";
369 
370 			sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
371 		}
372 
373 		if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
374 		{
375 			fragmentSrc << "#version 450\n"
376 						<< "layout(location = 0) in highp vec4 vtxColor;\n"
377 						<< "layout(location = 0) out highp vec4 fragColor;\n"
378 						<< "layout(push_constant) uniform Material {\n";
379 
380 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
381 			{
382 				fragmentSrc << "    layout(offset = 0) int kind;\n"
383 							<< "} matInst;\n";
384 			}
385 			else
386 			{
387 				fragmentSrc << "    layout(offset = 16) int kind;\n"
388 							<< "} matInst;\n";
389 			}
390 
391 			fragmentSrc << "void main (void)\n"
392 						<< "{\n"
393 						<< "    switch (matInst.kind) {\n"
394 						<< "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
395 						<< "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
396 						<< "    case 2: fragColor = vtxColor; break;\n"
397 						<< "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
398 						<< "}\n";
399 
400 			sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
401 		}
402 	}
403 
404 	// add a pass through fragment shader if it's not activated in push constant ranges
405 	if (fragmentSrc.str().empty())
406 	{
407 		fragmentSrc << "#version 450\n"
408 					<< "layout(location = 0) in highp vec4 vtxColor;\n"
409 					<< "layout(location = 0) out highp vec4 fragColor;\n"
410 					<< "void main (void)\n"
411 					<< "{\n"
412 					<< "	fragColor = vtxColor;\n"
413 					<< "}\n";
414 
415 		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
416 	}
417 }
418 
createShaderStage(const DeviceInterface & vk,VkDevice device,const BinaryCollection & programCollection,const char * name,VkShaderStageFlagBits stage,Move<VkShaderModule> * module)419 void PushConstantGraphicsTestInstance::createShaderStage (const DeviceInterface&	vk,
420 														  VkDevice					device,
421 														  const BinaryCollection&	programCollection,
422 														  const char*				name,
423 														  VkShaderStageFlagBits		stage,
424 														  Move<VkShaderModule>*		module)
425 {
426 	*module = createShaderModule(vk, device, programCollection.get(name), 0);
427 
428 	const vk::VkPipelineShaderStageCreateInfo	stageCreateInfo	=
429 	{
430 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
431 		DE_NULL,												// const void*							pNext;
432 		0u,														// VkPipelineShaderStageCreateFlags		flags;
433 		stage,													// VkShaderStageFlagBits				stage;
434 		**module,												// VkShaderModule						module;
435 		"main",													// const char*							pName;
436 		DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
437 	};
438 
439 	m_shaderStage.push_back(stageCreateInfo);
440 }
441 
createQuad(const float size)442 std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
443 {
444 	std::vector<Vertex4RGBA>	vertices;
445 
446 	const tcu::Vec4				color				= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
447 	const Vertex4RGBA			lowerLeftVertex		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
448 	const Vertex4RGBA			lowerRightVertex	= {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
449 	const Vertex4RGBA			UpperLeftVertex		= {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
450 	const Vertex4RGBA			UpperRightVertex	= {tcu::Vec4(size, size, 0.0f, 1.0f), color};
451 
452 	vertices.push_back(lowerLeftVertex);
453 	vertices.push_back(lowerRightVertex);
454 	vertices.push_back(UpperLeftVertex);
455 	vertices.push_back(UpperLeftVertex);
456 	vertices.push_back(lowerRightVertex);
457 	vertices.push_back(UpperRightVertex);
458 
459 	return vertices;
460 }
461 
PushConstantGraphicsTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate)462 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context&					context,
463 																	const deUint32				rangeCount,
464 																	const PushConstantData		pushConstantRange[MAX_RANGE_COUNT],
465 																	deBool						multipleUpdate)
466 	: vkt::TestInstance		(context)
467 	, m_renderSize			(32, 32)
468 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
469 	, m_rangeCount			(rangeCount)
470 	, m_multipleUpdate		(multipleUpdate)
471 	, m_shaderFlags			(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
472 {
473 	const DeviceInterface&		vk						= context.getDeviceInterface();
474 	const VkDevice				vkDevice				= context.getDevice();
475 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
476 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
477 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
478 
479 	deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
480 
481 	// Create color image
482 	{
483 		const VkImageCreateInfo colorImageParams =
484 		{
485 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
486 			DE_NULL,																	// const void*				pNext;
487 			0u,																			// VkImageCreateFlags		flags;
488 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
489 			m_colorFormat,																// VkFormat					format;
490 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
491 			1u,																			// deUint32					mipLevels;
492 			1u,																			// deUint32					arrayLayers;
493 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
494 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
495 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
496 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
497 			1u,																			// deUint32					queueFamilyIndexCount;
498 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
499 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
500 		};
501 
502 		m_colorImageCreateInfo	= colorImageParams;
503 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
504 
505 		// Allocate and bind color image memory
506 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
507 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
508 	}
509 
510 	// Create color attachment view
511 	{
512 		const VkImageViewCreateInfo colorAttachmentViewParams =
513 		{
514 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType				sType;
515 			DE_NULL,											// const void*					pNext;
516 			0u,													// VkImageViewCreateFlags		flags;
517 			*m_colorImage,										// VkImage						image;
518 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType				viewType;
519 			m_colorFormat,										// VkFormat						format;
520 			componentMappingRGBA,								// VkChannelMapping				channels;
521 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange		subresourceRange;
522 		};
523 
524 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
525 	}
526 
527 	// Create render pass
528 	{
529 		const VkAttachmentDescription colorAttachmentDescription =
530 		{
531 			0u,													// VkAttachmentDescriptionFlags		flags;
532 			m_colorFormat,										// VkFormat							format;
533 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
534 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
535 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
536 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
537 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
538 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
539 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
540 		};
541 
542 		const VkAttachmentDescription attachments[1] =
543 		{
544 			colorAttachmentDescription
545 		};
546 
547 		const VkAttachmentReference colorAttachmentReference =
548 		{
549 			0u,													// deUint32			attachment;
550 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
551 		};
552 
553 		const VkAttachmentReference depthAttachmentReference =
554 		{
555 			VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
556 			VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
557 		};
558 
559 		const VkSubpassDescription subpassDescription =
560 		{
561 			0u,													// VkSubpassDescriptionFlags		flags;
562 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
563 			0u,													// deUint32							inputAttachmentCount;
564 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
565 			1u,													// deUint32							colorAttachmentCount;
566 			&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
567 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
568 			&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
569 			0u,													// deUint32							preserveAttachmentCount;
570 			DE_NULL												// const VkAttachmentReference*		pPreserveAttachments;
571 		};
572 
573 		const VkRenderPassCreateInfo renderPassParams =
574 		{
575 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
576 			DE_NULL,											// const void*						pNext;
577 			0u,													// VkRenderPassCreateFlags			flags;
578 			1u,													// deUint32							attachmentCount;
579 			attachments,										// const VkAttachmentDescription*	pAttachments;
580 			1u,													// deUint32							subpassCount;
581 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
582 			0u,													// deUint32							dependencyCount;
583 			DE_NULL												// const VkSubpassDependency*		pDependencies;
584 		};
585 
586 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
587 	}
588 
589 	// Create framebuffer
590 	{
591 		const VkImageView attachmentBindInfos[1] =
592 		{
593 		  *m_colorAttachmentView
594 		};
595 
596 		const VkFramebufferCreateInfo framebufferParams =
597 		{
598 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
599 			DE_NULL,											// const void*					pNext;
600 			0u,													// VkFramebufferCreateFlags		flags;
601 			*m_renderPass,										// VkRenderPass					renderPass;
602 			1u,													// deUint32						attachmentCount;
603 			attachmentBindInfos,								// const VkImageView*			pAttachments;
604 			(deUint32)m_renderSize.x(),							// deUint32						width;
605 			(deUint32)m_renderSize.y(),							// deUint32						height;
606 			1u													// deUint32						layers;
607 		};
608 
609 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
610 	}
611 
612 	// Create pipeline layout
613 	{
614 		// create push constant range
615 		VkPushConstantRange	pushConstantRanges[MAX_RANGE_COUNT];
616 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
617 		{
618 			pushConstantRanges[rangeNdx].stageFlags	= m_pushConstantRange[rangeNdx].range.shaderStage;
619 			pushConstantRanges[rangeNdx].offset		= m_pushConstantRange[rangeNdx].range.offset;
620 			pushConstantRanges[rangeNdx].size		= m_pushConstantRange[rangeNdx].range.size;
621 		}
622 
623 		// create descriptor set layout
624 		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
625 
626 		// create descriptor pool
627 		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
628 
629 		// create uniform buffer
630 		const VkBufferCreateInfo uniformBufferCreateInfo =
631 		{
632 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
633 			DE_NULL,													// const void*			pNext;
634 			0u,															// VkBufferCreateFlags	flags
635 			16u,														// VkDeviceSize			size;
636 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,							// VkBufferUsageFlags	usage;
637 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
638 			1u,															// deUint32				queueFamilyCount;
639 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
640 		};
641 
642 		m_uniformBuffer			= createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
643 		m_uniformBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
644 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
645 
646 		tcu::Vec4	value	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
647 		deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
648 		flushMappedMemoryRange(vk, vkDevice, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset(), 16u);
649 
650 		// create and update descriptor set
651 		const VkDescriptorSetAllocateInfo allocInfo =
652 		{
653 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                             sType;
654 			DE_NULL,													// const void*                                 pNext;
655 			*m_descriptorPool,											// VkDescriptorPool                            descriptorPool;
656 			1u,															// uint32_t                                    setLayoutCount;
657 			&(*m_descriptorSetLayout),									// const VkDescriptorSetLayout*                pSetLayouts;
658 		};
659 		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
660 
661 		const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
662 
663 		DescriptorSetUpdateBuilder()
664 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
665 			.update(vk, vkDevice);
666 
667 		// create pipeline layout
668 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
669 		{
670 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
671 			DE_NULL,											// const void*					pNext;
672 			0u,													// VkPipelineLayoutCreateFlags	flags;
673 			1u,													// deUint32						descriptorSetCount;
674 			&(*m_descriptorSetLayout),							// const VkDescriptorSetLayout*	pSetLayouts;
675 			m_rangeCount,										// deUint32						pushConstantRangeCount;
676 			pushConstantRanges									// const VkPushConstantRange*	pPushConstantRanges;
677 		};
678 
679 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
680 	}
681 
682 	// Create shaders
683 	{
684 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
685 		{
686 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
687 			{
688 				m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
689 			}
690 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
691 			{
692 				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
693 			}
694 			if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
695 			{
696 				m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
697 			}
698 		}
699 
700 		VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
701 
702 		createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", VK_SHADER_STAGE_VERTEX_BIT , &m_vertexShaderModule);
703 		if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
704 		{
705 			if (features.tessellationShader == VK_FALSE)
706 			{
707 				TCU_THROW(NotSupportedError, "Tessellation Not Supported");
708 			}
709 			createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessControlShaderModule);
710 			createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvaluationShaderModule);
711 		}
712 		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
713 		{
714 			if (features.geometryShader == VK_FALSE)
715 			{
716 				TCU_THROW(NotSupportedError, "Geometry Not Supported");
717 			}
718 			createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
719 		}
720 		createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
721 	}
722 
723 	// Create pipeline
724 	{
725 		const VkVertexInputBindingDescription vertexInputBindingDescription =
726 		{
727 			0u,										// deUint32					binding;
728 			sizeof(Vertex4RGBA),					// deUint32					strideInBytes;
729 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	stepRate;
730 		};
731 
732 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
733 		{
734 			{
735 				0u,									// deUint32	location;
736 				0u,									// deUint32	binding;
737 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
738 				0u									// deUint32	offsetInBytes;
739 			},
740 			{
741 				1u,									// deUint32	location;
742 				0u,									// deUint32	binding;
743 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
744 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
745 			}
746 		};
747 
748 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
749 		{
750 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
751 			DE_NULL,														// const void*								pNext;
752 			0u,																// vkPipelineVertexInputStateCreateFlags	flags;
753 			1u,																// deUint32									bindingCount;
754 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
755 			2u,																// deUint32									attributeCount;
756 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
757 		};
758 
759 		const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
760 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
761 		{
762 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
763 			DE_NULL,														// const void*								pNext;
764 			(VkPipelineInputAssemblyStateCreateFlags)0u,					// VkPipelineInputAssemblyStateCreateFlags	flags;
765 			topology,														// VkPrimitiveTopology						topology;
766 			false															// VkBool32									primitiveRestartEnable;
767 		};
768 
769 		const VkViewport viewport =
770 		{
771 			0.0f,						// float	originX;
772 			0.0f,						// float	originY;
773 			(float)m_renderSize.x(),	// float	width;
774 			(float)m_renderSize.y(),	// float	height;
775 			0.0f,						// float	minDepth;
776 			1.0f						// float	maxDepth;
777 		};
778 
779 		const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
780 
781 		const VkPipelineViewportStateCreateInfo viewportStateParams =
782 		{
783 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
784 			DE_NULL,														// const void*							pNext;
785 			(VkPipelineViewportStateCreateFlags)0u,							// VkPipelineViewportStateCreateFlags	flags;
786 			1u,																// deUint32								viewportCount;
787 			&viewport,														// const VkViewport*					pViewports;
788 			1u,																// deUint32								scissorCount;
789 			&scissor,														// const VkRect2D*						pScissors;
790 		};
791 
792 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
793 		{
794 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
795 			DE_NULL,														// const void*								pNext;
796 			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
797 			false,															// VkBool32									depthClampEnable;
798 			false,															// VkBool32									rasterizerDiscardEnable;
799 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
800 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
801 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
802 			VK_FALSE,														// VkBool32									depthBiasEnable;
803 			0.0f,															// float									depthBiasConstantFactor;
804 			0.0f,															// float									depthBiasClamp;
805 			0.0f,															// float									depthBiasSlopeFactor;
806 			1.0f,															// float									lineWidth;
807 		};
808 
809 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
810 		{
811 			false,															// VkBool32					blendEnable;
812 			VK_BLEND_FACTOR_ONE,											// VkBlendFactor			srcColorBlendFactor;
813 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstColorBlendFactor;
814 			VK_BLEND_OP_ADD,												// VkBlendOp				colorBlendOp;
815 			VK_BLEND_FACTOR_ONE,											// VkBlendFactor			srcAlphaBlendFactor;
816 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstAlphaBlendFactor;
817 			VK_BLEND_OP_ADD,												// VkBlendOp				alphaBlendOp;
818 			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |			// VkColorComponentFlags	colorWriteMask;
819 				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
820 		};
821 
822 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
823 		{
824 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
825 			DE_NULL,													// const void*									pNext;
826 			0,															// VkPipelineColorBlendStateCreateFlags			flags;
827 			false,														// VkBool32										logicOpEnable;
828 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
829 			1u,															// deUint32										attachmentCount;
830 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
831 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
832 		};
833 
834 		const VkPipelineMultisampleStateCreateInfo	multisampleStateParams	=
835 		{
836 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
837 			DE_NULL,													// const void*								pNext;
838 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
839 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
840 			false,														// VkBool32									sampleShadingEnable;
841 			0.0f,														// float									minSampleShading;
842 			DE_NULL,													// const VkSampleMask*						pSampleMask;
843 			false,														// VkBool32									alphaToCoverageEnable;
844 			false														// VkBool32									alphaToOneEnable;
845 		};
846 
847 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
848 		{
849 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
850 			DE_NULL,													// const void*								pNext;
851 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
852 			false,														// VkBool32									depthTestEnable;
853 			false,														// VkBool32									depthWriteEnable;
854 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
855 			false,														// VkBool32									depthBoundsTestEnable;
856 			false,														// VkBool32									stencilTestEnable;
857 			// VkStencilOpState	front;
858 			{
859 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilFailOp;
860 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilPassOp;
861 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilDepthFailOp;
862 				VK_COMPARE_OP_NEVER,	// VkCompareOp	stencilCompareOp;
863 				0u,						// deUint32		stencilCompareMask;
864 				0u,						// deUint32		stencilWriteMask;
865 				0u,						// deUint32		stencilReference;
866 			},
867 			// VkStencilOpState	back;
868 			{
869 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilFailOp;
870 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilPassOp;
871 				VK_STENCIL_OP_KEEP,		// VkStencilOp	stencilDepthFailOp;
872 				VK_COMPARE_OP_NEVER,	// VkCompareOp	stencilCompareOp;
873 				0u,						// deUint32		stencilCompareMask;
874 				0u,						// deUint32		stencilWriteMask;
875 				0u,						// deUint32		stencilReference;
876 			},
877 			0.0f,														// float			minDepthBounds;
878 			1.0f,														// float			maxDepthBounds;
879 		};
880 
881 		const VkPipelineTessellationStateCreateInfo tessellationStateParams =
882 		{
883 			VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
884 			DE_NULL,														// const void*                                 pNext;
885 			0u,																// VkPipelineTessellationStateCreateFlags      flags;
886 			3u,																// uint32_t                                    patchControlPoints;
887 		};
888 
889 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
890 		{
891 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
892 			DE_NULL,											// const void*										pNext;
893 			0u,													// VkPipelineCreateFlags							flags;
894 			(deUint32)m_shaderStage.size(),						// deUint32											stageCount;
895 			&m_shaderStage[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
896 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
897 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
898 			(m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &tessellationStateParams: DE_NULL),			// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
899 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
900 			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
901 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
902 			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
903 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
904 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
905 			*m_pipelineLayout,									// VkPipelineLayout									layout;
906 			*m_renderPass,										// VkRenderPass										renderPass;
907 			0u,													// deUint32											subpass;
908 			0u,													// VkPipeline										basePipelineHandle;
909 			0u													// deInt32											basePipelineIndex;
910 		};
911 
912 		m_graphicsPipelines = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
913 	}
914 
915 	// Create vertex buffer
916 	{
917 		m_vertices			= createQuad(1.0f);
918 
919 		const VkBufferCreateInfo vertexBufferParams =
920 		{
921 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
922 			DE_NULL,													// const void*			pNext;
923 			0u,															// VkBufferCreateFlags	flags;
924 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
925 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
926 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
927 			1u,															// deUint32				queueFamilyCount;
928 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
929 		};
930 
931 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
932 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
933 
934 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
935 
936 		// Load vertices into vertex buffer
937 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
938 		flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
939 	}
940 
941 	// Create command pool
942 	{
943 		const VkCommandPoolCreateInfo cmdPoolParams =
944 		{
945 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,	// VkStructureType		sType;
946 			DE_NULL,									// const void*			pNext;
947 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,		// VkCmdPoolCreateFlags	flags;
948 			queueFamilyIndex							// deUint32				queueFamilyIndex;
949 		};
950 		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
951 	}
952 
953 	// Create command buffer
954 	{
955 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
956 		{
957 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
958 			DE_NULL,										// const void*				pNext;
959 			*m_cmdPool,										// VkCommandPool			commandPool;
960 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
961 			1u												// deUint32					bufferCount;
962 		};
963 
964 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
965 		{
966 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
967 			DE_NULL,										// const void*						pNext;
968 			0u,												// VkCommandBufferUsageFlags		flags;
969 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
970 		};
971 
972 		const VkClearValue attachmentClearValues[] =
973 		{
974 			defaultClearValue(m_colorFormat)
975 		};
976 
977 		const VkRenderPassBeginInfo renderPassBeginInfo =
978 		{
979 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
980 			DE_NULL,												// const void*			pNext;
981 			*m_renderPass,											// VkRenderPass			renderPass;
982 			*m_framebuffer,											// VkFramebuffer		framebuffer;
983 			{ { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
984 			1,														// deUint32				clearValueCount;
985 			attachmentClearValues									// const VkClearValue*	pClearValues;
986 		};
987 
988 		const VkImageMemoryBarrier attachmentLayoutBarrier =
989 		{
990 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
991 			DE_NULL,										// const void*				pNext;
992 			0u,												// VkAccessFlags			srcAccessMask;
993 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
994 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
995 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
996 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
997 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
998 			*m_colorImage,									// VkImage					image;
999 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1000 		};
1001 
1002 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1003 
1004 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1005 
1006 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1007 			0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1008 
1009 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1010 
1011 		// update push constant
1012 		std::vector<tcu::Vec4> color(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1013 		std::vector<tcu::Vec4> allOnes(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1014 
1015 		const deUint32	kind	= 2u;
1016 		const void*		value	= DE_NULL;
1017 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1018 		{
1019 			value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
1020 
1021 			vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
1022 
1023 			if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1024 			{
1025 				value = (void*)(&allOnes[0]);
1026 				vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
1027 			}
1028 		}
1029 
1030 		// draw quad
1031 		const VkDeviceSize	triangleOffset	= (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
1032 		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1033 		{
1034 			VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
1035 
1036 			if (m_multipleUpdate)
1037 			{
1038 				vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
1039 			}
1040 
1041 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
1042 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1043 			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1044 
1045 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
1046 		}
1047 
1048 		vk.cmdEndRenderPass(*m_cmdBuffer);
1049 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1050 	}
1051 
1052 	// Create fence
1053 	{
1054 		const VkFenceCreateInfo fenceParams =
1055 		{
1056 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1057 			DE_NULL,								// const void*			pNext;
1058 			0u										// VkFenceCreateFlags	flags;
1059 		};
1060 
1061 		m_fence = createFence(vk, vkDevice, &fenceParams);
1062 	}
1063 }
1064 
~PushConstantGraphicsTestInstance(void)1065 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
1066 {
1067 }
1068 
iterate(void)1069 tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
1070 {
1071 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1072 	const VkDevice				vkDevice	= m_context.getDevice();
1073 	const VkQueue				queue		= m_context.getUniversalQueue();
1074 	const VkSubmitInfo			submitInfo	=
1075 	{
1076 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
1077 		DE_NULL,						// const void*				pNext;
1078 		0u,								// deUint32					waitSemaphoreCount;
1079 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
1080 		(const VkPipelineStageFlags*)DE_NULL,
1081 		1u,								// deUint32					commandBufferCount;
1082 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
1083 		0u,								// deUint32					signalSemaphoreCount;
1084 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
1085 	};
1086 
1087 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1088 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1089 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1090 
1091 	return verifyImage();
1092 }
1093 
verifyImage(void)1094 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
1095 {
1096 	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
1097 	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
1098 	const ColorVertexShader		vertexShader;
1099 	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
1100 	const rr::Program			program			(&vertexShader, &fragmentShader);
1101 	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1102 	bool						compareOk		= false;
1103 
1104 	// Render reference image
1105 	{
1106 		if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
1107 		{
1108 			m_vertices = createQuad(0.5f);
1109 		}
1110 
1111 		for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1112 		{
1113 			if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1114 			{
1115 				for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1116 				{
1117 					m_vertices[vertexNdx].color.xyzw() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1118 				}
1119 			}
1120 		}
1121 
1122 		if (m_multipleUpdate)
1123 		{
1124 			for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
1125 			{
1126 				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
1127 			}
1128 			for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
1129 			{
1130 				m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
1131 			}
1132 		}
1133 
1134 		for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1135 		{
1136 			rr::RenderState renderState(refRenderer.getViewportState());
1137 
1138 			refRenderer.draw(renderState,
1139 							 rr::PRIMITIVETYPE_TRIANGLES,
1140 							 std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
1141 													  m_vertices.begin() + (triangleNdx + 1) * 3));
1142 		}
1143 	}
1144 
1145 	// Compare result with reference image
1146 	{
1147 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
1148 		const VkDevice					vkDevice			= m_context.getDevice();
1149 		const VkQueue					queue				= m_context.getUniversalQueue();
1150 		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1151 		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1152 		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1153 
1154 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1155 															  "IntImageCompare",
1156 															  "Image comparison",
1157 															  refRenderer.getAccess(),
1158 															  result->getAccess(),
1159 															  tcu::UVec4(2, 2, 2, 2),
1160 															  tcu::IVec3(1, 1, 0),
1161 															  true,
1162 															  tcu::COMPARE_LOG_RESULT);
1163 	}
1164 
1165 	if (compareOk)
1166 		return tcu::TestStatus::pass("Result image matches reference");
1167 	else
1168 		return tcu::TestStatus::fail("Image mismatch");
1169 }
1170 
1171 class PushConstantComputeTest : public vkt::TestCase
1172 {
1173 public:
1174 							PushConstantComputeTest		(tcu::TestContext&		testContext,
1175 														 const std::string&		name,
1176 														 const std::string&		description,
1177 														 const PushConstantData	pushConstantRange);
1178 	virtual					~PushConstantComputeTest	(void);
1179 	virtual void			initPrograms				(SourceCollections& sourceCollections) const;
1180 	virtual TestInstance*	createInstance				(Context& context) const;
1181 
1182 private:
1183 	const PushConstantData	m_pushConstantRange;
1184 };
1185 
1186 class PushConstantComputeTestInstance : public vkt::TestInstance
1187 {
1188 public:
1189 							PushConstantComputeTestInstance		(Context&				context,
1190 																 const PushConstantData	pushConstantRange);
1191 	virtual					~PushConstantComputeTestInstance	(void);
1192 	virtual tcu::TestStatus	iterate								(void);
1193 
1194 private:
1195 	const PushConstantData			m_pushConstantRange;
1196 
1197 	Move<VkBuffer>					m_outBuffer;
1198 	de::MovePtr<Allocation>			m_outBufferAlloc;
1199 	Move<VkDescriptorPool>			m_descriptorPool;
1200 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1201 	Move<VkDescriptorSet>			m_descriptorSet;
1202 
1203 	Move<VkPipelineLayout>			m_pipelineLayout;
1204 	Move<VkPipeline>				m_computePipelines;
1205 
1206 	Move<VkShaderModule>			m_computeShaderModule;
1207 
1208 	Move<VkCommandPool>				m_cmdPool;
1209 	Move<VkCommandBuffer>			m_cmdBuffer;
1210 
1211 	Move<VkFence>					m_fence;
1212 };
1213 
PushConstantComputeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const PushConstantData pushConstantRange)1214 PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext&			testContext,
1215 												  const std::string&		name,
1216 												  const std::string&		description,
1217 												  const PushConstantData	pushConstantRange)
1218 	: vkt::TestCase			(testContext, name, description)
1219 	, m_pushConstantRange	(pushConstantRange)
1220 {
1221 }
1222 
~PushConstantComputeTest(void)1223 PushConstantComputeTest::~PushConstantComputeTest (void)
1224 {
1225 }
1226 
createInstance(Context & context) const1227 TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1228 {
1229 	return new PushConstantComputeTestInstance(context, m_pushConstantRange);
1230 }
1231 
initPrograms(SourceCollections & sourceCollections) const1232 void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1233 {
1234 	std::ostringstream	computeSrc;
1235 
1236 	computeSrc << "#version 450\n"
1237 			   << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1238 			   << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1239 			   << "  vec4 elements[];\n"
1240 			   << "} outData;\n"
1241 			   << "layout(push_constant) uniform Material{\n"
1242 			   << "  vec4 element;\n"
1243 			   << "} matInst;\n"
1244 			   << "void main (void)\n"
1245 			   << "{\n"
1246 			   << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1247 			   << "}\n";
1248 
1249 	sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1250 }
1251 
PushConstantComputeTestInstance(Context & context,const PushConstantData pushConstantRange)1252 PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context&					context,
1253 																  const PushConstantData	pushConstantRange)
1254 	: vkt::TestInstance		(context)
1255 	, m_pushConstantRange	(pushConstantRange)
1256 {
1257 	const DeviceInterface&		vk					= context.getDeviceInterface();
1258 	const VkDevice				vkDevice			= context.getDevice();
1259 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1260 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1261 
1262 	// Create pipeline layout
1263 	{
1264 		// create push constant range
1265 		VkPushConstantRange	pushConstantRanges;
1266 		pushConstantRanges.stageFlags	= m_pushConstantRange.range.shaderStage;
1267 		pushConstantRanges.offset		= m_pushConstantRange.range.offset;
1268 		pushConstantRanges.size			= m_pushConstantRange.range.size;
1269 
1270 		// create descriptor set layout
1271 		m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1272 
1273 		// create descriptor pool
1274 		m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1275 
1276 		// create uniform buffer
1277 		const VkDeviceSize			bufferSize			= sizeof(tcu::Vec4) * 8;
1278 		const VkBufferCreateInfo	bufferCreateInfo	=
1279 		{
1280 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
1281 			DE_NULL,													// const void*			pNext;
1282 			0u,															// VkBufferCreateFlags	flags
1283 			bufferSize,													// VkDeviceSize			size;
1284 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,							// VkBufferUsageFlags	usage;
1285 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
1286 			1u,															// deUint32				queueFamilyCount;
1287 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
1288 		};
1289 
1290 		m_outBuffer			= createBuffer(vk, vkDevice, &bufferCreateInfo);
1291 		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1292 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1293 
1294 		// create and update descriptor set
1295 		const VkDescriptorSetAllocateInfo allocInfo =
1296 		{
1297 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                             sType;
1298 			DE_NULL,													// const void*                                 pNext;
1299 			*m_descriptorPool,											// VkDescriptorPool                            descriptorPool;
1300 			1u,															// uint32_t                                    setLayoutCount;
1301 			&(*m_descriptorSetLayout),									// const VkDescriptorSetLayout*                pSetLayouts;
1302 		};
1303 		m_descriptorSet	= allocateDescriptorSet(vk, vkDevice, &allocInfo);
1304 
1305 		const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1306 
1307 		DescriptorSetUpdateBuilder()
1308 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1309 			.update(vk, vkDevice);
1310 
1311 		// create pipeline layout
1312 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
1313 		{
1314 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1315 			DE_NULL,											// const void*					pNext;
1316 			0u,													// VkPipelineLayoutCreateFlags	flags;
1317 			1u,													// deUint32						descriptorSetCount;
1318 			&(*m_descriptorSetLayout),							// const VkDescriptorSetLayout*	pSetLayouts;
1319 			1u,													// deUint32						pushConstantRangeCount;
1320 			&pushConstantRanges									// const VkPushConstantRange*	pPushConstantRanges;
1321 		};
1322 
1323 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1324 	}
1325 
1326 	// create pipeline
1327 	{
1328 		m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1329 
1330 		const VkPipelineShaderStageCreateInfo	stageCreateInfo	=
1331 		{
1332 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1333 			DE_NULL,												// const void*							pNext;
1334 			0u,														// VkPipelineShaderStageCreateFlags		flags;
1335 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1336 			*m_computeShaderModule,									// VkShaderModule						module;
1337 			"main",													// const char*							pName;
1338 			DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
1339 		};
1340 
1341 		const VkComputePipelineCreateInfo		createInfo	=
1342 		{
1343 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType                             sType;
1344 			DE_NULL,												// const void*                                 pNext;
1345 			0u,														// VkPipelineCreateFlags                       flags;
1346 			stageCreateInfo,										// VkPipelineShaderStageCreateInfo             stage;
1347 			*m_pipelineLayout,										// VkPipelineLayout                            layout;
1348 			(VkPipeline)0,											// VkPipeline                                  basePipelineHandle;
1349 			0u,														// int32_t                                     basePipelineIndex;
1350 		};
1351 
1352 		m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1353 	}
1354 
1355 	// Create command pool
1356 	{
1357 		const VkCommandPoolCreateInfo cmdPoolParams =
1358 		{
1359 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
1360 			DE_NULL,										// const void*			pNext;
1361 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
1362 			queueFamilyIndex								// deUint32				queueFamilyIndex;
1363 		};
1364 		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1365 	}
1366 
1367 	// Create command buffer
1368 	{
1369 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1370 		{
1371 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1372 			DE_NULL,										// const void*				pNext;
1373 			*m_cmdPool,										// VkCommandPool			commandPool;
1374 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
1375 			1u												// deUint32					bufferCount;
1376 		};
1377 
1378 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1379 
1380 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1381 		{
1382 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
1383 			DE_NULL,										// const void*						pNext;
1384 			0u,												// VkCommandBufferUsageFlags		flags;
1385 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1386 		};
1387 
1388 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1389 
1390 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1391 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1392 
1393 		// update push constant
1394 		tcu::Vec4	value	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1395 		vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1396 
1397 		vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1398 
1399 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1400 	}
1401 
1402 	// Create fence
1403 	{
1404 		const VkFenceCreateInfo fenceParams =
1405 		{
1406 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1407 			DE_NULL,								// const void*			pNext;
1408 			0u										// VkFenceCreateFlags	flags;
1409 		};
1410 
1411 		m_fence = createFence(vk, vkDevice, &fenceParams);
1412 	}
1413 }
1414 
~PushConstantComputeTestInstance(void)1415 PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1416 {
1417 }
1418 
iterate(void)1419 tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1420 {
1421 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1422 	const VkDevice				vkDevice	= m_context.getDevice();
1423 	const VkQueue				queue		= m_context.getUniversalQueue();
1424 	const VkSubmitInfo			submitInfo	=
1425 	{
1426 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
1427 		DE_NULL,						// const void*				pNext;
1428 		0u,								// deUint32					waitSemaphoreCount;
1429 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
1430 		(const VkPipelineStageFlags*)DE_NULL,
1431 		1u,								// deUint32					commandBufferCount;
1432 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
1433 		0u,								// deUint32					signalSemaphoreCount;
1434 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
1435 	};
1436 
1437 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1438 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1439 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1440 
1441 	// verify result
1442 	std::vector<tcu::Vec4>	expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1443 	if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1444 	{
1445 		return tcu::TestStatus::fail("Image mismatch");
1446 	}
1447 	return tcu::TestStatus::pass("result image matches with reference");
1448 }
1449 
1450 } // anonymous
1451 
createPushConstantTests(tcu::TestContext & testCtx)1452 tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
1453 {
1454 	static const struct
1455 	{
1456 		const char*			name;
1457 		const char*			description;
1458 		deUint32			count;
1459 		PushConstantData	range[MAX_RANGE_COUNT];
1460 		deBool				hasMultipleUpdates;
1461 	} graphicsParams[] =
1462 	{
1463 		// test range size from minimum valid size to maximum
1464 		{
1465 			"range_size_4",
1466 			"test range size is 4 bytes(minimum valid size)",
1467 			1u,
1468 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
1469 			false
1470 		},
1471 		{
1472 			"range_size_16",
1473 			"test range size is 16 bytes, and together with a normal uniform",
1474 			1u,
1475 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
1476 			false
1477 		},
1478 		{
1479 			"range_size_128",
1480 			"test range size is 128 bytes(maximum valid size)",
1481 			1u,
1482 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
1483 			false
1484 		},
1485 		// test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
1486 		{
1487 			"count_2_shader_VF",
1488 			"test range count is 2, use vertex and fragment shaders",
1489 			2u,
1490 			{
1491 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1492 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1493 			},
1494 			false
1495 		},
1496 		{
1497 			"count_3shader_VGF",
1498 			"test range count is 3, use vertex, geometry and fragment shaders",
1499 			3u,
1500 			{
1501 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1502 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1503 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1504 			},
1505 			false
1506 		},
1507 		{
1508 			"count_5_shader_VTGF",
1509 			"test range count is 5, use vertex, tessellation, geometry and fragment shaders",
1510 			5u,
1511 			{
1512 				{ { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1513 				{ { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1514 				{ { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1515 				{ { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
1516 				{ { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
1517 			},
1518 			false
1519 		},
1520 		{
1521 			"count_1_shader_VF",
1522 			"test range count is 1, vertex and fragment shaders share one range",
1523 			1u,
1524 			{ { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
1525 			false
1526 		},
1527 		// test data partial update and multiple times update
1528 		{
1529 			"data_update_partial_1",
1530 			"test partial update of the values",
1531 			1u,
1532 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
1533 			false
1534 		},
1535 		{
1536 			"data_update_partial_2",
1537 			"test partial update of the values",
1538 			1u,
1539 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
1540 			false
1541 		},
1542 		{
1543 			"data_update_multiple",
1544 			"test multiple times update of the values",
1545 			1u,
1546 			{ { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
1547 			true
1548 		},
1549 	};
1550 
1551 	static const struct
1552 	{
1553 		const char*			name;
1554 		const char*			description;
1555 		PushConstantData	range;
1556 	} computeParams[] =
1557 	{
1558 		{
1559 			"simple_test",
1560 			"test compute pipeline",
1561 			{ { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
1562 		},
1563 	};
1564 
1565 	de::MovePtr<tcu::TestCaseGroup>	pushConstantTests	(new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
1566 
1567 	de::MovePtr<tcu::TestCaseGroup>	graphicsTests	(new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
1568 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
1569 	{
1570 		graphicsTests->addChild(new PushConstantGraphicsTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates));
1571 	}
1572 	pushConstantTests->addChild(graphicsTests.release());
1573 
1574 	de::MovePtr<tcu::TestCaseGroup>	computeTests	(new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
1575 	computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
1576 	pushConstantTests->addChild(computeTests.release());
1577 
1578 	return pushConstantTests.release();
1579 }
1580 
1581 } // pipeline
1582 } // vkt
1583