• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve Corporation.
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 Mesh Shader Misc Tests for VK_EXT_mesh_shader
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktMeshShaderMiscTests.hpp"
26 #include "vktMeshShaderUtil.hpp"
27 #include "vktTestCase.hpp"
28 
29 #include "vkBuilderUtil.hpp"
30 #include "vkImageWithMemory.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 
38 #include "tcuDefs.hpp"
39 #include "tcuVectorType.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTexture.hpp"
42 #include "tcuTextureUtil.hpp"
43 #include "tcuMaybe.hpp"
44 #include "tcuStringTemplate.hpp"
45 #include "tcuTestLog.hpp"
46 
47 #include "deRandom.hpp"
48 
49 #include <cstdint>
50 #include <memory>
51 #include <utility>
52 #include <vector>
53 #include <string>
54 #include <sstream>
55 #include <map>
56 #include <type_traits>
57 #include <limits>
58 
59 namespace vkt
60 {
61 namespace MeshShader
62 {
63 
64 namespace
65 {
66 
67 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
68 
69 using namespace vk;
70 
71 // Output images will use this format.
getOutputFormat()72 VkFormat getOutputFormat ()
73 {
74 	return VK_FORMAT_R8G8B8A8_UNORM;
75 }
76 
77 // Threshold that's reasonable for the previous format.
getCompareThreshold()78 float getCompareThreshold ()
79 {
80 	return 0.005f; // 1/256 < 0.005 < 2/256
81 }
82 
83 // Check mesh shader support.
genericCheckSupport(Context & context,bool requireTaskShader,bool requireVertexStores)84 void genericCheckSupport (Context& context, bool requireTaskShader, bool requireVertexStores)
85 {
86 	checkTaskMeshShaderSupportEXT(context, requireTaskShader, true);
87 
88 	if (requireVertexStores)
89 	{
90 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
91 	}
92 }
93 
94 struct MiscTestParams
95 {
96 	tcu::Maybe<tcu::UVec3>	taskCount;
97 	tcu::UVec3				meshCount;
98 
99 	uint32_t				width;
100 	uint32_t				height;
101 
MiscTestParamsvkt::MeshShader::__anond8548dd90111::MiscTestParams102 	MiscTestParams (const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_)
103 		: taskCount		(taskCount_)
104 		, meshCount		(meshCount_)
105 		, width			(width_)
106 		, height		(height_)
107 	{}
108 
109 	// Makes the class polymorphic and allows the right destructor to be used for subclasses.
~MiscTestParamsvkt::MeshShader::__anond8548dd90111::MiscTestParams110 	virtual ~MiscTestParams () {}
111 
needsTaskShadervkt::MeshShader::__anond8548dd90111::MiscTestParams112 	bool needsTaskShader () const
113 	{
114 		return static_cast<bool>(taskCount);
115 	}
116 
drawCountvkt::MeshShader::__anond8548dd90111::MiscTestParams117 	tcu::UVec3 drawCount () const
118 	{
119 		if (needsTaskShader())
120 			return taskCount.get();
121 		return meshCount;
122 	}
123 };
124 
125 using ParamsPtr = std::unique_ptr<MiscTestParams>;
126 
127 class MeshShaderMiscCase : public vkt::TestCase
128 {
129 public:
130 					MeshShaderMiscCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params);
~MeshShaderMiscCase(void)131 	virtual			~MeshShaderMiscCase		(void) {}
132 
133 	void			checkSupport			(Context& context) const override;
134 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
135 
136 protected:
137 	std::unique_ptr<MiscTestParams> m_params;
138 };
139 
MeshShaderMiscCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)140 MeshShaderMiscCase::MeshShaderMiscCase (tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
141 	: vkt::TestCase	(testCtx, name)
142 	, m_params		(params.release())
143 {}
144 
checkSupport(Context & context) const145 void MeshShaderMiscCase::checkSupport (Context& context) const
146 {
147 	genericCheckSupport(context, m_params->needsTaskShader(), /*requireVertexStores*/false);
148 }
149 
150 // Adds the generic fragment shader. To be called by subclasses.
initPrograms(vk::SourceCollections & programCollection) const151 void MeshShaderMiscCase::initPrograms (vk::SourceCollections& programCollection) const
152 {
153 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
154 
155 	std::string frag =
156 		"#version 450\n"
157 		"#extension GL_EXT_mesh_shader : enable\n"
158 		"\n"
159 		"layout (location=0) in perprimitiveEXT vec4 primitiveColor;\n"
160 		"layout (location=0) out vec4 outColor;\n"
161 		"\n"
162 		"void main ()\n"
163 		"{\n"
164 		"    outColor = primitiveColor;\n"
165 		"}\n"
166 		;
167 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag) << buildOptions;
168 }
169 
170 class MeshShaderMiscInstance : public vkt::TestInstance
171 {
172 public:
MeshShaderMiscInstance(Context & context,const MiscTestParams * params)173 					MeshShaderMiscInstance	(Context& context, const MiscTestParams* params)
174 						: vkt::TestInstance	(context)
175 						, m_params			(params)
176 						, m_referenceLevel	()
177 					{
178 					}
179 
180 	void			generateSolidRefLevel	(const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output);
181 	virtual void	generateReferenceLevel	() = 0;
182 
183 	virtual bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const;
184 	virtual bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess) const;
185 	tcu::TestStatus	iterate					() override;
186 
187 protected:
188 	const MiscTestParams*				m_params;
189 	std::unique_ptr<tcu::TextureLevel>	m_referenceLevel;
190 };
191 
generateSolidRefLevel(const tcu::Vec4 & color,std::unique_ptr<tcu::TextureLevel> & output)192 void MeshShaderMiscInstance::generateSolidRefLevel (const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output)
193 {
194 	const auto format		= getOutputFormat();
195 	const auto tcuFormat	= mapVkFormat(format);
196 
197 	const auto iWidth		= static_cast<int>(m_params->width);
198 	const auto iHeight		= static_cast<int>(m_params->height);
199 
200 	output.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
201 
202 	const auto access		= output->getAccess();
203 
204 	// Fill with solid color.
205 	tcu::clear(access, color);
206 }
207 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess) const208 bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
209 {
210 	return verifyResult(resultAccess, *m_referenceLevel);
211 }
212 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess,const tcu::TextureLevel & referenceLevel) const213 bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const
214 {
215 	const auto referenceAccess = referenceLevel.getAccess();
216 
217 	const auto refWidth		= referenceAccess.getWidth();
218 	const auto refHeight	= referenceAccess.getHeight();
219 	const auto refDepth		= referenceAccess.getDepth();
220 
221 	const auto resWidth		= resultAccess.getWidth();
222 	const auto resHeight	= resultAccess.getHeight();
223 	const auto resDepth		= resultAccess.getDepth();
224 
225 	DE_ASSERT(resWidth == refWidth || resHeight == refHeight || resDepth == refDepth);
226 
227 	// For release builds.
228 	DE_UNREF(refWidth);
229 	DE_UNREF(refHeight);
230 	DE_UNREF(refDepth);
231 	DE_UNREF(resWidth);
232 	DE_UNREF(resHeight);
233 	DE_UNREF(resDepth);
234 
235 	const auto outputFormat		= getOutputFormat();
236 	const auto expectedFormat	= mapVkFormat(outputFormat);
237 	const auto resFormat		= resultAccess.getFormat();
238 	const auto refFormat		= referenceAccess.getFormat();
239 
240 	DE_ASSERT(resFormat == expectedFormat && refFormat == expectedFormat);
241 
242 	// For release builds
243 	DE_UNREF(expectedFormat);
244 	DE_UNREF(resFormat);
245 	DE_UNREF(refFormat);
246 
247 	auto&			log				= m_context.getTestContext().getLog();
248 	const auto		threshold		= getCompareThreshold();
249 	const tcu::Vec4	thresholdVec	(threshold, threshold, threshold, threshold);
250 
251 	return tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, thresholdVec, tcu::COMPARE_LOG_ON_ERROR);
252 }
253 
iterate()254 tcu::TestStatus MeshShaderMiscInstance::iterate ()
255 {
256 	const auto&		vkd			= m_context.getDeviceInterface();
257 	const auto		device		= m_context.getDevice();
258 	auto&			alloc		= m_context.getDefaultAllocator();
259 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
260 	const auto		queue		= m_context.getUniversalQueue();
261 
262 	const auto		imageFormat	= getOutputFormat();
263 	const auto		tcuFormat	= mapVkFormat(imageFormat);
264 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
265 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
266 
267 	const VkImageCreateInfo colorBufferInfo =
268 	{
269 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
270 		nullptr,								//	const void*				pNext;
271 		0u,										//	VkImageCreateFlags		flags;
272 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
273 		imageFormat,							//	VkFormat				format;
274 		imageExtent,							//	VkExtent3D				extent;
275 		1u,										//	uint32_t				mipLevels;
276 		1u,										//	uint32_t				arrayLayers;
277 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
278 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
279 		imageUsage,								//	VkImageUsageFlags		usage;
280 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
281 		0u,										//	uint32_t				queueFamilyIndexCount;
282 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
283 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
284 	};
285 
286 	// Create color image and view.
287 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
288 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
289 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
290 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
291 
292 	// Create a memory buffer for verification.
293 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
294 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
295 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
296 
297 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
298 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
299 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
300 
301 	// Pipeline layout.
302 	const auto pipelineLayout = makePipelineLayout(vkd, device);
303 
304 	// Shader modules.
305 	const auto&	binaries	= m_context.getBinaryCollection();
306 	const auto	hasTask		= binaries.contains("task");
307 
308 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
309 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
310 
311 	Move<VkShaderModule> taskShader;
312 	if (hasTask)
313 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
314 
315 	// Render pass.
316 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
317 
318 	// Framebuffer.
319 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
320 
321 	// Viewport and scissor.
322 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
323 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
324 
325 	// Color blending.
326 	const auto									colorWriteMask	= (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
327 	const VkPipelineColorBlendAttachmentState	blendAttState	=
328 	{
329 		VK_TRUE,				//	VkBool32				blendEnable;
330 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcColorBlendFactor;
331 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstColorBlendFactor;
332 		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
333 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcAlphaBlendFactor;
334 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstAlphaBlendFactor;
335 		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
336 		colorWriteMask,			//	VkColorComponentFlags	colorWriteMask;
337 	};
338 
339 	const VkPipelineColorBlendStateCreateInfo colorBlendInfo =
340 	{
341 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
342 		nullptr,													//	const void*									pNext;
343 		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
344 		VK_FALSE,													//	VkBool32									logicOpEnable;
345 		VK_LOGIC_OP_OR,												//	VkLogicOp									logicOp;
346 		1u,															//	uint32_t									attachmentCount;
347 		&blendAttState,												//	const VkPipelineColorBlendAttachmentState*	pAttachments;
348 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
349 	};
350 
351 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
352 		taskShader.get(), meshShader.get(), fragShader.get(),
353 		renderPass.get(), viewports, scissors, 0u/*subpass*/,
354 		nullptr, nullptr, nullptr, &colorBlendInfo);
355 
356 	// Command pool and buffer.
357 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
358 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
359 	const auto cmdBuffer	= cmdBufferPtr.get();
360 
361 	beginCommandBuffer(vkd, cmdBuffer);
362 
363 	// Run pipeline.
364 	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 0.0f);
365 	const auto		drawCount	= m_params->drawCount();
366 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
367 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
368 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
369 	endRenderPass(vkd, cmdBuffer);
370 
371 	// Copy color buffer to verification buffer.
372 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
373 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
374 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
375 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
376 
377 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
378 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
379 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
380 
381 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
382 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
383 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
384 
385 	endCommandBuffer(vkd, cmdBuffer);
386 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
387 
388 	// Generate reference image and compare results.
389 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
390 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
391 
392 	generateReferenceLevel();
393 	invalidateAlloc(vkd, device, verificationBufferAlloc);
394 	if (!verifyResult(verificationAccess))
395 		TCU_FAIL("Result does not match reference; check log for details");
396 
397 	return tcu::TestStatus::pass("Pass");
398 }
399 
400 // Verify passing more complex data between the task and mesh shaders.
401 class ComplexTaskDataCase : public MeshShaderMiscCase
402 {
403 public:
ComplexTaskDataCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)404 					ComplexTaskDataCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
405 						: MeshShaderMiscCase (testCtx, name, std::move(params))
406 					{}
407 
408 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
409 	TestInstance*	createInstance			(Context& context) const override;
410 };
411 
412 class ComplexTaskDataInstance : public MeshShaderMiscInstance
413 {
414 public:
ComplexTaskDataInstance(Context & context,const MiscTestParams * params)415 	ComplexTaskDataInstance (Context& context, const MiscTestParams* params)
416 		: MeshShaderMiscInstance (context, params)
417 	{}
418 
419 	void	generateReferenceLevel	() override;
420 };
421 
generateReferenceLevel()422 void ComplexTaskDataInstance::generateReferenceLevel ()
423 {
424 	const auto format		= getOutputFormat();
425 	const auto tcuFormat	= mapVkFormat(format);
426 
427 	const auto iWidth		= static_cast<int>(m_params->width);
428 	const auto iHeight		= static_cast<int>(m_params->height);
429 
430 	const auto halfWidth	= iWidth / 2;
431 	const auto halfHeight	= iHeight / 2;
432 
433 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
434 
435 	const auto access		= m_referenceLevel->getAccess();
436 
437 	// Each image quadrant gets a different color.
438 	for (int y = 0; y < iHeight; ++y)
439 	for (int x = 0; x < iWidth; ++x)
440 	{
441 		const float	red			= ((y < halfHeight) ? 0.0f : 1.0f);
442 		const float	green		= ((x < halfWidth)  ? 0.0f : 1.0f);
443 		const auto	refColor	= tcu::Vec4(red, green, 1.0f, 1.0f);
444 		access.setPixel(refColor, x, y);
445 	}
446 }
447 
initPrograms(vk::SourceCollections & programCollection) const448 void ComplexTaskDataCase::initPrograms (vk::SourceCollections& programCollection) const
449 {
450 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
451 
452 	// Add the generic fragment shader.
453 	MeshShaderMiscCase::initPrograms(programCollection);
454 
455 	const std::string taskDataDecl =
456 		"struct RowId {\n"
457 		"    uint id;\n"
458 		"};\n"
459 		"\n"
460 		"struct WorkGroupData {\n"
461 		"    float WorkGroupIdPlusOnex1000Iota[10];\n"
462 		"    RowId rowId;\n"
463 		"    uvec3 WorkGroupIdPlusOnex2000Iota;\n"
464 		"    vec2  WorkGroupIdPlusOnex3000Iota;\n"
465 		"};\n"
466 		"\n"
467 		"struct ExternalData {\n"
468 		"    float OneMillion;\n"
469 		"    uint  TwoMillion;\n"
470 		"    WorkGroupData workGroupData;\n"
471 		"};\n"
472 		"\n"
473 		"struct TaskData {\n"
474 		"    uint yes;\n"
475 		"    ExternalData externalData;\n"
476 		"};\n"
477 		"taskPayloadSharedEXT TaskData td;\n"
478 		;
479 
480 	{
481 		std::ostringstream task;
482 		task
483 			<< "#version 450\n"
484 			<< "#extension GL_EXT_mesh_shader : enable\n"
485 			<< "\n"
486 			<< "layout (local_size_x=1) in;\n"
487 			<< "\n"
488 			<< taskDataDecl
489 			<< "\n"
490 			<< "void main ()\n"
491 			<< "{\n"
492 			<< "    td.yes = 1u;\n"
493 			<< "    td.externalData.OneMillion = 1000000.0;\n"
494 			<< "    td.externalData.TwoMillion = 2000000u;\n"
495 			<< "    for (uint i = 0; i < 10; i++) {\n"
496 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] = float((gl_WorkGroupID.x + 1u) * 1000 + i);\n"
497 			<< "    }\n"
498 			<< "    {\n"
499 			<< "        uint baseVal = (gl_WorkGroupID.x + 1u) * 2000;\n"
500 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
501 			<< "    }\n"
502 			<< "    {\n"
503 			<< "        uint baseVal = (gl_WorkGroupID.x + 1u) * 3000;\n"
504 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota = vec2(baseVal, baseVal + 1);\n"
505 			<< "    }\n"
506 			<< "    td.externalData.workGroupData.rowId.id = gl_WorkGroupID.x;\n"
507 			<< "    EmitMeshTasksEXT(2u, 1u, 1u);\n"
508 			<< "}\n"
509 			;
510 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
511 	}
512 
513 	{
514 		std::ostringstream mesh;
515 		mesh
516 			<< "#version 450\n"
517 			<< "#extension GL_EXT_mesh_shader : enable\n"
518 			<< "\n"
519 			<< "layout(local_size_x=2) in;\n"
520 			<< "layout(triangles) out;\n"
521 			<< "layout(max_vertices=4, max_primitives=2) out;\n"
522 			<< "\n"
523 			<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
524 			<< "\n"
525 			<< taskDataDecl
526 			<< "\n"
527 			<< "void main ()\n"
528 			<< "{\n"
529 			<< "    bool dataOK = true;\n"
530 			<< "    dataOK = (dataOK && (td.yes == 1u));\n"
531 			<< "    dataOK = (dataOK && (td.externalData.OneMillion == 1000000.0 && td.externalData.TwoMillion == 2000000u));\n"
532 			<< "    uint rowId = td.externalData.workGroupData.rowId.id;\n"
533 			<< "    dataOK = (dataOK && (rowId == 0u || rowId == 1u));\n"
534 			<< "\n"
535 			<< "    {\n"
536 			<< "        uint baseVal = (rowId + 1u) * 1000u;\n"
537 			<< "        for (uint i = 0; i < 10; i++) {\n"
538 			<< "            if (td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] != float(baseVal + i)) {\n"
539 			<< "                dataOK = false;\n"
540 			<< "                break;\n"
541 			<< "            }\n"
542 			<< "        }\n"
543 			<< "    }\n"
544 			<< "\n"
545 			<< "    {\n"
546 			<< "        uint baseVal = (rowId + 1u) * 2000;\n"
547 			<< "        uvec3 expected = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
548 			<< "        if (td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota != expected) {\n"
549 			<< "            dataOK = false;\n"
550 			<< "        }\n"
551 			<< "    }\n"
552 			<< "\n"
553 			<< "    {\n"
554 			<< "        uint baseVal = (rowId + 1u) * 3000;\n"
555 			<< "        vec2 expected = vec2(baseVal, baseVal + 1);\n"
556 			<< "        if (td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota != expected) {\n"
557 			<< "            dataOK = false;\n"
558 			<< "        }\n"
559 			<< "    }\n"
560 			<< "\n"
561 			<< "    uint columnId = gl_WorkGroupID.x;\n"
562 			<< "\n"
563 			<< "    uvec2 vertPrim = uvec2(0u, 0u);\n"
564 			<< "    if (dataOK) {\n"
565 			<< "        vertPrim = uvec2(4u, 2u);\n"
566 			<< "    }\n"
567 			<< "    SetMeshOutputsEXT(vertPrim.x, vertPrim.y);\n"
568 			<< "    if (vertPrim.y == 0u) {\n"
569 			<< "        return;\n"
570 			<< "    }\n"
571 			<< "\n"
572 			<< "    const vec4 outColor = vec4(rowId, columnId, 1.0f, 1.0f);\n"
573 			<< "    triangleColor[0] = outColor;\n"
574 			<< "    triangleColor[1] = outColor;\n"
575 			<< "\n"
576 			<< "    // Each local invocation will generate two points and one triangle from the quad.\n"
577 			<< "    // The first local invocation will generate the top quad vertices.\n"
578 			<< "    // The second invocation will generate the two bottom vertices.\n"
579 			<< "    vec4 left  = vec4(0.0, 0.0, 0.0, 1.0);\n"
580 			<< "    vec4 right = vec4(1.0, 0.0, 0.0, 1.0);\n"
581 			<< "\n"
582 			<< "    float localInvocationOffsetY = float(gl_LocalInvocationIndex);\n"
583 			<< "    left.y  += localInvocationOffsetY;\n"
584 			<< "    right.y += localInvocationOffsetY;\n"
585 			<< "\n"
586 			<< "    // The code above creates a quad from (0, 0) to (1, 1) but we need to offset it\n"
587 			<< "    // in X and/or Y depending on the row and column, to place it in other quadrants.\n"
588 			<< "    float quadrantOffsetX = float(int(columnId) - 1);\n"
589 			<< "    float quadrantOffsetY = float(int(rowId) - 1);\n"
590 			<< "\n"
591 			<< "    left.x  += quadrantOffsetX;\n"
592 			<< "    right.x += quadrantOffsetX;\n"
593 			<< "\n"
594 			<< "    left.y  += quadrantOffsetY;\n"
595 			<< "    right.y += quadrantOffsetY;\n"
596 			<< "\n"
597 			<< "    uint baseVertexId = 2*gl_LocalInvocationIndex;\n"
598 			<< "    gl_MeshVerticesEXT[baseVertexId + 0].gl_Position = left;\n"
599 			<< "    gl_MeshVerticesEXT[baseVertexId + 1].gl_Position = right;\n"
600 			<< "\n"
601 			<< "    // 0,1,2 or 1,2,3 (note: triangles alternate front face this way)\n"
602 			<< "    const uvec3 indices = uvec3(0 + gl_LocalInvocationIndex, 1 + gl_LocalInvocationIndex, 2 + gl_LocalInvocationIndex);\n"
603 			<< "    gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex] = indices;\n"
604 			<< "}\n"
605 			;
606 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
607 	}
608 }
609 
createInstance(Context & context) const610 TestInstance* ComplexTaskDataCase::createInstance (Context& context) const
611 {
612 	return new ComplexTaskDataInstance(context, m_params.get());
613 }
614 
615 // Verify drawing a single point.
616 class SinglePointCase : public MeshShaderMiscCase
617 {
618 public:
SinglePointCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params,bool writePointSize=true)619 					SinglePointCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params, bool writePointSize = true)
620 						: MeshShaderMiscCase (testCtx, name, std::move(params))
621 						, m_writePointSize(writePointSize)
622 					{}
623 
624 	void			checkSupport			(Context& context) const override;
625 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
626 	TestInstance*	createInstance			(Context& context) const override;
627 
628 protected:
629 	const bool		m_writePointSize = true;
630 };
631 
632 class SinglePointInstance : public MeshShaderMiscInstance
633 {
634 public:
SinglePointInstance(Context & context,const MiscTestParams * params)635 	SinglePointInstance (Context& context, const MiscTestParams* params)
636 		: MeshShaderMiscInstance (context, params)
637 	{}
638 
639 	void	generateReferenceLevel	() override;
640 };
641 
checkSupport(Context & context) const642 void SinglePointCase::checkSupport (Context& context) const
643 {
644 	MeshShaderMiscCase::checkSupport(context);
645 
646 	if (!m_writePointSize)
647 		context.requireDeviceFunctionality("VK_KHR_maintenance5");
648 }
649 
createInstance(Context & context) const650 TestInstance* SinglePointCase::createInstance (Context& context) const
651 {
652 	return new SinglePointInstance (context, m_params.get());
653 }
654 
initPrograms(vk::SourceCollections & programCollection) const655 void SinglePointCase::initPrograms (vk::SourceCollections& programCollection) const
656 {
657 	DE_ASSERT(!m_params->needsTaskShader());
658 
659 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
660 
661 	MeshShaderMiscCase::initPrograms(programCollection);
662 
663 	std::ostringstream mesh;
664 	mesh
665 		<< "#version 450\n"
666 		<< "#extension GL_EXT_mesh_shader : enable\n"
667 		<< "\n"
668 		<< "layout(local_size_x=1) in;\n"
669 		<< "layout(points) out;\n"
670 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
671 		<< "\n"
672 		<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
673 		<< "\n"
674 		<< "void main ()\n"
675 		<< "{\n"
676 		<< "    SetMeshOutputsEXT(1u, 1u);\n"
677 		<< "    pointColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
678 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n";
679 	if (m_writePointSize)
680 	{
681 	mesh
682 		<< "    gl_MeshVerticesEXT[0].gl_PointSize = 1.0f;\n";
683 	}
684 	mesh
685 		<< "    gl_PrimitivePointIndicesEXT[0] = 0;\n"
686 		<< "}\n"
687 		;
688 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
689 }
690 
generateReferenceLevel()691 void SinglePointInstance::generateReferenceLevel ()
692 {
693 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
694 
695 	const auto halfWidth	= static_cast<int>(m_params->width / 2u);
696 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
697 	const auto access		= m_referenceLevel->getAccess();
698 
699 	access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
700 }
701 
702 // Verify drawing a single line.
703 class SingleLineCase : public MeshShaderMiscCase
704 {
705 public:
SingleLineCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)706 					SingleLineCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
707 						: MeshShaderMiscCase (testCtx, name, std::move(params))
708 					{}
709 
710 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
711 	TestInstance*	createInstance			(Context& context) const override;
712 };
713 
714 class SingleLineInstance : public MeshShaderMiscInstance
715 {
716 public:
SingleLineInstance(Context & context,const MiscTestParams * params)717 	SingleLineInstance (Context& context, const MiscTestParams* params)
718 		: MeshShaderMiscInstance (context, params)
719 	{}
720 
721 	void	generateReferenceLevel	() override;
722 };
723 
createInstance(Context & context) const724 TestInstance* SingleLineCase::createInstance (Context& context) const
725 {
726 	return new SingleLineInstance (context, m_params.get());
727 }
728 
initPrograms(vk::SourceCollections & programCollection) const729 void SingleLineCase::initPrograms (vk::SourceCollections& programCollection) const
730 {
731 	DE_ASSERT(!m_params->needsTaskShader());
732 
733 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
734 
735 	MeshShaderMiscCase::initPrograms(programCollection);
736 
737 	std::ostringstream mesh;
738 	mesh
739 		<< "#version 450\n"
740 		<< "#extension GL_EXT_mesh_shader : enable\n"
741 		<< "\n"
742 		<< "layout(local_size_x=1) in;\n"
743 		<< "layout(lines) out;\n"
744 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
745 		<< "\n"
746 		<< "layout (location=0) out perprimitiveEXT vec4 lineColor[];\n"
747 		<< "\n"
748 		<< "void main ()\n"
749 		<< "{\n"
750 		<< "    SetMeshOutputsEXT(2u, 1u);\n"
751 		<< "    lineColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
752 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0f, 0.0f, 0.0f, 1.0f);\n"
753 		<< "    gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0f, 0.0f, 0.0f, 1.0f);\n"
754 		<< "    gl_PrimitiveLineIndicesEXT[gl_LocalInvocationIndex] = uvec2(0u, 1u);\n"
755 		<< "}\n"
756 		;
757 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
758 }
759 
generateReferenceLevel()760 void SingleLineInstance::generateReferenceLevel ()
761 {
762 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
763 
764 	const auto iWidth		= static_cast<int>(m_params->width);
765 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
766 	const auto access		= m_referenceLevel->getAccess();
767 
768 	// Center row.
769 	for (int x = 0; x < iWidth; ++x)
770 		access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), x, halfHeight);
771 }
772 
773 // Verify drawing a single triangle.
774 class SingleTriangleCase : public MeshShaderMiscCase
775 {
776 public:
SingleTriangleCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)777 					SingleTriangleCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
778 						: MeshShaderMiscCase (testCtx, name, std::move(params))
779 					{}
780 
781 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
782 	TestInstance*	createInstance			(Context& context) const override;
783 };
784 
785 class SingleTriangleInstance : public MeshShaderMiscInstance
786 {
787 public:
SingleTriangleInstance(Context & context,const MiscTestParams * params)788 	SingleTriangleInstance (Context& context, const MiscTestParams* params)
789 		: MeshShaderMiscInstance (context, params)
790 	{}
791 
792 	void	generateReferenceLevel	() override;
793 };
794 
createInstance(Context & context) const795 TestInstance* SingleTriangleCase::createInstance (Context& context) const
796 {
797 	return new SingleTriangleInstance (context, m_params.get());
798 }
799 
initPrograms(vk::SourceCollections & programCollection) const800 void SingleTriangleCase::initPrograms (vk::SourceCollections& programCollection) const
801 {
802 	DE_ASSERT(!m_params->needsTaskShader());
803 
804 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
805 
806 	MeshShaderMiscCase::initPrograms(programCollection);
807 
808 	const float halfPixelX = 2.0f / static_cast<float>(m_params->width);
809 	const float halfPixelY = 2.0f / static_cast<float>(m_params->height);
810 
811 	std::ostringstream mesh;
812 	mesh
813 		<< "#version 450\n"
814 		<< "#extension GL_EXT_mesh_shader : enable\n"
815 		<< "\n"
816 		<< "layout(local_size_x=1) in;\n"
817 		<< "layout(triangles) out;\n"
818 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
819 		<< "\n"
820 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
821 		<< "\n"
822 		<< "void main ()\n"
823 		<< "{\n"
824 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
825 		<< "    triangleColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
826 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(" <<  halfPixelY << ", " << -halfPixelX << ", 0.0f, 1.0f);\n"
827 		<< "    gl_MeshVerticesEXT[1].gl_Position = vec4(" <<  halfPixelY << ", " <<  halfPixelX << ", 0.0f, 1.0f);\n"
828 		<< "    gl_MeshVerticesEXT[2].gl_Position = vec4(" << -halfPixelY << ", 0.0f, 0.0f, 1.0f);\n"
829 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0u, 1u, 2u);\n"
830 		<< "}\n"
831 		;
832 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
833 }
834 
generateReferenceLevel()835 void SingleTriangleInstance::generateReferenceLevel ()
836 {
837 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
838 
839 	const auto halfWidth	= static_cast<int>(m_params->width / 2u);
840 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
841 	const auto access		= m_referenceLevel->getAccess();
842 
843 	// Single pixel in the center.
844 	access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
845 }
846 
847 // Verify drawing the maximum number of points.
848 class MaxPointsCase : public MeshShaderMiscCase
849 {
850 public:
MaxPointsCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)851 					MaxPointsCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
852 						: MeshShaderMiscCase (testCtx, name, std::move(params))
853 					{}
854 
855 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
856 	TestInstance*	createInstance			(Context& context) const override;
857 };
858 
859 class MaxPointsInstance : public MeshShaderMiscInstance
860 {
861 public:
MaxPointsInstance(Context & context,const MiscTestParams * params)862 	MaxPointsInstance (Context& context, const MiscTestParams* params)
863 		: MeshShaderMiscInstance (context, params)
864 	{}
865 
866 	void	generateReferenceLevel	() override;
867 };
868 
createInstance(Context & context) const869 TestInstance* MaxPointsCase::createInstance (Context& context) const
870 {
871 	return new MaxPointsInstance (context, m_params.get());
872 }
873 
initPrograms(vk::SourceCollections & programCollection) const874 void MaxPointsCase::initPrograms (vk::SourceCollections& programCollection) const
875 {
876 	DE_ASSERT(!m_params->needsTaskShader());
877 
878 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
879 
880 	MeshShaderMiscCase::initPrograms(programCollection);
881 
882 	// Fill a 16x16 image with 256 points. Each of the 64 local invocations will handle a segment of 4 pixels. 4 segments per row.
883 	DE_ASSERT(m_params->width == 16u && m_params->height == 16u);
884 
885 	std::ostringstream mesh;
886 	mesh
887 		<< "#version 450\n"
888 		<< "#extension GL_EXT_mesh_shader : enable\n"
889 		<< "\n"
890 		<< "layout(local_size_x=8, local_size_y=2, local_size_z=4) in;\n"
891 		<< "layout(points) out;\n"
892 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
893 		<< "\n"
894 		<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
895 		<< "\n"
896 		<< "void main ()\n"
897 		<< "{\n"
898 		<< "    SetMeshOutputsEXT(256u, 256u);\n"
899 		<< "    uint firstPixel = 4u * gl_LocalInvocationIndex;\n"
900 		<< "    uint row = firstPixel / 16u;\n"
901 		<< "    uint col = firstPixel % 16u;\n"
902 		<< "    float pixSize = 2.0f / 16.0f;\n"
903 		<< "    float yCoord = pixSize * (float(row) + 0.5f) - 1.0f;\n"
904 		<< "    float baseXCoord = pixSize * (float(col) + 0.5f) - 1.0f;\n"
905 		<< "    for (uint i = 0; i < 4u; i++) {\n"
906 		<< "        float xCoord = baseXCoord + pixSize * float(i);\n"
907 		<< "        uint pixId = firstPixel + i;\n"
908 		<< "        gl_MeshVerticesEXT[pixId].gl_Position = vec4(xCoord, yCoord, 0.0f, 1.0f);\n"
909 		<< "        gl_MeshVerticesEXT[pixId].gl_PointSize = 1.0f;\n"
910 		<< "        gl_PrimitivePointIndicesEXT[pixId] = pixId;\n"
911 		<< "        pointColor[pixId] = vec4(((xCoord + 1.0f) / 2.0f), ((yCoord + 1.0f) / 2.0f), 0.0f, 1.0f);\n"
912 		<< "    }\n"
913 		<< "}\n"
914 		;
915 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
916 }
917 
generateReferenceLevel()918 void MaxPointsInstance::generateReferenceLevel ()
919 {
920 	const auto format		= getOutputFormat();
921 	const auto tcuFormat	= mapVkFormat(format);
922 
923 	const auto iWidth		= static_cast<int>(m_params->width);
924 	const auto iHeight		= static_cast<int>(m_params->height);
925 	const auto fWidth		= static_cast<float>(m_params->width);
926 	const auto fHeight		= static_cast<float>(m_params->height);
927 
928 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
929 
930 	const auto access		= m_referenceLevel->getAccess();
931 
932 	// Fill with gradient like the shader does.
933 	for (int y = 0; y < iHeight; ++y)
934 	for (int x = 0; x < iWidth; ++x)
935 	{
936 		const tcu::Vec4 color (
937 			((static_cast<float>(x) + 0.5f) / fWidth),
938 			((static_cast<float>(y) + 0.5f) / fHeight),
939 			0.0f, 1.0f);
940 		access.setPixel(color, x, y);
941 	}
942 }
943 
944 // Verify drawing the maximum number of lines.
945 class MaxLinesCase : public MeshShaderMiscCase
946 {
947 public:
MaxLinesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)948 					MaxLinesCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
949 						: MeshShaderMiscCase (testCtx, name, std::move(params))
950 					{}
951 
952 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
953 	TestInstance*	createInstance			(Context& context) const override;
954 };
955 
956 class MaxLinesInstance : public MeshShaderMiscInstance
957 {
958 public:
MaxLinesInstance(Context & context,const MiscTestParams * params)959 	MaxLinesInstance (Context& context, const MiscTestParams* params)
960 		: MeshShaderMiscInstance (context, params)
961 	{}
962 
963 	void	generateReferenceLevel	() override;
964 };
965 
createInstance(Context & context) const966 TestInstance* MaxLinesCase::createInstance (Context& context) const
967 {
968 	return new MaxLinesInstance (context, m_params.get());
969 }
970 
initPrograms(vk::SourceCollections & programCollection) const971 void MaxLinesCase::initPrograms (vk::SourceCollections& programCollection) const
972 {
973 	DE_ASSERT(!m_params->needsTaskShader());
974 
975 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
976 
977 	MeshShaderMiscCase::initPrograms(programCollection);
978 
979 	// Fill a 1x1020 image with 255 lines, each line being 4 pixels tall. Each invocation will generate ~4 lines.
980 	DE_ASSERT(m_params->width == 1u && m_params->height == 1020u);
981 
982 	std::ostringstream mesh;
983 	mesh
984 		<< "#version 450\n"
985 		<< "#extension GL_EXT_mesh_shader : enable\n"
986 		<< "\n"
987 		<< "layout(local_size_x=4, local_size_y=2, local_size_z=8) in;\n"
988 		<< "layout(lines) out;\n"
989 		<< "layout(max_vertices=256, max_primitives=255) out;\n"
990 		<< "\n"
991 		<< "layout (location=0) out perprimitiveEXT vec4 lineColor[];\n"
992 		<< "\n"
993 		<< "void main ()\n"
994 		<< "{\n"
995 		<< "    SetMeshOutputsEXT(256u, 255u);\n"
996 		<< "    uint firstLine = 4u * gl_LocalInvocationIndex;\n"
997 		<< "    for (uint i = 0u; i < 4u; i++) {\n"
998 		<< "        uint lineId = firstLine + i;\n"
999 		<< "        uint topPixel = 4u * lineId;\n"
1000 		<< "        uint bottomPixel = 3u + topPixel;\n"
1001 		<< "        if (bottomPixel < 1020u) {\n"
1002 		<< "            float bottomCoord = ((float(bottomPixel) + 1.0f) / 1020.0) * 2.0 - 1.0;\n"
1003 		<< "            gl_MeshVerticesEXT[lineId + 1u].gl_Position = vec4(0.0, bottomCoord, 0.0f, 1.0f);\n"
1004 		<< "            gl_PrimitiveLineIndicesEXT[lineId] = uvec2(lineId, lineId + 1u);\n"
1005 		<< "            lineColor[lineId] = vec4(0.0f, 1.0f, float(lineId) / 255.0f, 1.0f);\n"
1006 		<< "        } else {\n"
1007 		<< "            // The last iteration of the last invocation emits the first point\n"
1008 		<< "            gl_MeshVerticesEXT[0].gl_Position = vec4(0.0, -1.0, 0.0f, 1.0f);\n"
1009 		<< "        }\n"
1010 		<< "    }\n"
1011 		<< "}\n"
1012 		;
1013 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1014 }
1015 
generateReferenceLevel()1016 void MaxLinesInstance::generateReferenceLevel ()
1017 {
1018 	const auto format		= getOutputFormat();
1019 	const auto tcuFormat	= mapVkFormat(format);
1020 
1021 	const auto iWidth		= static_cast<int>(m_params->width);
1022 	const auto iHeight		= static_cast<int>(m_params->height);
1023 
1024 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
1025 
1026 	const auto access		= m_referenceLevel->getAccess();
1027 
1028 	// Fill lines, 4 pixels per line.
1029 	const uint32_t kNumLines = 255u;
1030 	const uint32_t kLineHeight = 4u;
1031 
1032 	for (uint32_t i = 0u; i < kNumLines; ++i)
1033 	{
1034 		const tcu::Vec4 color (0.0f, 1.0f, static_cast<float>(i) / static_cast<float>(kNumLines), 1.0f);
1035 		for (uint32_t j = 0u; j < kLineHeight; ++j)
1036 			access.setPixel(color, 0, i*kLineHeight + j);
1037 	}
1038 }
1039 
1040 // Verify drawing the maximum number of triangles.
1041 class MaxTrianglesCase : public MeshShaderMiscCase
1042 {
1043 public:
1044 	struct Params : public MiscTestParams
1045 	{
1046 		tcu::UVec3 localSize;
1047 
Paramsvkt::MeshShader::__anond8548dd90111::MaxTrianglesCase::Params1048 		Params (const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_, const tcu::UVec3& localSize_)
1049 			: MiscTestParams	(tcu::Nothing, meshCount_, width_, height_)
1050 			, localSize			(localSize_)
1051 			{}
1052 	};
1053 
MaxTrianglesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1054 					MaxTrianglesCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1055 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1056 					{}
1057 
1058 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1059 	TestInstance*	createInstance			(Context& context) const override;
1060 
1061 	static constexpr uint32_t kNumVertices	= 256u;
1062 	static constexpr uint32_t kNumTriangles	= 254u;
1063 };
1064 
1065 class MaxTrianglesInstance : public MeshShaderMiscInstance
1066 {
1067 public:
MaxTrianglesInstance(Context & context,const MiscTestParams * params)1068 	MaxTrianglesInstance (Context& context, const MiscTestParams* params)
1069 		: MeshShaderMiscInstance (context, params)
1070 	{}
1071 
1072 	void	generateReferenceLevel	() override;
1073 };
1074 
createInstance(Context & context) const1075 TestInstance* MaxTrianglesCase::createInstance (Context& context) const
1076 {
1077 	return new MaxTrianglesInstance (context, m_params.get());
1078 }
1079 
initPrograms(vk::SourceCollections & programCollection) const1080 void MaxTrianglesCase::initPrograms (vk::SourceCollections& programCollection) const
1081 {
1082 	// Default frag shader.
1083 	MeshShaderMiscCase::initPrograms(programCollection);
1084 
1085 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1086 	const auto params		= dynamic_cast<const MaxTrianglesCase::Params*>(m_params.get());
1087 
1088 	DE_ASSERT(params);
1089 	DE_ASSERT(!params->needsTaskShader());
1090 
1091 	const auto&	localSize		= params->localSize;
1092 	const auto	workGroupSize	= (localSize.x() * localSize.y() * localSize.z());
1093 
1094 	DE_ASSERT(kNumVertices % workGroupSize == 0u);
1095 	const auto trianglesPerInvocation = kNumVertices / workGroupSize;
1096 
1097 	// Fill a sufficiently large image with solid color. Generate a quarter of a circle with the center in the top left corner,
1098 	// using a triangle fan that advances from top to bottom. Each invocation will generate ~trianglesPerInvocation triangles.
1099 	std::ostringstream mesh;
1100 	mesh
1101 		<< "#version 450\n"
1102 		<< "#extension GL_EXT_mesh_shader : enable\n"
1103 		<< "\n"
1104 		<< "layout(local_size_x=" << localSize.x() << ", local_size_y=" << localSize.y() << ", local_size_z=" << localSize.z() << ") in;\n"
1105 		<< "layout(triangles) out;\n"
1106 		<< "layout(max_vertices=" << kNumVertices << ", max_primitives=" << kNumTriangles << ") out;\n"
1107 		<< "\n"
1108 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
1109 		<< "\n"
1110 		<< "const float PI_2 = 1.57079632679489661923;\n"
1111 		<< "const float RADIUS = 4.5;\n"
1112 		<< "\n"
1113 		<< "void main ()\n"
1114 		<< "{\n"
1115 		<< "    const uint trianglesPerInvocation = " << trianglesPerInvocation << "u;\n"
1116 		<< "    const uint numVertices = " << kNumVertices << "u;\n"
1117 		<< "    const uint numTriangles = " << kNumTriangles << "u;\n"
1118 		<< "    const float fNumTriangles = float(numTriangles);\n"
1119 		<< "    SetMeshOutputsEXT(numVertices, numTriangles);\n"
1120 		<< "    uint firstTriangle = trianglesPerInvocation * gl_LocalInvocationIndex;\n"
1121 		<< "    for (uint i = 0u; i < trianglesPerInvocation; i++) {\n"
1122 		<< "        uint triangleId = firstTriangle + i;\n"
1123 		<< "        if (triangleId < numTriangles) {\n"
1124 		<< "            uint vertexId = triangleId + 2u;\n"
1125 		<< "            float angleProportion = float(vertexId - 1u) / fNumTriangles;\n"
1126 		<< "            float angle = PI_2 * angleProportion;\n"
1127 		<< "            float xCoord = cos(angle) * RADIUS - 1.0;\n"
1128 		<< "            float yCoord = sin(angle) * RADIUS - 1.0;\n"
1129 		<< "            gl_MeshVerticesEXT[vertexId].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1130 		<< "            gl_PrimitiveTriangleIndicesEXT[triangleId] = uvec3(0u, triangleId + 1u, triangleId + 2u);\n"
1131 		<< "            triangleColor[triangleId] = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n"
1132 		<< "        } else {\n"
1133 		<< "            // The last iterations of the last invocation emit the first two vertices\n"
1134 		<< "            uint vertexId = triangleId - numTriangles;\n"
1135 		<< "            if (vertexId == 0u) {\n"
1136 		<< "                gl_MeshVerticesEXT[0u].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1137 		<< "            } else {\n"
1138 		<< "                gl_MeshVerticesEXT[1u].gl_Position = vec4(RADIUS, -1.0, 0.0, 1.0);\n"
1139 		<< "            }\n"
1140 		<< "        }\n"
1141 		<< "    }\n"
1142 		<< "}\n"
1143 		;
1144 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1145 }
1146 
generateReferenceLevel()1147 void MaxTrianglesInstance::generateReferenceLevel ()
1148 {
1149 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1150 }
1151 
1152 struct LargeWorkGroupParams : public MiscTestParams
1153 {
LargeWorkGroupParamsvkt::MeshShader::__anond8548dd90111::LargeWorkGroupParams1154 	LargeWorkGroupParams (const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_, const tcu::UVec3& localInvocations_)
1155 		: MiscTestParams	(taskCount_, meshCount_, width_, height_)
1156 		, localInvocations	(localInvocations_)
1157 	{}
1158 
1159 	tcu::UVec3 localInvocations;
1160 };
1161 
1162 // Large work groups with many threads.
1163 class LargeWorkGroupCase : public MeshShaderMiscCase
1164 {
1165 public:
LargeWorkGroupCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1166 					LargeWorkGroupCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1167 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1168 					{}
1169 
1170 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1171 	TestInstance*	createInstance			(Context& context) const override;
1172 };
1173 
1174 class LargeWorkGroupInstance : public MeshShaderMiscInstance
1175 {
1176 public:
LargeWorkGroupInstance(Context & context,const MiscTestParams * params)1177 	LargeWorkGroupInstance (Context& context, const MiscTestParams* params)
1178 		: MeshShaderMiscInstance (context, params)
1179 	{}
1180 
1181 	void	generateReferenceLevel	() override;
1182 };
1183 
createInstance(Context & context) const1184 TestInstance* LargeWorkGroupCase::createInstance (Context& context) const
1185 {
1186 	return new LargeWorkGroupInstance(context, m_params.get());
1187 }
1188 
generateReferenceLevel()1189 void LargeWorkGroupInstance::generateReferenceLevel ()
1190 {
1191 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1192 }
1193 
1194 // 'x', 'y' or 'z' depending on if dim is 0, 1 or 2, respectively.
dimSuffix(int dim)1195 char dimSuffix (int dim)
1196 {
1197 	const std::string suffixes = "xyz";
1198 	DE_ASSERT(dim >= 0 && dim < static_cast<int>(suffixes.size()));
1199 	return suffixes[dim];
1200 }
1201 
initPrograms(vk::SourceCollections & programCollection) const1202 void LargeWorkGroupCase::initPrograms (vk::SourceCollections& programCollection) const
1203 {
1204 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1205 	const auto params		= dynamic_cast<LargeWorkGroupParams*>(m_params.get());
1206 	DE_ASSERT(params);
1207 
1208 	const auto	totalInvocations	= params->localInvocations.x() * params->localInvocations.y() * params->localInvocations.z();
1209 	const auto	useTaskShader		= params->needsTaskShader();
1210 	uint32_t	taskMultiplier		= 1u;
1211 	const auto&	meshCount			= params->meshCount;
1212 	const auto	meshMultiplier		= meshCount.x() * meshCount.y() * meshCount.z();
1213 
1214 	if (useTaskShader)
1215 	{
1216 		const auto dim	= params->taskCount.get();
1217 		taskMultiplier	= dim.x() * dim.y() * dim.z();
1218 	}
1219 
1220 	// Add the frag shader.
1221 	MeshShaderMiscCase::initPrograms(programCollection);
1222 
1223 	std::ostringstream taskData;
1224 	taskData
1225 		<< "struct TaskData {\n"
1226 		<< "    uint parentTask[" << totalInvocations << "];\n"
1227 		<< "};\n"
1228 		<< "taskPayloadSharedEXT TaskData td;\n"
1229 		;
1230 	const auto taskDataStr = taskData.str();
1231 
1232 	const std::string localSizeStr = "layout ("
1233 		"local_size_x=" + std::to_string(params->localInvocations.x()) + ", "
1234 		"local_size_y=" + std::to_string(params->localInvocations.y()) + ", "
1235 		"local_size_z=" + std::to_string(params->localInvocations.z())
1236 		+ ") in;\n"
1237 		;
1238 
1239 	if (useTaskShader)
1240 	{
1241 		std::ostringstream task;
1242 		task
1243 			<< "#version 450\n"
1244 			<< "#extension GL_EXT_mesh_shader : enable\n"
1245 			<< "\n"
1246 			<< localSizeStr
1247 			<< "\n"
1248 			<< taskDataStr
1249 			<< "\n"
1250 			<< "void main () {\n"
1251 			<< "    const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1252 			<< "    td.parentTask[gl_LocalInvocationIndex] = workGroupIndex;\n"
1253 			<< "    EmitMeshTasksEXT(" << meshCount.x() << ", " << meshCount.y() << ", " << meshCount.z() << ");\n"
1254 			<< "}\n"
1255 			;
1256 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1257 	}
1258 
1259 	// Needed for the code below to work.
1260 	DE_ASSERT(params->width * params->height == taskMultiplier * meshMultiplier * totalInvocations);
1261 	DE_UNREF(taskMultiplier); // For release builds.
1262 
1263 	// Emit one point per framebuffer pixel. The number of jobs (params->localInvocations in each mesh shader work group, multiplied
1264 	// by the number of mesh work groups emitted by each task work group) must be the same as the total framebuffer size. Calculate
1265 	// a job ID corresponding to the current mesh shader invocation, and assign a pixel position to it. Draw a point at that
1266 	// position.
1267 	std::ostringstream mesh;
1268 	mesh
1269 		<< "#version 450\n"
1270 		<< "#extension GL_EXT_mesh_shader : enable\n"
1271 		<< "\n"
1272 		<< localSizeStr
1273 		<< "layout (points) out;\n"
1274 		<< "layout (max_vertices=" << totalInvocations << ", max_primitives=" << totalInvocations << ") out;\n"
1275 		<< "\n"
1276 		<< (useTaskShader ? taskDataStr : "")
1277 		<< "\n"
1278 		<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
1279 		<< "\n"
1280 		<< "void main () {\n"
1281 		<< "    uint parentTask = " << (useTaskShader ? "td.parentTask[0]" : "0") << ";\n";
1282 		;
1283 
1284 	if (useTaskShader)
1285 	{
1286 		mesh
1287 			<< "    if (td.parentTask[gl_LocalInvocationIndex] != parentTask || parentTask >= " << taskMultiplier << ") {\n"
1288 			<< "        return;\n"
1289 			<< "    }\n"
1290 			;
1291 	}
1292 
1293 	mesh
1294 		<< "    SetMeshOutputsEXT(" << totalInvocations << ", " << totalInvocations << ");\n"
1295 		<< "    const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1296 		<< "    uint jobId = ((parentTask * " << meshMultiplier << ") + workGroupIndex) * " << totalInvocations << " + gl_LocalInvocationIndex;\n"
1297 		<< "    uint row = jobId / " << params->width << ";\n"
1298 		<< "    uint col = jobId % " << params->width << ";\n"
1299 		<< "    float yCoord = (float(row + 0.5) / " << params->height << ".0) * 2.0 - 1.0;\n"
1300 		<< "    float xCoord = (float(col + 0.5) / " << params->width << ".0) * 2.0 - 1.0;\n"
1301 		<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1302 		<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_PointSize = 1.0;\n"
1303 		<< "    gl_PrimitivePointIndicesEXT[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
1304 		<< "    vec4 resultColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1305 		;
1306 
1307 	mesh
1308 		<< "    pointColor[gl_LocalInvocationIndex] = resultColor;\n"
1309 		<< "}\n"
1310 		;
1311 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1312 }
1313 
1314 // Tests that generate no primitives of a given type.
1315 enum class PrimitiveType { POINTS=0, LINES, TRIANGLES };
1316 
primitiveTypeName(PrimitiveType primitiveType)1317 std::string primitiveTypeName (PrimitiveType primitiveType)
1318 {
1319 	std::string primitiveName;
1320 
1321 	switch (primitiveType)
1322 	{
1323 	case PrimitiveType::POINTS:		primitiveName = "points";		break;
1324 	case PrimitiveType::LINES:		primitiveName = "lines";		break;
1325 	case PrimitiveType::TRIANGLES:	primitiveName = "triangles";	break;
1326 	default: DE_ASSERT(false); break;
1327 	}
1328 
1329 	return primitiveName;
1330 }
1331 
1332 struct NoPrimitivesParams : public MiscTestParams
1333 {
NoPrimitivesParamsvkt::MeshShader::__anond8548dd90111::NoPrimitivesParams1334 	NoPrimitivesParams (const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_, PrimitiveType primitiveType_)
1335 		: MiscTestParams	(taskCount_, meshCount_, width_, height_)
1336 		, primitiveType		(primitiveType_)
1337 		{}
1338 
1339 	PrimitiveType primitiveType;
1340 };
1341 
1342 class NoPrimitivesCase : public MeshShaderMiscCase
1343 {
1344 public:
NoPrimitivesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1345 					NoPrimitivesCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1346 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1347 					{}
1348 
1349 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1350 	TestInstance*	createInstance			(Context& context) const override;
1351 };
1352 
1353 class NoPrimitivesInstance : public MeshShaderMiscInstance
1354 {
1355 public:
NoPrimitivesInstance(Context & context,const MiscTestParams * params)1356 	NoPrimitivesInstance (Context& context, const MiscTestParams* params)
1357 		: MeshShaderMiscInstance (context, params)
1358 	{}
1359 
1360 	void	generateReferenceLevel	() override;
1361 };
1362 
generateReferenceLevel()1363 void NoPrimitivesInstance::generateReferenceLevel ()
1364 {
1365 	// No primitives: clear color.
1366 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
1367 }
1368 
createInstance(Context & context) const1369 TestInstance* NoPrimitivesCase::createInstance (Context& context) const
1370 {
1371 	return new NoPrimitivesInstance(context, m_params.get());
1372 }
1373 
initPrograms(vk::SourceCollections & programCollection) const1374 void NoPrimitivesCase::initPrograms (vk::SourceCollections& programCollection) const
1375 {
1376 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1377 	const auto params		= dynamic_cast<NoPrimitivesParams*>(m_params.get());
1378 
1379 	DE_ASSERT(params);
1380 	DE_ASSERT(!params->needsTaskShader());
1381 
1382 	const auto primitiveName = primitiveTypeName(params->primitiveType);
1383 
1384 	std::ostringstream mesh;
1385 	mesh
1386 		<< "#version 450\n"
1387 		<< "#extension GL_EXT_mesh_shader : enable\n"
1388 		<< "\n"
1389 		<< "layout (local_size_x=128) in;\n"
1390 		<< "layout (" << primitiveName << ") out;\n"
1391 		<< "layout (max_vertices=256, max_primitives=256) out;\n"
1392 		<< "\n"
1393 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
1394 		<< "\n"
1395 		<< "void main () {\n"
1396 		<< "    SetMeshOutputsEXT(0u, 0u);\n"
1397 		<< "}\n"
1398 		;
1399 
1400 	MeshShaderMiscCase::initPrograms(programCollection);
1401 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1402 }
1403 
1404 class NoPrimitivesExtraWritesCase : public NoPrimitivesCase
1405 {
1406 public:
NoPrimitivesExtraWritesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1407 					NoPrimitivesExtraWritesCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1408 						: NoPrimitivesCase (testCtx, name, std::move(params))
1409 					{}
1410 
1411 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1412 
1413 	static constexpr uint32_t kLocalInvocations = 128u;
1414 };
1415 
initPrograms(vk::SourceCollections & programCollection) const1416 void NoPrimitivesExtraWritesCase::initPrograms (vk::SourceCollections& programCollection) const
1417 {
1418 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1419 	const auto params		= dynamic_cast<NoPrimitivesParams*>(m_params.get());
1420 
1421 	DE_ASSERT(params);
1422 	DE_ASSERT(m_params->needsTaskShader());
1423 
1424 	std::ostringstream taskData;
1425 	taskData
1426 		<< "struct TaskData {\n"
1427 		<< "    uint localInvocations[" << kLocalInvocations << "];\n"
1428 		<< "};\n"
1429 		<< "taskPayloadSharedEXT TaskData td;\n"
1430 		;
1431 	const auto taskDataStr = taskData.str();
1432 
1433 	std::ostringstream task;
1434 	task
1435 		<< "#version 450\n"
1436 		<< "#extension GL_EXT_mesh_shader : enable\n"
1437 		<< "\n"
1438 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1439 		<< "\n"
1440 		<< taskDataStr
1441 		<< "\n"
1442 		<< "void main () {\n"
1443 		<< "    td.localInvocations[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
1444 		<< "    EmitMeshTasksEXT(" << params->meshCount.x() << ", " << params->meshCount.y() << ", " << params->meshCount.z() << ");\n"
1445 		<< "}\n"
1446 		;
1447 	programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1448 
1449 	const auto primitiveName = primitiveTypeName(params->primitiveType);
1450 
1451 	// Otherwise the shader would be illegal.
1452 	DE_ASSERT(kLocalInvocations > 2u);
1453 
1454 	uint32_t maxPrimitives = 0u;
1455 	switch (params->primitiveType)
1456 	{
1457 	case PrimitiveType::POINTS:		maxPrimitives = kLocalInvocations - 0u;	break;
1458 	case PrimitiveType::LINES:		maxPrimitives = kLocalInvocations - 1u;	break;
1459 	case PrimitiveType::TRIANGLES:	maxPrimitives = kLocalInvocations - 2u;	break;
1460 	default: DE_ASSERT(false); break;
1461 	}
1462 
1463 	const std::string pointSizeDecl	= ((params->primitiveType == PrimitiveType::POINTS)
1464 									? "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_PointSize = 1.0;\n"
1465 									: "");
1466 
1467 	std::ostringstream mesh;
1468 	mesh
1469 		<< "#version 450\n"
1470 		<< "#extension GL_EXT_mesh_shader : enable\n"
1471 		<< "\n"
1472 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1473 		<< "layout (" << primitiveName << ") out;\n"
1474 		<< "layout (max_vertices=" << kLocalInvocations << ", max_primitives=" << maxPrimitives << ") out;\n"
1475 		<< "\n"
1476 		<< taskDataStr
1477 		<< "\n"
1478 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
1479 		<< "\n"
1480 		<< "shared uint sumOfIds;\n"
1481 		<< "\n"
1482 		<< "const float PI_2 = 1.57079632679489661923;\n"
1483 		<< "const float RADIUS = 1.0f;\n"
1484 		<< "\n"
1485 		<< "void main ()\n"
1486 		<< "{\n"
1487 		<< "    sumOfIds = 0u;\n"
1488 		<< "    memoryBarrierShared();\n"
1489 		<< "    barrier();\n"
1490 		<< "    atomicAdd(sumOfIds, td.localInvocations[gl_LocalInvocationIndex]);\n"
1491 		<< "    memoryBarrierShared();\n"
1492 		<< "    barrier();\n"
1493 		<< "    // This should dynamically give 0\n"
1494 		<< "    uint primitiveCount = sumOfIds - (" << kLocalInvocations * (kLocalInvocations - 1u) / 2u << ");\n"
1495 		<< "    SetMeshOutputsEXT(primitiveCount, primitiveCount);\n"
1496 		<< "\n"
1497 		<< "    // Emit points and primitives to the arrays in any case\n"
1498 		<< "    if (gl_LocalInvocationIndex > 0u) {\n"
1499 		<< "        float proportion = (float(gl_LocalInvocationIndex - 1u) + 0.5f) / float(" << kLocalInvocations << " - 1u);\n"
1500 		<< "        float angle = PI_2 * proportion;\n"
1501 		<< "        float xCoord = cos(angle) * RADIUS - 1.0;\n"
1502 		<< "        float yCoord = sin(angle) * RADIUS - 1.0;\n"
1503 		<< "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1504 		<< pointSizeDecl
1505 		<< "    } else {\n"
1506 		<< "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1507 		<< pointSizeDecl
1508 		<< "    }\n"
1509 		<< "    uint primitiveId = max(gl_LocalInvocationIndex, " << (maxPrimitives - 1u) << ");\n"
1510 		<< "    primitiveColor[primitiveId] = vec4(0.0, 0.0, 1.0, 1.0);\n"
1511 		;
1512 
1513 	if (params->primitiveType == PrimitiveType::POINTS)
1514 		mesh << "    gl_PrimitivePointIndicesEXT[primitiveId] = primitiveId;\n";
1515 	else if (params->primitiveType == PrimitiveType::LINES)
1516 		mesh << "    gl_PrimitiveLineIndicesEXT[primitiveId] = uvec2(primitiveId + 0u, primitiveId + 1u);\n";
1517 	else if (params->primitiveType == PrimitiveType::TRIANGLES)
1518 		mesh << "    gl_PrimitiveTriangleIndicesEXT[primitiveId] = uvec3(0u, primitiveId + 1u, primitiveId + 3u);\n";
1519 	else
1520 		DE_ASSERT(false);
1521 
1522 	mesh << "}\n";
1523 
1524 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1525 
1526 	MeshShaderMiscCase::initPrograms(programCollection);
1527 }
1528 
1529 // Case testing barrier().
1530 class SimpleBarrierCase : public MeshShaderMiscCase
1531 {
1532 public:
SimpleBarrierCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1533 					SimpleBarrierCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1534 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1535 					{}
1536 
1537 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1538 	TestInstance*	createInstance			(Context& context) const override;
1539 
1540 	static constexpr uint32_t kLocalInvocations = 32u;
1541 };
1542 
1543 class SimpleBarrierInstance : public MeshShaderMiscInstance
1544 {
1545 public:
SimpleBarrierInstance(Context & context,const MiscTestParams * params)1546 	SimpleBarrierInstance (Context& context, const MiscTestParams* params)
1547 		: MeshShaderMiscInstance (context, params)
1548 	{}
1549 
1550 	void	generateReferenceLevel	() override;
1551 };
1552 
createInstance(Context & context) const1553 TestInstance* SimpleBarrierCase::createInstance (Context& context) const
1554 {
1555 	return new SimpleBarrierInstance(context, m_params.get());
1556 }
1557 
generateReferenceLevel()1558 void SimpleBarrierInstance::generateReferenceLevel ()
1559 {
1560 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1561 }
1562 
initPrograms(vk::SourceCollections & programCollection) const1563 void SimpleBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
1564 {
1565 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1566 
1567 	// Generate frag shader.
1568 	MeshShaderMiscCase::initPrograms(programCollection);
1569 
1570 	DE_ASSERT(m_params->meshCount == tcu::UVec3(1u, 1u, 1u));
1571 	DE_ASSERT(m_params->width == 1u && m_params->height == 1u);
1572 
1573 	const std::string taskOK		= "workGroupSize = uvec3(1u, 1u, 1u);\n";
1574 	const std::string taskFAIL		= "workGroupSize = uvec3(0u, 0u, 0u);\n";
1575 
1576 	const std::string meshOK		= "vertPrim = uvec2(1u, 1u);\n";
1577 	const std::string meshFAIL		= "vertPrim = uvec2(0u, 0u);\n";
1578 
1579 	const std::string okStatement	= (m_params->needsTaskShader() ? taskOK : meshOK);
1580 	const std::string failStatement	= (m_params->needsTaskShader() ? taskFAIL : meshFAIL);
1581 
1582 	const std::string	sharedDecl = "shared uint counter;\n\n";
1583 	std::ostringstream	verification;
1584 	verification
1585 		<< "counter = 0;\n"
1586 		<< "memoryBarrierShared();\n"
1587 		<< "barrier();\n"
1588 		<< "atomicAdd(counter, 1u);\n"
1589 		<< "memoryBarrierShared();\n"
1590 		<< "barrier();\n"
1591 		<< "if (gl_LocalInvocationIndex == 0u) {\n"
1592 		<< "    if (counter == " << kLocalInvocations << ") {\n"
1593 		<< "\n"
1594 		<< okStatement
1595 		<< "\n"
1596 		<< "    } else {\n"
1597 		<< "\n"
1598 		<< failStatement
1599 		<< "\n"
1600 		<< "    }\n"
1601 		<< "}\n"
1602 		;
1603 
1604 	// The mesh shader is very similar in both cases, so we use a template.
1605 	std::ostringstream meshTemplateStr;
1606 	meshTemplateStr
1607 		<< "#version 450\n"
1608 		<< "#extension GL_EXT_mesh_shader : enable\n"
1609 		<< "\n"
1610 		<< "layout (local_size_x=${LOCAL_SIZE}) in;\n"
1611 		<< "layout (points) out;\n"
1612 		<< "layout (max_vertices=1, max_primitives=1) out;\n"
1613 		<< "\n"
1614 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
1615 		<< "\n"
1616 		<< "${GLOBALS:opt}"
1617 		<< "void main ()\n"
1618 		<< "{\n"
1619 		<< "    uvec2 vertPrim = uvec2(0u, 0u);\n"
1620 		<< "${BODY}"
1621 		<< "    SetMeshOutputsEXT(vertPrim.x, vertPrim.y);\n"
1622 		<< "    if (gl_LocalInvocationIndex == 0u && vertPrim.x > 0u) {\n"
1623 		<< "        gl_MeshVerticesEXT[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1624 		<< "        gl_MeshVerticesEXT[0].gl_PointSize = 1.0;\n"
1625 		<< "        primitiveColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
1626 		<< "        gl_PrimitivePointIndicesEXT[0] = 0;\n"
1627 		<< "    }\n"
1628 		<< "}\n"
1629 		;
1630 	const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
1631 
1632 	if (m_params->needsTaskShader())
1633 	{
1634 		std::ostringstream task;
1635 		task
1636 			<< "#version 450\n"
1637 			<< "#extension GL_EXT_mesh_shader : enable\n"
1638 			<< "\n"
1639 			<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1640 			<< "\n"
1641 			<< sharedDecl
1642 			<< "void main ()\n"
1643 			<< "{\n"
1644 			<< "    uvec3 workGroupSize = uvec3(0u, 0u, 0u);\n"
1645 			<< verification.str()
1646 			<< "    EmitMeshTasksEXT(workGroupSize.x, workGroupSize.y, workGroupSize.z);\n"
1647 			<< "}\n"
1648 			;
1649 
1650 		std::map<std::string, std::string> replacements;
1651 		replacements["LOCAL_SIZE"]	= "1";
1652 		replacements["BODY"]		= meshOK;
1653 
1654 		const auto meshStr = meshTemplate.specialize(replacements);
1655 
1656 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1657 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr) << buildOptions;
1658 	}
1659 	else
1660 	{
1661 		std::map<std::string, std::string> replacements;
1662 		replacements["LOCAL_SIZE"]	= std::to_string(kLocalInvocations);
1663 		replacements["BODY"]		= verification.str();
1664 		replacements["GLOBALS"]		= sharedDecl;
1665 
1666 		const auto meshStr = meshTemplate.specialize(replacements);
1667 
1668 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr) << buildOptions;
1669 	}
1670 }
1671 
1672 // Case testing memoryBarrierShared() and groupMemoryBarrier().
1673 enum class MemoryBarrierType { SHARED = 0, GROUP };
1674 
1675 struct MemoryBarrierParams : public MiscTestParams
1676 {
MemoryBarrierParamsvkt::MeshShader::__anond8548dd90111::MemoryBarrierParams1677 	MemoryBarrierParams (const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_, MemoryBarrierType memBarrierType_)
1678 		: MiscTestParams	(taskCount_, meshCount_, width_, height_)
1679 		, memBarrierType	(memBarrierType_)
1680 	{}
1681 
1682 	MemoryBarrierType memBarrierType;
1683 
glslFuncvkt::MeshShader::__anond8548dd90111::MemoryBarrierParams1684 	std::string glslFunc () const
1685 	{
1686 		std::string funcName;
1687 
1688 		switch (memBarrierType)
1689 		{
1690 		case MemoryBarrierType::SHARED:		funcName = "memoryBarrierShared";	break;
1691 		case MemoryBarrierType::GROUP:		funcName = "groupMemoryBarrier";	break;
1692 		default: DE_ASSERT(false); break;
1693 		}
1694 
1695 		return funcName;
1696 	}
1697 
1698 };
1699 
1700 class MemoryBarrierCase : public MeshShaderMiscCase
1701 {
1702 public:
MemoryBarrierCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1703 					MemoryBarrierCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1704 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1705 					{}
1706 
1707 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1708 	TestInstance*	createInstance			(Context& context) const override;
1709 
1710 	static constexpr uint32_t kLocalInvocations = 2u;
1711 };
1712 
1713 class MemoryBarrierInstance : public MeshShaderMiscInstance
1714 {
1715 public:
MemoryBarrierInstance(Context & context,const MiscTestParams * params)1716 	MemoryBarrierInstance (Context& context, const MiscTestParams* params)
1717 		: MeshShaderMiscInstance (context, params)
1718 	{}
1719 
1720 	void	generateReferenceLevel	() override;
1721 	bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess) const override;
1722 
1723 protected:
1724 	// Allow two possible outcomes.
1725 	std::unique_ptr<tcu::TextureLevel>	m_referenceLevel2;
1726 };
1727 
createInstance(Context & context) const1728 TestInstance* MemoryBarrierCase::createInstance (Context& context) const
1729 {
1730 	return new MemoryBarrierInstance(context, m_params.get());
1731 }
1732 
generateReferenceLevel()1733 void MemoryBarrierInstance::generateReferenceLevel ()
1734 {
1735 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1736 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), m_referenceLevel2);
1737 }
1738 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess) const1739 bool MemoryBarrierInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
1740 {
1741 	// Any of the two results is considered valid.
1742 	constexpr auto Message		= tcu::TestLog::Message;
1743 	constexpr auto EndMessage	= tcu::TestLog::EndMessage;
1744 
1745 	// Clarify what we are checking in the logs; otherwise, they could be confusing.
1746 	auto& log = m_context.getTestContext().getLog();
1747 	const std::vector<tcu::TextureLevel*> levels = { m_referenceLevel.get(), m_referenceLevel2.get() };
1748 
1749 	bool good = false;
1750 	for (size_t i = 0; i < levels.size(); ++i)
1751 	{
1752 		log << Message << "Comparing result with reference " << i << "..." << EndMessage;
1753 		const auto success = MeshShaderMiscInstance::verifyResult(resultAccess, *levels[i]);
1754 		if (success)
1755 		{
1756 			log << Message << "Match! The test has passed" << EndMessage;
1757 			good = true;
1758 			break;
1759 		}
1760 	}
1761 
1762 	return good;
1763 }
1764 
initPrograms(vk::SourceCollections & programCollection) const1765 void MemoryBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
1766 {
1767 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1768 	const auto params		= dynamic_cast<MemoryBarrierParams*>(m_params.get());
1769 	DE_ASSERT(params);
1770 
1771 	// Generate frag shader.
1772 	MeshShaderMiscCase::initPrograms(programCollection);
1773 
1774 	DE_ASSERT(params->meshCount == tcu::UVec3(1u, 1u, 1u));
1775 	DE_ASSERT(params->width == 1u && params->height == 1u);
1776 
1777 	const bool taskShader = params->needsTaskShader();
1778 
1779 	const std::string	taskDataDecl	= "struct TaskData { float blue; }; taskPayloadSharedEXT TaskData td;\n\n";
1780 	const auto			barrierFunc		= params->glslFunc();
1781 
1782 	const std::string taskAction	= "td.blue = float(iterations % 2u);\nworkGroupSize = uvec3(1u, 1u, 1u);\n";
1783 	const std::string meshAction	= "vertPrim = uvec2(1u, 1u);\n";
1784 	const std::string action		= (taskShader ? taskAction : meshAction);
1785 
1786 	const std::string	sharedDecl = "shared uint flags[2];\n\n";
1787 	std::ostringstream	verification;
1788 	verification
1789 		<< "flags[gl_LocalInvocationIndex] = 0u;\n"
1790 		<< "barrier();\n"
1791 		<< "flags[gl_LocalInvocationIndex] = 1u;\n"
1792 		<<  barrierFunc << "();\n"
1793 		<< "uint otherInvocation = 1u - gl_LocalInvocationIndex;\n"
1794 		<< "uint iterations = 0u;\n"
1795 		<< "while (flags[otherInvocation] != 1u) {\n"
1796 		<< "    iterations++;\n"
1797 		<< "}\n"
1798 		<< "if (gl_LocalInvocationIndex == 0u) {\n"
1799 		<< "\n"
1800 		<< action
1801 		<< "\n"
1802 		<< "}\n"
1803 		;
1804 
1805 	// The mesh shader is very similar in both cases, so we use a template.
1806 	std::ostringstream meshTemplateStr;
1807 	meshTemplateStr
1808 		<< "#version 450\n"
1809 		<< "#extension GL_EXT_mesh_shader : enable\n"
1810 		<< "\n"
1811 		<< "layout (local_size_x=${LOCAL_SIZE}) in;\n"
1812 		<< "layout (points) out;\n"
1813 		<< "layout (max_vertices=1, max_primitives=1) out;\n"
1814 		<< "\n"
1815 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
1816 		<< "\n"
1817 		<< "${GLOBALS}"
1818 		<< "void main ()\n"
1819 		<< "{\n"
1820 		<< "    uvec2 vertPrim = uvec2(0u, 0u);\n"
1821 		<< "${BODY}"
1822 		<< "    SetMeshOutputsEXT(vertPrim.x, vertPrim.y);\n"
1823 		<< "    if (gl_LocalInvocationIndex == 0u && vertPrim.x > 0u) {\n"
1824 		<< "        gl_MeshVerticesEXT[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1825 		<< "        gl_MeshVerticesEXT[0].gl_PointSize = 1.0;\n"
1826 		<< "        primitiveColor[0] = vec4(0.0, 0.0, ${BLUE}, 1.0);\n"
1827 		<< "        gl_PrimitivePointIndicesEXT[0] = 0;\n"
1828 		<< "    }\n"
1829 		<< "}\n"
1830 		;
1831 	const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
1832 
1833 	if (params->needsTaskShader())
1834 	{
1835 		std::ostringstream task;
1836 		task
1837 			<< "#version 450\n"
1838 			<< "#extension GL_EXT_mesh_shader : enable\n"
1839 			<< "\n"
1840 			<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1841 			<< "\n"
1842 			<< sharedDecl
1843 			<< taskDataDecl
1844 			<< "void main ()\n"
1845 			<< "{\n"
1846 			<< "    uvec3 workGroupSize = uvec3(0u, 0u, 0u);\n"
1847 			<< verification.str()
1848 			<< "    EmitMeshTasksEXT(workGroupSize.x, workGroupSize.y, workGroupSize.z);\n"
1849 			<< "}\n"
1850 			;
1851 
1852 		std::map<std::string, std::string> replacements;
1853 		replacements["LOCAL_SIZE"]	= "1";
1854 		replacements["BODY"]		= meshAction;
1855 		replacements["GLOBALS"]		= taskDataDecl;
1856 		replacements["BLUE"]		= "td.blue";
1857 
1858 		const auto meshStr = meshTemplate.specialize(replacements);
1859 
1860 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1861 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr) << buildOptions;
1862 	}
1863 	else
1864 	{
1865 		std::map<std::string, std::string> replacements;
1866 		replacements["LOCAL_SIZE"]	= std::to_string(kLocalInvocations);
1867 		replacements["BODY"]		= verification.str();
1868 		replacements["GLOBALS"]		= sharedDecl;
1869 		replacements["BLUE"]		= "float(iterations % 2u)";
1870 
1871 		const auto meshStr = meshTemplate.specialize(replacements);
1872 
1873 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr) << buildOptions;
1874 	}
1875 }
1876 
1877 // Test the task payload can be read by all invocations in the work group.
1878 class PayloadReadCase : public MeshShaderMiscCase
1879 {
1880 public:
PayloadReadCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)1881 					PayloadReadCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
1882 						: MeshShaderMiscCase (testCtx, name, std::move(params))
1883 					{}
1884 
1885 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1886 	TestInstance*	createInstance			(Context& context) const override;
1887 
1888 	static constexpr uint32_t kLocalInvocations = 128u;
1889 };
1890 
1891 class PayloadReadInstance : public MeshShaderMiscInstance
1892 {
1893 public:
PayloadReadInstance(Context & context,const MiscTestParams * params)1894 	PayloadReadInstance (Context& context, const MiscTestParams* params)
1895 		: MeshShaderMiscInstance (context, params)
1896 	{}
1897 
1898 	void	generateReferenceLevel	() override;
1899 };
1900 
createInstance(Context & context) const1901 TestInstance* PayloadReadCase::createInstance (Context &context) const
1902 {
1903 	return new PayloadReadInstance(context, m_params.get());
1904 }
1905 
initPrograms(vk::SourceCollections & programCollection) const1906 void PayloadReadCase::initPrograms (vk::SourceCollections &programCollection) const
1907 {
1908 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1909 
1910 	// Add default fragment shader.
1911 	MeshShaderMiscCase::initPrograms(programCollection);
1912 
1913 	std::ostringstream taskPayload;
1914 	taskPayload
1915 		<< "struct TaskData {\n"
1916 		<< "    uint verificationCodes[" << kLocalInvocations << "];\n"
1917 		<< "    vec4 color;\n"
1918 		<< "};\n"
1919 		<< "taskPayloadSharedEXT TaskData td;\n"
1920 		;
1921 	const std::string taskPayloadDecl = taskPayload.str();
1922 
1923 	DE_ASSERT(m_params->needsTaskShader());
1924 
1925 	const auto& meshCount = m_params->meshCount;
1926 	DE_ASSERT(meshCount.x() == 1u && meshCount.y() == 1u && meshCount.z() == 1u);
1927 
1928 	const auto kLocalInvocations2 = kLocalInvocations * 2u;
1929 
1930 	std::ostringstream task;
1931 	task
1932 		<< "#version 450\n"
1933 		<< "#extension GL_EXT_mesh_shader : enable\n"
1934 		<< "\n"
1935 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1936 		<< "\n"
1937 		<< taskPayloadDecl
1938 		<< "shared uint verificationOK[" << kLocalInvocations << "];\n"
1939 		<< "\n"
1940 		<< "void main ()\n"
1941 		<< "{\n"
1942 		<< "    td.verificationCodes[gl_LocalInvocationIndex] = (" << kLocalInvocations2 << " - gl_LocalInvocationIndex);\n"
1943 		<< "    memoryBarrierShared();\n"
1944 		<< "    barrier();\n"
1945 		// Verify all codes from all invocations.
1946 		<< "    uint verificationResult = 1u;\n"
1947 		<< "    for (uint i = 0u; i < " << kLocalInvocations << "; ++i) {\n"
1948 		<< "        if (td.verificationCodes[i] != (" << kLocalInvocations2 << " - i)) {\n"
1949 		<< "            verificationResult = 0u;\n"
1950 		<< "            break;\n"
1951 		<< "        }\n"
1952 		<< "    }\n"
1953 		<< "    verificationOK[gl_LocalInvocationIndex] = verificationResult;\n"
1954 		<< "    memoryBarrierShared();\n"
1955 		<< "    barrier();\n"
1956 		// Check all verifications were OK (from the first invocation).
1957 		<< "    if (gl_LocalInvocationIndex == 0u) {\n"
1958 		<< "        vec4 color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1959 		<< "        for (uint i = 0u; i < " << kLocalInvocations << "; ++i) {\n"
1960 		<< "            if (verificationOK[i] == 0u) {\n"
1961 		<< "                color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1962 		<< "            }\n"
1963 		<< "        }\n"
1964 		<< "        td.color = color;\n"
1965 		<< "    }\n"
1966 		<< "    EmitMeshTasksEXT(" << meshCount.x() << ", " << meshCount.y() << ", " << meshCount.z() << ");\n"
1967 		<< "}\n"
1968 		;
1969 	programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1970 
1971 	std::ostringstream mesh;
1972 	mesh
1973 		<< "#version 450\n"
1974 		<< "#extension GL_EXT_mesh_shader : enable\n"
1975 		<< "\n"
1976 		<< "layout (local_size_x=1) in;\n"
1977 		<< "layout (triangles) out;\n"
1978 		<< "layout (max_vertices=3, max_primitives=1) out;\n"
1979 		<< "\n"
1980 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
1981 		<< taskPayloadDecl
1982 		<< "\n"
1983 		<< "void main ()\n"
1984 		<< "{\n"
1985 		// Verify data one more time from the mesh shader invocation.
1986 		<< "    uint verificationResult = 1u;\n"
1987 		<< "    for (uint i = 0u; i < " << kLocalInvocations << "; ++i) {\n"
1988 		<< "        if (td.verificationCodes[i] != (" << kLocalInvocations2 << " - i)) {\n"
1989 		<< "            verificationResult = 0u;\n"
1990 		<< "            break;\n"
1991 		<< "        }\n"
1992 		<< "    }\n"
1993 		<< "    const vec4 finalColor = ((verificationResult == 0u) ? vec4(0.0, 0.0, 0.0, 1.0) : td.color);\n"
1994 		<< "\n"
1995 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
1996 		<< "\n"
1997 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1998 		<< "    gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1999 		<< "    gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
2000 		<< "\n"
2001 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
2002 		<< "    primitiveColor[0] = finalColor;\n"
2003 		<< "}\n"
2004 		;
2005 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
2006 }
2007 
generateReferenceLevel()2008 void PayloadReadInstance::generateReferenceLevel ()
2009 {
2010 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
2011 }
2012 
2013 // Test with custom per-vertex and per-primitive attributes of different types.
2014 class CustomAttributesCase : public MeshShaderMiscCase
2015 {
2016 public:
CustomAttributesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)2017 					CustomAttributesCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
2018 						: MeshShaderMiscCase(testCtx, name, std::move(params)) {}
~CustomAttributesCase(void)2019 	virtual			~CustomAttributesCase		(void) {}
2020 
2021 	TestInstance*	createInstance				(Context& context) const override;
2022 	void			checkSupport				(Context& context) const override;
2023 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
2024 };
2025 
2026 class CustomAttributesInstance : public MeshShaderMiscInstance
2027 {
2028 public:
CustomAttributesInstance(Context & context,const MiscTestParams * params)2029 						CustomAttributesInstance	(Context& context, const MiscTestParams* params)
2030 							: MeshShaderMiscInstance(context, params) {}
~CustomAttributesInstance(void)2031 	virtual				~CustomAttributesInstance	(void) {}
2032 
2033 	void				generateReferenceLevel		() override;
2034 	tcu::TestStatus		iterate						(void) override;
2035 };
2036 
createInstance(Context & context) const2037 TestInstance* CustomAttributesCase::createInstance (Context& context) const
2038 {
2039 	return new CustomAttributesInstance(context, m_params.get());
2040 }
2041 
checkSupport(Context & context) const2042 void CustomAttributesCase::checkSupport (Context& context) const
2043 {
2044 	MeshShaderMiscCase::checkSupport(context);
2045 
2046 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
2047 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
2048 }
2049 
initPrograms(vk::SourceCollections & programCollection) const2050 void CustomAttributesCase::initPrograms (vk::SourceCollections& programCollection) const
2051 {
2052 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
2053 
2054 	std::ostringstream frag;
2055 	frag
2056 		<< "#version 450\n"
2057 		<< "#extension GL_EXT_mesh_shader : enable\n"
2058 		<< "\n"
2059 		<< "layout (location=0) in vec4 customAttribute1;\n"
2060 		<< "layout (location=1) in flat float customAttribute2;\n"
2061 		<< "layout (location=2) in flat int customAttribute3;\n"
2062 		<< "\n"
2063 		<< "layout (location=3) in perprimitiveEXT flat uvec4 customAttribute4;\n"
2064 		<< "layout (location=4) in perprimitiveEXT float customAttribute5;\n"
2065 		<< "\n"
2066 		<< "layout (location=0) out vec4 outColor;\n"
2067 		<< "\n"
2068 		<< "void main ()\n"
2069 		<< "{\n"
2070 		<< "    bool goodPrimitiveID = (gl_PrimitiveID == 1000 || gl_PrimitiveID == 1001);\n"
2071 		<< "    bool goodViewportIndex = (gl_ViewportIndex == 1);\n"
2072 		<< "    bool goodCustom1 = (customAttribute1.x >= 0.25 && customAttribute1.x <= 0.5 &&\n"
2073 		<< "                        customAttribute1.y >= 0.5  && customAttribute1.y <= 1.0 &&\n"
2074 		<< "                        customAttribute1.z >= 10.0 && customAttribute1.z <= 20.0 &&\n"
2075 		<< "                        customAttribute1.w == 3.0);\n"
2076 		<< "    bool goodCustom2 = (customAttribute2 == 1.0 || customAttribute2 == 2.0);\n"
2077 		<< "    bool goodCustom3 = (customAttribute3 == 3 || customAttribute3 == 4);\n"
2078 		<< "    bool goodCustom4 = ((gl_PrimitiveID == 1000 && customAttribute4 == uvec4(100, 101, 102, 103)) ||\n"
2079 		<< "                        (gl_PrimitiveID == 1001 && customAttribute4 == uvec4(200, 201, 202, 203)));\n"
2080 		<< "    bool goodCustom5 = ((gl_PrimitiveID == 1000 && customAttribute5 == 6.0) ||\n"
2081 		<< "                        (gl_PrimitiveID == 1001 && customAttribute5 == 7.0));\n"
2082 		<< "    \n"
2083 		<< "    if (goodPrimitiveID && goodViewportIndex && goodCustom1 && goodCustom2 && goodCustom3 && goodCustom4 && goodCustom5) {\n"
2084 		<< "        outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
2085 		<< "    } else {\n"
2086 		<< "        outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
2087 		<< "    }\n"
2088 		<< "}\n"
2089 		;
2090 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str()) << buildOptions;
2091 
2092 	std::ostringstream pvdDataDeclStream;
2093 	pvdDataDeclStream
2094 		<< "    vec4 positions[4];\n"
2095 		<< "    float pointSizes[4];\n"
2096 		<< "    float clipDistances[4];\n"
2097 		<< "    vec4 custom1[4];\n"
2098 		<< "    float custom2[4];\n"
2099 		<< "    int custom3[4];\n"
2100 		;
2101 	const auto pvdDataDecl = pvdDataDeclStream.str();
2102 
2103 	std::ostringstream ppdDataDeclStream;
2104 	ppdDataDeclStream
2105 		<< "    int primitiveIds[2];\n"
2106 		<< "    int viewportIndices[2];\n"
2107 		<< "    uvec4 custom4[2];\n"
2108 		<< "    float custom5[2];\n"
2109 		;
2110 	const auto ppdDataDecl = ppdDataDeclStream.str();
2111 
2112 	std::ostringstream bindingsDeclStream;
2113 	bindingsDeclStream
2114 		<< "layout (set=0, binding=0, std430) buffer PerVertexData {\n"
2115 		<< pvdDataDecl
2116 		<< "} pvd;\n"
2117 		<< "layout (set=0, binding=1) uniform PerPrimitiveData {\n"
2118 		<< ppdDataDecl
2119 		<< "} ppd;\n"
2120 		<< "\n"
2121 		;
2122 	const auto bindingsDecl = bindingsDeclStream.str();
2123 
2124 	std::ostringstream taskDataStream;
2125 	taskDataStream
2126 		<< "struct TaskData {\n"
2127 		<< pvdDataDecl
2128 		<< ppdDataDecl
2129 		<< "};\n"
2130 		<< "taskPayloadSharedEXT TaskData td;\n"
2131 		<< "\n"
2132 		;
2133 	const auto taskDataDecl = taskDataStream.str();
2134 
2135 	const auto taskShader = m_params->needsTaskShader();
2136 
2137 	const auto meshPvdPrefix = (taskShader ? "td" : "pvd");
2138 	const auto meshPpdPrefix = (taskShader ? "td" : "ppd");
2139 
2140 	std::ostringstream mesh;
2141 	mesh
2142 		<< "#version 450\n"
2143 		<< "#extension GL_EXT_mesh_shader : enable\n"
2144 		<< "\n"
2145 		<< "layout (local_size_x=1) in;\n"
2146 		<< "layout (max_primitives=2, max_vertices=4) out;\n"
2147 		<< "layout (triangles) out;\n"
2148 		<< "\n"
2149 		<< "out gl_MeshPerVertexEXT {\n"
2150 		<< "    vec4  gl_Position;\n"
2151 		<< "    float gl_PointSize;\n"
2152 		<< "    float gl_ClipDistance[1];\n"
2153 		<< "} gl_MeshVerticesEXT[];\n"
2154 		<< "\n"
2155 		<< "layout (location=0) out vec4 customAttribute1[];\n"
2156 		<< "layout (location=1) out flat float customAttribute2[];\n"
2157 		<< "layout (location=2) out int customAttribute3[];\n"
2158 		<< "\n"
2159 		<< "layout (location=3) out perprimitiveEXT uvec4 customAttribute4[];\n"
2160 		<< "layout (location=4) out perprimitiveEXT float customAttribute5[];\n"
2161 		<< "\n"
2162 		<< "out perprimitiveEXT gl_MeshPerPrimitiveEXT {\n"
2163 		<< "  int gl_PrimitiveID;\n"
2164 		<< "  int gl_ViewportIndex;\n"
2165 		<< "} gl_MeshPrimitivesEXT[];\n"
2166 		<< "\n"
2167 		<< (taskShader ? taskDataDecl : bindingsDecl)
2168 		<< "void main ()\n"
2169 		<< "{\n"
2170 		<< "    SetMeshOutputsEXT(4u, 2u);\n"
2171 		<< "\n"
2172 		<< "    gl_MeshVerticesEXT[0].gl_Position = " << meshPvdPrefix << ".positions[0]; //vec4(-1.0, -1.0, 0.0, 1.0)\n"
2173 		<< "    gl_MeshVerticesEXT[1].gl_Position = " << meshPvdPrefix << ".positions[1]; //vec4( 1.0, -1.0, 0.0, 1.0)\n"
2174 		<< "    gl_MeshVerticesEXT[2].gl_Position = " << meshPvdPrefix << ".positions[2]; //vec4(-1.0,  1.0, 0.0, 1.0)\n"
2175 		<< "    gl_MeshVerticesEXT[3].gl_Position = " << meshPvdPrefix << ".positions[3]; //vec4( 1.0,  1.0, 0.0, 1.0)\n"
2176 		<< "\n"
2177 		<< "    gl_MeshVerticesEXT[0].gl_PointSize = " << meshPvdPrefix << ".pointSizes[0]; //1.0\n"
2178 		<< "    gl_MeshVerticesEXT[1].gl_PointSize = " << meshPvdPrefix << ".pointSizes[1]; //1.0\n"
2179 		<< "    gl_MeshVerticesEXT[2].gl_PointSize = " << meshPvdPrefix << ".pointSizes[2]; //1.0\n"
2180 		<< "    gl_MeshVerticesEXT[3].gl_PointSize = " << meshPvdPrefix << ".pointSizes[3]; //1.0\n"
2181 		<< "\n"
2182 		<< "    // Remove geometry on the right side.\n"
2183 		<< "    gl_MeshVerticesEXT[0].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[0]; // 1.0\n"
2184 		<< "    gl_MeshVerticesEXT[1].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[1]; //-1.0\n"
2185 		<< "    gl_MeshVerticesEXT[2].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[2]; // 1.0\n"
2186 		<< "    gl_MeshVerticesEXT[3].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[3]; //-1.0\n"
2187 		<< "    \n"
2188 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
2189 		<< "    gl_PrimitiveTriangleIndicesEXT[1] = uvec3(2, 3, 1);\n"
2190 		<< "\n"
2191 		<< "    gl_MeshPrimitivesEXT[0].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[0]; //1000\n"
2192 		<< "    gl_MeshPrimitivesEXT[1].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[1]; //1001\n"
2193 		<< "\n"
2194 		<< "    gl_MeshPrimitivesEXT[0].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[0]; //1\n"
2195 		<< "    gl_MeshPrimitivesEXT[1].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[1]; //1\n"
2196 		<< "\n"
2197 		<< "    // Custom per-vertex attributes\n"
2198 		<< "    customAttribute1[0] = " << meshPvdPrefix << ".custom1[0]; //vec4(0.25, 0.5, 10.0, 3.0)\n"
2199 		<< "    customAttribute1[1] = " << meshPvdPrefix << ".custom1[1]; //vec4(0.25, 1.0, 20.0, 3.0)\n"
2200 		<< "    customAttribute1[2] = " << meshPvdPrefix << ".custom1[2]; //vec4( 0.5, 0.5, 20.0, 3.0)\n"
2201 		<< "    customAttribute1[3] = " << meshPvdPrefix << ".custom1[3]; //vec4( 0.5, 1.0, 10.0, 3.0)\n"
2202 		<< "\n"
2203 		<< "    customAttribute2[0] = " << meshPvdPrefix << ".custom2[0]; //1.0f\n"
2204 		<< "    customAttribute2[1] = " << meshPvdPrefix << ".custom2[1]; //1.0f\n"
2205 		<< "    customAttribute2[2] = " << meshPvdPrefix << ".custom2[2]; //2.0f\n"
2206 		<< "    customAttribute2[3] = " << meshPvdPrefix << ".custom2[3]; //2.0f\n"
2207 		<< "\n"
2208 		<< "    customAttribute3[0] = " << meshPvdPrefix << ".custom3[0]; //3\n"
2209 		<< "    customAttribute3[1] = " << meshPvdPrefix << ".custom3[1]; //3\n"
2210 		<< "    customAttribute3[2] = " << meshPvdPrefix << ".custom3[2]; //4\n"
2211 		<< "    customAttribute3[3] = " << meshPvdPrefix << ".custom3[3]; //4\n"
2212 		<< "\n"
2213 		<< "    // Custom per-primitive attributes.\n"
2214 		<< "    customAttribute4[0] = " << meshPpdPrefix << ".custom4[0]; //uvec4(100, 101, 102, 103)\n"
2215 		<< "    customAttribute4[1] = " << meshPpdPrefix << ".custom4[1]; //uvec4(200, 201, 202, 203)\n"
2216 		<< "\n"
2217 		<< "    customAttribute5[0] = " << meshPpdPrefix << ".custom5[0]; //6.0\n"
2218 		<< "    customAttribute5[1] = " << meshPpdPrefix << ".custom5[1]; //7.0\n"
2219 		<< "}\n"
2220 		;
2221 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
2222 
2223 	if (taskShader)
2224 	{
2225 		const auto& meshCount = m_params->meshCount;
2226 		std::ostringstream task;
2227 		task
2228 			<< "#version 450\n"
2229 			<< "#extension GL_EXT_mesh_shader : enable\n"
2230 			<< "\n"
2231 			<< taskDataDecl
2232 			<< bindingsDecl
2233 			<< "void main ()\n"
2234 			<< "{\n"
2235 			<< "    td.positions[0] = pvd.positions[0];\n"
2236 			<< "    td.positions[1] = pvd.positions[1];\n"
2237 			<< "    td.positions[2] = pvd.positions[2];\n"
2238 			<< "    td.positions[3] = pvd.positions[3];\n"
2239 			<< "\n"
2240 			<< "    td.pointSizes[0] = pvd.pointSizes[0];\n"
2241 			<< "    td.pointSizes[1] = pvd.pointSizes[1];\n"
2242 			<< "    td.pointSizes[2] = pvd.pointSizes[2];\n"
2243 			<< "    td.pointSizes[3] = pvd.pointSizes[3];\n"
2244 			<< "\n"
2245 			<< "    td.clipDistances[0] = pvd.clipDistances[0];\n"
2246 			<< "    td.clipDistances[1] = pvd.clipDistances[1];\n"
2247 			<< "    td.clipDistances[2] = pvd.clipDistances[2];\n"
2248 			<< "    td.clipDistances[3] = pvd.clipDistances[3];\n"
2249 			<< "\n"
2250 			<< "    td.custom1[0] = pvd.custom1[0];\n"
2251 			<< "    td.custom1[1] = pvd.custom1[1];\n"
2252 			<< "    td.custom1[2] = pvd.custom1[2];\n"
2253 			<< "    td.custom1[3] = pvd.custom1[3];\n"
2254 			<< "\n"
2255 			<< "    td.custom2[0] = pvd.custom2[0];\n"
2256 			<< "    td.custom2[1] = pvd.custom2[1];\n"
2257 			<< "    td.custom2[2] = pvd.custom2[2];\n"
2258 			<< "    td.custom2[3] = pvd.custom2[3];\n"
2259 			<< "\n"
2260 			<< "    td.custom3[0] = pvd.custom3[0];\n"
2261 			<< "    td.custom3[1] = pvd.custom3[1];\n"
2262 			<< "    td.custom3[2] = pvd.custom3[2];\n"
2263 			<< "    td.custom3[3] = pvd.custom3[3];\n"
2264 			<< "\n"
2265 			<< "    td.primitiveIds[0] = ppd.primitiveIds[0];\n"
2266 			<< "    td.primitiveIds[1] = ppd.primitiveIds[1];\n"
2267 			<< "\n"
2268 			<< "    td.viewportIndices[0] = ppd.viewportIndices[0];\n"
2269 			<< "    td.viewportIndices[1] = ppd.viewportIndices[1];\n"
2270 			<< "\n"
2271 			<< "    td.custom4[0] = ppd.custom4[0];\n"
2272 			<< "    td.custom4[1] = ppd.custom4[1];\n"
2273 			<< "\n"
2274 			<< "    td.custom5[0] = ppd.custom5[0];\n"
2275 			<< "    td.custom5[1] = ppd.custom5[1];\n"
2276 			<< "\n"
2277 			<< "    EmitMeshTasksEXT(" << meshCount.x() << ", " << meshCount.y() << ", " << meshCount.z() << ");\n"
2278 			<< "}\n"
2279 			;
2280 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
2281 	}
2282 }
2283 
generateReferenceLevel()2284 void CustomAttributesInstance::generateReferenceLevel ()
2285 {
2286 	const auto format		= getOutputFormat();
2287 	const auto tcuFormat	= mapVkFormat(format);
2288 
2289 	const auto iWidth		= static_cast<int>(m_params->width);
2290 	const auto iHeight		= static_cast<int>(m_params->height);
2291 
2292 	const auto halfWidth	= iWidth / 2;
2293 	const auto halfHeight	= iHeight / 2;
2294 
2295 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
2296 
2297 	const auto access		= m_referenceLevel->getAccess();
2298 	const auto clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
2299 	const auto blueColor	= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2300 
2301 	tcu::clear(access, clearColor);
2302 
2303 	// Fill the top left quarter.
2304 	for (int y = 0; y < halfWidth; ++y)
2305 	for (int x = 0; x < halfHeight; ++x)
2306 	{
2307 		access.setPixel(blueColor, x, y);
2308 	}
2309 }
2310 
iterate()2311 tcu::TestStatus CustomAttributesInstance::iterate ()
2312 {
2313 	struct PerVertexData
2314 	{
2315 		tcu::Vec4	positions[4];
2316 		float		pointSizes[4];
2317 		float		clipDistances[4];
2318 		tcu::Vec4	custom1[4];
2319 		float		custom2[4];
2320 		int32_t		custom3[4];
2321 	};
2322 
2323 	struct PerPrimitiveData
2324 	{
2325 		// Note some of these are declared as vectors to match the std140 layout.
2326 		tcu::IVec4	primitiveIds[2];
2327 		tcu::IVec4	viewportIndices[2];
2328 		tcu::UVec4	custom4[2];
2329 		tcu::Vec4	custom5[2];
2330 	};
2331 
2332 	const auto&		vkd			= m_context.getDeviceInterface();
2333 	const auto		device		= m_context.getDevice();
2334 	auto&			alloc		= m_context.getDefaultAllocator();
2335 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
2336 	const auto		queue		= m_context.getUniversalQueue();
2337 
2338 	const auto		imageFormat	= getOutputFormat();
2339 	const auto		tcuFormat	= mapVkFormat(imageFormat);
2340 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
2341 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2342 
2343 	const auto&		binaries	= m_context.getBinaryCollection();
2344 	const auto		hasTask		= binaries.contains("task");
2345 	const auto		bufStages	= (hasTask ? VK_SHADER_STAGE_TASK_BIT_EXT : VK_SHADER_STAGE_MESH_BIT_EXT);
2346 
2347 	const VkImageCreateInfo colorBufferInfo =
2348 	{
2349 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2350 		nullptr,								//	const void*				pNext;
2351 		0u,										//	VkImageCreateFlags		flags;
2352 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2353 		imageFormat,							//	VkFormat				format;
2354 		imageExtent,							//	VkExtent3D				extent;
2355 		1u,										//	uint32_t				mipLevels;
2356 		1u,										//	uint32_t				arrayLayers;
2357 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2358 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2359 		imageUsage,								//	VkImageUsageFlags		usage;
2360 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2361 		0u,										//	uint32_t				queueFamilyIndexCount;
2362 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2363 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2364 	};
2365 
2366 	// Create color image and view.
2367 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
2368 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2369 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2370 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2371 
2372 	// Create a memory buffer for verification.
2373 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
2374 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2375 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
2376 
2377 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
2378 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
2379 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
2380 
2381 	// This needs to match what the fragment shader will expect.
2382 	const PerVertexData perVertexData =
2383 	{
2384 		//	tcu::Vec4	positions[4];
2385 		{
2386 			tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2387 			tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
2388 			tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
2389 			tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
2390 		},
2391 		//	float		pointSizes[4];
2392 		{ 1.0f, 1.0f, 1.0f, 1.0f, },
2393 		//	float		clipDistances[4];
2394 		{
2395 			1.0f,
2396 			-1.0f,
2397 			1.0f,
2398 			-1.0f,
2399 		},
2400 		//	tcu::Vec4	custom1[4];
2401 		{
2402 			tcu::Vec4(0.25, 0.5, 10.0, 3.0),
2403 			tcu::Vec4(0.25, 1.0, 20.0, 3.0),
2404 			tcu::Vec4( 0.5, 0.5, 20.0, 3.0),
2405 			tcu::Vec4( 0.5, 1.0, 10.0, 3.0),
2406 		},
2407 		//	float		custom2[4];
2408 		{ 1.0f, 1.0f, 2.0f, 2.0f, },
2409 		//	int32_t		custom3[4];
2410 		{ 3, 3, 4, 4 },
2411 	};
2412 
2413 	// This needs to match what the fragment shader will expect. Reminder: some of these are declared as gvec4 to match the std140
2414 	// layout, but only the first component is actually used.
2415 	const PerPrimitiveData perPrimitiveData =
2416 	{
2417 		//	int			primitiveIds[2];
2418 		{
2419 			tcu::IVec4(1000, 0, 0, 0),
2420 			tcu::IVec4(1001, 0, 0, 0),
2421 		},
2422 		//	int			viewportIndices[2];
2423 		{
2424 			tcu::IVec4(1, 0, 0, 0),
2425 			tcu::IVec4(1, 0, 0, 0),
2426 		},
2427 		//	uvec4		custom4[2];
2428 		{
2429 			tcu::UVec4(100u, 101u, 102u, 103u),
2430 			tcu::UVec4(200u, 201u, 202u, 203u),
2431 		},
2432 		//	float		custom5[2];
2433 		{
2434 			tcu::Vec4(6.0f, 0.0f, 0.0f, 0.0f),
2435 			tcu::Vec4(7.0f, 0.0f, 0.0f, 0.0f),
2436 		},
2437 	};
2438 
2439 	// Create and fill buffers with this data.
2440 	const auto			pvdSize		= static_cast<VkDeviceSize>(sizeof(perVertexData));
2441 	const auto			pvdInfo		= makeBufferCreateInfo(pvdSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2442 	BufferWithMemory	pvdData		(vkd, device, alloc, pvdInfo, MemoryRequirement::HostVisible);
2443 	auto&				pvdAlloc	= pvdData.getAllocation();
2444 	void*				pvdPtr		= pvdAlloc.getHostPtr();
2445 
2446 	const auto			ppdSize		= static_cast<VkDeviceSize>(sizeof(perPrimitiveData));
2447 	const auto			ppdInfo		= makeBufferCreateInfo(ppdSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
2448 	BufferWithMemory	ppdData		(vkd, device, alloc, ppdInfo, MemoryRequirement::HostVisible);
2449 	auto&				ppdAlloc	= ppdData.getAllocation();
2450 	void*				ppdPtr		= ppdAlloc.getHostPtr();
2451 
2452 	deMemcpy(pvdPtr, &perVertexData, sizeof(perVertexData));
2453 	deMemcpy(ppdPtr, &perPrimitiveData, sizeof(perPrimitiveData));
2454 
2455 	flushAlloc(vkd, device, pvdAlloc);
2456 	flushAlloc(vkd, device, ppdAlloc);
2457 
2458 	// Descriptor set layout.
2459 	DescriptorSetLayoutBuilder setLayoutBuilder;
2460 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bufStages);
2461 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bufStages);
2462 	const auto setLayout = setLayoutBuilder.build(vkd, device);
2463 
2464 	// Create and update descriptor set.
2465 	DescriptorPoolBuilder descriptorPoolBuilder;
2466 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2467 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
2468 	const auto descriptorPool	= descriptorPoolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2469 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2470 
2471 	DescriptorSetUpdateBuilder updateBuilder;
2472 	const auto storageBufferInfo = makeDescriptorBufferInfo(pvdData.get(), 0ull, pvdSize);
2473 	const auto uniformBufferInfo = makeDescriptorBufferInfo(ppdData.get(), 0ull, ppdSize);
2474 	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
2475 	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo);
2476 	updateBuilder.update(vkd, device);
2477 
2478 	// Pipeline layout.
2479 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2480 
2481 	// Shader modules.
2482 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
2483 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
2484 
2485 	Move<VkShaderModule> taskShader;
2486 	if (hasTask)
2487 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
2488 
2489 	// Render pass.
2490 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2491 
2492 	// Framebuffer.
2493 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
2494 
2495 	// Viewport and scissor.
2496 	const auto						topHalf		= makeViewport(imageExtent.width, imageExtent.height / 2u);
2497 	const std::vector<VkViewport>	viewports	{ makeViewport(imageExtent), topHalf };
2498 	const std::vector<VkRect2D>		scissors	(2u, makeRect2D(imageExtent));
2499 
2500 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2501 		taskShader.get(), meshShader.get(), fragShader.get(),
2502 		renderPass.get(), viewports, scissors);
2503 
2504 	// Command pool and buffer.
2505 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2506 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2507 	const auto cmdBuffer	= cmdBufferPtr.get();
2508 
2509 	beginCommandBuffer(vkd, cmdBuffer);
2510 
2511 	// Run pipeline.
2512 	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 0.0f);
2513 	const auto		drawCount	= m_params->drawCount();
2514 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2515 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2516 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2517 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
2518 	endRenderPass(vkd, cmdBuffer);
2519 
2520 	// Copy color buffer to verification buffer.
2521 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2522 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
2523 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
2524 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
2525 
2526 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
2527 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
2528 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
2529 
2530 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
2531 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2532 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
2533 
2534 	endCommandBuffer(vkd, cmdBuffer);
2535 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2536 
2537 	// Generate reference image and compare results.
2538 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
2539 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
2540 
2541 	generateReferenceLevel();
2542 	invalidateAlloc(vkd, device, verificationBufferAlloc);
2543 	if (!verifyResult(verificationAccess))
2544 		TCU_FAIL("Result does not match reference; check log for details");
2545 
2546 	return tcu::TestStatus::pass("Pass");
2547 }
2548 
2549 // Tests that use push constants in the new stages.
2550 class PushConstantCase : public MeshShaderMiscCase
2551 {
2552 public:
PushConstantCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)2553 					PushConstantCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
2554 						: MeshShaderMiscCase (testCtx, name, std::move(params))
2555 					{}
2556 
2557 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
2558 	TestInstance*	createInstance			(Context& context) const override;
2559 };
2560 
2561 class PushConstantInstance : public MeshShaderMiscInstance
2562 {
2563 public:
PushConstantInstance(Context & context,const MiscTestParams * params)2564 	PushConstantInstance (Context& context, const MiscTestParams* params)
2565 		: MeshShaderMiscInstance (context, params)
2566 	{}
2567 
2568 	void			generateReferenceLevel	() override;
2569 	tcu::TestStatus	iterate					() override;
2570 };
2571 
createInstance(Context & context) const2572 TestInstance* PushConstantCase::createInstance (Context& context) const
2573 {
2574 	return new PushConstantInstance(context, m_params.get());
2575 }
2576 
generateReferenceLevel()2577 void PushConstantInstance::generateReferenceLevel ()
2578 {
2579 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
2580 }
2581 
initPrograms(vk::SourceCollections & programCollection) const2582 void PushConstantCase::initPrograms (vk::SourceCollections& programCollection) const
2583 {
2584 	const auto buildOptions		= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
2585 	const auto useTaskShader	= m_params->needsTaskShader();
2586 	const auto pcNumFloats		= (useTaskShader ? 2u : 4u);
2587 
2588 	std::ostringstream pushConstantStream;
2589 	pushConstantStream
2590 		<< "layout (push_constant, std430) uniform PushConstantBlock {\n"
2591 		<< "    layout (offset=${PCOFFSET}) float values[" << pcNumFloats << "];\n"
2592 		<< "} pc;\n"
2593 		<< "\n"
2594 		;
2595 	const tcu::StringTemplate pushConstantsTemplate (pushConstantStream.str());
2596 	using TemplateMap = std::map<std::string, std::string>;
2597 
2598 	std::ostringstream taskDataStream;
2599 	taskDataStream
2600 		<< "struct TaskData {\n"
2601 		<< "    float values[2];\n"
2602 		<< "};\n"
2603 		<< "taskPayloadSharedEXT TaskData td;\n"
2604 		<< "\n"
2605 		;
2606 	const auto taskDataDecl = taskDataStream.str();
2607 
2608 	if (useTaskShader)
2609 	{
2610 		TemplateMap taskMap;
2611 		taskMap["PCOFFSET"] = std::to_string(2u * sizeof(float));
2612 
2613 		const auto& meshCount = m_params->meshCount;
2614 		std::ostringstream task;
2615 		task
2616 			<< "#version 450\n"
2617 			<< "#extension GL_EXT_mesh_shader : enable\n"
2618 			<< "\n"
2619 			<< "layout(local_size_x=1) in;\n"
2620 			<< "\n"
2621 			<< taskDataDecl
2622 			<< pushConstantsTemplate.specialize(taskMap)
2623 			<< "void main ()\n"
2624 			<< "{\n"
2625 			<< "    td.values[0] = pc.values[0];\n"
2626 			<< "    td.values[1] = pc.values[1];\n"
2627 			<< "\n"
2628 			<< "    EmitMeshTasksEXT(" << meshCount.x() << ", " << meshCount.y() << ", " << meshCount.z() << ");\n"
2629 			<< "}\n"
2630 			;
2631 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
2632 	}
2633 
2634 	{
2635 		const std::string blue	= (useTaskShader ? "td.values[0] + pc.values[0]" : "pc.values[0] + pc.values[2]");
2636 		const std::string alpha	= (useTaskShader ? "td.values[1] + pc.values[1]" : "pc.values[1] + pc.values[3]");
2637 
2638 		TemplateMap meshMap;
2639 		meshMap["PCOFFSET"] = "0";
2640 
2641 		std::ostringstream mesh;
2642 		mesh
2643 			<< "#version 450\n"
2644 			<< "#extension GL_EXT_mesh_shader : enable\n"
2645 			<< "\n"
2646 			<< "layout(local_size_x=1) in;\n"
2647 			<< "layout(triangles) out;\n"
2648 			<< "layout(max_vertices=3, max_primitives=1) out;\n"
2649 			<< "\n"
2650 			<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
2651 			<< "\n"
2652 			<< pushConstantsTemplate.specialize(meshMap)
2653 			<< (useTaskShader ? taskDataDecl : "")
2654 			<< "void main ()\n"
2655 			<< "{\n"
2656 			<< "    SetMeshOutputsEXT(3u, 1u);\n"
2657 			<< "\n"
2658 			<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
2659 			<< "    gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
2660 			<< "    gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
2661 			<< "\n"
2662 			<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
2663 			<< "    triangleColor[0] = vec4(0.0, 0.0, " << blue << ", " << alpha << ");\n"
2664 			<< "}\n"
2665 			;
2666 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
2667 	}
2668 
2669 	// Add default fragment shader.
2670 	MeshShaderMiscCase::initPrograms(programCollection);
2671 }
2672 
iterate()2673 tcu::TestStatus PushConstantInstance::iterate ()
2674 {
2675 	const auto&		vkd			= m_context.getDeviceInterface();
2676 	const auto		device		= m_context.getDevice();
2677 	auto&			alloc		= m_context.getDefaultAllocator();
2678 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
2679 	const auto		queue		= m_context.getUniversalQueue();
2680 
2681 	const auto		imageFormat	= getOutputFormat();
2682 	const auto		tcuFormat	= mapVkFormat(imageFormat);
2683 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
2684 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2685 
2686 	const auto&		binaries	= m_context.getBinaryCollection();
2687 	const auto		hasTask		= binaries.contains("task");
2688 
2689 	const VkImageCreateInfo colorBufferInfo =
2690 	{
2691 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2692 		nullptr,								//	const void*				pNext;
2693 		0u,										//	VkImageCreateFlags		flags;
2694 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2695 		imageFormat,							//	VkFormat				format;
2696 		imageExtent,							//	VkExtent3D				extent;
2697 		1u,										//	uint32_t				mipLevels;
2698 		1u,										//	uint32_t				arrayLayers;
2699 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2700 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2701 		imageUsage,								//	VkImageUsageFlags		usage;
2702 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2703 		0u,										//	uint32_t				queueFamilyIndexCount;
2704 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2705 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2706 	};
2707 
2708 	// Create color image and view.
2709 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
2710 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2711 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2712 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2713 
2714 	// Create a memory buffer for verification.
2715 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
2716 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2717 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
2718 
2719 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
2720 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
2721 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
2722 
2723 	// Push constant ranges.
2724 	std::vector<float> pcData { 0.25f, 0.25f, 0.75f, 0.75f };
2725 	const auto pcSize		= static_cast<uint32_t>(de::dataSize(pcData));
2726 	const auto pcHalfSize	= pcSize / 2u;
2727 
2728 	std::vector<VkPushConstantRange> pcRanges;
2729 	if (hasTask)
2730 	{
2731 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_EXT, 0u, pcHalfSize));
2732 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_TASK_BIT_EXT, pcHalfSize, pcHalfSize));
2733 	}
2734 	else
2735 	{
2736 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_EXT, 0u, pcSize));
2737 	}
2738 
2739 	// Pipeline layout.
2740 	const auto pipelineLayout = makePipelineLayout(vkd, device, 0u, nullptr, static_cast<uint32_t>(pcRanges.size()), de::dataOrNull(pcRanges));
2741 
2742 	// Shader modules.
2743 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
2744 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
2745 
2746 	Move<VkShaderModule> taskShader;
2747 	if (hasTask)
2748 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
2749 
2750 	// Render pass.
2751 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2752 
2753 	// Framebuffer.
2754 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
2755 
2756 	// Viewport and scissor.
2757 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
2758 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
2759 
2760 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2761 		taskShader.get(), meshShader.get(), fragShader.get(),
2762 		renderPass.get(), viewports, scissors);
2763 
2764 	// Command pool and buffer.
2765 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2766 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2767 	const auto cmdBuffer	= cmdBufferPtr.get();
2768 
2769 	beginCommandBuffer(vkd, cmdBuffer);
2770 
2771 	// Run pipeline.
2772 	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 0.0f);
2773 	const auto		drawCount	= m_params->drawCount();
2774 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2775 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2776 	for (const auto& range : pcRanges)
2777 		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), range.stageFlags, range.offset, range.size, reinterpret_cast<const char*>(pcData.data()) + range.offset);
2778 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
2779 	endRenderPass(vkd, cmdBuffer);
2780 
2781 	// Copy color buffer to verification buffer.
2782 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2783 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
2784 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
2785 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
2786 
2787 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
2788 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
2789 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
2790 
2791 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
2792 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2793 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
2794 
2795 	endCommandBuffer(vkd, cmdBuffer);
2796 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2797 
2798 	// Generate reference image and compare results.
2799 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
2800 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
2801 
2802 	generateReferenceLevel();
2803 	invalidateAlloc(vkd, device, verificationBufferAlloc);
2804 	if (!verifyResult(verificationAccess))
2805 		TCU_FAIL("Result does not match reference; check log for details");
2806 
2807 	return tcu::TestStatus::pass("Pass");
2808 }
2809 
2810 // Use large work group size, large number of vertices and large number of primitives.
2811 struct MaximizeThreadsParams : public MiscTestParams
2812 {
MaximizeThreadsParamsvkt::MeshShader::__anond8548dd90111::MaximizeThreadsParams2813 	MaximizeThreadsParams	(const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_,
2814 							 uint32_t localSize_, uint32_t numVertices_, uint32_t numPrimitives_)
2815 		: MiscTestParams	(taskCount_, meshCount_, width_, height_)
2816 		, localSize			(localSize_)
2817 		, numVertices		(numVertices_)
2818 		, numPrimitives		(numPrimitives_)
2819 		{}
2820 
2821 	uint32_t localSize;
2822 	uint32_t numVertices;
2823 	uint32_t numPrimitives;
2824 
checkSupportvkt::MeshShader::__anond8548dd90111::MaximizeThreadsParams2825 	void checkSupport (Context& context) const
2826 	{
2827 		const auto& properties = context.getMeshShaderPropertiesEXT();
2828 
2829 		if (localSize > properties.maxMeshWorkGroupSize[0])
2830 			TCU_THROW(NotSupportedError, "Required local size not supported");
2831 
2832 		if (numVertices > properties.maxMeshOutputVertices)
2833 			TCU_THROW(NotSupportedError, "Required number of output vertices not supported");
2834 
2835 		if (numPrimitives > properties.maxMeshOutputPrimitives)
2836 			TCU_THROW(NotSupportedError, "Required number of output primitives not supported");
2837 	}
2838 };
2839 
2840 // Focus on the number of primitives.
2841 class MaximizePrimitivesCase : public MeshShaderMiscCase
2842 {
2843 public:
MaximizePrimitivesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)2844 					MaximizePrimitivesCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
2845 						: MeshShaderMiscCase (testCtx, name, std::move(params))
2846 					{
2847 						const auto mtParams = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2848 						DE_ASSERT(mtParams);
2849 						DE_UNREF(mtParams); // For release builds.
2850 					}
2851 
2852 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
2853 	void			checkSupport			(Context& context) const override;
2854 	TestInstance*	createInstance			(Context& context) const override;
2855 };
2856 
2857 class MaximizePrimitivesInstance : public MeshShaderMiscInstance
2858 {
2859 public:
MaximizePrimitivesInstance(Context & context,const MiscTestParams * params)2860 	MaximizePrimitivesInstance (Context& context, const MiscTestParams* params)
2861 		: MeshShaderMiscInstance (context, params)
2862 	{}
2863 
2864 	void	generateReferenceLevel	() override;
2865 };
2866 
createInstance(Context & context) const2867 TestInstance* MaximizePrimitivesCase::createInstance (Context& context) const
2868 {
2869 	return new MaximizePrimitivesInstance (context, m_params.get());
2870 }
2871 
checkSupport(Context & context) const2872 void MaximizePrimitivesCase::checkSupport (Context& context) const
2873 {
2874 	MeshShaderMiscCase::checkSupport(context);
2875 
2876 	const auto params = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2877 	params->checkSupport(context);
2878 }
2879 
initPrograms(vk::SourceCollections & programCollection) const2880 void MaximizePrimitivesCase::initPrograms (vk::SourceCollections& programCollection) const
2881 {
2882 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
2883 	const auto params		= dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2884 
2885 	DE_ASSERT(!params->needsTaskShader());
2886 	MeshShaderMiscCase::initPrograms(programCollection);
2887 
2888 	// Idea behind the test: generate 128 vertices, 1 per each pixel in a 128x1 image. Then, use each vertex to generate two points,
2889 	// adding the colors of each point using color blending to make sure every point is properly generated.
2890 
2891 	DE_ASSERT(params->numPrimitives == params->numVertices * 2u);
2892 	DE_ASSERT(params->numVertices == params->width);
2893 
2894 	const auto verticesPerInvocation	= params->numVertices / params->localSize;
2895 	const auto primitivesPerVertex		= params->numPrimitives / params->numVertices;
2896 
2897 	std::ostringstream mesh;
2898 	mesh
2899 		<< "#version 450\n"
2900 		<< "#extension GL_EXT_mesh_shader : enable\n"
2901 		<< "\n"
2902 		<< "layout(local_size_x=" << params->localSize << ") in;\n"
2903 		<< "layout(points) out;\n"
2904 		<< "layout(max_vertices=" << params->numVertices << ", max_primitives=" << params->numPrimitives << ") out;\n"
2905 		<< "\n"
2906 		<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
2907 		<< "\n"
2908 		<< "const uint verticesPerInvocation = " << verticesPerInvocation << ";\n"
2909 		<< "const uint primitivesPerVertex   = " << primitivesPerVertex << ";\n"
2910 		<< "\n"
2911 		<< "vec4 colors[primitivesPerVertex] = vec4[](\n"
2912 		<< "    vec4(0.0, 0.0, 1.0, 1.0),\n"
2913 		<< "    vec4(1.0, 0.0, 0.0, 1.0)\n"
2914 		<< ");\n"
2915 		<< "void main ()\n"
2916 		<< "{\n"
2917 		<< "    SetMeshOutputsEXT(" << params->numVertices << ", " << params->numPrimitives << ");\n"
2918 		<< "    const uint firstVertex = gl_LocalInvocationIndex * verticesPerInvocation;\n"
2919 		<< "    for (uint i = 0u; i < verticesPerInvocation; ++i)\n"
2920 		<< "    {\n"
2921 		<< "        const uint vertexNumber = firstVertex + i;\n"
2922 		<< "        const float xCoord = ((float(vertexNumber) + 0.5) / " << params->width << ".0) * 2.0 - 1.0;\n"
2923 		<< "        const float yCoord = 0.0;\n"
2924 		<< "        gl_MeshVerticesEXT[vertexNumber].gl_Position = vec4(xCoord, yCoord, 0.0f, 1.0f);\n"
2925 		<< "        gl_MeshVerticesEXT[vertexNumber].gl_PointSize = 1.0f;\n"
2926 		<< "        for (uint j = 0u; j < primitivesPerVertex; ++j)\n"
2927 		<< "        {\n"
2928 		<< "            const uint primitiveNumber = vertexNumber * primitivesPerVertex + j;\n"
2929 		<< "            gl_PrimitivePointIndicesEXT[primitiveNumber] = vertexNumber;\n"
2930 		<< "            pointColor[primitiveNumber] = colors[j];\n"
2931 		<< "        }\n"
2932 		<< "    }\n"
2933 		<< "}\n"
2934 		;
2935 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
2936 }
2937 
generateReferenceLevel()2938 void MaximizePrimitivesInstance::generateReferenceLevel ()
2939 {
2940 	generateSolidRefLevel(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
2941 }
2942 
2943 // Focus on the number of vertices.
2944 class MaximizeVerticesCase : public MeshShaderMiscCase
2945 {
2946 public:
MaximizeVerticesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)2947 					MaximizeVerticesCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
2948 						: MeshShaderMiscCase (testCtx, name, std::move(params))
2949 					{
2950 						const auto mtParams = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2951 						DE_ASSERT(mtParams);
2952 						DE_UNREF(mtParams); // For release builds.
2953 					}
2954 
2955 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
2956 	void			checkSupport			(Context& context) const override;
2957 	TestInstance*	createInstance			(Context& context) const override;
2958 };
2959 
2960 class MaximizeVerticesInstance : public MeshShaderMiscInstance
2961 {
2962 public:
MaximizeVerticesInstance(Context & context,const MiscTestParams * params)2963 	MaximizeVerticesInstance (Context& context, const MiscTestParams* params)
2964 		: MeshShaderMiscInstance (context, params)
2965 	{}
2966 
2967 	void	generateReferenceLevel	() override;
2968 };
2969 
createInstance(Context & context) const2970 TestInstance* MaximizeVerticesCase::createInstance (Context& context) const
2971 {
2972 	return new MaximizeVerticesInstance (context, m_params.get());
2973 }
2974 
checkSupport(Context & context) const2975 void MaximizeVerticesCase::checkSupport (Context& context) const
2976 {
2977 	MeshShaderMiscCase::checkSupport(context);
2978 
2979 	const auto params = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2980 	params->checkSupport(context);
2981 }
2982 
initPrograms(vk::SourceCollections & programCollection) const2983 void MaximizeVerticesCase::initPrograms (vk::SourceCollections& programCollection) const
2984 {
2985 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
2986 	const auto params		= dynamic_cast<MaximizeThreadsParams*>(m_params.get());
2987 
2988 	DE_ASSERT(!params->needsTaskShader());
2989 	MeshShaderMiscCase::initPrograms(programCollection);
2990 
2991 	// Idea behind the test: cover a framebuffer using a triangle quad per pixel (4 vertices, 2 triangles).
2992 	DE_ASSERT(params->numVertices == params->numPrimitives * 2u);
2993 	DE_ASSERT(params->numPrimitives == params->width * 2u);
2994 
2995 	const auto pixelsPerInvocation		= params->width / params->localSize;
2996 	const auto verticesPerPixel			= 4u;
2997 	const auto primitivesPerPixel		= 2u;
2998 	const auto verticesPerInvocation	= pixelsPerInvocation * verticesPerPixel;
2999 	const auto primitivesPerInvocation	= pixelsPerInvocation * primitivesPerPixel;
3000 
3001 	std::ostringstream mesh;
3002 	mesh
3003 		<< "#version 450\n"
3004 		<< "#extension GL_EXT_mesh_shader : enable\n"
3005 		<< "\n"
3006 		<< "layout(local_size_x=" << params->localSize << ") in;\n"
3007 		<< "layout(triangles) out;\n"
3008 		<< "layout(max_vertices=" << params->numVertices << ", max_primitives=" << params->numPrimitives << ") out;\n"
3009 		<< "\n"
3010 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
3011 		<< "\n"
3012 		<< "const uint pixelsPerInvocation     = " << pixelsPerInvocation << ";\n"
3013 		<< "const uint verticesPerInvocation   = " << verticesPerInvocation << ";\n"
3014 		<< "const uint primitivesPerInvocation = " << primitivesPerInvocation << ";\n"
3015 		<< "const uint indicesPerInvocation    = primitivesPerInvocation * 3u;\n"
3016 		<< "const uint verticesPerPixel        = " << verticesPerPixel << ";\n"
3017 		<< "const uint primitivesPerPixel      = " << primitivesPerPixel << ";\n"
3018 		<< "const uint indicesPerPixel         = primitivesPerPixel * 3u;\n"
3019 		<< "\n"
3020 		<< "void main ()\n"
3021 		<< "{\n"
3022 		<< "    SetMeshOutputsEXT(" << params->numVertices << ", " << params->numPrimitives << ");\n"
3023 		<< "\n"
3024 		<< "    const uint firstPixel    = gl_LocalInvocationIndex * pixelsPerInvocation;\n"
3025 		<< "    const float pixelWidth   = 2.0 / float(" << params->width << ");\n"
3026 		<< "    const float quarterWidth = pixelWidth / 4.0;\n"
3027 		<< "\n"
3028 		<< "    for (uint pixelIdx = 0u; pixelIdx < pixelsPerInvocation; ++pixelIdx)\n"
3029 		<< "    {\n"
3030 		<< "        const uint pixelId      = firstPixel + pixelIdx;\n"
3031 		<< "        const float pixelCenter = (float(pixelId) + 0.5) / float(" << params->width << ") * 2.0 - 1.0;\n"
3032 		<< "        const float left        = pixelCenter - quarterWidth;\n"
3033 		<< "        const float right       = pixelCenter + quarterWidth;\n"
3034 		<< "\n"
3035 		<< "        const uint firstVertex = gl_LocalInvocationIndex * verticesPerInvocation + pixelIdx * verticesPerPixel;\n"
3036 		<< "        gl_MeshVerticesEXT[firstVertex + 0].gl_Position = vec4(left,  -1.0, 0.0f, 1.0f);\n"
3037 		<< "        gl_MeshVerticesEXT[firstVertex + 1].gl_Position = vec4(left,   1.0, 0.0f, 1.0f);\n"
3038 		<< "        gl_MeshVerticesEXT[firstVertex + 2].gl_Position = vec4(right, -1.0, 0.0f, 1.0f);\n"
3039 		<< "        gl_MeshVerticesEXT[firstVertex + 3].gl_Position = vec4(right,  1.0, 0.0f, 1.0f);\n"
3040 		<< "\n"
3041 		<< "        const uint firstPrimitive = gl_LocalInvocationIndex * primitivesPerInvocation + pixelIdx * primitivesPerPixel;\n"
3042 		<< "        triangleColor[firstPrimitive + 0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
3043 		<< "        triangleColor[firstPrimitive + 1] = vec4(0.0, 0.0, 1.0, 1.0);\n"
3044 		<< "\n"
3045 		<< "        const uint firstIndex = gl_LocalInvocationIndex * indicesPerInvocation + pixelIdx * indicesPerPixel;\n"
3046 		<< "        gl_PrimitiveTriangleIndicesEXT[firstPrimitive + 0] = uvec3(firstVertex + 0, firstVertex + 1, firstVertex + 2);\n"
3047 		<< "        gl_PrimitiveTriangleIndicesEXT[firstPrimitive + 1] = uvec3(firstVertex + 1, firstVertex + 3, firstVertex + 2);\n"
3048 		<< "    }\n"
3049 		<< "}\n"
3050 		;
3051 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
3052 }
3053 
generateReferenceLevel()3054 void MaximizeVerticesInstance::generateReferenceLevel ()
3055 {
3056 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
3057 }
3058 
3059 // Focus on the number of invocations.
3060 class MaximizeInvocationsCase : public MeshShaderMiscCase
3061 {
3062 public:
MaximizeInvocationsCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)3063 					MaximizeInvocationsCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
3064 						: MeshShaderMiscCase (testCtx, name, std::move(params))
3065 					{
3066 						const auto mtParams = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
3067 						DE_ASSERT(mtParams);
3068 						DE_UNREF(mtParams); // For release builds.
3069 					}
3070 
3071 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
3072 	void			checkSupport			(Context& context) const override;
3073 	TestInstance*	createInstance			(Context& context) const override;
3074 };
3075 
3076 class MaximizeInvocationsInstance : public MeshShaderMiscInstance
3077 {
3078 public:
MaximizeInvocationsInstance(Context & context,const MiscTestParams * params)3079 	MaximizeInvocationsInstance (Context& context, const MiscTestParams* params)
3080 		: MeshShaderMiscInstance (context, params)
3081 	{}
3082 
3083 	void	generateReferenceLevel	() override;
3084 };
3085 
createInstance(Context & context) const3086 TestInstance* MaximizeInvocationsCase::createInstance (Context& context) const
3087 {
3088 	return new MaximizeInvocationsInstance (context, m_params.get());
3089 }
3090 
checkSupport(Context & context) const3091 void MaximizeInvocationsCase::checkSupport (Context& context) const
3092 {
3093 	MeshShaderMiscCase::checkSupport(context);
3094 
3095 	const auto params = dynamic_cast<MaximizeThreadsParams*>(m_params.get());
3096 	params->checkSupport(context);
3097 }
3098 
initPrograms(vk::SourceCollections & programCollection) const3099 void MaximizeInvocationsCase::initPrograms (vk::SourceCollections& programCollection) const
3100 {
3101 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
3102 	const auto params		= dynamic_cast<MaximizeThreadsParams*>(m_params.get());
3103 
3104 	DE_ASSERT(!params->needsTaskShader());
3105 	MeshShaderMiscCase::initPrograms(programCollection);
3106 
3107 	// Idea behind the test: use two invocations to generate one point per framebuffer pixel.
3108 	DE_ASSERT(params->localSize == params->width * 2u);
3109 	DE_ASSERT(params->localSize == params->numPrimitives * 2u);
3110 	DE_ASSERT(params->localSize == params->numVertices * 2u);
3111 
3112 	std::ostringstream mesh;
3113 	mesh
3114 		<< "#version 450\n"
3115 		<< "#extension GL_EXT_mesh_shader : enable\n"
3116 		<< "\n"
3117 		<< "layout(local_size_x=" << params->localSize << ") in;\n"
3118 		<< "layout(points) out;\n"
3119 		<< "layout(max_vertices=" << params->numVertices << ", max_primitives=" << params->numPrimitives << ") out;\n"
3120 		<< "\n"
3121 		<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
3122 		<< "\n"
3123 		<< "void main ()\n"
3124 		<< "{\n"
3125 		<< "    SetMeshOutputsEXT(" << params->numVertices << ", " << params->numPrimitives << ");\n"
3126 		<< "    const uint pixelId = gl_LocalInvocationIndex / 2u;\n"
3127 		<< "    if (gl_LocalInvocationIndex % 2u == 0u)\n"
3128 		<< "    {\n"
3129 		<< "        const float xCoord = (float(pixelId) + 0.5) / float(" << params->width << ") * 2.0 - 1.0;\n"
3130 		<< "        gl_MeshVerticesEXT[pixelId].gl_Position = vec4(xCoord, 0.0, 0.0f, 1.0f);\n"
3131 		<< "        gl_MeshVerticesEXT[pixelId].gl_PointSize = 1.0f;\n"
3132 		<< "    }\n"
3133 		<< "    else\n"
3134 		<< "    {\n"
3135 		<< "        gl_PrimitivePointIndicesEXT[pixelId] = pixelId;\n"
3136 		<< "        pointColor[pixelId] = vec4(0.0, 0.0, 1.0, 1.0);\n"
3137 		<< "    }\n"
3138 		<< "}\n"
3139 		;
3140 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
3141 }
3142 
generateReferenceLevel()3143 void MaximizeInvocationsInstance::generateReferenceLevel ()
3144 {
3145 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
3146 }
3147 
3148 // Verify mixing classic and mesh shading pipelines in the same render pass.
3149 struct MixedPipelinesParams : public MiscTestParams
3150 {
3151 public:
3152 	bool dynamicTopology;
3153 
MixedPipelinesParamsvkt::MeshShader::__anond8548dd90111::MixedPipelinesParams3154 	MixedPipelinesParams (const tcu::Maybe<tcu::UVec3>& taskCount_, const tcu::UVec3& meshCount_, uint32_t width_, uint32_t height_, bool dynamicTopology_)
3155 		: MiscTestParams	(taskCount_, meshCount_, width_, height_)
3156 		, dynamicTopology	(dynamicTopology_)
3157 	{}
3158 };
3159 
3160 // Global idea behind this case: draw 4 times with classic, mesh, classic and mesh pipelines. Each draw will use a full screen quad
3161 // and a dynamic scissor to restrict drawing in the framebuffer to one specific quadrant of the color attachment. The color of each
3162 // quadrant will be taken from a push constant that changes between steps, so each quadrant ends up with a different color.
3163 class MixedPipelinesCase : public MeshShaderMiscCase
3164 {
3165 public:
MixedPipelinesCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)3166 					MixedPipelinesCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
3167 						: MeshShaderMiscCase (testCtx, name, std::move(params))
3168 					{}
3169 
3170 	void			checkSupport			(Context& context) const override;
3171 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
3172 	TestInstance*	createInstance			(Context& context) const override;
3173 };
3174 
3175 class MixedPipelinesInstance : public MeshShaderMiscInstance
3176 {
3177 public:
MixedPipelinesInstance(Context & context,const MiscTestParams * params)3178 	MixedPipelinesInstance (Context& context, const MiscTestParams* params)
3179 		: MeshShaderMiscInstance (context, params)
3180 	{}
3181 
3182 	typedef std::pair<VkRect2D, tcu::Vec4>	RectColor;
3183 	typedef std::vector<RectColor>			RectColorVec;
3184 	RectColorVec	getQuadrantColors		();
3185 	tcu::Vec4		getClearColor			();
3186 
3187 	void			generateReferenceLevel	() override;
3188 	tcu::TestStatus	iterate					() override;
3189 
3190 };
3191 
createInstance(Context & context) const3192 TestInstance* MixedPipelinesCase::createInstance (Context& context) const
3193 {
3194 	return new MixedPipelinesInstance (context, m_params.get());
3195 }
3196 
checkSupport(Context & context) const3197 void MixedPipelinesCase::checkSupport (Context& context) const
3198 {
3199 	const auto params = dynamic_cast<MixedPipelinesParams*>(m_params.get());
3200 	DE_ASSERT(params);
3201 
3202 	MeshShaderMiscCase::checkSupport(context);
3203 
3204 	if (params->dynamicTopology)
3205 		context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
3206 }
3207 
initPrograms(vk::SourceCollections & programCollection) const3208 void MixedPipelinesCase::initPrograms (vk::SourceCollections& programCollection) const
3209 {
3210 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
3211 
3212 	DE_ASSERT(!m_params->needsTaskShader());
3213 
3214 	// The fragment shader will draw using the color indicated by the push constant.
3215 	const std::string frag =
3216 		"#version 450\n"
3217 		"\n"
3218 		"layout (location=0) out vec4 outColor;\n"
3219 		"layout (push_constant, std430) uniform PushConstantBlock {\n"
3220 		"    vec4 color;\n"
3221 		"} pc;\n"
3222 		"\n"
3223 		"void main ()\n"
3224 		"{\n"
3225 		"    outColor = pc.color;\n"
3226 		"}\n"
3227 		;
3228 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
3229 
3230 	const std::string vert =
3231 		"#version 450\n"
3232 		"\n"
3233 		"void main()\n"
3234 		"{\n"
3235 		// Full-screen clockwise triangle strip with 4 vertices.
3236 		"    const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
3237 		"    const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
3238 		"    gl_Position = vec4(x, y, 0.0, 1.0);\n"
3239 		"}\n"
3240 		;
3241 	programCollection.glslSources.add("vert") << glu::VertexSource(vert);
3242 
3243 	const std::string mesh =
3244 		"#version 450\n"
3245 		"#extension GL_EXT_mesh_shader : enable\n"
3246 		"\n"
3247 		"layout(local_size_x=4) in;\n"
3248 		"layout(triangles) out;\n"
3249 		"layout(max_vertices=4, max_primitives=2) out;\n"
3250 		"\n"
3251 		"void main ()\n"
3252 		"{\n"
3253 		"    SetMeshOutputsEXT(4u, 2u);\n"
3254 		// Full-screen clockwise triangle strip with 4 vertices.
3255 		"    const float x = (-1.0+2.0*((gl_LocalInvocationIndex & 2)>>1));\n"
3256 		"    const float y = ( 1.0-2.0*((gl_LocalInvocationIndex & 1)   ));\n"
3257 		"    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(x, y, 0.0, 1.0);\n"
3258 		"    if (gl_LocalInvocationIndex == 0u) {\n"
3259 		"        gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0u, 1u, 2u);\n"
3260 		"        gl_PrimitiveTriangleIndicesEXT[1] = uvec3(2u, 1u, 3u);\n"
3261 		"    }\n"
3262 		"}\n"
3263 		;
3264 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh) << buildOptions;
3265 }
3266 
getQuadrantColors()3267 MixedPipelinesInstance::RectColorVec MixedPipelinesInstance::getQuadrantColors ()
3268 {
3269 	const auto width		= m_params->width;
3270 	const auto height		= m_params->height;
3271 	const auto halfWidth	= width / 2u;
3272 	const auto halfHeight	= height / 2u;
3273 	const auto iHalfWidth	= static_cast<int>(halfWidth);
3274 	const auto iHalfHeight	= static_cast<int>(halfHeight);
3275 
3276 	DE_ASSERT(width % 2u == 0u);
3277 	DE_ASSERT(height % 2u == 0u);
3278 
3279 	// Associate a different color to each rectangle.
3280 	const RectColorVec quadrantColors {
3281 		std::make_pair(makeRect2D(0,          0,           halfWidth, halfHeight), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)),
3282 		std::make_pair(makeRect2D(0,          iHalfHeight, halfWidth, halfHeight), tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f)),
3283 		std::make_pair(makeRect2D(iHalfWidth, 0,           halfWidth, halfHeight), tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f)),
3284 		std::make_pair(makeRect2D(iHalfWidth, iHalfHeight, halfWidth, halfHeight), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)),
3285 	};
3286 	return quadrantColors;
3287 }
3288 
getClearColor()3289 tcu::Vec4 MixedPipelinesInstance::getClearColor ()
3290 {
3291 	return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3292 }
3293 
generateReferenceLevel()3294 void MixedPipelinesInstance::generateReferenceLevel ()
3295 {
3296 	const auto format		= getOutputFormat();
3297 	const auto tcuFormat	= mapVkFormat(format);
3298 
3299 	const auto iWidth		= static_cast<int>(m_params->width);
3300 	const auto iHeight		= static_cast<int>(m_params->height);
3301 
3302 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
3303 
3304 	const auto access		= m_referenceLevel->getAccess();
3305 	const auto quadColors	= getQuadrantColors();
3306 	const auto clearColor	= getClearColor();
3307 
3308 	// Each image quadrant gets a different color.
3309 	tcu::clear(access, clearColor);
3310 
3311 	for (int y = 0; y < iHeight; ++y)
3312 	for (int x = 0; x < iWidth; ++x)
3313 	{
3314 		for (const auto& quadrant : quadColors)
3315 		{
3316 			const auto minX = quadrant.first.offset.x;
3317 			const auto minY = quadrant.first.offset.y;
3318 			const auto maxX = quadrant.first.offset.x + static_cast<int32_t>(quadrant.first.extent.width);
3319 			const auto maxY = quadrant.first.offset.y + static_cast<int32_t>(quadrant.first.extent.height);
3320 
3321 			if (x >= minX && x < maxX && y >= minY && y < maxY)
3322 				access.setPixel(quadrant.second, x, y);
3323 		}
3324 	}
3325 }
3326 
iterate()3327 tcu::TestStatus MixedPipelinesInstance::iterate ()
3328 {
3329 	const auto params = dynamic_cast<const MixedPipelinesParams*>(m_params);
3330 	DE_ASSERT(params);
3331 
3332 	const auto&		vkd			= m_context.getDeviceInterface();
3333 	const auto		device		= m_context.getDevice();
3334 	auto&			alloc		= m_context.getDefaultAllocator();
3335 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
3336 	const auto		queue		= m_context.getUniversalQueue();
3337 
3338 	const auto		dynTopo		= params->dynamicTopology;
3339 	const auto		imageFormat	= getOutputFormat();
3340 	const auto		tcuFormat	= mapVkFormat(imageFormat);
3341 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
3342 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
3343 
3344 	const VkImageCreateInfo colorBufferInfo =
3345 	{
3346 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
3347 		nullptr,								//	const void*				pNext;
3348 		0u,										//	VkImageCreateFlags		flags;
3349 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
3350 		imageFormat,							//	VkFormat				format;
3351 		imageExtent,							//	VkExtent3D				extent;
3352 		1u,										//	uint32_t				mipLevels;
3353 		1u,										//	uint32_t				arrayLayers;
3354 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
3355 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
3356 		imageUsage,								//	VkImageUsageFlags		usage;
3357 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
3358 		0u,										//	uint32_t				queueFamilyIndexCount;
3359 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
3360 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
3361 	};
3362 
3363 	// Create color image and view.
3364 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
3365 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3366 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
3367 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
3368 
3369 	// Create a memory buffer for verification.
3370 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
3371 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3372 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
3373 
3374 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
3375 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
3376 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
3377 
3378 	// Pipeline layouts for the mesh and classic pipelines.
3379 	const auto pcSize					= static_cast<uint32_t>(sizeof(tcu::Vec4));
3380 	const auto pcRange					= makePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0u, pcSize);
3381 	const auto classicPipelineLayout	= makePipelineLayout(vkd, device, DE_NULL, &pcRange);
3382 	const auto meshPipelineLayout		= makePipelineLayout(vkd, device, DE_NULL, &pcRange);
3383 
3384 	// Shader modules.
3385 	const auto&	binaries	= m_context.getBinaryCollection();
3386 	const auto	vertShader	= createShaderModule(vkd, device, binaries.get("vert"));
3387 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
3388 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
3389 
3390 	// Render pass.
3391 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
3392 
3393 	// Framebuffer.
3394 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
3395 
3396 	// Viewport and scissor.
3397 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
3398 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
3399 
3400 	// Color blending.
3401 	const auto									colorWriteMask	= (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
3402 	const VkPipelineColorBlendAttachmentState	blendAttState	=
3403 	{
3404 		VK_TRUE,				//	VkBool32				blendEnable;
3405 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcColorBlendFactor;
3406 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstColorBlendFactor;
3407 		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
3408 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcAlphaBlendFactor;
3409 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstAlphaBlendFactor;
3410 		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
3411 		colorWriteMask,			//	VkColorComponentFlags	colorWriteMask;
3412 	};
3413 
3414 	const VkPipelineColorBlendStateCreateInfo colorBlendInfo =
3415 	{
3416 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
3417 		nullptr,													//	const void*									pNext;
3418 		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
3419 		VK_FALSE,													//	VkBool32									logicOpEnable;
3420 		VK_LOGIC_OP_OR,												//	VkLogicOp									logicOp;
3421 		1u,															//	uint32_t									attachmentCount;
3422 		&blendAttState,												//	const VkPipelineColorBlendAttachmentState*	pAttachments;
3423 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
3424 	};
3425 
3426 	const std::vector<VkDynamicState>	meshDynamicStates		{ VK_DYNAMIC_STATE_SCISSOR };
3427 	std::vector<VkDynamicState>			classicDynamicStates	(meshDynamicStates);
3428 	if (dynTopo)
3429 		classicDynamicStates.push_back(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
3430 
3431 	const VkPipelineDynamicStateCreateInfo meshDynamicStateInfo =
3432 	{
3433 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
3434 		nullptr,												//	const void*							pNext;
3435 		0u,														//	VkPipelineDynamicStateCreateFlags	flags;
3436 		static_cast<uint32_t>(meshDynamicStates.size()),		//	uint32_t							dynamicStateCount;
3437 		de::dataOrNull(meshDynamicStates),						//	const VkDynamicState*				pDynamicStates;
3438 	};
3439 	const VkPipelineDynamicStateCreateInfo	classicDynamicStateInfo	=
3440 	{
3441 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
3442 		nullptr,												//	const void*							pNext;
3443 		0u,														//	VkPipelineDynamicStateCreateFlags	flags;
3444 		static_cast<uint32_t>(classicDynamicStates.size()),		//	uint32_t							dynamicStateCount;
3445 		de::dataOrNull(classicDynamicStates),					//	const VkDynamicState*				pDynamicStates;
3446 	};
3447 
3448 	const auto meshPipeline = makeGraphicsPipeline(vkd, device, meshPipelineLayout.get(),
3449 		DE_NULL, meshShader.get(), fragShader.get(),
3450 		renderPass.get(), viewports, scissors, 0u/*subpass*/,
3451 		nullptr, nullptr, nullptr, &colorBlendInfo, &meshDynamicStateInfo);
3452 
3453 	const VkPipelineVertexInputStateCreateInfo vertexInputInfo = initVulkanStructure();
3454 
3455 	const auto staticTopo		= (dynTopo ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
3456 	const auto classicPipeline	= makeGraphicsPipeline(vkd, device, classicPipelineLayout.get(),
3457 		vertShader.get(), DE_NULL, DE_NULL, DE_NULL, fragShader.get(),
3458 		renderPass.get(), viewports, scissors, staticTopo, 0u/*subpass*/, 0u/*patchControlPoints*/,
3459 			&vertexInputInfo, nullptr, nullptr, nullptr, nullptr, &classicDynamicStateInfo);
3460 
3461 	// Command pool and buffer.
3462 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
3463 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3464 	const auto cmdBuffer	= cmdBufferPtr.get();
3465 
3466 	// Pipeline list.
3467 	beginCommandBuffer(vkd, cmdBuffer);
3468 
3469 	// Run pipeline.
3470 	const auto clearColor	= getClearColor();
3471 	const auto drawCount	= m_params->drawCount();
3472 	const auto quadColors	= getQuadrantColors();
3473 	DE_ASSERT(drawCount.x() == 1u && drawCount.y() == 1u && drawCount.z() == 1u);
3474 
3475 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
3476 	for (size_t idx = 0u; idx < quadColors.size(); ++idx)
3477 	{
3478 		const auto& rectColor = quadColors.at(idx);
3479 		vkd.cmdSetScissor(cmdBuffer, 0u, 1u, &rectColor.first);
3480 
3481 		if (idx % 2u == 0u)
3482 		{
3483 			vkd.cmdPushConstants(cmdBuffer, classicPipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0u, pcSize, &rectColor.second);
3484 			if (dynTopo)
3485 				vkd.cmdSetPrimitiveTopology(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
3486 			vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, classicPipeline.get());
3487 			vkd.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
3488 		}
3489 		else
3490 		{
3491 			vkd.cmdPushConstants(cmdBuffer, meshPipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0u, pcSize, &rectColor.second);
3492 			vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, meshPipeline.get());
3493 			vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
3494 		}
3495 	}
3496 	endRenderPass(vkd, cmdBuffer);
3497 
3498 	// Copy color buffer to verification buffer.
3499 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
3500 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
3501 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
3502 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
3503 
3504 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
3505 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
3506 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
3507 
3508 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
3509 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
3510 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
3511 
3512 	endCommandBuffer(vkd, cmdBuffer);
3513 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3514 
3515 	// Generate reference image and compare results.
3516 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
3517 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
3518 
3519 	generateReferenceLevel();
3520 	invalidateAlloc(vkd, device, verificationBufferAlloc);
3521 	if (!verifyResult(verificationAccess))
3522 		TCU_FAIL("Result does not match reference; check log for details");
3523 
3524 	return tcu::TestStatus::pass("Pass");
3525 }
3526 
3527 // Tests to check SetMeshOutputsEXT() and EmitMeshTasksEXT() take values from the first invocation.
3528 class FirstInvocationCase : public MeshShaderMiscCase
3529 {
3530 public:
FirstInvocationCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)3531 					FirstInvocationCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
3532 						: MeshShaderMiscCase (testCtx, name, std::move(params))
3533 					{}
3534 
3535 	void			checkSupport			(Context& context) const override;
3536 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
3537 	TestInstance*	createInstance			(Context& context) const override;
3538 
3539 	static constexpr uint32_t kColoredPixels = 120u;
3540 };
3541 
3542 class FirstInvocationInstance : public MeshShaderMiscInstance
3543 {
3544 public:
FirstInvocationInstance(Context & context,const MiscTestParams * params)3545 	FirstInvocationInstance (Context& context, const MiscTestParams* params)
3546 		: MeshShaderMiscInstance (context, params)
3547 	{}
3548 
3549 	void	generateReferenceLevel	() override;
3550 };
3551 
generateReferenceLevel()3552 void FirstInvocationInstance::generateReferenceLevel ()
3553 {
3554 	DE_ASSERT(m_params->height == 1u && m_params->width == 128u);
3555 	DE_ASSERT(FirstInvocationCase::kColoredPixels < m_params->width);
3556 
3557 	const auto format		= getOutputFormat();
3558 	const auto tcuFormat	= mapVkFormat(format);
3559 
3560 	const auto iWidth		= static_cast<int>(m_params->width);
3561 	const auto iHeight		= static_cast<int>(m_params->height);
3562 
3563 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
3564 
3565 	const auto clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
3566 	const auto geomColor	= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
3567 	const auto access		= m_referenceLevel->getAccess();
3568 
3569 	// Fill the expected amount of colored pixels with solid color.
3570 	for (int i = 0; i < iWidth; ++i)
3571 	{
3572 		const auto& color = ((static_cast<uint32_t>(i) < FirstInvocationCase::kColoredPixels) ? geomColor : clearColor);
3573 		access.setPixel(color, i, 0);
3574 	}
3575 }
3576 
createInstance(Context & context) const3577 TestInstance* FirstInvocationCase::createInstance (Context& context) const
3578 {
3579 	return new FirstInvocationInstance(context, m_params.get());
3580 }
3581 
checkSupport(Context & context) const3582 void FirstInvocationCase::checkSupport (Context &context) const
3583 {
3584 	MeshShaderMiscCase::checkSupport(context);
3585 
3586 	if (context.getUsedApiVersion() < VK_MAKE_VERSION(1, 1, 0))
3587 		TCU_THROW(NotSupportedError, "Vulkan API version >= 1.1 required");
3588 
3589 	const auto &subgroupProperties = context.getSubgroupProperties();
3590 	if (!(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT))
3591 		TCU_THROW(NotSupportedError, "Subgroup basic features not supported");
3592 }
3593 
initPrograms(vk::SourceCollections & programCollection) const3594 void FirstInvocationCase::initPrograms (vk::SourceCollections& programCollection) const
3595 {
3596 	DE_ASSERT(m_params->height == 1u && m_params->width == 128u);
3597 	DE_ASSERT(kColoredPixels < m_params->width);
3598 
3599 	// Add generic fragment shader.
3600 	MeshShaderMiscCase::initPrograms(programCollection);
3601 
3602 	const bool					useTask			= m_params->needsTaskShader();
3603 	const auto					fbWidth			= m_params->width;
3604 	const auto					meshLocalSize	= (useTask ? 1u : fbWidth);
3605 	const auto					taskLocalSize	= fbWidth;
3606 	const auto					pointsPerMeshWG	= (useTask ? 1u : kColoredPixels);
3607 	const auto					jobID			= (useTask ? "gl_WorkGroupID.x" : "gl_LocalInvocationIndex");
3608 	const auto					buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
3609 
3610 	std::string taskDataDecl;
3611 	if (useTask)
3612 	{
3613 		std::ostringstream aux;
3614 		aux
3615 			<< "struct TaskData {\n"
3616 			<< "    uint values[" << taskLocalSize << "];\n"
3617 			<< "};\n"
3618 			<< "taskPayloadSharedEXT TaskData td;\n"
3619 			;
3620 		taskDataDecl = aux.str();
3621 	}
3622 
3623 	if (useTask)
3624 	{
3625 		std::ostringstream task;
3626 		task
3627 			<< "#version 450\n"
3628 			<< "#extension GL_EXT_mesh_shader : enable\n"
3629 			<< "#extension GL_KHR_shader_subgroup_basic : enable\n"
3630 			<< "\n"
3631 			<< "layout(local_size_x=" << taskLocalSize << ", local_size_y=1, local_size_z=1) in;\n"
3632 			<< "\n"
3633 			<< taskDataDecl
3634 			<< "\n"
3635 			<< "void main ()\n"
3636 			<< "{\n"
3637 			<< "    td.values[gl_LocalInvocationIndex] = gl_LocalInvocationIndex * 2u;\n"
3638 			<< "\n"
3639 			<< "    uint total_jobs = max(" << kColoredPixels << " / 2u, 1u);\n"
3640 			<< "    if (gl_LocalInvocationIndex == 0u) {\n"
3641 			<< "        total_jobs = " << kColoredPixels << ";\n"
3642 			<< "    } else if (gl_SubgroupID > 0u) {\n"
3643 			<< "        total_jobs = max(" << kColoredPixels << " / 4u, 1u);\n"
3644 			<< "    }\n"
3645 			<< "\n"
3646 			<< "    EmitMeshTasksEXT(total_jobs, 1u, 1u);\n"
3647 			<< "}\n"
3648 			;
3649 
3650 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
3651 	}
3652 
3653 	{
3654 		std::ostringstream mesh;
3655 		mesh
3656 			<< "#version 450\n"
3657 			<< "#extension GL_EXT_mesh_shader : enable\n"
3658 			<< "#extension GL_KHR_shader_subgroup_basic : enable\n"
3659 			<< "\n"
3660 			<< "layout(local_size_x=" << meshLocalSize << ", local_size_y=1, local_size_z=1) in;\n"
3661 			<< "layout(points) out;\n"
3662 			<< "layout(max_primitives=" << meshLocalSize << ", max_vertices=" << meshLocalSize << ") out;\n"
3663 			<< "\n"
3664 			<< "layout (location=0) out perprimitiveEXT vec4 pointColor[];\n"
3665 			<< taskDataDecl
3666 			<< "\n"
3667 			<< "void main ()\n"
3668 			<< "{\n"
3669 			<< "    uint total_points = max(" << pointsPerMeshWG << " / 2u, 1u);\n"
3670 			<< "    \n"
3671 			;
3672 
3673 		if (!useTask)
3674 		{
3675 			mesh
3676 				<< "    if (gl_LocalInvocationIndex == 0u) {\n"
3677 				<< "        total_points = " << pointsPerMeshWG << ";\n"
3678 				<< "    } else if (gl_SubgroupID > 0u) {\n"
3679 				<< "        total_points = max(" << pointsPerMeshWG << " / 4u, 1u);\n"
3680 				<< "    }\n"
3681 				<< "    \n"
3682 				;
3683 		}
3684 
3685 		mesh
3686 			<< "    SetMeshOutputsEXT(total_points, total_points);\n"
3687 			<< "    if (gl_LocalInvocationIndex < " << pointsPerMeshWG << ") {\n"
3688 			<< "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_PointSize = 1.0;\n"
3689 			<< "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(((float(" << jobID << ") + 0.5) / " << fbWidth << ") * 2.0 - 1.0, 0.0, 0.0, 1.0);\n"
3690 			<< "        gl_PrimitivePointIndicesEXT[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
3691 			<< "        pointColor[gl_LocalInvocationIndex] = vec4(0.0, 0.0, 1.0, 1.0);\n"
3692 			<< "    }\n"
3693 			<< "}\n"
3694 			;
3695 
3696 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
3697 	}
3698 }
3699 
3700 // Tests that check LocalSizeId works as expected.
3701 class LocalSizeIdCase : public MeshShaderMiscCase
3702 {
3703 public:
LocalSizeIdCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)3704 					LocalSizeIdCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
3705 						: MeshShaderMiscCase (testCtx, name, std::move(params))
3706 					{}
3707 
3708 	void			checkSupport			(Context& context) const override;
3709 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
3710 	TestInstance*	createInstance			(Context& context) const override;
3711 };
3712 
3713 class LocalSizeIdInstance : public MeshShaderMiscInstance
3714 {
3715 public:
LocalSizeIdInstance(Context & context,const MiscTestParams * params)3716 	LocalSizeIdInstance (Context& context, const MiscTestParams* params)
3717 		: MeshShaderMiscInstance (context, params)
3718 	{}
3719 
3720 	void			generateReferenceLevel	() override;
3721 	tcu::TestStatus	iterate					() override;
3722 };
3723 
createInstance(Context & context) const3724 TestInstance* LocalSizeIdCase::createInstance (Context& context) const
3725 {
3726 	return new LocalSizeIdInstance(context, m_params.get());
3727 }
3728 
generateReferenceLevel()3729 void LocalSizeIdInstance::generateReferenceLevel ()
3730 {
3731 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
3732 }
3733 
checkSupport(Context & context) const3734 void LocalSizeIdCase::checkSupport (Context &context) const
3735 {
3736 	// Generic checks.
3737 	MeshShaderMiscCase::checkSupport(context);
3738 
3739 	// Needed for LocalSizeId.
3740 	context.requireDeviceFunctionality("VK_KHR_maintenance4");
3741 }
3742 
initPrograms(vk::SourceCollections & programCollection) const3743 void LocalSizeIdCase::initPrograms (vk::SourceCollections& programCollection) const
3744 {
3745 	const SpirVAsmBuildOptions	spvOptions	(programCollection.usedVulkanVersion, SPIRV_VERSION_1_5, false/*allowSpirv14*/, true/*allowMaintenance4*/);
3746 	const auto					useTask		= m_params->needsTaskShader();
3747 
3748 	DE_ASSERT(m_params->height == 1u && m_params->width == 32u);
3749 
3750 	// Add generic fragment shader.
3751 	MeshShaderMiscCase::initPrograms(programCollection);
3752 
3753 	if (useTask)
3754 	{
3755 		// Roughly equivalent to the following shader.
3756 		//	#version 450
3757 		//	#extension GL_EXT_mesh_shader : enable
3758 		//
3759 		//	layout(local_size_x_id=10, local_size_y_id=11, local_size_z_id=12) in;
3760 		//	struct TaskData {
3761 		//	    uint pixelID[32];
3762 		//	};
3763 		//	taskPayloadSharedEXT TaskData td;
3764 		//
3765 		//	void main ()
3766 		//	{
3767 		//	    td.pixelID[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
3768 		//	    EmitMeshTasksEXT(1u, 1u, 1u);
3769 		//	}
3770 
3771 		std::ostringstream taskSPV;
3772 		taskSPV
3773 			<< "      ; SPIR-V\n"
3774 			<< "      ; Version: 1.0\n"
3775 			<< "      ; Generator: Khronos Glslang Reference Front End; 10\n"
3776 			<< "      ; Bound: 26\n"
3777 			<< "      ; Schema: 0\n"
3778 			<< "      OpCapability MeshShadingEXT\n"
3779 			<< "      OpExtension \"SPV_EXT_mesh_shader\"\n"
3780 			<< " %1 = OpExtInstImport \"GLSL.std.450\"\n"
3781 			<< "      OpMemoryModel Logical GLSL450\n"
3782 			<< "      OpEntryPoint TaskEXT %4 \"main\" %11 %15\n"
3783 			<< "      OpExecutionModeId %4 LocalSizeId %21 %22 %23\n"
3784 			<< "      OpDecorate %15 BuiltIn LocalInvocationIndex\n"
3785 			<< "      OpDecorate %21 SpecId 10\n"
3786 			<< "      OpDecorate %22 SpecId 11\n"
3787 			<< "      OpDecorate %23 SpecId 12\n"
3788 			<< " %2 = OpTypeVoid\n"
3789 			<< " %3 = OpTypeFunction %2\n"
3790 			<< " %6 = OpTypeInt 32 0\n"
3791 			<< " %7 = OpConstant %6 32\n"
3792 			<< " %8 = OpTypeArray %6 %7\n"
3793 			<< " %9 = OpTypeStruct %8\n"
3794 			<< "%10 = OpTypePointer TaskPayloadWorkgroupEXT %9\n"
3795 			<< "%11 = OpVariable %10 TaskPayloadWorkgroupEXT\n"
3796 			<< "%12 = OpTypeInt 32 1\n"
3797 			<< "%13 = OpConstant %12 0\n"
3798 			<< "%14 = OpTypePointer Input %6\n"
3799 			<< "%15 = OpVariable %14 Input\n"
3800 			<< "%18 = OpTypePointer TaskPayloadWorkgroupEXT %6\n"
3801 			<< "%20 = OpConstant %6 1\n"
3802 			<< "%21 = OpSpecConstant %6 1\n"
3803 			<< "%22 = OpSpecConstant %6 1\n"
3804 			<< "%23 = OpSpecConstant %6 1\n"
3805 			<< " %4 = OpFunction %2 None %3\n"
3806 			<< " %5 = OpLabel\n"
3807 			<< "%16 = OpLoad %6 %15\n"
3808 			<< "%17 = OpLoad %6 %15\n"
3809 			<< "%19 = OpAccessChain %18 %11 %13 %16\n"
3810 			<< "      OpStore %19 %17\n"
3811 			<< "      OpEmitMeshTasksEXT %20 %20 %20 %11\n"
3812 			<< "      OpFunctionEnd\n"
3813 			;
3814 
3815 		programCollection.spirvAsmSources.add("task") << taskSPV.str() << spvOptions;
3816 	}
3817 
3818 	{
3819 		// Roughly equivalent to the following shader.
3820 		//	#version 450
3821 		//	#extension GL_EXT_mesh_shader : enable
3822 		//
3823 		//	layout(local_size_x_id=20, local_size_y_id=21, local_size_z_id=22) in;
3824 		//	layout(points) out;
3825 		//	layout(max_primitives=32, max_vertices=32) out;
3826 		//
3827 		//	layout (location=0) out perprimitiveEXT vec4 pointColor[];
3828 		//#if useTask
3829 		//	struct TaskData {
3830 		//	    uint pixelID[32];
3831 		//	};
3832 		//	taskPayloadSharedEXT TaskData td;
3833 		//#endif
3834 		//
3835 		//	void main ()
3836 		//	{
3837 		//#if useTask
3838 		//	    const uint pixelId = td.pixelID[gl_LocalInvocationIndex];
3839 		//#else
3840 		//	    const uint pixelId = gl_LocalInvocationIndex;
3841 		//#endif
3842 		//	    SetMeshOutputsEXT(32u, 32u);
3843 		//	    gl_MeshVerticesEXT[pixelId].gl_PointSize = 1.0;
3844 		//	    gl_MeshVerticesEXT[pixelId].gl_Position = vec4(((float(pixelId) + 0.5) / 32.0) * 2.0 - 1.0, 0.0, 0.0, 1.0);
3845 		//	    gl_PrimitivePointIndicesEXT[pixelId] = pixelId;
3846 		//	    pointColor[pixelId] = vec4(0.0, 0.0, 1.0, 1.0);
3847 		//	}
3848 		std::ostringstream meshSPV;
3849 		meshSPV
3850 			<< "                              OpCapability MeshShadingEXT\n"
3851 			<< "                              OpExtension \"SPV_EXT_mesh_shader\"\n"
3852 			<< "                         %1 = OpExtInstImport \"GLSL.std.450\"\n"
3853 			<< "                              OpMemoryModel Logical GLSL450\n"
3854 			<< "                              OpEntryPoint MeshEXT %main \"main\" %local_invocation_index %mesh_vertices %primitive_point_indices %primitive_colors" << (useTask ? " %task_data" : "") << "\n"
3855 			<< "                              OpExecutionModeId %main LocalSizeId %constand_id_20 %constant_id_21 %constant_id_22\n"
3856 			<< "                              OpExecutionMode %main OutputVertices 32\n"
3857 			<< "                              OpExecutionMode %main OutputPrimitivesNV 32\n"
3858 			<< "                              OpExecutionMode %main OutputPoints\n"
3859 			<< "                              OpDecorate %local_invocation_index BuiltIn LocalInvocationIndex\n"
3860 			<< "                              OpMemberDecorate %mesh_vertices_struct 0 BuiltIn Position\n"
3861 			<< "                              OpMemberDecorate %mesh_vertices_struct 1 BuiltIn PointSize\n"
3862 			<< "                              OpMemberDecorate %mesh_vertices_struct 2 BuiltIn ClipDistance\n"
3863 			<< "                              OpMemberDecorate %mesh_vertices_struct 3 BuiltIn CullDistance\n"
3864 			<< "                              OpDecorate %mesh_vertices_struct Block\n"
3865 			<< "                              OpDecorate %primitive_point_indices BuiltIn PrimitivePointIndicesEXT\n"
3866 			<< "                              OpDecorate %primitive_colors PerPrimitiveEXT\n"
3867 			<< "                              OpDecorate %primitive_colors Location 0\n"
3868 			<< "                              OpDecorate %constand_id_20 SpecId 20\n"
3869 			<< "                              OpDecorate %constant_id_21 SpecId 21\n"
3870 			<< "                              OpDecorate %constant_id_22 SpecId 22\n"
3871 			<< "                 %type_void = OpTypeVoid\n"
3872 			<< "                 %void_func = OpTypeFunction %type_void\n"
3873 			<< "                       %int = OpTypeInt 32 1\n"
3874 			<< "                      %uint = OpTypeInt 32 0\n"
3875 			<< "                     %float = OpTypeFloat 32\n"
3876 			<< "                      %vec4 = OpTypeVector %float 4\n"
3877 			<< "                     %uvec3 = OpTypeVector %uint 3\n"
3878 			<< "                     %int_0 = OpConstant %int 0\n"
3879 			<< "                     %int_1 = OpConstant %int 1\n"
3880 			<< "                    %uint_1 = OpConstant %uint 1\n"
3881 			<< "                   %uint_32 = OpConstant %uint 32\n"
3882 			<< "                   %float_0 = OpConstant %float 0\n"
3883 			<< "                   %float_1 = OpConstant %float 1\n"
3884 			<< "                 %float_0_5 = OpConstant %float 0.5\n"
3885 			<< "                  %float_32 = OpConstant %float 32\n"
3886 			<< "                   %float_2 = OpConstant %float 2\n"
3887 			<< "             %float_array_1 = OpTypeArray %float %uint_1\n"
3888 			<< "             %func_uint_ptr = OpTypePointer Function %uint\n"
3889 			<< "            %input_uint_ptr = OpTypePointer Input %uint\n"
3890 			<< "    %local_invocation_index = OpVariable %input_uint_ptr Input\n"
3891 			<< "      %mesh_vertices_struct = OpTypeStruct %vec4 %float %float_array_1 %float_array_1\n"
3892 			<< "       %mesh_vertices_array = OpTypeArray %mesh_vertices_struct %uint_32\n"
3893 			<< "     %mesh_vertices_out_ptr = OpTypePointer Output %mesh_vertices_array\n"
3894 			<< "             %mesh_vertices = OpVariable %mesh_vertices_out_ptr Output\n"
3895 			<< "          %output_float_ptr = OpTypePointer Output %float\n"
3896 			<< "           %output_vec4_ptr = OpTypePointer Output %vec4\n"
3897 			<< "             %uint_array_32 = OpTypeArray %uint %uint_32\n"
3898 			<< "\n"
3899 			;
3900 
3901 		if (useTask)
3902 		{
3903 			meshSPV
3904 				<< "\n"
3905 				<< "%uint_array_32_struct                  = OpTypeStruct %uint_array_32\n"
3906 				<< "%task_payload_uint_array_32_struct_ptr = OpTypePointer TaskPayloadWorkgroupEXT %uint_array_32_struct\n"
3907 				<< "%task_data                             = OpVariable %task_payload_uint_array_32_struct_ptr TaskPayloadWorkgroupEXT\n"
3908 				<< "%task_payload_uint_ptr                 = OpTypePointer TaskPayloadWorkgroupEXT %uint\n"
3909 				<< "\n"
3910 				;
3911 		}
3912 
3913 		meshSPV
3914 			<< "  %output_uint_array_32_ptr = OpTypePointer Output %uint_array_32\n"
3915 			<< "   %primitive_point_indices = OpVariable %output_uint_array_32_ptr Output\n"
3916 			<< "           %output_uint_ptr = OpTypePointer Output %uint\n"
3917 			<< "             %vec4_array_32 = OpTypeArray %vec4 %uint_32\n"
3918 			<< "  %output_vec4_array_32_ptr = OpTypePointer Output %vec4_array_32\n"
3919 			<< "          %primitive_colors = OpVariable %output_vec4_array_32_ptr Output\n"
3920 			<< "                      %blue = OpConstantComposite %vec4 %float_0 %float_0 %float_1 %float_1\n"
3921 			<< "            %constand_id_20 = OpSpecConstant %uint 1\n"
3922 			<< "            %constant_id_21 = OpSpecConstant %uint 1\n"
3923 			<< "            %constant_id_22 = OpSpecConstant %uint 1\n"
3924 			<< "                      %main = OpFunction %type_void None %void_func\n"
3925 			<< "                %main_label = OpLabel\n"
3926 			<< "                  %pixel_id = OpVariable %func_uint_ptr Function\n"
3927 			<< "%local_invocation_index_val = OpLoad %uint %local_invocation_index\n"
3928 			;
3929 
3930 		if (useTask)
3931 		{
3932 			meshSPV
3933 				<< "           %td_pixel_id_ptr = OpAccessChain %task_payload_uint_ptr %task_data %int_0 %local_invocation_index_val\n"
3934 				<< "           %td_pixel_id_val = OpLoad %uint %td_pixel_id_ptr\n"
3935 				<< "                              OpStore %pixel_id %td_pixel_id_val\n"
3936 				;
3937 		}
3938 		else
3939 		{
3940 			meshSPV << "                              OpStore %pixel_id %local_invocation_index_val\n";
3941 		}
3942 
3943 		meshSPV
3944 			<< "                              OpSetMeshOutputsEXT %uint_32 %uint_32\n"
3945 			<< "              %pixel_id_val = OpLoad %uint %pixel_id\n"
3946 			<< "                %point_size = OpAccessChain %output_float_ptr %mesh_vertices %pixel_id_val %int_1\n"
3947 			<< "                              OpStore %point_size %float_1\n"
3948 			<< "        %pixel_id_val_float = OpConvertUToF %float %pixel_id_val\n"
3949 			<< "       %pixel_id_val_center = OpFAdd %float %pixel_id_val_float %float_0_5\n"
3950 			<< "                   %x_unorm = OpFDiv %float %pixel_id_val_center %float_32\n"
3951 			<< "                 %x_unorm_2 = OpFMul %float %x_unorm %float_2\n"
3952 			<< "                    %x_norm = OpFSub %float %x_unorm_2 %float_1\n"
3953 			<< "                 %point_pos = OpCompositeConstruct %vec4 %x_norm %float_0 %float_0 %float_1\n"
3954 			<< "           %gl_position_ptr = OpAccessChain %output_vec4_ptr %mesh_vertices %pixel_id_val %int_0\n"
3955 			<< "                              OpStore %gl_position_ptr %point_pos\n"
3956 			<< "           %point_index_ptr = OpAccessChain %output_uint_ptr %primitive_point_indices %pixel_id_val\n"
3957 			<< "                              OpStore %point_index_ptr %pixel_id_val\n"
3958 			<< "           %point_color_ptr = OpAccessChain %output_vec4_ptr %primitive_colors %pixel_id_val\n"
3959 			<< "                              OpStore %point_color_ptr %blue\n"
3960 			<< "                              OpReturn\n"
3961 			<< "                              OpFunctionEnd\n"
3962 			;
3963 
3964 		programCollection.spirvAsmSources.add("mesh") << meshSPV.str() << spvOptions;
3965 	}
3966 }
3967 
iterate()3968 tcu::TestStatus LocalSizeIdInstance::iterate ()
3969 {
3970 	const auto&		vkd			= m_context.getDeviceInterface();
3971 	const auto		device		= m_context.getDevice();
3972 	auto&			alloc		= m_context.getDefaultAllocator();
3973 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
3974 	const auto		queue		= m_context.getUniversalQueue();
3975 
3976 	const auto		imageFormat	= getOutputFormat();
3977 	const auto		tcuFormat	= mapVkFormat(imageFormat);
3978 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
3979 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
3980 
3981 	const auto&		binaries	= m_context.getBinaryCollection();
3982 	const auto		hasTask		= binaries.contains("task");
3983 
3984 	const VkImageCreateInfo colorBufferInfo =
3985 	{
3986 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
3987 		nullptr,								//	const void*				pNext;
3988 		0u,										//	VkImageCreateFlags		flags;
3989 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
3990 		imageFormat,							//	VkFormat				format;
3991 		imageExtent,							//	VkExtent3D				extent;
3992 		1u,										//	uint32_t				mipLevels;
3993 		1u,										//	uint32_t				arrayLayers;
3994 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
3995 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
3996 		imageUsage,								//	VkImageUsageFlags		usage;
3997 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
3998 		0u,										//	uint32_t				queueFamilyIndexCount;
3999 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
4000 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
4001 	};
4002 
4003 	// Create color image and view.
4004 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
4005 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4006 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4007 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
4008 
4009 	// Create a memory buffer for verification.
4010 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
4011 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4012 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
4013 
4014 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
4015 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
4016 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
4017 
4018 	// Pipeline layout.
4019 	const auto pipelineLayout = makePipelineLayout(vkd, device, 0u, nullptr, 0u, nullptr);
4020 
4021 	// Shader modules.
4022 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
4023 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
4024 
4025 	Move<VkShaderModule> taskShader;
4026 	if (hasTask)
4027 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
4028 
4029 	// Spec constant data (must match shaders).
4030 	const std::vector<uint32_t> scData {
4031 		//	10		11		12		20		21		22
4032 			32u,	1u,		1u,		32u,	1u,		1u
4033 	};
4034 	const auto scSize = static_cast<uint32_t>(sizeof(uint32_t));
4035 	const std::vector<VkSpecializationMapEntry> scMapEntries {
4036 		makeSpecializationMapEntry(10u, 0u * scSize, scSize),
4037 		makeSpecializationMapEntry(11u, 1u * scSize, scSize),
4038 		makeSpecializationMapEntry(12u, 2u * scSize, scSize),
4039 		makeSpecializationMapEntry(20u, 3u * scSize, scSize),
4040 		makeSpecializationMapEntry(21u, 4u * scSize, scSize),
4041 		makeSpecializationMapEntry(22u, 5u * scSize, scSize),
4042 	};
4043 
4044 	const auto scMapInfo = makeSpecializationInfo(
4045 		static_cast<uint32_t>(scMapEntries.size()), de::dataOrNull(scMapEntries),
4046 		static_cast<uint32_t>(de::dataSize(scData)), de::dataOrNull(scData));
4047 
4048 	std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
4049 	shaderStages.push_back(makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_MESH_BIT_EXT, meshShader.get(), &scMapInfo));
4050 	shaderStages.push_back(makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragShader.get()));
4051 	if (hasTask)
4052 		shaderStages.push_back(makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TASK_BIT_EXT, taskShader.get(), &scMapInfo));
4053 
4054 	// Render pass.
4055 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
4056 
4057 	// Framebuffer.
4058 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
4059 
4060 	// Viewport and scissor.
4061 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
4062 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
4063 
4064 	// Pipeline with specialization constants.
4065 	const auto pipeline = makeGraphicsPipeline(vkd, device, DE_NULL, pipelineLayout.get(), 0u, shaderStages, renderPass.get(), viewports, scissors);
4066 
4067 	// Command pool and buffer.
4068 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
4069 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4070 	const auto cmdBuffer	= cmdBufferPtr.get();
4071 
4072 	beginCommandBuffer(vkd, cmdBuffer);
4073 
4074 	// Run pipeline.
4075 	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 0.0f);
4076 	const auto		drawCount	= m_params->drawCount();
4077 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
4078 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
4079 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
4080 	endRenderPass(vkd, cmdBuffer);
4081 
4082 	// Copy color buffer to verification buffer.
4083 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
4084 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
4085 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
4086 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
4087 
4088 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
4089 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
4090 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
4091 
4092 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
4093 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
4094 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
4095 
4096 	endCommandBuffer(vkd, cmdBuffer);
4097 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
4098 
4099 	// Generate reference image and compare results.
4100 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
4101 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
4102 
4103 	generateReferenceLevel();
4104 	invalidateAlloc(vkd, device, verificationBufferAlloc);
4105 	if (!verifyResult(verificationAccess))
4106 		TCU_FAIL("Result does not match reference; check log for details");
4107 
4108 	return tcu::TestStatus::pass("Pass");
4109 }
4110 
4111 // Test multiple task payloads.
4112 class MultipleTaskPayloadsCase : public MeshShaderMiscCase
4113 {
4114 public:
MultipleTaskPayloadsCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)4115 					MultipleTaskPayloadsCase	(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
4116 						: MeshShaderMiscCase (testCtx, name, std::move(params))
4117 					{
4118 					}
4119 
4120 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
4121 	TestInstance*	createInstance			(Context& context) const override;
4122 
4123 	static constexpr uint32_t kGoodKeyIdx	= 1u;
4124 };
4125 
4126 class MultipleTaskPayloadsInstance : public MeshShaderMiscInstance
4127 {
4128 public:
MultipleTaskPayloadsInstance(Context & context,const MiscTestParams * params)4129 	MultipleTaskPayloadsInstance (Context& context, const MiscTestParams* params)
4130 		: MeshShaderMiscInstance (context, params)
4131 	{}
4132 
4133 	void			generateReferenceLevel	() override;
4134 	tcu::TestStatus	iterate					() override;
4135 };
4136 
createInstance(Context & context) const4137 TestInstance* MultipleTaskPayloadsCase::createInstance (Context& context) const
4138 {
4139 	return new MultipleTaskPayloadsInstance (context, m_params.get());
4140 }
4141 
initPrograms(vk::SourceCollections & programCollection) const4142 void MultipleTaskPayloadsCase::initPrograms (vk::SourceCollections& programCollection) const
4143 {
4144 	DE_ASSERT(m_params->needsTaskShader());
4145 
4146 	const auto					buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
4147 	const auto					spvBuildOptions	= getMinMeshEXTSpvBuildOptions(programCollection.usedVulkanVersion);
4148 	const std::vector<uint32_t>	keys			{ 3717945376u, 2325956828u, 433982700u };
4149 	//const std::vector<uint32_t> keys { 85u, 170u, 255u };
4150 
4151 	// Generic fragment shader.
4152 	MeshShaderMiscCase::initPrograms(programCollection);
4153 
4154 	const std::string taskDataDecl =
4155 		"struct TaskData {\n"
4156 		"    uint key;\n"
4157 		"};\n"
4158 		"taskPayloadSharedEXT TaskData td;\n"
4159 		;
4160 
4161 	// Idea behind this test: verify that the right payload was passed to the mesh shader and set the geometry color based on that.
4162 	std::ostringstream mesh;
4163 	mesh
4164 		<< "#version 450\n"
4165 		<< "#extension GL_EXT_mesh_shader : enable\n"
4166 		<< "\n"
4167 		<< "layout(local_size_x=1) in;\n"
4168 		<< "layout(triangles) out;\n"
4169 		<< "layout(max_vertices=3, max_primitives=1) out;\n"
4170 		<< "\n"
4171 		<< "layout(location=0) out perprimitiveEXT vec4 triangleColor[];\n"
4172 		<< taskDataDecl
4173 		<< "\n"
4174 		<< "void main ()\n"
4175 		<< "{\n"
4176 		<< "    SetMeshOutputsEXT(3, 1);\n"
4177 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
4178 		<< "    gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
4179 		<< "    gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
4180 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
4181 		<< "    const vec4 color = ((td.key == " << keys[kGoodKeyIdx] << "u) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n"
4182 		//<< "    const vec4 color = vec4(0.0, 0.0, (float(td.key) / 255.0), 1.0);\n"
4183 		<< "    triangleColor[0] = color;\n"
4184 		<< "}\n"
4185 		;
4186 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
4187 
4188 	const auto& meshCount = m_params->meshCount;
4189 	DE_ASSERT(meshCount.x() == 1u && meshCount.y() == 1u && meshCount.z() == 1u);
4190 	DE_UNREF(meshCount); // For release builds.
4191 
4192 #if 0
4193 #if 0
4194 	// Note: pseudocode, this actually does not compile with glslang.
4195 	std::ostringstream task;
4196 	task
4197 		<< "#version 450\n"
4198 		<< "#extension GL_EXT_mesh_shader : enable\n"
4199 		<< "\n"
4200 		<< "layout(local_size_x=1) in;\n"
4201 		<< "layout(push_constant, std430) uniform PCBlock {\n"
4202 		<< "    uint index;\n"
4203 		<< "} pc;\n"
4204 		<< "struct TaskData {\n"
4205 		<< "    uint key;\n"
4206 		<< "};\n"
4207 		<< "taskPayloadSharedEXT TaskData td0;\n"
4208 		<< "taskPayloadSharedEXT TaskData td1;\n"
4209 		<< "taskPayloadSharedEXT TaskData td2;\n"
4210 		<< "\n"
4211 		<< "void main ()\n"
4212 		<< "{\n"
4213 		<< "    td0.key = " << keys.at(0) << "u;\n"
4214 		<< "    td1.key = " << keys.at(1) << "u;\n"
4215 		<< "    td2.key = " << keys.at(2) << "u;\n"
4216 		<< "    if (pc.index == 0u)      EmitMeshTasksEXT(1u, 1u, 1u, td0);\n"
4217 		<< "    else if (pc.index == 1u) EmitMeshTasksEXT(1u, 1u, 1u, td1);\n"
4218 		<< "    else                     EmitMeshTasksEXT(1u, 1u, 1u, td2);\n"
4219 		<< "}\n"
4220 		;
4221 	programCollection.glslSources.add("task") << glu::TaskSource(task.str());
4222 #else
4223 	// Similar shader to check the setup works.
4224 	std::ostringstream task;
4225 	task
4226 		<< "#version 450\n"
4227 		<< "#extension GL_EXT_mesh_shader : enable\n"
4228 		<< "\n"
4229 		<< "layout(local_size_x=1) in;\n"
4230 		<< "layout(push_constant, std430) uniform PCBlock {\n"
4231 		<< "    uint index;\n"
4232 		<< "} pc;\n"
4233 		<< "struct TaskData {\n"
4234 		<< "    uint key;\n"
4235 		<< "};\n"
4236 		<< "taskPayloadSharedEXT TaskData td;\n"
4237 		<< "\n"
4238 		<< "void main ()\n"
4239 		<< "{\n"
4240 		<< "    if (pc.index == 0u)      td.key = " << keys.at(0) << "u;\n"
4241 		<< "    else if (pc.index == 1u) td.key = " << keys.at(1) << "u;\n"
4242 		<< "    else                     td.key = " << keys.at(2) << "u;\n"
4243 		<< "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
4244 		<< "}\n"
4245 		;
4246 	programCollection.glslSources.add("task") << glu::TaskSource(task.str());
4247 #endif
4248 #else
4249 	std::ostringstream taskSPV;
4250 	taskSPV
4251 		<< "                    OpCapability MeshShadingEXT\n"
4252 		<< "                    OpExtension \"SPV_EXT_mesh_shader\"\n"
4253 		<< "               %1 = OpExtInstImport \"GLSL.std.450\"\n"
4254 		<< "                    OpMemoryModel Logical GLSL450\n"
4255 		<< "                    OpEntryPoint TaskEXT %main \"main\"\n"
4256 		<< "                    OpExecutionMode %main LocalSize 1 1 1\n"
4257 		<< "                    OpMemberDecorate %PCBlock 0 Offset 0\n"
4258 		<< "                    OpDecorate %PCBlock Block\n"
4259 		<< "                    OpDecorate %work_group_size BuiltIn WorkgroupSize\n"
4260 		<< "               %2 = OpTypeVoid\n"
4261 		<< "               %3 = OpTypeFunction %2\n"
4262 		<< "            %uint = OpTypeInt 32 0\n"
4263 		<< "        %TaskData = OpTypeStruct %uint\n"
4264 		<< "    %TaskData_ptr = OpTypePointer TaskPayloadWorkgroupEXT %TaskData\n"
4265 		<< "       %payload_0 = OpVariable %TaskData_ptr TaskPayloadWorkgroupEXT\n"
4266 		<< "       %payload_1 = OpVariable %TaskData_ptr TaskPayloadWorkgroupEXT\n"
4267 		<< "       %payload_2 = OpVariable %TaskData_ptr TaskPayloadWorkgroupEXT\n"
4268 		<< "             %int = OpTypeInt 32 1\n"
4269 		<< "           %int_0 = OpConstant %int 0\n"
4270 		<< "           %key_0 = OpConstant %uint " << keys.at(0) << "\n"
4271 		<< "           %key_1 = OpConstant %uint " << keys.at(1) << "\n"
4272 		<< "           %key_2 = OpConstant %uint " << keys.at(2) << "\n"
4273 		<< "%payload_uint_ptr = OpTypePointer TaskPayloadWorkgroupEXT %uint\n"
4274 		<< "         %PCBlock = OpTypeStruct %uint\n"
4275 		<< "     %PCBlock_ptr = OpTypePointer PushConstant %PCBlock\n"
4276 		<< "              %pc = OpVariable %PCBlock_ptr PushConstant\n"
4277 		<< "     %pc_uint_ptr = OpTypePointer PushConstant %uint\n"
4278 		<< "          %uint_0 = OpConstant %uint 0\n"
4279 		<< "          %uint_1 = OpConstant %uint 1\n"
4280 		<< "            %bool = OpTypeBool\n"
4281 		<< "           %uvec3 = OpTypeVector %uint 3\n"
4282 		<< " %work_group_size = OpConstantComposite %uvec3 %uint_1 %uint_1 %uint_1\n"
4283 		<< "            %main = OpFunction %2 None %3\n"
4284 		<< "               %5 = OpLabel\n"
4285 		<< "   %payload_0_key = OpAccessChain %payload_uint_ptr %payload_0 %int_0\n"
4286 		<< "   %payload_1_key = OpAccessChain %payload_uint_ptr %payload_1 %int_0\n"
4287 		<< "   %payload_2_key = OpAccessChain %payload_uint_ptr %payload_2 %int_0\n"
4288 		<< "                    OpStore %payload_0_key %key_0\n"
4289 		<< "                    OpStore %payload_1_key %key_1\n"
4290 		<< "                    OpStore %payload_2_key %key_2\n"
4291 		<< "    %pc_index_ptr = OpAccessChain %pc_uint_ptr %pc %int_0\n"
4292 		<< "        %pc_index = OpLoad %uint %pc_index_ptr\n"
4293 		<< "              %23 = OpIEqual %bool %pc_index %uint_0\n"
4294 		<< "                    OpSelectionMerge %25 None\n"
4295 		<< "                    OpBranchConditional %23 %24 %27\n"
4296 		<< "              %24 = OpLabel\n"
4297 		<< "                    OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload_0\n"
4298 		<< "                    OpBranch %25\n"
4299 		<< "              %27 = OpLabel\n"
4300 		<< "              %30 = OpIEqual %bool %pc_index %uint_1\n"
4301 		<< "                    OpSelectionMerge %32 None\n"
4302 		<< "                    OpBranchConditional %30 %31 %33\n"
4303 		<< "              %31 = OpLabel\n"
4304 		<< "                    OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload_1\n"
4305 		<< "                    OpBranch %32\n"
4306 		<< "              %33 = OpLabel\n"
4307 		<< "                    OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload_2\n"
4308 		<< "                    OpBranch %32\n"
4309 		<< "              %32 = OpLabel\n"
4310 		<< "                    OpBranch %25\n"
4311 		<< "              %25 = OpLabel\n"
4312 		<< "                    OpReturn\n"
4313 		<< "                    OpFunctionEnd\n"
4314 		;
4315 	programCollection.spirvAsmSources.add("task") << taskSPV.str() << spvBuildOptions;
4316 #endif
4317 }
4318 
generateReferenceLevel()4319 void MultipleTaskPayloadsInstance::generateReferenceLevel ()
4320 {
4321 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
4322 }
4323 
iterate()4324 tcu::TestStatus MultipleTaskPayloadsInstance::iterate ()
4325 {
4326 	const auto&		vkd			= m_context.getDeviceInterface();
4327 	const auto		device		= m_context.getDevice();
4328 	auto&			alloc		= m_context.getDefaultAllocator();
4329 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
4330 	const auto		queue		= m_context.getUniversalQueue();
4331 
4332 	const auto		imageFormat	= getOutputFormat();
4333 	const auto		tcuFormat	= mapVkFormat(imageFormat);
4334 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
4335 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4336 
4337 	const VkImageCreateInfo colorBufferInfo =
4338 	{
4339 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
4340 		nullptr,								//	const void*				pNext;
4341 		0u,										//	VkImageCreateFlags		flags;
4342 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
4343 		imageFormat,							//	VkFormat				format;
4344 		imageExtent,							//	VkExtent3D				extent;
4345 		1u,										//	uint32_t				mipLevels;
4346 		1u,										//	uint32_t				arrayLayers;
4347 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
4348 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
4349 		imageUsage,								//	VkImageUsageFlags		usage;
4350 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
4351 		0u,										//	uint32_t				queueFamilyIndexCount;
4352 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
4353 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
4354 	};
4355 
4356 	// Create color image and view.
4357 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
4358 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4359 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4360 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
4361 
4362 	// Create a memory buffer for verification.
4363 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
4364 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4365 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
4366 
4367 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
4368 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
4369 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
4370 
4371 	// Pipeline layout.
4372 	const auto pcSize			= static_cast<uint32_t>(sizeof(uint32_t));
4373 	const auto pcRange			= makePushConstantRange(VK_SHADER_STAGE_TASK_BIT_EXT, 0u, pcSize);
4374 	const auto pipelineLayout	= makePipelineLayout(vkd, device, DE_NULL, &pcRange);
4375 
4376 	// Shader modules.
4377 	const auto&	binaries	= m_context.getBinaryCollection();
4378 	const auto	hasTask		= binaries.contains("task");
4379 
4380 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
4381 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
4382 
4383 	Move<VkShaderModule> taskShader;
4384 	if (hasTask)
4385 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
4386 
4387 	// Render pass.
4388 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
4389 
4390 	// Framebuffer.
4391 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
4392 
4393 	// Viewport and scissor.
4394 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
4395 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
4396 
4397 	// Color blending.
4398 	const auto									colorWriteMask	= (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
4399 	const VkPipelineColorBlendAttachmentState	blendAttState	=
4400 	{
4401 		VK_TRUE,				//	VkBool32				blendEnable;
4402 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcColorBlendFactor;
4403 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstColorBlendFactor;
4404 		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
4405 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			srcAlphaBlendFactor;
4406 		VK_BLEND_FACTOR_ONE,	//	VkBlendFactor			dstAlphaBlendFactor;
4407 		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
4408 		colorWriteMask,			//	VkColorComponentFlags	colorWriteMask;
4409 	};
4410 
4411 	const VkPipelineColorBlendStateCreateInfo colorBlendInfo =
4412 	{
4413 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
4414 		nullptr,													//	const void*									pNext;
4415 		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
4416 		VK_FALSE,													//	VkBool32									logicOpEnable;
4417 		VK_LOGIC_OP_OR,												//	VkLogicOp									logicOp;
4418 		1u,															//	uint32_t									attachmentCount;
4419 		&blendAttState,												//	const VkPipelineColorBlendAttachmentState*	pAttachments;
4420 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
4421 	};
4422 
4423 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
4424 		taskShader.get(), meshShader.get(), fragShader.get(),
4425 		renderPass.get(), viewports, scissors, 0u/*subpass*/,
4426 		nullptr, nullptr, nullptr, &colorBlendInfo);
4427 
4428 	// Command pool and buffer.
4429 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
4430 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4431 	const auto cmdBuffer	= cmdBufferPtr.get();
4432 
4433 	beginCommandBuffer(vkd, cmdBuffer);
4434 
4435 	// Run pipeline.
4436 	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 0.0f);
4437 	const auto		drawCount	= m_params->drawCount();
4438 	const uint32_t	pcData		= MultipleTaskPayloadsCase::kGoodKeyIdx;
4439 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
4440 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
4441 	vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_TASK_BIT_EXT, 0u, pcSize, &pcData);
4442 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
4443 	endRenderPass(vkd, cmdBuffer);
4444 
4445 	// Copy color buffer to verification buffer.
4446 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
4447 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
4448 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
4449 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
4450 
4451 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
4452 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
4453 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
4454 
4455 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
4456 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
4457 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
4458 
4459 	endCommandBuffer(vkd, cmdBuffer);
4460 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
4461 
4462 	// Generate reference image and compare results.
4463 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
4464 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
4465 
4466 	generateReferenceLevel();
4467 	invalidateAlloc(vkd, device, verificationBufferAlloc);
4468 	if (!verifyResult(verificationAccess))
4469 		TCU_FAIL("Result does not match reference; check log for details");
4470 
4471 	return tcu::TestStatus::pass("Pass");
4472 }
4473 
4474 // Test multiple task/mesh draw calls and updating push constants and descriptors in between. We will divide the output image in 4
4475 // quadrants, and use each task/mesh draw call to draw on a particular quadrant. The output color in each quadrant will be composed
4476 // of data from different sources: storage buffer, sampled image or push constant value, and those will change before each draw
4477 // call. We'll prepare different descriptors for each quadrant.
4478 class RebindSetsCase : public MeshShaderMiscCase
4479 {
4480 public:
RebindSetsCase(tcu::TestContext & testCtx,const std::string & name,ParamsPtr params)4481 					RebindSetsCase		(tcu::TestContext& testCtx, const std::string& name, ParamsPtr params)
4482 						: MeshShaderMiscCase(testCtx, name, std::move(params))
4483 						{
4484 							const auto drawCount = m_params->drawCount();
4485 							DE_ASSERT(drawCount.x() == 1u && drawCount.y() == 1u && drawCount.z() == 1u);
4486 							DE_UNREF(drawCount); // For release builds.
4487 						}
~RebindSetsCase(void)4488 	virtual			~RebindSetsCase		(void) {}
4489 
4490 	TestInstance*	createInstance		(Context& context) const override;
4491 	void			checkSupport		(Context& context) const override;
4492 	void			initPrograms		(vk::SourceCollections& programCollection) const override;
4493 };
4494 
4495 class RebindSetsInstance : public MeshShaderMiscInstance
4496 {
4497 public:
RebindSetsInstance(Context & context,const MiscTestParams * params)4498 						RebindSetsInstance		(Context& context, const MiscTestParams* params)
4499 							: MeshShaderMiscInstance(context, params) {}
~RebindSetsInstance(void)4500 	virtual				~RebindSetsInstance		(void) {}
4501 
4502 	void				generateReferenceLevel	() override;
4503 	tcu::TestStatus		iterate					(void) override;
4504 
4505 protected:
4506 	struct QuadrantInfo
4507 	{
4508 		// Offsets in framebuffer coordinates (0 to 2, final coordinates in range -1 to 1)
4509 		float		offsetX;
4510 		float		offsetY;
4511 		tcu::Vec4	color;
4512 
QuadrantInfovkt::MeshShader::__anond8548dd90111::RebindSetsInstance::QuadrantInfo4513 		QuadrantInfo (float offsetX_, float offsetY_, float red, float green, float blue)
4514 			: offsetX	(offsetX_)
4515 			, offsetY	(offsetY_)
4516 			, color		(red, green, blue, 1.0f)
4517 		{}
4518 	};
4519 
getQuadrantInfos()4520 	static std::vector<QuadrantInfo> getQuadrantInfos ()
4521 	{
4522 		std::vector<QuadrantInfo> infos;
4523 		infos.reserve(4u);
4524 
4525 		//                 offsets     rgb
4526 		infos.emplace_back(0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
4527 		infos.emplace_back(1.0f, 0.0f, 1.0f, 1.0f, 0.0f);
4528 		infos.emplace_back(0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
4529 		infos.emplace_back(1.0f, 1.0f, 0.0f, 1.0f, 1.0f);
4530 
4531 		return infos;
4532 	}
4533 
4534 	struct PushConstants
4535 	{
4536 		float offsetX;
4537 		float offsetY;
4538 		float blueComponent;
4539 	};
4540 };
4541 
createInstance(Context & context) const4542 TestInstance* RebindSetsCase::createInstance (Context &context) const
4543 {
4544 	return new RebindSetsInstance(context, m_params.get());
4545 }
4546 
checkSupport(Context & context) const4547 void RebindSetsCase::checkSupport (Context& context) const
4548 {
4549 	genericCheckSupport(context, true, false);
4550 }
4551 
initPrograms(vk::SourceCollections & programCollection) const4552 void RebindSetsCase::initPrograms (vk::SourceCollections& programCollection) const
4553 {
4554 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
4555 
4556 	// Generic fragment shader.
4557 	MeshShaderMiscCase::initPrograms(programCollection);
4558 
4559 	const std::string ssbo		= "layout (set=0, binding=0, std430) readonly buffer SSBOBlock { float redComponent; } ssbo;\n";
4560 	const std::string combined	= "layout (set=0, binding=1) uniform sampler2D greenComponent;\n";
4561 	const std::string pc		= "layout (push_constant, std430) uniform PCBlock { float offsetX; float offsetY; float blueComponent; } pc;\n";
4562 	const std::string payload	= "struct TaskData { float redComponent; }; taskPayloadSharedEXT TaskData td;\n";
4563 
4564 	std::ostringstream task;
4565 	task
4566 		<< "#version 450\n"
4567 		<< "#extension GL_EXT_mesh_shader : enable\n"
4568 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
4569 		<< "\n"
4570 		<< ssbo
4571 		<< payload
4572 		<< "\n"
4573 		<< "void main (void)\n"
4574 		<< "{\n"
4575 		<< "    td.redComponent = ssbo.redComponent;\n"
4576 		<< "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
4577 		<< "}\n"
4578 		;
4579 	programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
4580 
4581 	std::ostringstream mesh;
4582 	mesh
4583 		<< "#version 450\n"
4584 		<< "#extension GL_EXT_mesh_shader : enable\n"
4585 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
4586 		<< "layout (triangles) out;\n"
4587 		<< "layout (max_vertices=4, max_primitives=2) out;\n"
4588 		<< "\n"
4589 		<< combined
4590 		<< pc
4591 		<< payload
4592 		<< "layout (location=0) out perprimitiveEXT vec4 primitiveColor[];\n"
4593 		<< "\n"
4594 		<< "void main (void)\n"
4595 		<< "{\n"
4596 		<< "    SetMeshOutputsEXT(4u, 2u);\n"
4597 		<< "\n"
4598 		<< "    gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0 + pc.offsetX, -1.0 + pc.offsetY, 0.0, 1.0);\n"
4599 		<< "    gl_MeshVerticesEXT[1].gl_Position = vec4( 0.0 + pc.offsetX, -1.0 + pc.offsetY, 0.0, 1.0);\n"
4600 		<< "    gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0 + pc.offsetX,  0.0 + pc.offsetY, 0.0, 1.0);\n"
4601 		<< "    gl_MeshVerticesEXT[3].gl_Position = vec4( 0.0 + pc.offsetX,  0.0 + pc.offsetY, 0.0, 1.0);\n"
4602 		<< "\n"
4603 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(2u, 1u, 0u);\n"
4604 		<< "    gl_PrimitiveTriangleIndicesEXT[1] = uvec3(2u, 3u, 1u);\n"
4605 		<< "\n"
4606 		<< "    const vec4 primColor = vec4(td.redComponent, texture(greenComponent, vec2(0.5, 0.5)).x, pc.blueComponent, 1.0);\n"
4607 		<< "    primitiveColor[0] = primColor;\n"
4608 		<< "    primitiveColor[1] = primColor;\n"
4609 		<< "}\n"
4610 		;
4611 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
4612 }
4613 
generateReferenceLevel()4614 void RebindSetsInstance::generateReferenceLevel ()
4615 {
4616 	const auto iWidth	= static_cast<int>(m_params->width);
4617 	const auto iHeight	= static_cast<int>(m_params->height);
4618 	const auto fWidth	= static_cast<float>(iWidth);
4619 	const auto fHeight	= static_cast<float>(iHeight);
4620 
4621 	DE_ASSERT(iWidth % 2 == 0);
4622 	DE_ASSERT(iHeight % 2 == 0);
4623 
4624 	const auto halfWidth	= iWidth / 2;
4625 	const auto halfHeight	= iHeight / 2;
4626 
4627 	const auto format		= getOutputFormat();
4628 	const auto tcuFormat	= mapVkFormat(format);
4629 
4630 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
4631 	const auto access = m_referenceLevel->getAccess();
4632 
4633 	const auto quadrantInfos = getQuadrantInfos();
4634 	DE_ASSERT(quadrantInfos.size() == 4u);
4635 
4636 	for (const auto& quadrantInfo : quadrantInfos)
4637 	{
4638 		const auto xCorner		= static_cast<int>(quadrantInfo.offsetX / 2.0f * fWidth);
4639 		const auto yCorner		= static_cast<int>(quadrantInfo.offsetY / 2.0f * fHeight);
4640 		const auto subregion	= tcu::getSubregion(access, xCorner, yCorner, halfWidth, halfHeight);
4641 
4642 		tcu::clear(subregion, quadrantInfo.color);
4643 	}
4644 }
4645 
iterate(void)4646 tcu::TestStatus RebindSetsInstance::iterate (void)
4647 {
4648 	const auto&			vkd				= m_context.getDeviceInterface();
4649 	const auto			device			= m_context.getDevice();
4650 	auto&				alloc			= m_context.getDefaultAllocator();
4651 	const auto			queueIndex		= m_context.getUniversalQueueFamilyIndex();
4652 	const auto			queue			= m_context.getUniversalQueue();
4653 	const auto			quadrantInfos	= getQuadrantInfos();
4654 	const auto			setCount		= static_cast<uint32_t>(quadrantInfos.size());
4655 	const auto			textureExtent	= makeExtent3D(1u, 1u, 1u);
4656 	const tcu::IVec3	iTexExtent		(static_cast<int>(textureExtent.width), static_cast<int>(textureExtent.height), static_cast<int>(textureExtent.depth));
4657 	const auto			textureFormat	= VK_FORMAT_R8G8B8A8_UNORM;
4658 	const auto			tcuTexFormat	= mapVkFormat(textureFormat);
4659 	const auto			textureUsage	= (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
4660 	const auto			colorExtent		= makeExtent3D(m_params->width, m_params->height, 1u);
4661 	const auto			colorFormat		= getOutputFormat();
4662 	const auto			tcuColorFormat	= mapVkFormat(colorFormat);
4663 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4664 
4665 	DE_ASSERT(quadrantInfos.size() == 4u);
4666 
4667 	// We need 4 descriptor sets: 4 buffers, 4 images and 1 sampler.
4668 	const VkSamplerCreateInfo	samplerCreateInfo	= initVulkanStructure();
4669 	const auto					sampler				= createSampler(vkd, device, &samplerCreateInfo);
4670 
4671 	// Buffers.
4672 	const auto					ssboSize			= static_cast<VkDeviceSize>(sizeof(float));
4673 	const auto					ssboCreateInfo		= makeBufferCreateInfo(ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
4674 
4675 	std::vector<std::unique_ptr<BufferWithMemory>> ssbos;
4676 	ssbos.reserve(quadrantInfos.size());
4677 	for (const auto& quadrantInfo : quadrantInfos)
4678 	{
4679 		ssbos.emplace_back(new BufferWithMemory(vkd, device, alloc, ssboCreateInfo, MemoryRequirement::HostVisible));
4680 		void* data = ssbos.back()->getAllocation().getHostPtr();
4681 		const auto redComponent = quadrantInfo.color.x();
4682 		deMemcpy(data, &redComponent, sizeof(redComponent));
4683 	}
4684 
4685 	// Textures.
4686 	const VkImageCreateInfo textureCreateInfo =
4687 	{
4688 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
4689 		nullptr,								//	const void*				pNext;
4690 		0u,										//	VkImageCreateFlags		flags;
4691 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
4692 		textureFormat,							//	VkFormat				format;
4693 		textureExtent,							//	VkExtent3D				extent;
4694 		1u,										//	uint32_t				mipLevels;
4695 		1u,										//	uint32_t				arrayLayers;
4696 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
4697 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
4698 		textureUsage,							//	VkImageUsageFlags		usage;
4699 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
4700 		0u,										//	uint32_t				queueFamilyIndexCount;
4701 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
4702 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
4703 	};
4704 	const auto textureSRR			= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4705 	const auto textureSRL			= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4706 	const auto textureCopyRegion	= makeBufferImageCopy(textureExtent, textureSRL);
4707 
4708 	std::vector<std::unique_ptr<ImageWithMemory>> textures;
4709 	for (size_t i = 0u; i < quadrantInfos.size(); ++i)
4710 		textures.emplace_back(new ImageWithMemory(vkd, device, alloc, textureCreateInfo, MemoryRequirement::Any));
4711 
4712 	std::vector<Move<VkImageView>> textureViews;
4713 	textureViews.reserve(quadrantInfos.size());
4714 	for (const auto& texture : textures)
4715 		textureViews.push_back(makeImageView(vkd, device, texture->get(), VK_IMAGE_VIEW_TYPE_2D, textureFormat, textureSRR));
4716 
4717 	// Auxiliar buffers to fill the images with the right colors.
4718 	const auto pixelSize				= tcu::getPixelSize(tcuTexFormat);
4719 	const auto pixelCount				= textureExtent.width * textureExtent.height * textureExtent.depth;
4720 	const auto auxiliarBufferSize		= static_cast<VkDeviceSize>(static_cast<VkDeviceSize>(pixelSize) * static_cast<VkDeviceSize>(pixelCount));
4721 	const auto auxiliarBufferCreateInfo	= makeBufferCreateInfo(auxiliarBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
4722 
4723 	std::vector<std::unique_ptr<BufferWithMemory>> auxiliarBuffers;
4724 	auxiliarBuffers.reserve(quadrantInfos.size());
4725 	for (const auto& quadrantInfo : quadrantInfos)
4726 	{
4727 		auxiliarBuffers.emplace_back(new BufferWithMemory(vkd, device, alloc, auxiliarBufferCreateInfo, MemoryRequirement::HostVisible));
4728 
4729 		void*					data			= auxiliarBuffers.back()->getAllocation().getHostPtr();
4730 		tcu::PixelBufferAccess	access			(tcuTexFormat, iTexExtent, data);
4731 		const tcu::Vec4			quadrantColor	(quadrantInfo.color.y(), 0.0f, 0.0f, 1.0f);
4732 
4733 		tcu::clear(access, quadrantColor);
4734 	}
4735 
4736 	// Descriptor set layout.
4737 	DescriptorSetLayoutBuilder layoutBuilder;
4738 	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_TASK_BIT_EXT);
4739 	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_MESH_BIT_EXT);
4740 	const auto setLayout = layoutBuilder.build(vkd, device);
4741 
4742 	// Pipeline layout.
4743 	const auto pcSize			= static_cast<uint32_t>(sizeof(PushConstants));
4744 	const auto pcRange			= makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_EXT, 0u, pcSize);
4745 	const auto pipelineLayout	= makePipelineLayout(vkd, device, setLayout.get(), &pcRange);
4746 
4747 	// Descriptor pool and sets.
4748 	DescriptorPoolBuilder poolBuilder;
4749 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, setCount);
4750 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, setCount);
4751 	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setCount);
4752 
4753 	std::vector<Move<VkDescriptorSet>> descriptorSets;
4754 	for (size_t i = 0; i < quadrantInfos.size(); ++i)
4755 		descriptorSets.push_back(makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get()));
4756 
4757 	// Update descriptor sets.
4758 	DescriptorSetUpdateBuilder updateBuilder;
4759 	for (size_t i = 0; i < descriptorSets.size(); ++i)
4760 	{
4761 		const auto&	descriptorSet	= descriptorSets.at(i);
4762 		const auto&	ssbo			= ssbos.at(i);
4763 		const auto&	textureView		= textureViews.at(i);
4764 		const auto	descBufferInfo	= makeDescriptorBufferInfo(ssbo->get(), 0ull, ssboSize);
4765 		const auto	descImageInfo	= makeDescriptorImageInfo(sampler.get(), textureView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4766 
4767 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBufferInfo);
4768 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descImageInfo);
4769 	}
4770 	updateBuilder.update(vkd, device);
4771 
4772 	// Color attachment.
4773 	const VkImageCreateInfo colorCreateInfo =
4774 	{
4775 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
4776 		nullptr,								//	const void*				pNext;
4777 		0u,										//	VkImageCreateFlags		flags;
4778 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
4779 		colorFormat,							//	VkFormat				format;
4780 		colorExtent,							//	VkExtent3D				extent;
4781 		1u,										//	uint32_t				mipLevels;
4782 		1u,										//	uint32_t				arrayLayers;
4783 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
4784 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
4785 		colorUsage,								//	VkImageUsageFlags		usage;
4786 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
4787 		0u,										//	uint32_t				queueFamilyIndexCount;
4788 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
4789 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
4790 	};
4791 	const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4792 	const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4793 
4794 	ImageWithMemory	colorAttachment	(vkd, device, alloc, colorCreateInfo, MemoryRequirement::Any);
4795 	const auto		colorView		= makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
4796 
4797 	// Create a memory buffer for verification.
4798 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(colorExtent.width * colorExtent.height * tcu::getPixelSize(tcuColorFormat));
4799 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4800 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
4801 
4802 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
4803 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
4804 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
4805 
4806 	// Render pass and framebuffer.
4807 	const auto renderPass	= makeRenderPass(vkd, device, colorFormat);
4808 	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), colorExtent.width, colorExtent.height);
4809 
4810 	const std::vector<VkViewport>	viewports	(1u, makeViewport(colorExtent));
4811 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(colorExtent));
4812 
4813 	// Shader modules and pipeline.
4814 	const auto&	binaries	= m_context.getBinaryCollection();
4815 	const auto	taskShader	= createShaderModule(vkd, device, binaries.get("task"));
4816 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
4817 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
4818 	const auto	pipeline	= makeGraphicsPipeline(
4819 		vkd, device, pipelineLayout.get(),
4820 		taskShader.get(), meshShader.get(), fragShader.get(),
4821 		renderPass.get(), viewports, scissors);
4822 
4823 	// Command pool and buffer.
4824 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
4825 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4826 	const auto cmdBuffer	= cmdBufferPtr.get();
4827 
4828 	beginCommandBuffer(vkd, cmdBuffer);
4829 
4830 	// Copy data from auxiliar buffers to textures.
4831 	for (const auto& texture : textures)
4832 	{
4833 		const auto prepareTextureForCopy = makeImageMemoryBarrier(
4834 			0u, VK_ACCESS_TRANSFER_WRITE_BIT,
4835 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4836 			texture->get(), textureSRR);
4837 		cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &prepareTextureForCopy);
4838 	}
4839 
4840 	for (size_t i = 0; i < auxiliarBuffers.size(); ++i)
4841 	{
4842 		const auto& auxBuffer	= auxiliarBuffers.at(i);
4843 		const auto& texture		= textures.at(i);
4844 		vkd.cmdCopyBufferToImage(cmdBuffer, auxBuffer->get(), texture->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &textureCopyRegion);
4845 	}
4846 
4847 	// Prepare textures for sampling.
4848 	for (const auto& texture : textures)
4849 	{
4850 		const auto prepareTextureForSampling = makeImageMemoryBarrier(
4851 			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
4852 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4853 			texture->get(), textureSRR);
4854 		cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, &prepareTextureForSampling);
4855 	}
4856 
4857 	// Render stuff.
4858 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
4859 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
4860 
4861 	const auto drawCount = m_params->drawCount();
4862 	for (size_t i = 0; i < quadrantInfos.size(); ++i)
4863 	{
4864 		const auto& quadrantInfo = quadrantInfos.at(i);
4865 		const auto& descriptorSet = descriptorSets.at(i);
4866 
4867 		PushConstants pcData;
4868 		pcData.blueComponent = quadrantInfo.color.z();
4869 		pcData.offsetX = quadrantInfo.offsetX;
4870 		pcData.offsetY = quadrantInfo.offsetY;
4871 
4872 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
4873 		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_MESH_BIT_EXT, 0u, pcSize, &pcData);
4874 		vkd.cmdDrawMeshTasksEXT(cmdBuffer, drawCount.x(), drawCount.y(), drawCount.z());
4875 	}
4876 
4877 	endRenderPass(vkd, cmdBuffer);
4878 
4879 	// Copy color attachment to verification buffer.
4880 	const auto preCopyBarrier	= makeImageMemoryBarrier(
4881 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
4882 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4883 		colorAttachment.get(), colorSRR);
4884 	const auto postCopyBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
4885 	const auto copyRegion		= makeBufferImageCopy(colorExtent, colorSRL);
4886 
4887 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
4888 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
4889 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
4890 
4891 	endCommandBuffer(vkd, cmdBuffer);
4892 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
4893 
4894 	// Generate reference image and compare results.
4895 	const tcu::IVec3					iColorExtent		(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), 1);
4896 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuColorFormat, iColorExtent, verificationBufferData);
4897 
4898 	generateReferenceLevel();
4899 	invalidateAlloc(vkd, device, verificationBufferAlloc);
4900 	if (!verifyResult(verificationAccess))
4901 		TCU_FAIL("Result does not match reference; check log for details");
4902 
4903 	return tcu::TestStatus::pass("Pass");
4904 }
4905 
4906 } // anonymous namespace
4907 
createMeshShaderMiscTestsEXT(tcu::TestContext & testCtx)4908 tcu::TestCaseGroup* createMeshShaderMiscTestsEXT (tcu::TestContext& testCtx)
4909 {
4910 	GroupPtr miscTests (new tcu::TestCaseGroup(testCtx, "misc"));
4911 
4912 	{
4913 		ParamsPtr paramsPtr (new MiscTestParams(
4914 			/*taskCount*/	tcu::just(tcu::UVec3(2u, 1u, 1u)),
4915 			/*meshCount*/	tcu::UVec3(2u, 1u, 1u),
4916 			/*width*/		8u,
4917 			/*height*/		8u));
4918 
4919 		// Pass a complex structure from the task to the mesh shader
4920 		miscTests->addChild(new ComplexTaskDataCase(testCtx, "complex_task_data", std::move(paramsPtr)));
4921 	}
4922 
4923 	{
4924 		ParamsPtr paramsPtr (new MiscTestParams(
4925 			/*taskCount*/	tcu::Nothing,
4926 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4927 			/*width*/		5u,		// Use an odd value so there's a pixel in the exact center.
4928 			/*height*/		7u));	// Idem.
4929 
4930 		// Draw a single point
4931 		miscTests->addChild(new SinglePointCase(testCtx, "single_point", std::move(paramsPtr)));
4932 	}
4933 
4934 	{
4935 		ParamsPtr paramsPtr (new MiscTestParams(
4936 			/*taskCount*/	tcu::Nothing,
4937 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4938 			/*width*/		5u,		// Use an odd value so there's a pixel in the exact center.
4939 			/*height*/		7u));	// Idem.
4940 
4941 		// VK_KHR_maintenance5: Test default point size is 1.0f
4942 		// Draw a single point without writing to PointSize
4943 		miscTests->addChild(new SinglePointCase(testCtx, "single_point_default_size", std::move(paramsPtr), false));
4944 	}
4945 
4946 	{
4947 		ParamsPtr paramsPtr (new MiscTestParams(
4948 			/*taskCount*/	tcu::Nothing,
4949 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4950 			/*width*/		8u,
4951 			/*height*/		5u));	// Use an odd value so there's a center line.
4952 
4953 		// Draw a single line
4954 		miscTests->addChild(new SingleLineCase(testCtx, "single_line", std::move(paramsPtr)));
4955 	}
4956 
4957 	{
4958 		ParamsPtr paramsPtr (new MiscTestParams(
4959 			/*taskCount*/	tcu::Nothing,
4960 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4961 			/*width*/		5u,	// Use an odd value so there's a pixel in the exact center.
4962 			/*height*/		7u));	// Idem.
4963 
4964 		// Draw a single triangle
4965 		miscTests->addChild(new SingleTriangleCase(testCtx, "single_triangle", std::move(paramsPtr)));
4966 	}
4967 
4968 	{
4969 		ParamsPtr paramsPtr (new MiscTestParams(
4970 			/*taskCount*/	tcu::Nothing,
4971 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4972 			/*width*/		16u,
4973 			/*height*/		16u));
4974 
4975 		// Draw the maximum number of points
4976 		miscTests->addChild(new MaxPointsCase(testCtx, "max_points", std::move(paramsPtr)));
4977 	}
4978 
4979 	{
4980 		ParamsPtr paramsPtr (new MiscTestParams(
4981 			/*taskCount*/	tcu::Nothing,
4982 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
4983 			/*width*/		1u,
4984 			/*height*/		1020u));
4985 
4986 		// Draw the maximum number of lines
4987 		miscTests->addChild(new MaxLinesCase(testCtx, "max_lines", std::move(paramsPtr)));
4988 	}
4989 
4990 	{
4991 		const tcu::UVec3 localSizes[] =
4992 		{
4993 			tcu::UVec3(2u, 4u, 8u),
4994 			tcu::UVec3(4u, 2u, 4u),
4995 			tcu::UVec3(2u, 2u, 4u),
4996 		};
4997 
4998 		// Draw the maximum number of triangles using a work group size of...
4999 		for (const auto& localSize : localSizes)
5000 		{
5001 			const auto workGroupSize	= (localSize.x() * localSize.y() * localSize.z());
5002 			const auto wgsStr			= std::to_string(workGroupSize);
5003 			const auto testName			= "max_triangles_workgroupsize_" + wgsStr;
5004 
5005 			ParamsPtr paramsPtr (new MaxTrianglesCase::Params(
5006 				/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5007 				/*width*/		512u,
5008 				/*height*/		512u,
5009 				/*localSize*/	localSize));
5010 
5011 			miscTests->addChild(new MaxTrianglesCase(testCtx, testName, std::move(paramsPtr)));
5012 		}
5013 	}
5014 
5015 	using LargeWorkGroupParamsPtr = std::unique_ptr<LargeWorkGroupParams>;
5016 	const int dimensionCases[] = { 0, 1, 2 };
5017 
5018 	for (const auto& dim : dimensionCases)
5019 	{
5020 		const auto dimChar = dimSuffix(dim);
5021 
5022 		{
5023 			tcu::UVec3 taskCount (8u, 8u, 8u);
5024 			taskCount[dim] = 65535u;
5025 
5026 			LargeWorkGroupParamsPtr lwgParamsPtr	(new LargeWorkGroupParams(
5027 				/*taskCount*/						tcu::just(taskCount),
5028 				/*meshCount*/						tcu::UVec3(1u, 1u, 1u),
5029 				/*width*/							2040u,
5030 				/*height*/							2056u,
5031 				/*localInvocations*/				tcu::UVec3(1u, 1u, 1u)));
5032 
5033 			ParamsPtr paramsPtr (lwgParamsPtr.release());
5034 
5035 			const auto name = std::string("many_task_work_groups_") + dimChar;
5036 
5037 			miscTests->addChild(new LargeWorkGroupCase(testCtx, name, std::move(paramsPtr)));
5038 		}
5039 
5040 		{
5041 			tcu::UVec3 meshCount (8u, 8u, 8u);
5042 			meshCount[dim] = 65535u;
5043 
5044 			LargeWorkGroupParamsPtr lwgParamsPtr	(new LargeWorkGroupParams(
5045 				/*taskCount*/						tcu::Nothing,
5046 				/*meshCount*/						meshCount,
5047 				/*width*/							2040u,
5048 				/*height*/							2056u,
5049 				/*localInvocations*/				tcu::UVec3(1u, 1u, 1u)));
5050 
5051 			ParamsPtr paramsPtr (lwgParamsPtr.release());
5052 
5053 			const auto name = std::string("many_mesh_work_groups_") + dimChar;
5054 
5055 			miscTests->addChild(new LargeWorkGroupCase(testCtx, name, std::move(paramsPtr)));
5056 		}
5057 
5058 		{
5059 			tcu::UVec3 meshCount (1u, 1u, 1u);
5060 			tcu::UVec3 taskCount (1u, 1u, 1u);
5061 			tcu::UVec3 localInvs (1u, 1u, 1u);
5062 
5063 			meshCount[dim] = 256u;
5064 			taskCount[dim] = 128u;
5065 			localInvs[dim] = 128u;
5066 
5067 			LargeWorkGroupParamsPtr lwgParamsPtr	(new LargeWorkGroupParams(
5068 				/*taskCount*/						tcu::just(taskCount),
5069 				/*meshCount*/						meshCount,
5070 				/*width*/							2048u,
5071 				/*height*/							2048u,
5072 				/*localInvocations*/				localInvs));
5073 
5074 			ParamsPtr paramsPtr (lwgParamsPtr.release());
5075 
5076 			const auto name = std::string("many_task_mesh_work_groups_") + dimChar;
5077 
5078 			miscTests->addChild(new LargeWorkGroupCase(testCtx, name, std::move(paramsPtr)));
5079 		}
5080 	}
5081 
5082 	{
5083 		const PrimitiveType types[] = {
5084 			PrimitiveType::POINTS,
5085 			PrimitiveType::LINES,
5086 			PrimitiveType::TRIANGLES,
5087 		};
5088 
5089 		for (int i = 0; i < 2; ++i)
5090 		{
5091 			const bool extraWrites = (i > 0);
5092 
5093 			// XXX Is this test legal? [https://gitlab.khronos.org/GLSL/GLSL/-/merge_requests/77#note_348252]
5094 			if (extraWrites)
5095 				continue;
5096 
5097 			for (const auto primType : types)
5098 			{
5099 				std::unique_ptr<NoPrimitivesParams> params	(new NoPrimitivesParams(
5100 					/*taskCount*/							(extraWrites ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::Nothing),
5101 					/*meshCount*/							tcu::UVec3(1u, 1u, 1u),
5102 					/*width*/								16u,
5103 					/*height*/								16u,
5104 					/*primitiveType*/						primType));
5105 
5106 				ParamsPtr			paramsPtr	(params.release());
5107 				const auto			primName	= primitiveTypeName(primType);
5108 				const std::string	name		= "no_" + primName + (extraWrites ? "_extra_writes" : "");
5109 
5110 				miscTests->addChild(extraWrites
5111 					? (new NoPrimitivesExtraWritesCase(testCtx, name, std::move(paramsPtr)))
5112 					: (new NoPrimitivesCase(testCtx, name, std::move(paramsPtr))));
5113 			}
5114 		}
5115 	}
5116 
5117 	{
5118 		for (int i = 0; i < 2; ++i)
5119 		{
5120 			const bool useTaskShader = (i == 0);
5121 
5122 			ParamsPtr paramsPtr (new MiscTestParams(
5123 				/*taskCount*/		(useTaskShader ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::Nothing),
5124 				/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5125 				/*width*/			1u,
5126 				/*height*/			1u));
5127 
5128 			const std::string shader	= (useTaskShader ? "task" : "mesh");
5129 			const std::string name		= "barrier_in_" + shader;
5130 
5131 			miscTests->addChild(new SimpleBarrierCase(testCtx, name, std::move(paramsPtr)));
5132 		}
5133 	}
5134 
5135 	{
5136 		const struct
5137 		{
5138 			MemoryBarrierType	memBarrierType;
5139 			std::string			caseName;
5140 		} barrierTypes[] =
5141 		{
5142 			{ MemoryBarrierType::SHARED,	"memory_barrier_shared"	},
5143 			{ MemoryBarrierType::GROUP,		"group_memory_barrier"	},
5144 		};
5145 
5146 		for (const auto& barrierCase : barrierTypes)
5147 		{
5148 			for (int i = 0; i < 2; ++i)
5149 			{
5150 				const bool useTaskShader = (i == 0);
5151 
5152 				std::unique_ptr<MemoryBarrierParams> paramsPtr	(new MemoryBarrierParams(
5153 					/*taskCount*/								(useTaskShader ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::Nothing),
5154 					/*meshCount*/								tcu::UVec3(1u, 1u, 1u),
5155 					/*width*/									1u,
5156 					/*height*/									1u,
5157 					/*memBarrierType*/							barrierCase.memBarrierType));
5158 
5159 				const std::string shader	= (useTaskShader ? "task" : "mesh");
5160 				const std::string name		= barrierCase.caseName + "_in_" + shader;
5161 
5162 				miscTests->addChild(new MemoryBarrierCase(testCtx, name, std::move(paramsPtr)));
5163 			}
5164 		}
5165 	}
5166 
5167 	{
5168 		for (int i = 0; i < 2; ++i)
5169 		{
5170 			const bool useTaskShader	= (i > 0);
5171 			const auto name				= std::string("custom_attributes") + (useTaskShader ? "_and_task_shader" : "");
5172 
5173 			ParamsPtr paramsPtr (new MiscTestParams(
5174 				/*taskCount*/		(useTaskShader ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::Nothing),
5175 				/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5176 				/*width*/			32u,
5177 				/*height*/			32u));
5178 
5179 			miscTests->addChild(new CustomAttributesCase(testCtx, name, std::move(paramsPtr)));
5180 		}
5181 	}
5182 
5183 	{
5184 		for (int i = 0; i < 2; ++i)
5185 		{
5186 			const bool useTaskShader	= (i > 0);
5187 			const auto name				= std::string("push_constant") + (useTaskShader ? "_and_task_shader" : "");
5188 
5189 			ParamsPtr paramsPtr (new MiscTestParams(
5190 				/*taskCount*/		(useTaskShader ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::Nothing),
5191 				/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5192 				/*width*/			16u,
5193 				/*height*/			16u));
5194 
5195 			miscTests->addChild(new PushConstantCase(testCtx, name, std::move(paramsPtr)));
5196 		}
5197 	}
5198 
5199 	{
5200 		ParamsPtr paramsPtr (new MaximizeThreadsParams(
5201 			/*taskCount*/		tcu::Nothing,
5202 			/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5203 			/*width*/			128u,
5204 			/*height*/			1u,
5205 			/*localSize*/		32u,
5206 			/*numVertices*/		128u,
5207 			/*numPrimitives*/	256u));
5208 
5209 		miscTests->addChild(new MaximizePrimitivesCase(testCtx, "maximize_primitives", std::move(paramsPtr)));
5210 	}
5211 
5212 	{
5213 		ParamsPtr paramsPtr (new MaximizeThreadsParams(
5214 			/*taskCount*/		tcu::Nothing,
5215 			/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5216 			/*width*/			64u,
5217 			/*height*/			1u,
5218 			/*localSize*/		32u,
5219 			/*numVertices*/		256u,
5220 			/*numPrimitives*/	128u));
5221 
5222 		miscTests->addChild(new MaximizeVerticesCase(testCtx, "maximize_vertices", std::move(paramsPtr)));
5223 	}
5224 
5225 	{
5226 		const uint32_t kInvocationCases[] = { 32u, 64u, 128u, 256u };
5227 
5228 		for (const auto& invocationCase : kInvocationCases)
5229 		{
5230 			const auto invsStr		= std::to_string(invocationCase);
5231 			const auto numPixels	= invocationCase / 2u;
5232 
5233 			ParamsPtr paramsPtr (new MaximizeThreadsParams(
5234 				/*taskCount*/		tcu::Nothing,
5235 				/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5236 				/*width*/			numPixels,
5237 				/*height*/			1u,
5238 				/*localSize*/		invocationCase,
5239 				/*numVertices*/		numPixels,
5240 				/*numPrimitives*/	numPixels));
5241 
5242 			miscTests->addChild(new MaximizeInvocationsCase(testCtx, "maximize_invocations_" + invsStr, std::move(paramsPtr)));
5243 		}
5244 	}
5245 
5246 	{
5247 		for (int i = 0; i < 2; ++i)
5248 		{
5249 			const bool useDynamicTopology = (i > 0);
5250 
5251 			ParamsPtr paramsPtr (new MixedPipelinesParams(
5252 				/*taskCount*/		tcu::Nothing,
5253 				/*meshCount*/		tcu::UVec3(1u, 1u, 1u),
5254 				/*width*/			8u,
5255 				/*height*/			8u,
5256 				/*dynamicTopology*/	useDynamicTopology));
5257 
5258 			const std::string nameSuffix = (useDynamicTopology ? "_dynamic_topology" : "");
5259 			const std::string descSuffix = (useDynamicTopology ? " and use dynamic topology" : "");
5260 
5261 			miscTests->addChild(new MixedPipelinesCase(testCtx, "mixed_pipelines" + nameSuffix, std::move(paramsPtr)));
5262 		}
5263 	}
5264 
5265 	for (int i = 0; i < 2; ++i)
5266 	{
5267 		const bool						useTask		= (i > 0);
5268 		const tcu::Maybe<tcu::UVec3>	taskCount	= (useTask ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::nothing<tcu::UVec3>());
5269 		const std::string				testName	= std::string("first_invocation_") + (useTask ? "task" : "mesh");
5270 
5271 		ParamsPtr paramsPtr (new MiscTestParams(
5272 			/*taskCount*/	taskCount,
5273 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5274 			/*width*/		128u,
5275 			/*height*/		1u));
5276 
5277 		miscTests->addChild(new FirstInvocationCase(testCtx, testName, std::move(paramsPtr)));
5278 	}
5279 
5280 	for (int i = 0; i < 2; ++i)
5281 	{
5282 		const bool						useTask		= (i > 0);
5283 		const tcu::Maybe<tcu::UVec3>	taskCount	= (useTask ? tcu::just(tcu::UVec3(1u, 1u, 1u)) : tcu::nothing<tcu::UVec3>());
5284 		const std::string				testName	= std::string("local_size_id_") + (useTask ? "task" : "mesh");
5285 
5286 		ParamsPtr paramsPtr (new MiscTestParams(
5287 			/*taskCount*/	taskCount,
5288 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5289 			/*width*/		32u,
5290 			/*height*/		1u));
5291 
5292 		miscTests->addChild(new LocalSizeIdCase(testCtx, testName, std::move(paramsPtr)));
5293 	}
5294 
5295 	if (false) // Disabled. This may be illegal.
5296 	{
5297 		ParamsPtr paramsPtr (new MiscTestParams(
5298 			/*taskCount*/	tcu::UVec3(1u, 1u, 1u),
5299 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5300 			/*width*/		8u,
5301 			/*height*/		8u));
5302 
5303 		miscTests->addChild(new MultipleTaskPayloadsCase(testCtx, "multiple_task_payloads", std::move(paramsPtr)));
5304 	}
5305 
5306 	{
5307 		ParamsPtr paramsPtr (new MiscTestParams(
5308 			/*taskCount*/	tcu::UVec3(1u, 1u, 1u),
5309 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5310 			/*width*/		8u,
5311 			/*height*/		8u));
5312 
5313 		miscTests->addChild(new PayloadReadCase(testCtx, "payload_read", std::move(paramsPtr)));
5314 	}
5315 
5316 	{
5317 		ParamsPtr paramsPtr (new MiscTestParams(
5318 			/*taskCount*/	tcu::UVec3(1u, 1u, 1u),
5319 			/*meshCount*/	tcu::UVec3(1u, 1u, 1u),
5320 			/*width*/		8u,
5321 			/*height*/		8u));
5322 
5323 		miscTests->addChild(new RebindSetsCase(testCtx, "rebind_sets", std::move(paramsPtr)));
5324 	}
5325 
5326 	return miscTests.release();
5327 }
5328 
5329 } // MeshShader
5330 } // vkt
5331