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