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