1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Google LLC
6 * Copyright (c) 2019 The Khronos Group Inc.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Miscellaneous pipeline tests.
25 *//*--------------------------------------------------------------------*/
26
27#include <string>
28#include <memory>
29#include <vector>
30#include <algorithm>
31#include <array>
32#include <numeric>
33#include <memory>
34
35#include "vkPipelineConstructionUtil.hpp"
36#include "vktTestGroupUtil.hpp"
37#include "vktAmberTestCase.hpp"
38#include "vktPipelineMiscTests.hpp"
39
40#include "vkDefs.hpp"
41#include "tcuImageCompare.hpp"
42#include "vkImageUtil.hpp"
43#include "deStringUtil.hpp"
44#include "vktTestCaseUtil.hpp"
45#include "vkTypeUtil.hpp"
46#include "vkCmdUtil.hpp"
47#include "vkObjUtil.hpp"
48#include "vkImageWithMemory.hpp"
49#include "vkBarrierUtil.hpp"
50#include "vkBufferWithMemory.hpp"
51#include "vkBuilderUtil.hpp"
52#include "vktPipelineReferenceRenderer.hpp"
53#include "vkBuilderUtil.hpp"
54
55namespace vkt
56{
57namespace pipeline
58{
59
60using namespace vk;
61
62namespace
63{
64
65enum AmberFeatureBits
66{
67	AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS	= (1 <<	0),
68	AMBER_FEATURE_TESSELATION_SHADER					= (1 <<	1),
69	AMBER_FEATURE_GEOMETRY_SHADER						= (1 <<	2),
70};
71
72using AmberFeatureFlags = deUint32;
73
74#ifndef CTS_USES_VULKANSC
75std::vector<std::string> getFeatureList (AmberFeatureFlags flags)
76{
77	std::vector<std::string> requirements;
78
79	if (flags & AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS)
80		requirements.push_back("Features.vertexPipelineStoresAndAtomics");
81
82	if (flags & AMBER_FEATURE_TESSELATION_SHADER)
83		requirements.push_back("Features.tessellationShader");
84
85	if (flags & AMBER_FEATURE_GEOMETRY_SHADER)
86		requirements.push_back("Features.geometryShader");
87
88	return requirements;
89}
90#endif // CTS_USES_VULKANSC
91
92void addMonolithicAmberTests (tcu::TestCaseGroup* tests)
93{
94#ifndef CTS_USES_VULKANSC
95	tcu::TestContext& testCtx = tests->getTestContext();
96
97	// Shader test files are saved in <path>/external/vulkancts/data/vulkan/amber/pipeline/<basename>.amber
98	struct Case {
99		const char*			basename;
100		AmberFeatureFlags	flags;
101	};
102
103	const Case cases[] =
104	{
105		{
106			"position_to_ssbo",
107			(AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS),
108		},
109		{
110			"primitive_id_from_tess",
111			(AMBER_FEATURE_TESSELATION_SHADER | AMBER_FEATURE_GEOMETRY_SHADER),
112		},
113	};
114	for (unsigned i = 0; i < DE_LENGTH_OF_ARRAY(cases) ; ++i)
115	{
116		std::string					file			= std::string(cases[i].basename) + ".amber";
117		std::vector<std::string>	requirements	= getFeatureList(cases[i].flags);
118		cts_amber::AmberTestCase	*testCase		= cts_amber::createAmberTestCase(testCtx, cases[i].basename, "pipeline", file, requirements);
119
120		tests->addChild(testCase);
121	}
122#else
123	DE_UNREF(tests);
124#endif
125}
126
127class ImplicitPrimitiveIDPassthroughCase : public vkt::TestCase
128{
129public:
130	ImplicitPrimitiveIDPassthroughCase		(tcu::TestContext&                  testCtx,
131											 const std::string&                 name,
132											 const PipelineConstructionType		pipelineConstructionType,
133											 bool withTessellation)
134		: vkt::TestCase(testCtx, name)
135		, m_pipelineConstructionType(pipelineConstructionType)
136		, m_withTessellationPassthrough(withTessellation)
137	{
138	}
139	~ImplicitPrimitiveIDPassthroughCase		    (void) {}
140	void			initPrograms				(SourceCollections& programCollection) const override;
141	void			checkSupport				(Context& context) const override;
142	TestInstance*	createInstance				(Context& context) const override;
143
144	const PipelineConstructionType m_pipelineConstructionType;
145private:
146	bool m_withTessellationPassthrough;
147};
148
149class ImplicitPrimitiveIDPassthroughInstance : public vkt::TestInstance
150{
151public:
152	ImplicitPrimitiveIDPassthroughInstance	(Context&                           context,
153											 const PipelineConstructionType		pipelineConstructionType,
154											 bool withTessellation)
155		: vkt::TestInstance				(context)
156		, m_pipelineConstructionType	(pipelineConstructionType)
157		, m_renderSize					(2, 2)
158		, m_extent(makeExtent3D			(m_renderSize.x(), m_renderSize.y(), 1u))
159		, m_graphicsPipeline			(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
160		, m_withTessellationPassthrough	(withTessellation)
161	{
162	}
163	~ImplicitPrimitiveIDPassthroughInstance	(void) {}
164	tcu::TestStatus		iterate				(void) override;
165
166private:
167	PipelineConstructionType	m_pipelineConstructionType;
168	const tcu::UVec2            m_renderSize;
169	const VkExtent3D		    m_extent;
170	const VkFormat		        m_format = VK_FORMAT_R8G8B8A8_UNORM;
171	GraphicsPipelineWrapper		m_graphicsPipeline;
172	bool                        m_withTessellationPassthrough;
173};
174
175TestInstance* ImplicitPrimitiveIDPassthroughCase::createInstance (Context& context) const
176{
177	return new ImplicitPrimitiveIDPassthroughInstance(context, m_pipelineConstructionType, m_withTessellationPassthrough);
178}
179
180void ImplicitPrimitiveIDPassthroughCase::checkSupport (Context &context) const
181{
182	if (m_withTessellationPassthrough)
183		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
184
185	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
186
187	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
188}
189
190void ImplicitPrimitiveIDPassthroughCase::initPrograms(SourceCollections& sources) const
191{
192	std::ostringstream vert;
193	// Generate a vertically split framebuffer, filled with red on the
194	// left, and a green on the right.
195	vert
196		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
197		<< "void main ()\n"
198		<< "{\n"
199		<< "    switch (gl_VertexIndex) {\n"
200		<< "        case 0:\n"
201		<< "            gl_Position = vec4(-3.0, -1.0, 0.0, 1.0);\n"
202		<< "            break;\n"
203		<< "        case 1:\n"
204		<< "            gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
205		<< "            break;\n"
206		<< "        case 2:\n"
207		<< "            gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
208		<< "            break;\n"
209		<< "        case 3:\n"
210		<< "            gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
211		<< "            break;\n"
212		<< "        case 4:\n"
213		<< "            gl_Position = vec4(3.0, -1.0, 0.0, 1.0);\n"
214		<< "            break;\n"
215		<< "        case 5:\n"
216		<< "            gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
217		<< "            break;\n"
218		<< "    }\n"
219		<< "}\n"
220		;
221	sources.glslSources.add("vert") << glu::VertexSource(vert.str());
222
223	if (m_withTessellationPassthrough) {
224		std::ostringstream tsc;
225		tsc
226			<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
227			<< "layout (vertices = 3) out;\n"
228			<< "\n"
229			<< "void main ()\n"
230			<< "{\n"
231			<< "    if (gl_InvocationID == 0) {\n"
232			<< "        gl_TessLevelInner[0] = 1.0;\n"
233			<< "        gl_TessLevelInner[1] = 1.0;\n"
234			<< "        gl_TessLevelOuter[0] = 1.0;\n"
235			<< "        gl_TessLevelOuter[1] = 1.0;\n"
236			<< "        gl_TessLevelOuter[2] = 1.0;\n"
237			<< "        gl_TessLevelOuter[3] = 1.0;\n"
238			<< "    }\n"
239			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
240			<< "}\n";
241		sources.glslSources.add("tsc") << glu::TessellationControlSource(tsc.str());
242
243		std::ostringstream tse;
244		tse
245			<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
246			<< "layout (triangles, equal_spacing, cw) in;\n"
247			<< "\n"
248			<< "void main ()\n"
249			<< "{\n"
250			<< "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
251			<< "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
252			<< "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
253			<< "}\n"
254			;
255		sources.glslSources.add("tse") << glu::TessellationEvaluationSource(tse.str());
256	}
257
258	std::ostringstream frag;
259	frag
260		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
261		<< "layout (location=0) out vec4 outColor;\n"
262		<< "\n"
263		<< "void main ()\n"
264		<< "{\n"
265		<< "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
266		<< "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
267		<< "    outColor = (gl_PrimitiveID % 2 == 0) ? red : green;\n"
268		<< "}\n"
269		;
270	sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
271}
272
273tcu::TestStatus ImplicitPrimitiveIDPassthroughInstance::iterate ()
274{
275	const auto&			vkd					= m_context.getDeviceInterface();
276	const auto			device				= m_context.getDevice();
277	auto&				alloc				= m_context.getDefaultAllocator();
278	const auto			qIndex				= m_context.getUniversalQueueFamilyIndex();
279	const auto			queue				= m_context.getUniversalQueue();
280	const auto			tcuFormat			= mapVkFormat(m_format);
281	const auto			colorUsage			= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
282	const auto			verifBufferUsage	= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
283	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 1.0f);
284
285	// Color attachment.
286	const VkImageCreateInfo colorBufferInfo =
287	{
288		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
289		nullptr,								//	const void*				pNext;
290		0u,										//	VkImageCreateFlags		flags;
291		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
292		m_format,								//	VkFormat				format;
293		m_extent,								//	VkExtent3D				extent;
294		1u,										//	uint32_t				mipLevels;
295		1u,										//	uint32_t				arrayLayers;
296		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
297		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
298		colorUsage,								//	VkImageUsageFlags		usage;
299		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
300		0u,										//	uint32_t				queueFamilyIndexCount;
301		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
302		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
303	};
304	ImageWithMemory		colorBuffer		(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
305	const auto			colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
306	const auto			colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
307	const auto			colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
308
309	// Verification buffer.
310	const auto			verifBufferSize		= static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
311	const auto			verifBufferInfo		= makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
312	BufferWithMemory	verifBuffer			(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
313	auto&				verifBufferAlloc	= verifBuffer.getAllocation();
314
315	// Render pass and framebuffer.
316	RenderPassWrapper	renderPass			(m_pipelineConstructionType, vkd, device, m_format);
317	renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width, m_extent.height);
318
319	// Shader modules.
320	const auto&		binaries		= m_context.getBinaryCollection();
321	const auto		vertModule		= ShaderWrapper(vkd, device, binaries.get("vert"));
322	const auto		fragModule		= ShaderWrapper(vkd, device, binaries.get("frag"));
323	ShaderWrapper tscModule;
324	ShaderWrapper tseModule;
325
326	if (m_withTessellationPassthrough) {
327		tscModule = ShaderWrapper(vkd, device, binaries.get("tsc"));
328		tseModule = ShaderWrapper(vkd, device, binaries.get("tse"));
329	}
330
331	// Viewports and scissors.
332	const std::vector<VkViewport>	viewports	(1u, makeViewport(m_extent));
333	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(m_extent));
334
335	const VkPipelineVertexInputStateCreateInfo		vertexInputState	= initVulkanStructure();
336	const VkPipelineRasterizationStateCreateInfo    rasterizationState  =
337	{
338		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
339		DE_NULL,														// const void*                              pNext;
340		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
341		VK_FALSE,														// VkBool32                                 depthClampEnable;
342		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
343		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
344		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
345		VK_FRONT_FACE_CLOCKWISE,								// VkFrontFace								frontFace;
346		VK_FALSE,														// VkBool32									depthBiasEnable;
347		0.0f,															// float									depthBiasConstantFactor;
348		0.0f,															// float									depthBiasClamp;
349		0.0f,															// float									depthBiasSlopeFactor;
350		1.0f,															// float									lineWidth;
351	};
352
353	// Pipeline layout and graphics pipeline.
354	const PipelineLayoutWrapper pipelineLayout	(m_pipelineConstructionType, vkd, device);
355
356	const auto topology = m_withTessellationPassthrough ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
357	m_graphicsPipeline.setDefaultRasterizationState()
358		.setDefaultTopology(topology)
359		.setupVertexInputState(&vertexInputState)
360		.setDefaultDepthStencilState()
361		.setDefaultMultisampleState()
362		.setDefaultColorBlendState()
363		.setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, &rasterizationState, tscModule, tseModule)
364		.setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
365		.setupFragmentOutputState(*renderPass)
366		.setMonolithicPipelineLayout(pipelineLayout)
367		.buildPipeline();
368
369	// Command pool and buffer.
370	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
371	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
372	const auto cmdBuffer	= cmdBufferPtr.get();
373
374	beginCommandBuffer(vkd, cmdBuffer);
375
376	// Draw.
377	renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
378	m_graphicsPipeline.bind(cmdBuffer);
379	vkd.cmdDraw(cmdBuffer, 6, 1u, 0u, 0u);
380	renderPass.end(vkd, cmdBuffer);
381
382	// Copy to verification buffer.
383	const auto copyRegion		= makeBufferImageCopy(m_extent, colorSRL);
384	const auto transfer2Host	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
385	const auto color2Transfer	= makeImageMemoryBarrier(
386		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
387		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
388		colorBuffer.get(), colorSRR);
389
390	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
391	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, &copyRegion);
392	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host);
393
394	endCommandBuffer(vkd, cmdBuffer);
395
396	// Submit and validate result.
397	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
398
399	auto& log = m_context.getTestContext().getLog();
400	const tcu::IVec3					iExtent (static_cast<int>(m_extent.width), static_cast<int>(m_extent.height), static_cast<int>(m_extent.depth));
401	void*								verifBufferData		= verifBufferAlloc.getHostPtr();
402	const tcu::ConstPixelBufferAccess	verifAccess		(tcuFormat, iExtent, verifBufferData);
403	invalidateAlloc(vkd, device, verifBufferAlloc);
404
405	const auto red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
406	const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
407
408	for (int x = 0; x < iExtent.x(); ++x)
409		for (int y = 0; y < iExtent.y(); ++y) {
410			const auto resultColor = verifAccess.getPixel(x, y);
411			const auto expectedColor = (x < iExtent.x() / 2) ? red : green;
412			if (resultColor != expectedColor) {
413				log << tcu::TestLog::ImageSet("Result image", "Expect left side of framebuffer red, and right side green")
414					<< tcu::TestLog::Image("Result", "Verification buffer", verifAccess)
415					<< tcu::TestLog::EndImageSet;
416				TCU_FAIL("Expected a vertically split framebuffer, filled with red on the left and green the right; see the log for the unexpected result");
417			}
418		}
419
420	return tcu::TestStatus::pass("Pass");
421}
422
423#ifndef CTS_USES_VULKANSC
424struct UnusedShaderStageParams
425{
426	PipelineConstructionType	pipelineConstructionType;
427	bool						useTessShaders;
428	bool						useGeomShader;
429};
430
431class UnusedShaderStagesCase : public vkt::TestCase
432{
433public:
434					UnusedShaderStagesCase	(tcu::TestContext& testCtx, const std::string& name, const UnusedShaderStageParams& params)
435						: vkt::TestCase	(testCtx, name)
436						, m_params		(params)
437						{}
438	virtual			~UnusedShaderStagesCase	(void) {}
439
440	void			initPrograms			(vk::SourceCollections& programCollection) const override;
441	TestInstance*	createInstance			(Context& context) const override;
442	void			checkSupport			(Context& context) const override;
443
444protected:
445	UnusedShaderStageParams m_params;
446};
447
448class UnusedShaderStagesInstance : public vkt::TestInstance
449{
450public:
451						UnusedShaderStagesInstance	(Context& context, const UnusedShaderStageParams& params)
452							: vkt::TestInstance	(context)
453							, m_params			(params)
454							{}
455	virtual				~UnusedShaderStagesInstance	(void) {}
456	tcu::TestStatus		iterate						(void) override;
457
458protected:
459	UnusedShaderStageParams m_params;
460};
461
462void UnusedShaderStagesCase::initPrograms (vk::SourceCollections &programCollection) const
463{
464	// Shaders that produce bad results.
465	{
466		std::ostringstream vert;
467		vert
468			<< "#version 460\n"
469			<< "out gl_PerVertex {\n"
470			<< "    vec4 gl_Position;\n"
471			<< "};\n"
472			<< "void main (void) {\n"
473			<< "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
474			<< "}\n"
475			;
476		programCollection.glslSources.add("bad_vert") << glu::VertexSource(vert.str());
477
478		std::ostringstream tesc;
479		tesc
480			<< "#version 460\n"
481			<< "layout (vertices=3) out;\n"
482			<< "in gl_PerVertex {\n"
483			<< "  vec4 gl_Position;\n"
484			<< "} gl_in[gl_MaxPatchVertices];\n"
485			<< "out gl_PerVertex {\n"
486			<< "  vec4 gl_Position;\n"
487			<< "} gl_out[];\n"
488			<< "void main (void) {\n"
489			<< "    gl_TessLevelInner[0] = 1.0;\n"
490			<< "    gl_TessLevelInner[1] = 1.0;\n"
491			<< "    gl_TessLevelOuter[0] = 1.0;\n"
492			<< "    gl_TessLevelOuter[1] = 1.0;\n"
493			<< "    gl_TessLevelOuter[2] = 1.0;\n"
494			<< "    gl_TessLevelOuter[3] = 1.0;\n"
495			<< "    gl_out[gl_InvocationID].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
496			<< "}\n"
497			;
498		programCollection.glslSources.add("bad_tesc") << glu::TessellationControlSource(tesc.str());
499
500		std::ostringstream tese;
501		tese
502			<< "#version 460\n"
503			<< "layout (triangles, fractional_odd_spacing, cw) in;\n"
504			<< "in gl_PerVertex {\n"
505			<< "  vec4 gl_Position;\n"
506			<< "} gl_in[gl_MaxPatchVertices];\n"
507			<< "out gl_PerVertex {\n"
508			<< "  vec4 gl_Position;\n"
509			<< "};\n"
510			<< "void main() {\n"
511			<< "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
512			<< "}\n"
513			;
514		programCollection.glslSources.add("bad_tese") << glu::TessellationEvaluationSource(tese.str());
515
516		std::ostringstream geom;
517		geom
518			<< "#version 460\n"
519			<< "layout (triangles) in;\n"
520			<< "layout (triangle_strip, max_vertices=3) out;\n"
521			<< "in gl_PerVertex {\n"
522			<< "    vec4 gl_Position;\n"
523			<< "} gl_in[3];\n"
524			<< "out gl_PerVertex {\n"
525			<< "    vec4 gl_Position;\n"
526			<< "};\n"
527			<< "void main() {\n"
528			// Avoid emitting any vertices.
529			<< "}\n"
530			;
531		programCollection.glslSources.add("bad_geom") << glu::GeometrySource(geom.str());
532
533		std::ostringstream frag;
534		frag
535			<< "#version 460\n"
536			<< "layout (location=0) out vec4 outColor;\n"
537			<< "void main (void) {\n"
538			<< "    outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
539			<< "}\n"
540			;
541		programCollection.glslSources.add("bad_frag") << glu::FragmentSource(frag.str());
542	}
543
544	// Shaders that produce the expected results.
545	{
546		std::ostringstream vert;
547		vert
548			<< "#version 460\n"
549			<< "out gl_PerVertex {\n"
550			<< "    vec4 gl_Position;\n"
551			<< "};\n"
552			<< "vec2 positions[3] = vec2[](\n"
553			<< "    vec2(-1.0, -1.0),\n"
554			<< "    vec2(-1.0,  3.0),\n"
555			<< "    vec2( 3.0, -1.0)\n"
556			<< ");\n"
557			<< "void main (void) {\n"
558			<< "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
559			<< "}\n"
560			;
561		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
562
563		std::ostringstream tesc;
564		tesc
565			<< "#version 460\n"
566			<< "layout (vertices=3) out;\n"
567			<< "in gl_PerVertex {\n"
568			<< "  vec4 gl_Position;\n"
569			<< "} gl_in[gl_MaxPatchVertices];\n"
570			<< "out gl_PerVertex {\n"
571			<< "  vec4 gl_Position;\n"
572			<< "} gl_out[];\n"
573			<< "void main (void) {\n"
574			<< "    gl_TessLevelInner[0] = 1.0;\n"
575			<< "    gl_TessLevelInner[1] = 1.0;\n"
576			<< "    gl_TessLevelOuter[0] = 1.0;\n"
577			<< "    gl_TessLevelOuter[1] = 1.0;\n"
578			<< "    gl_TessLevelOuter[2] = 1.0;\n"
579			<< "    gl_TessLevelOuter[3] = 1.0;\n"
580			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
581			<< "}\n"
582			;
583		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
584
585		std::ostringstream tese;
586		tese
587			<< "#version 460\n"
588			<< "layout (triangles, fractional_odd_spacing, cw) in;\n"
589			<< "in gl_PerVertex {\n"
590			<< "  vec4 gl_Position;\n"
591			<< "} gl_in[gl_MaxPatchVertices];\n"
592			<< "out gl_PerVertex {\n"
593			<< "  vec4 gl_Position;\n"
594			<< "};\n"
595			<< "void main() {\n"
596			<< "    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
597			<< "                  (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
598			<< "                  (gl_TessCoord.z * gl_in[2].gl_Position);\n"
599			<< "}\n"
600			;
601		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
602
603		std::ostringstream geom;
604		geom
605			<< "#version 460\n"
606			<< "layout (triangles) in;\n"
607			<< "layout (triangle_strip, max_vertices=3) out;\n"
608			<< "in gl_PerVertex {\n"
609			<< "    vec4 gl_Position;\n"
610			<< "} gl_in[3];\n"
611			<< "out gl_PerVertex {\n"
612			<< "    vec4 gl_Position;\n"
613			<< "};\n"
614			<< "void main() {\n"
615			<< "    gl_Position = gl_in[0].gl_Position; EmitVertex();\n"
616			<< "    gl_Position = gl_in[1].gl_Position; EmitVertex();\n"
617			<< "    gl_Position = gl_in[2].gl_Position; EmitVertex();\n"
618			<< "}\n"
619			;
620		programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
621
622		std::ostringstream frag;
623		frag
624			<< "#version 460\n"
625			<< "layout (location=0) out vec4 outColor;\n"
626			<< "void main (void) {\n"
627			<< "    outColor = vec4(0.0, 1.0, 0.0, 1.0);\n" // Blue instead of black.
628			<< "}\n"
629			;
630		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
631	}
632}
633
634TestInstance* UnusedShaderStagesCase::createInstance (Context &context) const
635{
636	return new UnusedShaderStagesInstance(context, m_params);
637}
638
639void UnusedShaderStagesCase::checkSupport (Context &context) const
640{
641	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
642
643	if (m_params.useTessShaders)
644		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
645
646	if (m_params.useGeomShader)
647		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
648}
649
650tcu::TestStatus UnusedShaderStagesInstance::iterate ()
651{
652	const auto&			vkd				= m_context.getDeviceInterface();
653	const auto			device			= m_context.getDevice();
654	auto&				alloc			= m_context.getDefaultAllocator();
655	const auto			queue			= m_context.getUniversalQueue();
656	const auto			queueIndex		= m_context.getUniversalQueueFamilyIndex();
657
658	const bool			isOptimized		= (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
659	const auto			colorExtent		= makeExtent3D(1u, 1u, 1u);
660	const tcu::IVec3	colorExtentVec	(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
661	const auto			colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
662	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
663	const auto			colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
664	const auto			colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
665	const auto			tcuFormat		= mapVkFormat(colorFormat);
666	const tcu::Vec4		clearColor		(0.0f, 0.0f, 0.0f, 0.0f);
667	const tcu::Vec4		expectedColor	(0.0f, 1.0f, 0.0f, 1.0f); // Must match the good frag shader.
668
669	// Good and bad shader modules.
670	const auto&	binaries			= m_context.getBinaryCollection();
671
672	const auto	goodVertModule		= createShaderModule(vkd, device, binaries.get("vert"));
673	const auto	goodTescModule		= (m_params.useTessShaders ?	createShaderModule(vkd, device, binaries.get("tesc")) : Move<VkShaderModule>());
674	const auto	goodTeseModule		= (m_params.useTessShaders ?	createShaderModule(vkd, device, binaries.get("tese")) : Move<VkShaderModule>());
675	const auto	goodGeomModule		= (m_params.useGeomShader ?		createShaderModule(vkd, device, binaries.get("geom")) : Move<VkShaderModule>());
676	const auto	goodFragModule		= createShaderModule(vkd, device, binaries.get("frag"));
677
678	const auto	goodVertShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, goodVertModule.get());
679	const auto	goodTescShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, goodTescModule.get());
680	const auto	goodTeseShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, goodTeseModule.get());
681	const auto	goodGeomShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, goodGeomModule.get());
682	const auto	goodFragShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, goodFragModule.get());
683
684	const auto	badVertModule		= createShaderModule(vkd, device, binaries.get("bad_vert"));
685	const auto	badTescModule		= (m_params.useTessShaders ?	createShaderModule(vkd, device, binaries.get("bad_tesc")) : Move<VkShaderModule>());
686	const auto	badTeseModule		= (m_params.useTessShaders ?	createShaderModule(vkd, device, binaries.get("bad_tese")) : Move<VkShaderModule>());
687	const auto	badGeomModule		= (m_params.useGeomShader ?		createShaderModule(vkd, device, binaries.get("bad_geom")) : Move<VkShaderModule>());
688	const auto	badFragModule		= createShaderModule(vkd, device, binaries.get("bad_frag"));
689
690	const auto	badVertShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, badVertModule.get());
691	const auto	badTescShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, badTescModule.get());
692	const auto	badTeseShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, badTeseModule.get());
693	const auto	badGeomShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, badGeomModule.get());
694	const auto	badFragShaderInfo	= makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, badFragModule.get());
695
696	// Color attachment.
697	const VkImageCreateInfo colorAttachmentCreateInfo =
698	{
699		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
700		nullptr,								//	const void*				pNext;
701		0u,										//	VkImageCreateFlags		flags;
702		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
703		colorFormat,							//	VkFormat				format;
704		colorExtent,							//	VkExtent3D				extent;
705		1u,										//	uint32_t				mipLevels;
706		1u,										//	uint32_t				arrayLayers;
707		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
708		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
709		colorUsage,								//	VkImageUsageFlags		usage;
710		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
711		0u,										//	uint32_t				queueFamilyIndexCount;
712		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
713		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
714	};
715	ImageWithMemory colorAttachment (vkd, device, alloc, colorAttachmentCreateInfo, MemoryRequirement::Any);
716
717	// Color attachment view.
718	const auto colorAttachmentView = makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
719
720	// Verification buffer.
721	const auto			verificationBufferSize			= static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * colorExtent.width * colorExtent.height * colorExtent.depth;
722	const auto			verificationBufferCreateInfo	= makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
723	BufferWithMemory	verificationBuffer				(vkd, device, alloc, verificationBufferCreateInfo, MemoryRequirement::HostVisible);
724	auto&				verificationBufferAlloc			= verificationBuffer.getAllocation();
725
726	// Render pass and framebuffer.
727	RenderPassWrapper	renderPass						(m_params.pipelineConstructionType, vkd, device, colorFormat);
728	renderPass.createFramebuffer(vkd, device, *colorAttachment, colorAttachmentView.get(), colorExtent.width, colorExtent.height);
729
730	// Pipeline layout.
731	const auto pipelineLayout = makePipelineLayout(vkd, device);
732
733	// Pipeline state.
734
735	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
736
737	const auto primitiveTopology = (m_params.useTessShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
738
739	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
740	{
741		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
742		nullptr,														//	const void*								pNext;
743		0u,																//	VkPipelineInputAssemblyStateCreateFlags	flags;
744		primitiveTopology,												//	VkPrimitiveTopology						topology;
745		VK_FALSE,														//	VkBool32								primitiveRestartEnable;
746	};
747
748	const VkPipelineTessellationStateCreateInfo tessellationStateInfo =
749	{
750		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
751		nullptr,													//	const void*								pNext;
752		0u,															//	VkPipelineTessellationStateCreateFlags	flags;
753		3u,															//	uint32_t								patchControlPoints;
754	};
755
756	const std::vector<VkViewport>	viewports	(1u, makeViewport(colorExtent));
757	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(colorExtent));
758
759	const VkPipelineViewportStateCreateInfo viewportStateInfo =
760	{
761		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	//	VkStructureType						sType;
762		nullptr,												//	const void*							pNext;
763		0u,														//	VkPipelineViewportStateCreateFlags	flags;
764		de::sizeU32(viewports),									//	uint32_t							viewportCount;
765		de::dataOrNull(viewports),								//	const VkViewport*					pViewports;
766		de::sizeU32(scissors),									//	uint32_t							scissorCount;
767		de::dataOrNull(scissors),								//	const VkRect2D*						pScissors;
768	};
769
770	const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
771	{
772		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//	VkStructureType							sType;
773		nullptr,														//	const void*								pNext;
774		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
775		VK_FALSE,														//	VkBool32								depthClampEnable;
776		VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
777		VK_POLYGON_MODE_FILL,											//	VkPolygonMode							polygonMode;
778		VK_CULL_MODE_BACK_BIT,											//	VkCullModeFlags							cullMode;
779		VK_FRONT_FACE_COUNTER_CLOCKWISE,								//	VkFrontFace								frontFace;
780		VK_FALSE,														//	VkBool32								depthBiasEnable;
781		0.0f,															//	float									depthBiasConstantFactor;
782		0.0f,															//	float									depthBiasClamp;
783		0.0f,															//	float									depthBiasSlopeFactor;
784		1.0f,															//	float									lineWidth;
785	};
786
787	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
788	{
789		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
790		nullptr,													//	const void*								pNext;
791		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
792		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
793		VK_FALSE,													//	VkBool32								sampleShadingEnable;
794		1.0f,														//	float									minSampleShading;
795		nullptr,													//	const VkSampleMask*						pSampleMask;
796		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
797		VK_FALSE,													//	VkBool32								alphaToOneEnable;
798	};
799
800	const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
801
802	const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
803
804	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
805	{
806		VK_FALSE,				//	VkBool32				blendEnable;
807		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcColorBlendFactor;
808		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstColorBlendFactor;
809		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
810		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcAlphaBlendFactor;
811		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstAlphaBlendFactor;
812		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
813		colorComponentFlags,	//	VkColorComponentFlags	colorWriteMask;
814	};
815
816	const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
817	{
818		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
819		nullptr,													//	const void*									pNext;
820		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
821		VK_FALSE,													//	VkBool32									logicOpEnable;
822		VK_LOGIC_OP_CLEAR,											//	VkLogicOp									logicOp;
823		1u,															//	uint32_t									attachmentCount;
824		&colorBlendAttachmentState,									//	const VkPipelineColorBlendAttachmentState*	pAttachments;
825		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
826	};
827
828	// Make a few vectors with the wrong shader modules.
829	std::vector<VkPipelineShaderStageCreateInfo> badPreRasterStages;
830	badPreRasterStages.push_back(badVertShaderInfo);
831	if (m_params.useTessShaders)
832	{
833		badPreRasterStages.push_back(badTescShaderInfo);
834		badPreRasterStages.push_back(badTeseShaderInfo);
835	}
836	if (m_params.useGeomShader)
837		badPreRasterStages.push_back(badGeomShaderInfo);
838
839	std::vector<VkPipelineShaderStageCreateInfo> allBadStages (badPreRasterStages);
840	allBadStages.push_back(badFragShaderInfo);
841
842	// Make a few vectors with the right shader modules.
843	std::vector<VkPipelineShaderStageCreateInfo> goodPreRasterStages;
844	goodPreRasterStages.push_back(goodVertShaderInfo);
845	if (m_params.useTessShaders)
846	{
847		goodPreRasterStages.push_back(goodTescShaderInfo);
848		goodPreRasterStages.push_back(goodTeseShaderInfo);
849	}
850	if (m_params.useGeomShader)
851		goodPreRasterStages.push_back(goodGeomShaderInfo);
852
853	std::vector<VkPipelineShaderStageCreateInfo> allGoodStages (goodPreRasterStages);
854	allGoodStages.push_back(goodFragShaderInfo);
855
856	// Build the different pipeline pieces.
857	Move<VkPipeline> vertexInputLib;
858	Move<VkPipeline> preRasterShaderLib;
859	Move<VkPipeline> fragShaderLib;
860	Move<VkPipeline> fragOutputLib;
861
862	VkPipelineCreateFlags libCreationFlags	= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
863	VkPipelineCreateFlags linkFlags			= 0u;
864
865	if (isOptimized)
866	{
867		libCreationFlags	|= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
868		linkFlags			|= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
869	}
870
871	// Vertex input state library.
872	{
873		VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo	= initVulkanStructure();
874		vertexInputLibInfo.flags									|= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
875
876		VkGraphicsPipelineCreateInfo vertexInputPipelineInfo	= initVulkanStructure(&vertexInputLibInfo);
877		vertexInputPipelineInfo.flags							= libCreationFlags;
878		vertexInputPipelineInfo.pVertexInputState				= &vertexInputStateInfo;
879		vertexInputPipelineInfo.pInputAssemblyState				= &inputAssemblyStateInfo;
880
881		// Add all bad shaders (they should be ignored).
882		vertexInputPipelineInfo.stageCount	= de::sizeU32(allBadStages);
883		vertexInputPipelineInfo.pStages		= de::dataOrNull(allBadStages);
884
885		vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputPipelineInfo);
886	}
887
888	// Pre-rasterization shader state library.
889	{
890		VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo	= initVulkanStructure();
891		preRasterShaderLibInfo.flags									|= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
892
893		VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo	= initVulkanStructure(&preRasterShaderLibInfo);
894		preRasterShaderPipelineInfo.flags							= libCreationFlags;
895		preRasterShaderPipelineInfo.layout							= pipelineLayout.get();
896		preRasterShaderPipelineInfo.pViewportState					= &viewportStateInfo;
897		preRasterShaderPipelineInfo.pRasterizationState				= &rasterizationStateInfo;
898		if (m_params.useTessShaders)
899		{
900			preRasterShaderPipelineInfo.pInputAssemblyState			= &inputAssemblyStateInfo;
901			preRasterShaderPipelineInfo.pTessellationState			= &tessellationStateInfo;
902		}
903		preRasterShaderPipelineInfo.renderPass						= renderPass.get();
904
905		// All good pre-rasterization stages.
906		auto preRasterStagesVec = goodPreRasterStages;
907		// The bad fragment shader state cannot be added here due to VUID-VkGraphicsPipelineCreateInfo-pStages-06894.
908		//preRasterStagesVec.push_back(badFragShaderInfo);
909
910		preRasterShaderPipelineInfo.stageCount	= de::sizeU32(preRasterStagesVec);
911		preRasterShaderPipelineInfo.pStages		= de::dataOrNull(preRasterStagesVec);
912
913		preRasterShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRasterShaderPipelineInfo);
914	}
915
916	// Fragment shader stage library.
917	{
918		VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo	= initVulkanStructure();
919		fragShaderLibInfo.flags										|= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
920
921		VkGraphicsPipelineCreateInfo fragShaderPipelineInfo	= initVulkanStructure(&fragShaderLibInfo);
922		fragShaderPipelineInfo.flags						= libCreationFlags;
923		fragShaderPipelineInfo.layout						= pipelineLayout.get();
924		fragShaderPipelineInfo.pMultisampleState			= &multisampleStateInfo;
925		fragShaderPipelineInfo.pDepthStencilState			= &depthStencilStateInfo;
926		fragShaderPipelineInfo.renderPass					= renderPass.get();
927
928		// The good fragment shader stage.
929		std::vector<VkPipelineShaderStageCreateInfo> fragShaderStagesVec;
930		// We cannot add the bad pre-rasterization shader stages due to VUID-VkGraphicsPipelineCreateInfo-pStages-06895.
931		//fragShaderStagesVec.insert(fragShaderStagesVec.end(), badPreRasterStages.begin(), badPreRasterStages.end())
932		fragShaderStagesVec.push_back(goodFragShaderInfo);
933
934		fragShaderPipelineInfo.stageCount	= de::sizeU32(fragShaderStagesVec);
935		fragShaderPipelineInfo.pStages		= de::dataOrNull(fragShaderStagesVec);
936
937		fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderPipelineInfo);
938	}
939
940	// Fragment output library.
941	{
942		VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo	= initVulkanStructure();
943		fragOutputLibInfo.flags										|= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
944
945		VkGraphicsPipelineCreateInfo fragOutputPipelineInfo	= initVulkanStructure(&fragOutputLibInfo);
946		fragOutputPipelineInfo.flags						= libCreationFlags;
947		fragOutputPipelineInfo.pColorBlendState				= &colorBlendStateInfo;
948		fragOutputPipelineInfo.renderPass					= renderPass.get();
949		fragOutputPipelineInfo.pMultisampleState			= &multisampleStateInfo;
950
951		// Add all bad shaders (they should be ignored).
952		fragOutputPipelineInfo.stageCount	= de::sizeU32(allBadStages);
953		fragOutputPipelineInfo.pStages		= de::dataOrNull(allBadStages);
954
955		fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputPipelineInfo);
956	}
957
958	// Linked pipeline.
959	const std::vector<VkPipeline> libraryHandles
960	{
961		vertexInputLib.get(),
962		preRasterShaderLib.get(),
963		fragShaderLib.get(),
964		fragOutputLib.get(),
965	};
966
967	VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo	= initVulkanStructure();
968	linkedPipelineLibraryInfo.libraryCount						= de::sizeU32(libraryHandles);
969	linkedPipelineLibraryInfo.pLibraries						= de::dataOrNull(libraryHandles);
970
971	VkGraphicsPipelineCreateInfo linkedPipelineInfo	= initVulkanStructure(&linkedPipelineLibraryInfo);
972	linkedPipelineInfo.flags						= linkFlags;
973	linkedPipelineInfo.layout						= pipelineLayout.get();
974	linkedPipelineInfo.stageCount					= de::sizeU32(allBadStages);
975	linkedPipelineInfo.pStages						= de::dataOrNull(allBadStages);
976
977	const auto pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &linkedPipelineInfo);
978
979	// Command pool, command buffer and draw.
980	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
981	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
982	const auto cmdBuffer	= cmdBufferPtr.get();
983
984	beginCommandBuffer(vkd, cmdBuffer);
985	renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
986	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
987	vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
988	renderPass.end(vkd, cmdBuffer);
989
990	// Copy color attachment to verification buffer.
991	const auto preCopyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
992														 VK_ACCESS_TRANSFER_READ_BIT,
993														 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
994														 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
995														 colorAttachment.get(), colorSRR);
996	const auto copyRegion		= makeBufferImageCopy(colorExtent, colorSRL);
997	const auto postCopyBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
998
999	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preCopyBarrier);
1000	vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
1001	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyBarrier);
1002
1003	endCommandBuffer(vkd, cmdBuffer);
1004
1005	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1006
1007	// Verify pixel contents.
1008	invalidateAlloc(vkd, device, verificationBufferAlloc);
1009	tcu::PixelBufferAccess resultAccess (tcuFormat, colorExtentVec, verificationBufferAlloc.getHostPtr());
1010
1011	for (int z = 0; z < colorExtentVec.z(); ++z)
1012		for (int y = 0; y < colorExtentVec.y(); ++y)
1013			for (int x = 0; x < colorExtentVec.x(); ++x)
1014			{
1015				const auto resultColor = resultAccess.getPixel(x, y, z);
1016				if (resultColor != expectedColor)
1017				{
1018					const tcu::IVec3 position(x, y, z);
1019					std::ostringstream msg;
1020					msg << "Bad color found at pixel " << position << ": expected " << expectedColor << " but found " << resultColor;
1021					TCU_FAIL(msg.str());
1022				}
1023			}
1024
1025	return tcu::TestStatus::pass("Pass");
1026}
1027#endif // CTS_USES_VULKANSC
1028
1029#ifndef CTS_USES_VULKANSC
1030class PipelineLibraryInterpolateAtSampleTestCase : public vkt::TestCase
1031{
1032public:
1033	PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name);
1034	void            initPrograms            (vk::SourceCollections& programCollection) const override;
1035	TestInstance*   createInstance          (Context& context) const override;
1036	void            checkSupport            (Context& context) const override;
1037	//there are 4 sample points, which may have a shader invocation each, each of them writes 5 values
1038	//and we render a 2x2 grid.
1039	static constexpr uint32_t				width		= 2;
1040	static constexpr uint32_t				height		= 2;
1041	static constexpr VkSampleCountFlagBits	sampleCount = VK_SAMPLE_COUNT_4_BIT;
1042	static constexpr uint32_t ResultCount = (sampleCount + 1) * sampleCount * width * height;
1043};
1044
1045class PipelineLibraryInterpolateAtSampleTestInstance : public vkt::TestInstance
1046{
1047public:
1048	PipelineLibraryInterpolateAtSampleTestInstance(Context& context);
1049	void runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type);
1050	virtual tcu::TestStatus iterate(void);
1051};
1052
1053PipelineLibraryInterpolateAtSampleTestCase::PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name):
1054	vkt::TestCase(context, name) { }
1055
1056void PipelineLibraryInterpolateAtSampleTestCase::checkSupport(Context& context) const
1057{
1058	context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1059	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1060	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1061}
1062
1063void PipelineLibraryInterpolateAtSampleTestCase::initPrograms(vk::SourceCollections& collection) const
1064{
1065	{
1066		std::ostringstream src;
1067		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1068		<< "vec2 positions[6] = vec2[](\n"
1069		<< "		vec2(1.0, 1.0),"
1070		<< "		vec2(-1.0, 1.0),"
1071		<< "		vec2(-1.0, -1.0),"
1072		<< "		vec2(-1.0, -1.0),"
1073		<< "		vec2(1.0, -1.0),"
1074		<< "		vec2(1.0, 1.0)"
1075		<< ");\n"
1076		<< "float values[6] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};\n"
1077		<< "layout (location=0) out float verify;"
1078		<< "void main() {\n"
1079		<< "		gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
1080		<< "		verify = values[gl_VertexIndex];\n"
1081		<< "}";
1082		collection.glslSources.add("vert") << glu::VertexSource(src.str());
1083	}
1084
1085	{
1086		std::ostringstream src;
1087		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1088		<< "layout(location = 0) out vec4 outColor;\n"
1089		<< "layout (location=0) in float verify;"
1090		<< "layout(std430, binding = 0) buffer Index {"
1091		<< "	uint writeIndex;"
1092		<< "} index;\n"
1093		<< "layout(std430, binding = 1) buffer Values {"
1094		<< "	float num[" << PipelineLibraryInterpolateAtSampleTestCase::ResultCount << "];"
1095		<< "} values;\n"
1096		<< "void main() {\n"
1097		<< "	uint index = atomicAdd(index.writeIndex, 5);"
1098		<< "	float iSample1 = interpolateAtSample(verify, 0);\n"
1099		<< "	float iSample2 = interpolateAtSample(verify, 1);\n"
1100		<< "	float iSample3 = interpolateAtSample(verify, 2);\n"
1101		<< "	float iSample4 = interpolateAtSample(verify, 3);\n"
1102		<< "	values.num[index] = verify;"
1103		<< "	values.num[index + 1] = iSample1;"
1104		<< "	values.num[index + 2] = iSample2;"
1105		<< "	values.num[index + 3] = iSample3;"
1106		<< "	values.num[index + 4] = iSample4;"
1107		<< "	outColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1108		<< "}";
1109		collection.glslSources.add("frag") << glu::FragmentSource(src.str());
1110	}
1111}
1112
1113TestInstance* PipelineLibraryInterpolateAtSampleTestCase::createInstance(Context& context) const
1114{
1115	return new PipelineLibraryInterpolateAtSampleTestInstance(context);
1116}
1117
1118PipelineLibraryInterpolateAtSampleTestInstance::PipelineLibraryInterpolateAtSampleTestInstance(Context& context) : vkt::TestInstance(context) { }
1119
1120void PipelineLibraryInterpolateAtSampleTestInstance::runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type)
1121{
1122	const auto& vki			= m_context.getInstanceInterface();
1123	const auto& vkd			= m_context.getDeviceInterface();
1124	const auto  physDevice	= m_context.getPhysicalDevice();
1125	const auto  device		= m_context.getDevice();
1126	auto& alloc				= m_context.getDefaultAllocator();
1127	auto imageFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
1128	auto imageExtent		= vk::makeExtent3D(2, 2, 1u);
1129
1130	const std::vector<vk::VkViewport>	viewports	{ makeViewport(imageExtent) };
1131	const std::vector<vk::VkRect2D>		scissors	{ makeRect2D(imageExtent) };
1132
1133	de::MovePtr<vk::ImageWithMemory>  colorAttachment;
1134
1135	vk::GraphicsPipelineWrapper pipeline1(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), type);
1136	const auto  qIndex	= m_context.getUniversalQueueFamilyIndex();
1137
1138	const auto  subresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1139	const auto  imageUsage			= static_cast<vk::VkImageUsageFlags>(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1140	const vk::VkImageCreateInfo imageCreateInfo =
1141	{
1142		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType				sType;
1143		nullptr,									//	const void*					pNext;
1144		0u,											//	VkImageCreateFlags			flags;
1145		vk::VK_IMAGE_TYPE_2D,						//	VkImageType					imageType;
1146		imageFormat,								//	VkFormat					format;
1147		imageExtent,								//	VkExtent3D					extent;
1148		1u,											//	deUint32					mipLevels;
1149		1u,											//	deUint32					arrayLayers;
1150		vk::VK_SAMPLE_COUNT_4_BIT,					//	VkSampleCountFlagBits		samples;
1151		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling				tiling;
1152		imageUsage,									//	VkImageUsageFlags			usage;
1153		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode				sharingMode;
1154		1u,											//	deUint32					queueFamilyIndexCount;
1155		&qIndex,									//	const deUint32*				pQueueFamilyIndices;
1156		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout				initialLayout;
1157	};
1158
1159	colorAttachment               = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any));
1160	auto colorAttachmentView      = vk::makeImageView(vkd, device, colorAttachment->get(), vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
1161
1162	vk::DescriptorSetLayoutBuilder layoutBuilder;
1163	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
1164	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
1165
1166	auto descriptorSetLayout    = layoutBuilder.build(vkd, device);
1167	vk::PipelineLayoutWrapper	graphicsPipelineLayout (type, vkd, device, descriptorSetLayout.get());
1168
1169	DescriptorPoolBuilder poolBuilder;
1170	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1171	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1172	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1173	const auto descriptorSetBuffer		= makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1174
1175	// Update descriptor sets.
1176	DescriptorSetUpdateBuilder updater;
1177
1178	const auto indexBufferInfo = makeDescriptorBufferInfo(index.get(), 0ull, sizeof(uint32_t));
1179	const auto valueBufferInfo = makeDescriptorBufferInfo(values.get(), 0ull, bufferSize);
1180	updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indexBufferInfo);
1181	updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &valueBufferInfo);
1182
1183	updater.update(vkd, device);
1184
1185	auto vtxshader  = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"));
1186	auto frgshader  = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"));
1187
1188	const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
1189	{
1190		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType sType
1191		nullptr,														// const void*                                 pNext
1192		0u,																// VkPipelineVertexInputStateCreateFlags       flags
1193		0u,																// deUint32                                    vertexBindingDescriptionCount
1194		nullptr,														// const VkVertexInputBindingDescription*      pVertexBindingDescriptions
1195		0u,																// deUint32                                    vertexAttributeDescriptionCount
1196		nullptr,														// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1197	};
1198
1199	VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
1200	multisampling.sampleShadingEnable = VK_FALSE;
1201	multisampling.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
1202	multisampling.minSampleShading = 1.0f; // Optional
1203	multisampling.pSampleMask = NULL; // Optional
1204	multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
1205	multisampling.alphaToOneEnable = VK_FALSE; // Optional
1206
1207	pipeline1.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1208		.setDefaultRasterizationState()
1209		.setDefaultDepthStencilState()
1210		.setDefaultColorBlendState()
1211		.setupVertexInputState(&vertexInputState)
1212		.setupPreRasterizationShaderState(
1213			viewports,
1214			scissors,
1215			graphicsPipelineLayout,
1216			DE_NULL,
1217			0u,
1218			vtxshader)
1219		.setupFragmentShaderState(graphicsPipelineLayout, DE_NULL, 0u,
1220			frgshader)
1221		.setupFragmentOutputState(DE_NULL, 0u, DE_NULL, &multisampling)
1222		.setMonolithicPipelineLayout(graphicsPipelineLayout).buildPipeline();
1223
1224	auto commandPool = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
1225	auto commandBuffer = vk::allocateCommandBuffer(vkd, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1226
1227	const auto		clearValueColor		= vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1228
1229	const vk::VkRect2D renderArea =
1230	{
1231		{ 0u, 0u },
1232		{ imageExtent.width, imageExtent.height }
1233	};
1234
1235	const vk::VkRenderingAttachmentInfoKHR colorAttachments = {
1236		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
1237		DE_NULL,												// const void*							pNext;
1238		colorAttachmentView.get(),								// VkImageView							imageView;
1239		vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,				// VkImageLayout						imageLayout;
1240		vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
1241		DE_NULL,												// VkImageView							resolveImageView;
1242		vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,				// VkImageLayout						resolveImageLayout;
1243		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp					loadOp;
1244		vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
1245		clearValueColor											// VkClearValue							clearValue;
1246	};
1247	const VkRenderingInfoKHR render_info = {
1248		VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
1249		0,
1250		0,
1251		renderArea,
1252		1,
1253		0,
1254		1,
1255		&colorAttachments,
1256		DE_NULL,
1257		DE_NULL
1258	};
1259
1260	vk::beginCommandBuffer(vkd, commandBuffer.get());
1261	vk::VkImageMemoryBarrier initialBarrier = makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,
1262		(*colorAttachment).get(), subresourceRange);
1263	vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, nullptr,
1264						  0, nullptr, 1, &initialBarrier);
1265	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
1266
1267	vkd.cmdBeginRendering(*commandBuffer, &render_info);
1268	pipeline1.bind(commandBuffer.get());
1269	vkd.cmdSetPatchControlPointsEXT(commandBuffer.get(), 3);
1270	vkd.cmdDraw(commandBuffer.get(), 6, 1, 0, 0);
1271	vkd.cmdEndRendering(*commandBuffer);
1272
1273	const VkBufferMemoryBarrier indexBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, index.get(), 0ull, sizeof(uint32_t));
1274	vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1275		0u, 0, nullptr, 1, &indexBufferBarrier, 0, nullptr);
1276
1277	const VkBufferMemoryBarrier valueBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, values.get(), 0ull, bufferSize);
1278	vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1279		0u, 0, nullptr, 1, &valueBufferBarrier, 0, nullptr);
1280
1281	vk::endCommandBuffer(vkd, commandBuffer.get());
1282	vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
1283}
1284
1285tcu::TestStatus PipelineLibraryInterpolateAtSampleTestInstance::iterate(void)
1286{
1287	const auto& vkd			= m_context.getDeviceInterface();
1288	const auto  device		= m_context.getDevice();
1289	auto& alloc				= m_context.getDefaultAllocator();
1290
1291	struct ValueBuffer {
1292		float values[PipelineLibraryInterpolateAtSampleTestCase::ResultCount];
1293	};
1294
1295	size_t resultSize = PipelineLibraryInterpolateAtSampleTestCase::ResultCount;
1296
1297	const auto			indexBufferSize	= static_cast<VkDeviceSize>(sizeof(uint32_t));
1298	const auto			valueBufferSize	= static_cast<VkDeviceSize>(sizeof(ValueBuffer));
1299
1300	auto indexCreateInfo	= makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1301	auto valuesCreateInfo	= makeBufferCreateInfo(valueBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1302
1303	BufferWithMemory	indexBufferMonolithic		(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
1304	BufferWithMemory	valuesBufferMonolithic		(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
1305	BufferWithMemory	indexBufferGPL				(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
1306	BufferWithMemory	valuesBufferGPL				(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
1307
1308	auto&				indexBufferMonolithicAlloc	= indexBufferMonolithic.getAllocation();
1309	auto&				valuesBufferMonolithicAlloc	= valuesBufferMonolithic.getAllocation();
1310	auto&				indexBufferGPLAlloc	= indexBufferGPL.getAllocation();
1311	auto&				valuesBufferGPLAlloc	= valuesBufferGPL.getAllocation();
1312
1313	void*				indexBufferMonolithicData	= indexBufferMonolithicAlloc.getHostPtr();
1314	void*				valuesBufferMonolithicData	= valuesBufferMonolithicAlloc.getHostPtr();
1315	void*				indexBufferGPLData	= indexBufferGPLAlloc.getHostPtr();
1316	void*				valuesBufferGPLData	= valuesBufferGPLAlloc.getHostPtr();
1317
1318	deMemset(indexBufferMonolithicData, 0, sizeof(uint32_t));
1319	deMemset(valuesBufferMonolithicData, 0, sizeof(ValueBuffer));
1320	deMemset(indexBufferGPLData, 0, sizeof(uint32_t));
1321	deMemset(valuesBufferGPLData, 0, sizeof(ValueBuffer));
1322
1323	flushAlloc(vkd, device, indexBufferMonolithicAlloc);
1324	flushAlloc(vkd, device, valuesBufferMonolithicAlloc);
1325	flushAlloc(vkd, device, indexBufferGPLAlloc);
1326	flushAlloc(vkd, device, valuesBufferGPLAlloc);
1327
1328	runTest(indexBufferMonolithic, valuesBufferMonolithic, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1329	runTest(indexBufferGPL, valuesBufferGPL, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1330
1331	invalidateAlloc(vkd, device, indexBufferMonolithicAlloc);
1332	invalidateAlloc(vkd, device, valuesBufferMonolithicAlloc);
1333	invalidateAlloc(vkd, device, indexBufferGPLAlloc);
1334	invalidateAlloc(vkd, device, valuesBufferGPLAlloc);
1335
1336	uint32_t monolithicIndex;
1337	uint32_t GPLIndex;
1338	struct ValueBuffer monolithicResult		= ValueBuffer();
1339	struct ValueBuffer GPLResult			= ValueBuffer();
1340	memcpy((void*)&monolithicIndex, indexBufferMonolithicData, sizeof(uint32_t));
1341	memcpy((void*)&GPLIndex, indexBufferGPLData, sizeof(uint32_t));
1342	memcpy((void*)&monolithicResult, valuesBufferMonolithicData, sizeof(ValueBuffer));
1343	memcpy((void*)&GPLResult, valuesBufferGPLData, sizeof(ValueBuffer));
1344
1345	//we can't know which order the shaders will run in
1346	std::sort(monolithicResult.values, monolithicResult.values + resultSize);
1347	std::sort(GPLResult.values, GPLResult.values + resultSize);
1348
1349	//check that the atomic counters are at enough for the number of invocations
1350	constexpr int expected = (PipelineLibraryInterpolateAtSampleTestCase::sampleCount + 1) *
1351		PipelineLibraryInterpolateAtSampleTestCase::width * PipelineLibraryInterpolateAtSampleTestCase::height;
1352
1353	if (monolithicIndex < expected && GPLIndex < expected) {
1354			return tcu::TestStatus::fail("Atomic counter value lower than expected");
1355	}
1356
1357	for (uint32_t i = 1; i < PipelineLibraryInterpolateAtSampleTestCase::ResultCount; i++) {
1358		if (monolithicResult.values[i] != monolithicResult.values[i]) {
1359			return tcu::TestStatus::fail("Comparison failed");
1360		}
1361	}
1362
1363	return tcu::TestStatus::pass("Pass");
1364}
1365#endif
1366
1367struct BindingTestConfig {
1368	PipelineConstructionType construction;
1369	bool backwardsBinding;
1370	bool holes;
1371};
1372
1373/*
1374 * Test the following behaviours:
1375 * Descriptor sets updated/bound in backwards order
1376 * Descriptor sets with index holes updated/bound/used
1377 */
1378class PipelineLayoutBindingTestCases : public vkt::TestCase
1379{
1380public:
1381	PipelineLayoutBindingTestCases		(tcu::TestContext&                  testCtx,
1382											 const std::string&                 name,
1383											 const BindingTestConfig&			config)
1384		: vkt::TestCase(testCtx, name)
1385		, m_config(config)
1386	{
1387	}
1388	~PipelineLayoutBindingTestCases		    (void) {}
1389	void			initPrograms				(SourceCollections& programCollection) const override;
1390	void			checkSupport				(Context& context) const override;
1391	TestInstance*	createInstance				(Context& context) const override;
1392
1393	const BindingTestConfig m_config;
1394};
1395
1396class PipelineLayoutBindingTestInstance : public vkt::TestInstance
1397{
1398public:
1399	PipelineLayoutBindingTestInstance	(Context& context,
1400										 const BindingTestConfig& config)
1401		: vkt::TestInstance				(context)
1402		, m_renderSize					(2, 2)
1403		, m_extent						(makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
1404		, m_format						(VK_FORMAT_R8G8B8A8_UNORM)
1405		, m_graphicsPipeline			(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), config.construction)
1406		, m_config						(config)
1407	{
1408	}
1409	~PipelineLayoutBindingTestInstance	(void) {}
1410	tcu::TestStatus		iterate				(void) override;
1411
1412private:
1413	const tcu::UVec2            m_renderSize;
1414	const VkExtent3D		    m_extent;
1415	const VkFormat		        m_format;
1416	GraphicsPipelineWrapper		m_graphicsPipeline;
1417	const BindingTestConfig		m_config;
1418};
1419
1420TestInstance* PipelineLayoutBindingTestCases::createInstance (Context& context) const
1421{
1422	return new PipelineLayoutBindingTestInstance(context, m_config);
1423}
1424
1425void PipelineLayoutBindingTestCases::checkSupport (Context &context) const
1426{
1427	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_config.construction);
1428}
1429
1430void PipelineLayoutBindingTestCases::initPrograms(SourceCollections& sources) const
1431{
1432	std::ostringstream src;
1433	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1434		<< "vec2 positions[3] = vec2[](\n"
1435		<< "		vec2(-1.0, -1.0),"
1436		<< "		vec2(3.0, -1.0),"
1437		<< "		vec2(-1.0, 3.0)"
1438		<< ");\n"
1439		<< "void main() {\n"
1440		<< "		gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
1441		<< "}";
1442	sources.glslSources.add("vert") << glu::VertexSource(src.str());
1443
1444	std::ostringstream frag;
1445	frag
1446		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1447		<< "layout (location=0) out vec4 outColor;\n"
1448		<< "layout(set = 0, binding = 0) uniform Output0 {"
1449		<< "	uint data;"
1450		<< "} buf0;\n";
1451		if (!m_config.holes) {
1452			frag
1453				<< "layout(set = 1, binding = 0) uniform Output1 {"
1454				<< "	uint data;"
1455				<< "} buf1;\n"
1456				<< "layout(set = 2, binding = 0) uniform Output2 {"
1457				<< "	uint data;"
1458				<< "} buf2;\n"
1459				<< "\n";
1460		}
1461	frag
1462				<< "layout(set = 3, binding = 0) uniform Output3 {"
1463				<< "	uint data;"
1464				<< "} buf3;\n"
1465				<< "void main ()\n"
1466				<< "{\n"
1467				<< "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
1468				<< "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n";
1469		if (!m_config.holes) {
1470			frag
1471				<< "    outColor = ((buf0.data == 0) && (buf1.data == 1) && (buf2.data == 2) && (buf3.data == 3)) ? green : red;\n";
1472		} else {
1473			frag
1474				<< "    outColor = ((buf0.data == 0) && (buf3.data == 3)) ? green : red;\n";
1475		}
1476		frag << "}\n";
1477	sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
1478}
1479
1480tcu::TestStatus PipelineLayoutBindingTestInstance::iterate ()
1481{
1482	const auto&			vkd					= m_context.getDeviceInterface();
1483	const auto			device				= m_context.getDevice();
1484	auto&				alloc				= m_context.getDefaultAllocator();
1485	const auto			qIndex				= m_context.getUniversalQueueFamilyIndex();
1486	const auto			queue				= m_context.getUniversalQueue();
1487	const auto			tcuFormat			= mapVkFormat(m_format);
1488	const auto			colorUsage			= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1489	const auto			verifBufferUsage	= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1490	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 1.0f);
1491
1492	// Color attachment.
1493	const VkImageCreateInfo colorBufferInfo =
1494	{
1495		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1496		nullptr,								//	const void*				pNext;
1497		0u,										//	VkImageCreateFlags		flags;
1498		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1499		m_format,								//	VkFormat				format;
1500		m_extent,								//	VkExtent3D				extent;
1501		1u,										//	uint32_t				mipLevels;
1502		1u,										//	uint32_t				arrayLayers;
1503		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
1504		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1505		colorUsage,								//	VkImageUsageFlags		usage;
1506		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1507		0u,										//	uint32_t				queueFamilyIndexCount;
1508		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
1509		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1510	};
1511	ImageWithMemory		colorBuffer		(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
1512	const auto			colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1513	const auto			colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1514	const auto			colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
1515
1516	// Verification buffer.
1517	const auto			verifBufferSize		= static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
1518	const auto			verifBufferInfo		= makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
1519	BufferWithMemory	verifBuffer			(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
1520	auto&				verifBufferAlloc	= verifBuffer.getAllocation();
1521
1522	// Render pass and framebuffer.
1523	RenderPassWrapper	renderPass			(m_config.construction, vkd, device, m_format);
1524	renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width, m_extent.height);
1525
1526	// Shader modules.
1527	const auto&		binaries		= m_context.getBinaryCollection();
1528	const auto		vertModule		= ShaderWrapper(vkd, device, binaries.get("vert"));
1529	const auto		fragModule		= ShaderWrapper(vkd, device, binaries.get("frag"));
1530
1531	// Viewports and scissors.
1532	const std::vector<VkViewport>	viewports	(1u, makeViewport(m_extent));
1533	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(m_extent));
1534
1535	const VkPipelineVertexInputStateCreateInfo		vertexInputState	= initVulkanStructure();
1536	const VkPipelineRasterizationStateCreateInfo    rasterizationState  =
1537	{
1538		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
1539		DE_NULL,														// const void*                              pNext;
1540		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
1541		VK_FALSE,														// VkBool32                                 depthClampEnable;
1542		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
1543		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
1544		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
1545		VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
1546		VK_FALSE,														// VkBool32									depthBiasEnable;
1547		0.0f,															// float									depthBiasConstantFactor;
1548		0.0f,															// float									depthBiasClamp;
1549		0.0f,															// float									depthBiasSlopeFactor;
1550		1.0f,															// float									lineWidth;
1551	};
1552
1553	std::array<int, 4> tmpIndices = {};
1554	std::array<int, 4> indices = {};
1555	std::iota(tmpIndices.begin(), tmpIndices.end(), 0);
1556	if (m_config.backwardsBinding) {
1557		std::copy(tmpIndices.rbegin(), tmpIndices.rend(), indices.begin());
1558	} else {
1559		std::copy(tmpIndices.begin(), tmpIndices.end(), indices.begin());
1560	}
1561
1562	vk::DescriptorSetLayoutBuilder layoutBuilder;
1563	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
1564
1565	std::vector<vk::Move<VkDescriptorSetLayout>>  descriptorSetLayouts = {};
1566
1567	for (size_t i = 0; i < indices.size(); i++) {
1568		descriptorSetLayouts.emplace_back(layoutBuilder.build(vkd, device));
1569	}
1570
1571	// Pipeline layout and graphics pipeline.
1572	uint32_t setAndDescriptorCount = de::sizeU32(indices);
1573	const vk::PipelineLayoutWrapper pipelineLayout	(m_config.construction, vkd, device, descriptorSetLayouts);
1574	DescriptorPoolBuilder poolBuilder;
1575	poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, setAndDescriptorCount);
1576	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setAndDescriptorCount);
1577	std::vector<vk::Move<VkDescriptorSet>> descriptorSetsWrap = {};
1578	std::vector<VkDescriptorSet> descriptorSets = {};
1579
1580	for (const auto& setLayout : descriptorSetLayouts) {
1581		descriptorSetsWrap.emplace_back(makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get()));
1582	}
1583
1584	for (size_t i = 0; i < indices.size(); i++) {
1585		descriptorSets.emplace_back(descriptorSetsWrap[i].get());
1586	}
1587
1588	const auto			bufferSize		= static_cast<VkDeviceSize>(sizeof(uint32_t));
1589	std::vector<std::unique_ptr<BufferWithMemory>> buffers;
1590	//create uniform buffers
1591	for (size_t i = 0; i < indices.size(); i++) {
1592		auto outBufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1593		auto buffer = std::unique_ptr<vk::BufferWithMemory>(new vk::BufferWithMemory(vkd, device, alloc, outBufferInfo, vk::MemoryRequirement::HostVisible));
1594		auto&				bufferAlloc		= buffer->getAllocation();
1595		uint32_t*			bufferData		= (uint32_t*)bufferAlloc.getHostPtr();
1596		*bufferData = (uint32_t)i;
1597		flushAlloc(vkd, device, bufferAlloc);
1598		buffers.push_back(std::move(buffer));
1599	}
1600
1601	DescriptorSetUpdateBuilder updater;
1602
1603	for (auto i : indices) {
1604		const auto bufferInfo = makeDescriptorBufferInfo(buffers[i]->get(), 0ull, bufferSize);
1605		updater.writeSingle(descriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo);
1606		updater.update(vkd, device);
1607	}
1608
1609	const auto topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1610	m_graphicsPipeline.setDefaultRasterizationState()
1611		.setDefaultTopology(topology)
1612		.setupVertexInputState(&vertexInputState)
1613		.setDefaultDepthStencilState()
1614		.setDefaultMultisampleState()
1615		.setDefaultColorBlendState()
1616		.setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, &rasterizationState)
1617		.setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1618		.setupFragmentOutputState(*renderPass)
1619		.setMonolithicPipelineLayout(pipelineLayout)
1620		.buildPipeline();
1621
1622	// Command pool and buffer.
1623	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
1624	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1625	const auto cmdBuffer	= cmdBufferPtr.get();
1626
1627	beginCommandBuffer(vkd, cmdBuffer);
1628
1629	// Draw.
1630	renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
1631	for (auto i : indices) {
1632		if (m_config.holes && ((i == 1) || (i == 2))) {
1633			continue;
1634		}
1635		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), i, 1, &descriptorSets[i], 0u, nullptr);
1636	}
1637	m_graphicsPipeline.bind(cmdBuffer);
1638	vkd.cmdDraw(cmdBuffer, 3, 1u, 0u, 0u);
1639	renderPass.end(vkd, cmdBuffer);
1640
1641	// Copy to verification buffer.
1642	const auto copyRegion		= makeBufferImageCopy(m_extent, colorSRL);
1643	const auto transfer2Host	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1644	const auto color2Transfer	= makeImageMemoryBarrier(
1645		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1646		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1647		colorBuffer.get(), colorSRR);
1648
1649	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
1650	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, &copyRegion);
1651	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host);
1652
1653	endCommandBuffer(vkd, cmdBuffer);
1654
1655	// Submit and validate result.
1656	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1657
1658	const tcu::IVec3					iExtent (static_cast<int>(m_extent.width), static_cast<int>(m_extent.height), static_cast<int>(m_extent.depth));
1659	void*								verifBufferData		= verifBufferAlloc.getHostPtr();
1660	const tcu::ConstPixelBufferAccess	verifAccess		(tcuFormat, iExtent, verifBufferData);
1661	invalidateAlloc(vkd, device, verifBufferAlloc);
1662
1663	const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1664	tcu::TextureLevel referenceLevel(mapVkFormat(m_format), m_extent.height, m_extent.height);
1665	tcu::PixelBufferAccess reference = referenceLevel.getAccess();
1666	tcu::clear(reference, green);
1667
1668	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference, verifAccess, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
1669		return tcu::TestStatus::fail("Image comparison failed");
1670
1671	return tcu::TestStatus::pass("Pass");
1672}
1673
1674} // anonymous
1675
1676tcu::TestCaseGroup* createMiscTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1677{
1678	de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc"));
1679
1680	// Location of the Amber script files under the data/vulkan/amber source tree.
1681	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1682		addMonolithicAmberTests(miscTests.get());
1683
1684	// Verify implicit access to gl_PrimtiveID works
1685	miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", pipelineConstructionType, false));
1686	// Verify implicit access to gl_PrimtiveID works with a tessellation shader
1687	miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation", pipelineConstructionType, true));
1688	#ifndef CTS_USES_VULKANSC
1689	if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY) {
1690		// Check if interpolateAtSample works as expected when using a pipeline library and null MSAA state in the fragment shader"
1691		miscTests->addChild(new PipelineLibraryInterpolateAtSampleTestCase(testCtx, "interpolate_at_sample_no_sample_shading"));
1692	}
1693	#endif
1694
1695#ifndef CTS_USES_VULKANSC
1696	if (isConstructionTypeLibrary(pipelineConstructionType))
1697	{
1698		for (int useTessIdx = 0; useTessIdx < 2; ++useTessIdx)
1699			for (int useGeomIdx = 0; useGeomIdx < 2; ++useGeomIdx)
1700			{
1701				const bool useTess = (useTessIdx > 0);
1702				const bool useGeom = (useGeomIdx > 0);
1703
1704				std::string testName = "unused_shader_stages";
1705
1706				if (useTess)
1707					testName += "_include_tess";
1708
1709				if (useGeom)
1710					testName += "_include_geom";
1711
1712				const UnusedShaderStageParams params { pipelineConstructionType, useTess, useGeom };
1713				miscTests->addChild(new UnusedShaderStagesCase(testCtx, testName, params));
1714			}
1715	}
1716#endif // CTS_USES_VULKANSC
1717
1718	BindingTestConfig config0 = {pipelineConstructionType, true, false};
1719	BindingTestConfig config1 = {pipelineConstructionType, false, true};
1720	BindingTestConfig config2 = {pipelineConstructionType, true, true};
1721
1722	// Verify implicit access to gl_PrimtiveID works with a tessellation shader
1723	miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards", config0));
1724	// Verify implicit access to gl_PrimtiveID works with a tessellation shader
1725	miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_holes", config1));
1726	// Verify implicit access to gl_PrimtiveID works with a tessellation shader
1727	miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards_holes", config2));
1728
1729	return miscTests.release();
1730}
1731
1732} // pipeline
1733} // vkt
1734